diff gcc/lra-eliminations.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
line wrap: on
line diff
--- a/gcc/lra-eliminations.c	Fri Oct 27 22:46:09 2017 +0900
+++ b/gcc/lra-eliminations.c	Thu Oct 25 07:37:49 2018 +0900
@@ -1,5 +1,5 @@
 /* Code for RTL register eliminations.
-   Copyright (C) 2010-2017 Free Software Foundation, Inc.
+   Copyright (C) 2010-2018 Free Software Foundation, Inc.
    Contributed by Vladimir Makarov <vmakarov@redhat.com>.
 
 This file is part of GCC.
@@ -79,9 +79,9 @@
   int to;
   /* Difference between values of the two hard registers above on
      previous iteration.  */
-  HOST_WIDE_INT previous_offset;
+  poly_int64 previous_offset;
   /* Difference between the values on the current iteration.  */
-  HOST_WIDE_INT offset;
+  poly_int64 offset;
   /* Nonzero if this elimination can be done.  */
   bool can_eliminate;
   /* CAN_ELIMINATE since the last check.  */
@@ -120,10 +120,14 @@
   struct lra_elim_table *ep;
 
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-    fprintf (f, "%s eliminate %d to %d (offset=" HOST_WIDE_INT_PRINT_DEC
-	     ", prev_offset=" HOST_WIDE_INT_PRINT_DEC ")\n",
-	     ep->can_eliminate ? "Can" : "Can't",
-	     ep->from, ep->to, ep->offset, ep->previous_offset);
+    {
+      fprintf (f, "%s eliminate %d to %d (offset=",
+	       ep->can_eliminate ? "Can" : "Can't", ep->from, ep->to);
+      print_dec (ep->offset, f);
+      fprintf (f, ", prev_offset=");
+      print_dec (ep->previous_offset, f);
+      fprintf (f, ")\n");
+    }
 }
 
 /* Print info about elimination table to stderr.  */
@@ -161,7 +165,7 @@
 /* Offsets should be used to restore original offsets for eliminable
    hard register which just became not eliminable.  Zero,
    otherwise.  */
-static HOST_WIDE_INT self_elim_offsets[FIRST_PSEUDO_REGISTER];
+static poly_int64_pod self_elim_offsets[FIRST_PSEUDO_REGISTER];
 
 /* Map: hard regno -> RTL presentation.	 RTL presentations of all
    potentially eliminable hard registers are stored in the map.	 */
