Fix PR44281, bad RA with global regs.
authorBernd Schmidt <bernds@redhat.com>
Tue, 3 May 2016 09:35:42 +0000 (09:35 +0000)
committerBernd Schmidt <bernds@gcc.gnu.org>
Tue, 3 May 2016 09:35:42 +0000 (09:35 +0000)
PR rtl-optimization/44281
* hard-reg-set.h (struct target_hard_regs): New field
x_fixed_nonglobal_reg_set.
(fixed_nonglobal_reg_set): New macro.
* reginfo.c (init_reg_sets_1): Initialize it.
* ira.c (setup_alloc_regs): Use fixed_nonglobal_reg_set instead
of fixed_reg_set.
* df-scan.c (df_insn_refs_collect): Asms may reference global regs.

testsuite/
PR rtl-optimization/44281
* gcc.target/i386/pr44281.c: New test.

From-SVN: r235809

gcc/ChangeLog
gcc/df-scan.c
gcc/hard-reg-set.h
gcc/ira.c
gcc/reginfo.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr44281.c [new file with mode: 0644]

index ffe45b718a5bc1fca6cb3683c07f12d7f1f08116..608f64b63898d870646fd164bd866ef8a46516b9 100644 (file)
@@ -1,3 +1,14 @@
+2016-05-03  Bernd Schmidt  <bschmidt@redhat.com>
+
+       PR rtl-optimization/44281
+       * hard-reg-set.h (struct target_hard_regs): New field
+       x_fixed_nonglobal_reg_set.
+       (fixed_nonglobal_reg_set): New macro.
+       * reginfo.c (init_reg_sets_1): Initialize it.
+       * ira.c (setup_alloc_regs): Use fixed_nonglobal_reg_set instead
+       of fixed_reg_set.
+       * df-scan.c (df_insn_refs_collect): Asms may reference global regs.
+
 2016-05-03  bin cheng  <bin.cheng@arm.com>
 
        PR tree-optimization/56541
index e6d01d600826a11b58e98a85358dd6dec3eac1bb..19d8e0f0eeb83f7e7fbc71355a632cc138f58467 100644 (file)
@@ -3223,11 +3223,22 @@ df_insn_refs_collect (struct df_collection_rec *collection_rec,
         }
     }
 
+  int flags = (is_cond_exec) ? DF_REF_CONDITIONAL : 0;
   /* For CALL_INSNs, first record DF_REF_BASE register defs, as well as
      uses from CALL_INSN_FUNCTION_USAGE. */
   if (CALL_P (insn_info->insn))
-    df_get_call_refs (collection_rec, bb, insn_info,
-                     (is_cond_exec) ? DF_REF_CONDITIONAL : 0);
+    df_get_call_refs (collection_rec, bb, insn_info, flags);
+
+  if (asm_noperands (PATTERN (insn_info->insn)) >= 0)
+    for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+      if (global_regs[i])
+       {
+         /* As with calls, asm statements reference all global regs. */
+         df_ref_record (DF_REF_BASE, collection_rec, regno_reg_rtx[i],
+                        NULL, bb, insn_info, DF_REF_REG_USE, flags);
+         df_ref_record (DF_REF_BASE, collection_rec, regno_reg_rtx[i],
+                        NULL, bb, insn_info, DF_REF_REG_DEF, flags);
+       }
 
   /* Record other defs.  These should be mostly for DF_REF_REGULAR, so
      that a qsort on the defs is unnecessary in most cases.  */
index 85541f7fda37bfba1a382c6b8ee0a92ec72a900a..b94ebb3929f2c4bc4e1e45bd0af1e04d1044065e 100644 (file)
@@ -660,6 +660,12 @@ struct target_hard_regs {
      across calls even if we are willing to save and restore them.  */
   HARD_REG_SET x_call_fixed_reg_set;
 
+  /* Contains registers that are fixed use -- i.e. in fixed_reg_set -- but
+     only if they are not merely part of that set because they are global
+     regs.  Global regs that are not otherwise fixed can still take part
+     in register allocation.  */
+  HARD_REG_SET x_fixed_nonglobal_reg_set;
+
   /* Contains 1 for registers that are set or clobbered by calls.  */
   /* ??? Ideally, this would be just call_used_regs plus global_regs, but
      for someone's bright idea to have call_used_regs strictly include
@@ -722,6 +728,8 @@ extern struct target_hard_regs *this_target_hard_regs;
   (this_target_hard_regs->x_fixed_regs)
 #define fixed_reg_set \
   (this_target_hard_regs->x_fixed_reg_set)
+#define fixed_nonglobal_reg_set \
+  (this_target_hard_regs->x_fixed_nonglobal_reg_set)
 #define call_used_regs \
   (this_target_hard_regs->x_call_used_regs)
 #define call_really_used_regs \
index a38e67e0b7c15338f6ee4dc2de1037575f764c90..d383a5513705e3447d26c64ea7343e607425ea7f 100644 (file)
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -512,7 +512,7 @@ setup_alloc_regs (bool use_hard_frame_p)
 #ifdef ADJUST_REG_ALLOC_ORDER
   ADJUST_REG_ALLOC_ORDER;
 #endif
-  COPY_HARD_REG_SET (no_unit_alloc_regs, fixed_reg_set);
+  COPY_HARD_REG_SET (no_unit_alloc_regs, fixed_nonglobal_reg_set);
   if (! use_hard_frame_p)
     SET_HARD_REG_BIT (no_unit_alloc_regs, HARD_FRAME_POINTER_REGNUM);
   setup_class_hard_regs ();
index ccf53bfbc1f10f9c604519d750986d6e7b2fa730..f4dac083045d99f7b838f599a7304dbada9af844 100644 (file)
@@ -449,6 +449,7 @@ init_reg_sets_1 (void)
     }
 
   COPY_HARD_REG_SET (call_fixed_reg_set, fixed_reg_set);
+  COPY_HARD_REG_SET (fixed_nonglobal_reg_set, fixed_reg_set);
 
   /* Preserve global registers if called more than once.  */
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
index 6ce2c7e916c30fefddc4351a37b9d0ce49538e55..bc7c93f5a5dd6d9dc74354f3c58722cd0a578950 100644 (file)
@@ -1,3 +1,8 @@
+2016-05-03  Bernd Schmidt  <bschmidt@redhat.com>
+
+       PR rtl-optimization/44281
+       * gcc.target/i386/pr44281.c: New test.
+
 2016-05-03  bin cheng  <bin.cheng@arm.com>
 
        PR tree-optimization/56541
diff --git a/gcc/testsuite/gcc.target/i386/pr44281.c b/gcc/testsuite/gcc.target/i386/pr44281.c
new file mode 100644 (file)
index 0000000..e8e9ede
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-std=gnu99 -O2" } */
+/* { dg-final { scan-assembler "salq\[ \\t\]+\\\$8, %rbx" } } */
+
+#include <stdint.h>
+
+register uint64_t global_flag_stack __asm__("rbx");
+
+void push_flag_into_global_reg_var(uint64_t a, uint64_t b) {
+  uint64_t flag = (a==b);
+  global_flag_stack <<= 8;
+  global_flag_stack  |= flag;
+}