re PR rtl-optimization/69447 (wrong code with -O2 -fno-schedule-insns and mixed 8...
authorRichard Henderson <rth@gcc.gnu.org>
Wed, 27 Jan 2016 22:08:02 +0000 (14:08 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 27 Jan 2016 22:08:02 +0000 (14:08 -0800)
PR rtl-opt/69447

  * lra-remat.c (subreg_regs): New.
  (dump_candidates_and_remat_bb_data): Dump it.
  (operand_to_remat): Reject if operand in subreg_regs.
  (set_bb_regs): Collect subreg_regs.
  (lra_remat): Init and free subreg_regs.  Compute
  calculate_local_reg_remat_bb_data before create_cands.

From-SVN: r232905

gcc/ChangeLog
gcc/lra-remat.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr69447.c [new file with mode: 0644]

index cc8b21c..4107546 100644 (file)
@@ -1,3 +1,13 @@
+2016-01-27  Richard Henderson  <rth@redhat.com>
+
+       PR rtl-opt/69447
+       * lra-remat.c (subreg_regs): New.
+       (dump_candidates_and_remat_bb_data): Dump it.
+       (operand_to_remat): Reject if operand in subreg_regs.
+       (set_bb_regs): Collect subreg_regs.
+       (lra_remat): Init and free subreg_regs.  Compute
+       calculate_local_reg_remat_bb_data before create_cands.
+
 2016-01-27  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR target/68986
index 6f490b9..4d8099f 100644 (file)
@@ -77,6 +77,9 @@ static int call_used_regs_arr[FIRST_PSEUDO_REGISTER];
 /* Bitmap used for different calculations.  */
 static bitmap_head temp_bitmap;
 
+/* Registers accessed via subreg_p.  */
+static bitmap_head subreg_regs;
+
 typedef struct cand *cand_t;
 typedef const struct cand *const_cand_t;
 
@@ -383,30 +386,30 @@ operand_to_remat (rtx_insn *insn)
     return -1;
   /* First find a pseudo which can be rematerialized.  */
   for (reg = id->regs; reg != NULL; reg = reg->next)
-    /* True FRAME_POINTER_NEEDED might be because we can not follow
-       changing sp offsets, e.g. alloca is used.  If the insn contains
-       stack pointer in such case, we can not rematerialize it as we
-       can not know sp offset at a rematerialization place.  */
-    if (reg->regno == STACK_POINTER_REGNUM && frame_pointer_needed)
-      return -1;
-    else if (reg->type == OP_OUT && ! reg->subreg_p
-            && find_regno_note (insn, REG_UNUSED, reg->regno) == NULL)
-      {
-       /* We permits only one spilled reg.  */
-       if (found_reg != NULL)
-         return -1;
-       found_reg = reg;
-      }
-    /* IRA calculates conflicts separately for subregs of two words
-       pseudo.  Even if the pseudo lives, e.g. one its subreg can be
-       used lately, another subreg hard register can be already used
-       for something else.  In such case, it is not safe to
-       rematerialize the insn.  */
-    else if (reg->type == OP_IN && reg->subreg_p
-            && reg->regno >= FIRST_PSEUDO_REGISTER
-            && (GET_MODE_SIZE (PSEUDO_REGNO_MODE (reg->regno))
-                == 2 * UNITS_PER_WORD))
-      return -1;
+    {
+      /* True FRAME_POINTER_NEEDED might be because we can not follow
+        changing sp offsets, e.g. alloca is used.  If the insn contains
+        stack pointer in such case, we can not rematerialize it as we
+        can not know sp offset at a rematerialization place.  */
+      if (reg->regno == STACK_POINTER_REGNUM && frame_pointer_needed)
+       return -1;
+      else if (reg->type == OP_OUT && ! reg->subreg_p
+              && find_regno_note (insn, REG_UNUSED, reg->regno) == NULL)
+       {
+         /* We permits only one spilled reg.  */
+         if (found_reg != NULL)
+           return -1;
+         found_reg = reg;
+        }
+      /* IRA calculates conflicts separately for subregs of two words
+        pseudo.  Even if the pseudo lives, e.g. one its subreg can be
+        used lately, another subreg hard register can be already used
+        for something else.  In such case, it is not safe to
+        rematerialize the insn.  */
+      if (reg->regno >= FIRST_PSEUDO_REGISTER
+         && bitmap_bit_p (&subreg_regs, reg->regno))
+       return -1;
+    }
   if (found_reg == NULL)
     return -1;
   if (found_reg->regno < FIRST_PSEUDO_REGISTER)
@@ -631,6 +634,9 @@ dump_candidates_and_remat_bb_data (void)
       lra_dump_bitmap_with_title ("avout cands in BB",
                                  &get_remat_bb_data (bb)->avout_cands, bb->index);
     }
+  fprintf (lra_dump_file, "subreg regs:");
+  dump_regset (&subreg_regs, lra_dump_file);
+  putc ('\n', lra_dump_file);
 }
 
 /* Free all BB data.  */