@@ -193,6 +197,7 @@
 form_sum (rtx x, rtx y)
 {
   machine_mode mode = GET_MODE (x);
+  poly_int64 offset;
 
   if (mode == VOIDmode)
     mode = GET_MODE (y);
@@ -200,10 +205,10 @@
   if (mode == VOIDmode)
     mode = Pmode;
 
-  if (CONST_INT_P (x))
-    return plus_constant (mode, y, INTVAL (x));
-  else if (CONST_INT_P (y))
-    return plus_constant (mode, x, INTVAL (y));
+  if (poly_int_rtx_p (x, &offset))
+    return plus_constant (mode, y, offset);
+  else if (poly_int_rtx_p (y, &offset))
+    return plus_constant (mode, x, offset);
   else if (CONSTANT_P (x))
     std::swap (x, y);
 
@@ -252,14 +257,14 @@
 {
   int hard_regno;
   struct lra_elim_table *ep;
-  HOST_WIDE_INT offset;
 
   lra_assert (REG_P (reg));
   if ((hard_regno = REGNO (reg)) < 0 || hard_regno >= FIRST_PSEUDO_REGISTER)
     return NULL;
   if ((ep = elimination_map[hard_regno]) != NULL)
     return ep->from_rtx != reg ? NULL : ep;
-  if ((offset = self_elim_offsets[hard_regno]) == 0)
+  poly_int64 offset = self_elim_offsets[hard_regno];
+  if (known_eq (offset, 0))
     return NULL;
   /* This is an iteration to restore offsets just after HARD_REGNO
      stopped to be eliminable.	*/
@@ -325,7 +330,7 @@
 rtx
 lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
 		      bool subst_p, bool update_p,
-		      HOST_WIDE_INT update_sp_offset, bool full_p)
+		      poly_int64 update_sp_offset, bool full_p)
 {
   enum rtx_code code = GET_CODE (x);
   struct lra_elim_table *ep;
@@ -335,7 +340,8 @@
   int copied = 0;
 
   lra_assert (!update_p || !full_p);
-  lra_assert (update_sp_offset == 0 || (!subst_p && update_p && !full_p));
+  lra_assert (known_eq (update_sp_offset, 0)
+	      || (!subst_p && update_p && !full_p));
   if (! current_function_decl)
     return x;
 
@@ -360,7 +366,7 @@
 	{
 	  rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
 
-	  if (update_sp_offset != 0)
+	  if (maybe_ne (update_sp_offset, 0))
 	    {
 	      if (ep->to_rtx == stack_pointer_rtx)
 		return plus_constant (Pmode, to, update_sp_offset);
@@ -387,20 +393,21 @@
 	{
 	  if ((ep = get_elimination (XEXP (x, 0))) != NULL)
 	    {
-	      HOST_WIDE_INT offset;
+	      poly_int64 offset, curr_offset;
 	      rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
 
 	      if (! update_p && ! full_p)
 		return gen_rtx_PLUS (Pmode, to, XEXP (x, 1));
 	      
-	      if (update_sp_offset != 0)
+	      if (maybe_ne (update_sp_offset, 0))
 		offset = ep->to_rtx == stack_pointer_rtx ? update_sp_offset : 0;
 	      else
 		offset = (update_p
 			  ? ep->offset - ep->previous_offset : ep->offset);
 	      if (full_p && insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx)
 		offset -= lra_get_insn_recog_data (insn)->sp_offset;
-	      if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == -offset)
+	      if (poly_int_rtx_p (XEXP (x, 1), &curr_offset)
+		  && known_eq (curr_offset, -offset))
 		return to;
 	      else
 		return gen_rtx_PLUS (Pmode, to,
@@ -449,7 +456,7 @@
 	{
 	  rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
 
-	  if (update_sp_offset != 0)
+	  if (maybe_ne (update_sp_offset, 0))
 	    {
 	      if (ep->to_rtx == stack_pointer_rtx)
 		return plus_constant (Pmode,
@@ -464,7 +471,7 @@
 				  * INTVAL (XEXP (x, 1)));
 	  else if (full_p)
 	    {
-	      HOST_WIDE_INT offset = ep->offset;
+	      poly_int64 offset = ep->offset;
 
 	      if (insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx)
 		offset -= lra_get_insn_recog_data (insn)->sp_offset;
@@ -647,6 +654,7 @@
       return x;
 
     case CLOBBER:
+    case CLOBBER_HIGH:
     case SET:
       gcc_unreachable ();
 
@@ -711,7 +719,7 @@
 /* Stack pointer offset before the current insn relative to one at the
    func start.  RTL insns can change SP explicitly.  We keep the
    changes from one insn to another through this variable.  */
-static HOST_WIDE_INT curr_sp_change;
+static poly_int64 curr_sp_change;
 
 /* Scan rtx X for references to elimination source or target registers
    in contexts that would prevent the elimination from happening.
@@ -725,6 +733,7 @@
   struct lra_elim_table *ep;
   int i, j;
   const char *fmt;
+  poly_int64 offset = 0;
 
   switch (code)
     {
@@ -738,9 +747,9 @@
 	  && ((code != PRE_MODIFY && code != POST_MODIFY)
 	      || (GET_CODE (XEXP (x, 1)) == PLUS
 		  && XEXP (x, 0) == XEXP (XEXP (x, 1), 0)
-		  && CONST_INT_P (XEXP (XEXP (x, 1), 1)))))
+		  && poly_int_rtx_p (XEXP (XEXP (x, 1), 1), &offset))))
 	{
-	  int size = GET_MODE_SIZE (mem_mode);
+	  poly_int64 size = GET_MODE_SIZE (mem_mode);
 	  
 #ifdef PUSH_ROUNDING
 	  /* If more bytes than MEM_MODE are pushed, account for
@@ -752,7 +761,7 @@
 	  else if (code == PRE_INC || code == POST_INC)
 	    curr_sp_change += size;
 	  else if (code == PRE_MODIFY || code == POST_MODIFY)
-	    curr_sp_change += INTVAL (XEXP (XEXP (x, 1), 1));
+	    curr_sp_change += offset;
 	}
       else if (REG_P (XEXP (x, 0))
 	       && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER)
@@ -798,13 +807,23 @@
 	    setup_can_eliminate (ep, false);
       return;
 
+    case CLOBBER_HIGH:
+      gcc_assert (REG_P (XEXP (x, 0)));
+      gcc_assert (REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER);
+      for (ep = reg_eliminate;
+	   ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
+	   ep++)
+	if (reg_is_clobbered_by_clobber_high (ep->to_rtx, XEXP (x, 0)))
+	  setup_can_eliminate (ep, false);
+      return;
+
     case SET:
       if (SET_DEST (x) == stack_pointer_rtx
 	  && GET_CODE (SET_SRC (x)) == PLUS
 	  && XEXP (SET_SRC (x), 0) == SET_DEST (x)
-	  && CONST_INT_P (XEXP (SET_SRC (x), 1)))
+	  && poly_int_rtx_p (XEXP (SET_SRC (x), 1), &offset))
 	{
-	  curr_sp_change += INTVAL (XEXP (SET_SRC (x), 1));
+	  curr_sp_change += offset;
 	  return;
 	}
       if (! REG_P (SET_DEST (x))
@@ -859,11 +878,11 @@
 
 #ifdef HARD_FRAME_POINTER_REGNUM
 
-/* Find offset equivalence note for reg WHAT in INSN and return the
-   found elmination offset.  If the note is not found, return NULL.
-   Remove the found note.  */
-static rtx
-remove_reg_equal_offset_note (rtx_insn *insn, rtx what)
+/* Search INSN's reg notes to see whether the destination is equal to
+   WHAT + C for some constant C.  Return true if so, storing C in
+   *OFFSET_OUT and removing the reg note.  */
+static bool
+remove_reg_equal_offset_note (rtx_insn *insn, rtx what, poly_int64 *offset_out)
 {
   rtx link, *link_loc;
 
@@ -873,12 +892,12 @@
     if (REG_NOTE_KIND (link) == REG_EQUAL
 	&& GET_CODE (XEXP (link, 0)) == PLUS
 	&& XEXP (XEXP (link, 0), 0) == what
-	&& CONST_INT_P (XEXP (XEXP (link, 0), 1)))
+	&& poly_int_rtx_p (XEXP (XEXP (link, 0), 1), offset_out))
       {
 	*link_loc = XEXP (link, 1);
-	return XEXP (XEXP (link, 0), 1);
+	return true;
       }
-  return NULL_RTX;
+  return false;
 }
 
 #endif
@@ -899,7 +918,7 @@
 
 void
 eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
-			HOST_WIDE_INT update_sp_offset)
+			poly_int64 update_sp_offset)
 {
   int icode = recog_memoized (insn);
   rtx old_set = single_set (insn);
@@ -940,28 +959,21 @@
 		 nonlocal goto.  */
 	      {
 		rtx src = SET_SRC (old_set);
-		rtx off = remove_reg_equal_offset_note (insn, ep->to_rtx);
-		
+		poly_int64 offset = 0;
+
 		/* We should never process such insn with non-zero
 		   UPDATE_SP_OFFSET.  */
-		lra_assert (update_sp_offset == 0);
+		lra_assert (known_eq (update_sp_offset, 0));
 		
-		if (off != NULL_RTX
-		    || src == ep->to_rtx
-		    || (GET_CODE (src) == PLUS
-			&& XEXP (src, 0) == ep->to_rtx
-			&& CONST_INT_P (XEXP (src, 1))))
+		if (remove_reg_equal_offset_note (insn, ep->to_rtx, &offset)
+		    || strip_offset (src, &offset) == ep->to_rtx)
 		  {
-		    HOST_WIDE_INT offset;
-		    
 		    if (replace_p)
 		      {
 			SET_DEST (old_set) = ep->to_rtx;
 			lra_update_insn_recog_data (insn);
 			return;
 		      }
-		    offset = (off != NULL_RTX ? INTVAL (off)
-			      : src == ep->to_rtx ? 0 : INTVAL (XEXP (src, 1)));
 		    offset -= (ep->offset - ep->previous_offset);
 		    src = plus_constant (Pmode, ep->to_rtx, offset);
 		    
@@ -997,13 +1009,13 @@
      currently support: a single set with the source or a REG_EQUAL
      note being a PLUS of an eliminable register and a constant.  */
   plus_src = plus_cst_src = 0;
+  poly_int64 offset = 0;
   if (old_set && REG_P (SET_DEST (old_set)))
     {
       if (GET_CODE (SET_SRC (old_set)) == PLUS)
 	plus_src = SET_SRC (old_set);
       /* First see if the source is of the form (plus (...) CST).  */
-      if (plus_src
-	  && CONST_INT_P (XEXP (plus_src, 1)))
+      if (plus_src && poly_int_rtx_p (XEXP (plus_src, 1), &offset))
 	plus_cst_src = plus_src;
       /* Check that the first operand of the PLUS is a hard reg or
 	 the lowpart subreg of one.  */
@@ -1021,7 +1033,6 @@
   if (plus_cst_src)
     {
       rtx reg = XEXP (plus_cst_src, 0);
-      HOST_WIDE_INT offset = INTVAL (XEXP (plus_cst_src, 1));
 
       if (GET_CODE (reg) == SUBREG)
 	reg = SUBREG_REG (reg);
@@ -1032,7 +1043,7 @@
 
 	  if (! replace_p)
 	    {
-	      if (update_sp_offset == 0)
+	      if (known_eq (update_sp_offset, 0))
 		offset += (ep->offset - ep->previous_offset);
 	      if (ep->to_rtx == stack_pointer_rtx)
 		{
@@ -1051,7 +1062,7 @@
 	     the cost of the insn by replacing a simple REG with (plus
 	     (reg sp) CST).  So try only when we already had a PLUS
 	     before.  */
-	  if (offset == 0 || plus_src)
+	  if (known_eq (offset, 0) || plus_src)
 	    {
 	      rtx new_src = plus_constant (GET_MODE (to_rtx), to_rtx, offset);
 
@@ -1175,7 +1186,7 @@
     if (bitmap_bit_p (&to_process, INSN_UID (insn)))
       {
 	lra_push_insn (insn);
-	lra_set_used_insn_alternative (insn, -1);
+	lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
       }
   bitmap_clear (&to_process);
 }
@@ -1239,7 +1250,7 @@
 	      if (lra_dump_file != NULL)
 		fprintf (lra_dump_file, "    Using elimination %d to %d now\n",
 			 ep1->from, ep1->to);
-	      lra_assert (ep1->previous_offset == 0);
+	      lra_assert (known_eq (ep1->previous_offset, 0));
 	      ep1->previous_offset = ep->offset;
 	    }
 	  else
@@ -1251,7 +1262,7 @@
 		fprintf (lra_dump_file, "    %d is not eliminable at all\n",
 			 ep->from);
 	      self_elim_offsets[ep->from] = -ep->offset;
-	      if (ep->offset != 0)
+	      if (maybe_ne (ep->offset, 0))
 		bitmap_ior_into (insns_with_changed_offsets,
 				 &lra_reg_info[ep->from].insn_bitmap);
 	    }
@@ -1264,14 +1275,14 @@
   CLEAR_HARD_REG_SET (temp_hard_reg_set);
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     if (elimination_map[ep->from] == NULL)
-      SET_HARD_REG_BIT (temp_hard_reg_set, ep->from);
+      add_to_hard_reg_set (&temp_hard_reg_set, Pmode, ep->from);
     else if (elimination_map[ep->from] == ep)
       {
 	/* Prevent the hard register into which we eliminate from
 	   the usage for pseudos.  */
         if (ep->from != ep->to)
-	  SET_HARD_REG_BIT (temp_hard_reg_set, ep->to);
-	if (ep->previous_offset != ep->offset)
+	  add_to_hard_reg_set (&temp_hard_reg_set, Pmode, ep->to);
+	if (maybe_ne (ep->previous_offset, ep->offset))
 	  {
 	    bitmap_ior_into (insns_with_changed_offsets,
 			     &lra_reg_info[ep->from].insn_bitmap);
@@ -1357,13 +1368,13 @@
 	    if (NONDEBUG_INSN_P (insn))
 	      {
 		mark_not_eliminable (PATTERN (insn), VOIDmode);
-		if (curr_sp_change != 0
+		if (maybe_ne (curr_sp_change, 0)
 		    && find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX))
 		  stop_to_sp_elimination_p = true;
 	      }
 	  }
       if (! frame_pointer_needed
-	  && (curr_sp_change != 0 || stop_to_sp_elimination_p)
+	  && (maybe_ne (curr_sp_change, 0) || stop_to_sp_elimination_p)
 	  && bb->succs && bb->succs->length () != 0)
 	for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
 	  if (ep->to == STACK_POINTER_REGNUM)
@@ -1408,7 +1419,7 @@
 	}
       lra_update_insn_regno_info (insn);
       lra_push_insn (insn);
-      lra_set_used_insn_alternative (insn, -1);
+      lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
     }
 }