This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fix PR44281 (bad RA with global regs)
- From: Bernd Schmidt <bschmidt at redhat dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 19 Feb 2016 23:03:02 +0100
- Subject: Fix PR44281 (bad RA with global regs)
- Authentication-results: sourceware.org; auth=none
- References: <56C78C62 dot 7050204 at t-online dot de>
In this PR, we generate unnecessarily bad code for code that declares a
global register var. Since global regs get added to fixed_regs, IRA
never considers them as candidates. However, we do seem to have proper
data flow information for them. In the testcase, the global reg dies,
some operations are done on temporary results, and the final result
stored back in the global reg. We can achieve the desired code
generation by reusing the global reg for those temporaries.
Bootstrapped and tested on x86_64-linux. Ok? An argument could be made
not to use this for gcc-6 since global register vars are both not very
important and not very well represented in the testsuite.
Bernd
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.
PR rtl-optimization/44281
* gcc.target/i386/pr44281.c: New test.
Index: gcc/hard-reg-set.h
===================================================================
--- gcc/hard-reg-set.h (revision 233451)
+++ gcc/hard-reg-set.h (working copy)
@@ -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_tar
(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: gcc/ira.c
===================================================================
--- gcc/ira.c (revision 233451)
+++ gcc/ira.c (working copy)
@@ -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: gcc/reginfo.c
===================================================================
--- gcc/reginfo.c (revision 233451)
+++ gcc/reginfo.c (working copy)
@@ -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: gcc/testsuite/gcc.target/i386/pr44281.c
===================================================================
--- gcc/testsuite/gcc.target/i386/pr44281.c (revision 0)
+++ gcc/testsuite/gcc.target/i386/pr44281.c (working copy)
@@ -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;
+}