re PR target/79131 (ICE: in extract_constrain_insn, at recog.c:2213, big-endian ARM)
authorVladimir Makarov <vmakarov@redhat.com>
Thu, 26 Jan 2017 17:08:12 +0000 (17:08 +0000)
committerVladimir Makarov <vmakarov@gcc.gnu.org>
Thu, 26 Jan 2017 17:08:12 +0000 (17:08 +0000)
2017-01-26  Vladimir Makarov  <vmakarov@redhat.com>

PR target/79131
* lra-assigns.c (setup_live_pseudos_and_spill_after_risky): Take
endianess for subregs into account.
* lra-constraints.c (lra_constraints): Do risky transformations
always on the first iteration.
* lra-lives.c (check_pseudos_live_through_calls): Add arg
last_call_used_reg_set.
(process_bb_lives): Define and use last_call_used_reg_set.
* lra.c (lra): Always continue after lra_constraints on the first
iteration.

2017-01-26  Vladimir Makarov  <vmakarov@redhat.com>

PR target/79131
* gcc.target/arm/pr79131.c: New.

From-SVN: r244942

gcc/ChangeLog
gcc/lra-assigns.c
gcc/lra-constraints.c
gcc/lra-lives.c
gcc/lra.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/pr79131.c [new file with mode: 0644]

index 903e966ac6e540052b6c9e223ab03162aa0a464b..d09061e724e3906c0a7309e09a3bb9d27489f500 100644 (file)
@@ -1,3 +1,16 @@
+2017-01-26  Vladimir Makarov  <vmakarov@redhat.com>
+
+       PR target/79131
+       * lra-assigns.c (setup_live_pseudos_and_spill_after_risky): Take
+       endianess for subregs into account.
+       * lra-constraints.c (lra_constraints): Do risky transformations
+       always on the first iteration.
+       * lra-lives.c (check_pseudos_live_through_calls): Add arg
+       last_call_used_reg_set.
+       (process_bb_lives): Define and use last_call_used_reg_set.
+       * lra.c (lra): Always continue after lra_constraints on the first
+       iteration.
+
 2017-01-26  Kirill Yukhin  <kirill.yukhin@gmail.com>
 
        * gcc.target/i386/avx512bw-kshiftlq-2.c: Use unsigned long long
index 8e21a497f0a4de23567e8c39188a9d8e27d7552e..74a3195c4db2a8d18a58fd717e5e742b4daec0f9 100644 (file)
@@ -1179,9 +1179,19 @@ setup_live_pseudos_and_spill_after_risky_transforms (bitmap
            /* If it is multi-register pseudos they should start on
               the same hard register.  */
            || hard_regno != reg_renumber[conflict_regno])
-         add_to_hard_reg_set (&conflict_set,
-                              lra_reg_info[conflict_regno].biggest_mode,
-                              reg_renumber[conflict_regno]);
+         {
+           int conflict_hard_regno = reg_renumber[conflict_regno];
+           machine_mode biggest_mode = lra_reg_info[conflict_regno].biggest_mode;
+           int biggest_nregs = hard_regno_nregs[conflict_hard_regno][biggest_mode];
+           int nregs_diff = (biggest_nregs
+                             - (hard_regno_nregs
+                                [conflict_hard_regno]
+                                [PSEUDO_REGNO_MODE (conflict_regno)]));
+           add_to_hard_reg_set (&conflict_set,
+                                biggest_mode,
+                                conflict_hard_regno
+                                - (WORDS_BIG_ENDIAN ? nregs_diff : 0));
+         }
       if (! overlaps_hard_reg_set_p (conflict_set, mode, hard_regno))
        {
          update_lives (regno, false);
index 7b0d2f4b85fca66fdec1b9c2265b1d409a5d3c48..25869134bd0d1fe5d16078888b303f8928324759 100644 (file)
@@ -4511,7 +4511,10 @@ lra_constraints (bool first_p)
       && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER)
     lra_risky_transformations_p = true;
   else