@@ -655,21 +661,24 @@ finish_remat_bb_data (void)
 
 \f
 
-/* Update changed_regs and dead_regs of BB from INSN.  */
+/* Update changed_regs, dead_regs, subreg_regs of BB from INSN.  */
 static void
 set_bb_regs (basic_block bb, rtx_insn *insn)
 {
   lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
+  remat_bb_data_t bb_info = get_remat_bb_data (bb);
   struct lra_insn_reg *reg;
 
   for (reg = id->regs; reg != NULL; reg = reg->next)
-    if (reg->type != OP_IN)
-      bitmap_set_bit (&get_remat_bb_data (bb)->changed_regs, reg->regno);
-    else
-      {
-       if (find_regno_note (insn, REG_DEAD, (unsigned) reg->regno) != NULL)
-         bitmap_set_bit (&get_remat_bb_data (bb)->dead_regs, reg->regno);
-      }
+    {
+      unsigned regno = reg->regno;
+      if (reg->type != OP_IN)
+        bitmap_set_bit (&bb_info->changed_regs, regno);
+      else if (find_regno_note (insn, REG_DEAD, regno) != NULL)
+       bitmap_set_bit (&bb_info->dead_regs, regno);
+      if (regno >= FIRST_PSEUDO_REGISTER && reg->subreg_p)
+       bitmap_set_bit (&subreg_regs, regno);
+    }
   if (CALL_P (insn))
     for (int i = 0; i < call_used_regs_arr_len; i++)
       bitmap_set_bit (&get_remat_bb_data (bb)->dead_regs,
@@ -1284,10 +1293,11 @@ lra_remat (void)
     if (call_used_regs[i])
       call_used_regs_arr[call_used_regs_arr_len++] = i;
   initiate_cand_table ();
-  create_cands ();
   create_remat_bb_data ();
   bitmap_initialize (&temp_bitmap, &reg_obstack);
+  bitmap_initialize (&subreg_regs, &reg_obstack);
   calculate_local_reg_remat_bb_data ();
+  create_cands ();
   calculate_livein_cands ();
   calculate_gen_cands ();
   bitmap_initialize (&all_blocks, &reg_obstack);
@@ -1298,6 +1308,7 @@ lra_remat (void)
   result = do_remat ();
   all_cands.release ();
   bitmap_clear (&temp_bitmap);
+  bitmap_clear (&subreg_regs);
   finish_remat_bb_data ();
   finish_cand_table ();
   bitmap_clear (&all_blocks);
index e1e3868..22c65a7 100644 (file)
@@ -1,4 +1,8 @@
-2015-01-27  Paul Thomas  <pault@gcc.gnu.org>
+2016-01-27  Richard Henderson  <rth@redhat.com>
+
+       * gcc.c-torture/execute/pr69447.c: New test.
+
+2016-01-27  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/69385
        * gfortran.dg/alloc_comp_assign_15.f03: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr69447.c b/gcc/testsuite/gcc.c-torture/execute/pr69447.c
new file mode 100644 (file)
index 0000000..b6d8591
--- /dev/null
@@ -0,0 +1,26 @@
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long long u64;
+
+u64 __attribute__((noinline, noclone))
+foo(u8 u8_0, u16 u16_0, u64 u64_0, u8 u8_1, u16 u16_1, u64 u64_1, u64 u64_2, u8 u8_3, u64 u64_3)
+{
+       u64_1 *= 0x7730;
+       u64_3 *= u64_3;
+       u16_1 |= u64_3;
+       u64_3 -= 2;
+       u8_3 /= u64_2;
+       u8_0 |= 3;
+       u64_3 %= u8_0;
+       u8_0 -= 1;
+       return u8_0 + u16_0 + u64_0 + u8_1 + u16_1 + u64_1 + u8_3 + u64_3;
+}
+
+int main()
+{
+       unsigned x = foo(1, 1, 1, 1, 1, 1, 1, 1, 1);
+       if (x != 0x7737)
+               __builtin_abort();
+       return 0;
+}