The following patch fixes building Ada on ppc64 with LRA (elimination part changes which makes it behave as reload pass code). The patch also fixes a failure on new test added for ppc recently. This change is in very sensitive part of LRA and there is possibility that other targets can be affected but I think the probability of this is very small.

The patch was successfully bootstrapped and tested on x86/x86-64 and ppc64.

Committed as rev. 203147.

2013-10-02  Vladimir Makarov  <vmaka...@redhat.com>

        * lra-constraints.c (process_alt_operand): Calculate scratch_p and
        use it.  Use smaller increase for scratch.  Don't increase reject
        for early clobber scratch.
        * lra-eliminations.c (eliminate_regs_in_insn): Remove all insns
        setting eliminated regs except setting fp from hfp.
        (lra_eliminate): Check lra_insn_recog_data on NULL.

Index: ChangeLog
===================================================================
--- ChangeLog   (revision 202721)
+++ ChangeLog   (working copy)
@@ -1,3 +1,12 @@
+2013-10-02  Vladimir Makarov  <vmaka...@redhat.com>
+
+       * lra-constraints.c (process_alt_operand): Calculate scratch_p and
+       use it.  Use smaller increase for scratch.  Don't increase reject
+       for early clobber scratch.
+       * lra-eliminations.c (eliminate_regs_in_insn): Remove all insns
+       setting eliminated regs except setting fp from hfp.
+       (lra_eliminate): Check lra_insn_recog_data on NULL.
+
 2013-09-18  Vladimir Makarov  <vmaka...@redhat.com>
 
        * lra-constraints.c (need_for_all_save_p): Use macro
Index: config/aarch64/aarch64.c
===================================================================
--- config/aarch64/aarch64.c    (revision 202626)
+++ config/aarch64/aarch64.c    (working copy)
@@ -8151,6 +8151,16 @@ aarch64_vectorize_vec_perm_const_ok (enu
   return ret;
 }
 
+/* Return true if we use LRA instead of reload pass.  */
+static bool
+aarch64_lra_p (void)
+{
+  return aarch64_lra_flag;
+}
+
+#undef TARGET_LRA_P
+#define TARGET_LRA_P aarch64_lra_p
+
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST aarch64_address_cost
 
Index: config/aarch64/aarch64.opt
===================================================================
--- config/aarch64/aarch64.opt  (revision 202626)
+++ config/aarch64/aarch64.opt  (working copy)
@@ -83,6 +83,10 @@ momit-leaf-frame-pointer
 Target Report Save Var(flag_omit_leaf_frame_pointer) Init(1)
 Omit the frame pointer in leaf functions
 
+mlra
+Target Report Save Var(aarch64_lra_flag) Init(0)
+Use LRA
+
 mtls-dialect=
 Target RejectNegative Joined Enum(tls_type) Var(aarch64_tls_dialect) 
Init(TLS_DESCRIPTORS)
 Specify TLS dialect