-    lra_risky_transformations_p = false;
+    /* On the first iteration we should check IRA assignment
+       correctness.  In rare cases, the assignments can be wrong as
+       early clobbers operands are ignored in IRA.  */
+    lra_risky_transformations_p = first_p;
   new_insn_uid_start = get_max_uid ();
   new_regno_start = first_p ? lra_constraint_new_regno_start : max_reg_num ();
   /* Mark used hard regs for target stack size calulations.  */
index 010d4e6f78764453dd0300cb1ae8cdcdfe29bc30..f0194387c6319f60617285d96bba2eeeaaf56810 100644 (file)
@@ -560,10 +560,11 @@ lra_setup_reload_pseudo_preferenced_hard_reg (int regno,
 }
 
 /* Check that REGNO living through calls and setjumps, set up conflict
-   regs, and clear corresponding bits in PSEUDOS_LIVE_THROUGH_CALLS and
-   PSEUDOS_LIVE_THROUGH_SETJUMPS.  */
+   regs using LAST_CALL_USED_REG_SET, and clear corresponding bits in
+   PSEUDOS_LIVE_THROUGH_CALLS and PSEUDOS_LIVE_THROUGH_SETJUMPS.  */
 static inline void
-check_pseudos_live_through_calls (int regno)
+check_pseudos_live_through_calls (int regno,
+                                 HARD_REG_SET last_call_used_reg_set)
 {
   int hr;
 
@@ -571,7 +572,7 @@ check_pseudos_live_through_calls (int regno)
     return;
   sparseset_clear_bit (pseudos_live_through_calls, regno);
   IOR_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs,
-                   call_used_reg_set);
+                   last_call_used_reg_set);
 
   for (hr = 0; hr < FIRST_PSEUDO_REGISTER; hr++)
     if (HARD_REGNO_CALL_PART_CLOBBERED (hr, PSEUDO_REGNO_MODE (regno)))
@@ -604,11 +605,13 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
   rtx_insn *next;
   rtx link, *link_loc;
   bool need_curr_point_incr;
-
+  HARD_REG_SET last_call_used_reg_set;
+  
   reg_live_out = df_get_live_out (bb);
   sparseset_clear (pseudos_live);
   sparseset_clear (pseudos_live_through_calls);
   sparseset_clear (pseudos_live_through_setjumps);
+  CLEAR_HARD_REG_SET (last_call_used_reg_set);
   REG_SET_TO_HARD_REG_SET (hard_regs_live, reg_live_out);
   AND_COMPL_HARD_REG_SET (hard_regs_live, eliminable_regset);
   EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi)
@@ -795,7 +798,8 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
            need_curr_point_incr
              |= mark_regno_live (reg->regno, reg->biggest_mode,
                                  curr_point);
-           check_pseudos_live_through_calls (reg->regno);
+           check_pseudos_live_through_calls (reg->regno,
+                                             last_call_used_reg_set);
          }
 
       for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
@@ -831,15 +835,27 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
 
       if (call_p)
        {
-         if (flag_ipa_ra)
+         if (! flag_ipa_ra)
+           COPY_HARD_REG_SET(last_call_used_reg_set, call_used_reg_set);
+         else
            {
              HARD_REG_SET this_call_used_reg_set;
              get_call_reg_set_usage (curr_insn, &this_call_used_reg_set,
                                      call_used_reg_set);
 
+             bool flush = (! hard_reg_set_empty_p (last_call_used_reg_set)
+                           && ! hard_reg_set_equal_p (last_call_used_reg_set,
+                                                      this_call_used_reg_set));
+
              EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, j)
-               IOR_HARD_REG_SET (lra_reg_info[j].actual_call_used_reg_set,
-                                 this_call_used_reg_set);
+               {
+                 IOR_HARD_REG_SET (lra_reg_info[j].actual_call_used_reg_set,
+                                   this_call_used_reg_set);
+                 if (flush)
+                   check_pseudos_live_through_calls
+                     (j, last_call_used_reg_set);
+               }
+             COPY_HARD_REG_SET(last_call_used_reg_set, this_call_used_reg_set);
            }
 
          sparseset_ior (pseudos_live_through_calls,
@@ -866,7 +882,8 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
            need_curr_point_incr
              |= mark_regno_live (reg->regno, reg->biggest_mode,
                                  curr_point);
-           check_pseudos_live_through_calls (reg->regno);
+           check_pseudos_live_through_calls (reg->regno,
+                                             last_call_used_reg_set);
          }
 
       for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
@@ -1009,7 +1026,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
       if (sparseset_cardinality (pseudos_live_through_calls) == 0)
        break;
       if (sparseset_bit_p (pseudos_live_through_calls, j))
-       check_pseudos_live_through_calls (j);
+       check_pseudos_live_through_calls (j, last_call_used_reg_set);
     }
 
   if (need_curr_point_incr)
index da3b955be3696a087e6adec4075c3abbbfd46ab0..9be0053f54369e16ce3722977bfd3f9c742afe19 100644 (file)
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -2295,7 +2295,7 @@ void
 lra (FILE *f)
 {
   int i;
-  bool live_p, scratch_p, inserted_p;
+  bool live_p, inserted_p;
 
   lra_dump_file = f;
 
@@ -2332,7 +2332,6 @@ lra (FILE *f)
   lra_constraint_new_regno_start = lra_new_regno_start = max_reg_num ();
   lra_bad_spill_regno_start = INT_MAX;
   remove_scratches ();
-  scratch_p = lra_constraint_new_regno_start != max_reg_num ();
 
   /* A function that has a non-local label that can reach the exit
      block via non-exceptional paths must save all call-saved
@@ -2372,11 +2371,12 @@ lra (FILE *f)
       for (;;)
        {
          /* We should try to assign hard registers to scratches even
-            if there were no RTL transformations in
-            lra_constraints.  */
+            if there were no RTL transformations in lra_constraints.
+            Also we should check IRA assignments on the first
+            iteration as they can be wrong because of early clobbers
+            operands which are ignored in IRA.  */
          if (! lra_constraints (lra_constraint_iter == 0)
-             && (lra_constraint_iter > 1
-                 || (! scratch_p && ! caller_save_needed)))
+             && lra_constraint_iter > 1)
            break;
          /* Constraint transformations may result in that eliminable
             hard regs become uneliminable and pseudos which use them
index bd07034dde1491f3f07ad0c8718547d6f2e12acf..8796bb59c869ca6ee221f56e2d150ff1b5d9008e 100644 (file)
@@ -1,3 +1,8 @@
+2017-01-26  Vladimir Makarov  <vmakarov@redhat.com>
+
+       PR target/79131
+       * gcc.target/arm/pr79131.c: New.
+
 2017-01-26  Bin Cheng  <bin.cheng@arm.com>
 
        * gcc.target/aarch64/ldp_vec_64_1.c: Xfail.
diff --git a/gcc/testsuite/gcc.target/arm/pr79131.c b/gcc/testsuite/gcc.target/arm/pr79131.c
new file mode 100644 (file)
index 0000000..3bd9e0f
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbig-endian" } */
+
+long long a;
+enum { NILFS_SEGMENT_USAGE_ACTIVE, NILFS_SEGMENT_USAGE_DIRTY } b;
+void nilfs_sufile_mod_counter(long long p1) {
+  long c = p1;
+  unsigned d = __builtin_bswap64(a);
+  a = __builtin_bswap64(d + c);
+}
+void nilfs_sufile_do_free() {
+  int e, f;
+  e = __builtin_bswap32(b) & 1 << NILFS_SEGMENT_USAGE_DIRTY;
+  f = e;
+  nilfs_sufile_mod_counter(f ? -1 : 0);
+}