Index: lra-constraints.c
===================================================================
--- lra-constraints.c   (revision 202721)
+++ lra-constraints.c   (working copy)
@@ -1453,6 +1453,7 @@ process_alt_operands (int only_alternati
          HARD_REG_SET this_alternative_set, this_costly_alternative_set;
          bool this_alternative_match_win, this_alternative_win;
          bool this_alternative_offmemok;
+         bool scratch_p;
          enum machine_mode mode;
 
          opalt_num = nalt * n_operands + nop;
@@ -1858,6 +1859,8 @@ process_alt_operands (int only_alternati
            }
          while ((p += len), c);
 
+         scratch_p = (operand_reg[nop] != NULL_RTX
+                      && lra_former_scratch_p (REGNO (operand_reg[nop])));
          /* Record which operands fit this alternative.  */
          if (win)
            {
@@ -1878,14 +1881,17 @@ process_alt_operands (int only_alternati
                    }
                  else
                    {
-                     /* Prefer won reg to spilled pseudo under other equal
-                        conditions.  */
-                     if (lra_dump_file != NULL)
-                       fprintf
-                         (lra_dump_file,
-                          "            %d Non pseudo reload: reject++\n",
-                          nop);
-                     reject++;
+                     /* Prefer won reg to spilled pseudo under other
+                        equal conditions for possibe inheritance.  */
+                     if (! scratch_p)
+                       {
+                         if (lra_dump_file != NULL)
+                           fprintf
+                             (lra_dump_file,
+                              "            %d Non pseudo reload: reject++\n",
+                              nop);
+                         reject++;
+                       }
                      if (in_class_p (operand_reg[nop],
                                      this_costly_alternative, NULL))
                        {
@@ -1904,13 +1910,13 @@ process_alt_operands (int only_alternati
                     insns are generated for the scratches.  So it
                     might cost something but probably less than old
                     reload pass believes.  */
-                 if (lra_former_scratch_p (REGNO (operand_reg[nop])))
+                 if (scratch_p)
                    {
                      if (lra_dump_file != NULL)
                        fprintf (lra_dump_file,
-                                "            %d Scratch win: reject+=3\n",
+                                "            %d Scratch win: reject+=2\n",
                                 nop);
-                     reject += 3;
+                     reject += 2;
                    }
                }
            }
@@ -2124,7 +2130,7 @@ process_alt_operands (int only_alternati
                }
            }
 
-         if (early_clobber_p)
+         if (early_clobber_p && ! scratch_p)
            {
              if (lra_dump_file != NULL)
                fprintf (lra_dump_file,
Index: lra-eliminations.c
===================================================================
--- lra-eliminations.c  (revision 202626)
+++ lra-eliminations.c  (working copy)
@@ -808,69 +808,69 @@ eliminate_regs_in_insn (rtx insn, bool r
   if (old_set != 0 && REG_P (SET_DEST (old_set))
       && (ep = get_elimination (SET_DEST (old_set))) != NULL)
     {
-      bool delete_p = replace_p;
-
+      for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+       if (ep->from_rtx == SET_DEST (old_set) && ep->can_eliminate)
+         {
+           bool delete_p = replace_p;
+           
 #ifdef HARD_FRAME_POINTER_REGNUM
-      /* If this is setting the frame pointer register to the hardware
-        frame pointer register and this is an elimination that will
-        be done (tested above), this insn is really adjusting the
-        frame pointer downward to compensate for the adjustment done
-        before a nonlocal goto.  */
-      if (ep->from == FRAME_POINTER_REGNUM
-         && ep->to == HARD_FRAME_POINTER_REGNUM)
-       {
-         rtx src = SET_SRC (old_set);
-         rtx off = remove_reg_equal_offset_note (insn, ep->to_rtx);
-
-         if (replace_p)
-           {
-             SET_DEST (old_set) = ep->to_rtx;
-             lra_update_insn_recog_data (insn);
-             return;
-           }
-         else if (off != NULL_RTX
-                  || src == ep->to_rtx
-                  || (GET_CODE (src) == PLUS
-                      && XEXP (src, 1) == ep->to_rtx
-                      && CONST_INT_P (XEXP (src, 1))))
-           {
-             HOST_WIDE_INT 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);
-             
-             /* First see if this insn remains valid when we make
-                the change.  If not, keep the INSN_CODE the same
-                and let the constraint pass fit it up.  */
-             validate_change (insn, &SET_SRC (old_set), src, 1);
-             validate_change (insn, &SET_DEST (old_set),
-                              ep->from_rtx, 1);
-             if (! apply_change_group ())
-               {
-                 SET_SRC (old_set) = src;
-                 SET_DEST (old_set) = ep->from_rtx;
-               }
-             lra_update_insn_recog_data (insn);
-             /* Add offset note for future updates.  */
-             add_reg_note (insn, REG_EQUAL, src);
-             return;
-           }
-
-
-         /* We can't delete this insn, but needn't process it
-            since it won't be used unless something changes.  */
-         delete_p = false;
-       }
+           if (ep->from == FRAME_POINTER_REGNUM
+               && ep->to == HARD_FRAME_POINTER_REGNUM)
+             /* If this is setting the frame pointer register to the
+                hardware frame pointer register and this is an
+                elimination that will be done (tested above), this
+                insn is really adjusting the frame pointer downward
+                to compensate for the adjustment done before a
+                nonlocal goto.  */
+             {
+               rtx src = SET_SRC (old_set);
+               rtx off = remove_reg_equal_offset_note (insn, ep->to_rtx);
+               
+               if (off != NULL_RTX
+                   || src == ep->to_rtx
+                   || (GET_CODE (src) == PLUS
+                       && XEXP (src, 0) == ep->to_rtx
+                       && CONST_INT_P (XEXP (src, 1))))
+                 {
+                   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);
+                   
+                   /* First see if this insn remains valid when we
+                      make the change.  If not, keep the INSN_CODE
+                      the same and let the constraint pass fit it
+                      up.  */
+                   validate_change (insn, &SET_SRC (old_set), src, 1);
+                   validate_change (insn, &SET_DEST (old_set),
+                                    ep->from_rtx, 1);
+                   if (! apply_change_group ())
+                     {
+                       SET_SRC (old_set) = src;
+                       SET_DEST (old_set) = ep->from_rtx;
+                     }
+                   lra_update_insn_recog_data (insn);
+                   /* Add offset note for future updates.  */
+                   add_reg_note (insn, REG_EQUAL, src);
+                   return;
+                 }
+             }
 #endif
-
-      /* This insn isn't serving a useful purpose.  We delete it
-        when REPLACE is set.  */
-      if (delete_p)
-       lra_delete_dead_insn (insn);
-      return;
+           
+           /* This insn isn't serving a useful purpose.  We delete it
+              when REPLACE is set.  */
+           if (delete_p)
+             lra_delete_dead_insn (insn);
+           return;
+         }
     }
 
   /* We allow one special case which happens to work on all machines we
@@ -1317,7 +1317,9 @@ lra_eliminate (bool final_p)
                   "Updating elimination of equiv for reg %d\n", i);
       }
   EXECUTE_IF_SET_IN_BITMAP (&insns_with_changed_offsets, 0, uid, bi)
-    process_insn_for_elimination (lra_insn_recog_data[uid]->insn, final_p);
+    /* A dead insn can be deleted in process_insn_for_elimination.  */
+    if (lra_insn_recog_data[uid] != NULL)
+      process_insn_for_elimination (lra_insn_recog_data[uid]->insn, final_p);
   bitmap_clear (&insns_with_changed_offsets);
 
 lra_eliminate_done:
Index: testsuite/gcc.target/i386/pr19398.c
===================================================================

Reply via email to