From: Bernd Schmidt Date: Tue, 3 May 2016 09:35:42 +0000 (+0000) Subject: Fix PR44281, bad RA with global regs. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f80041efb991e4326971dea550157192f912d9a4;p=gcc.git Fix PR44281, bad RA with global regs. 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ffe45b718a5..608f64b6389 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2016-05-03 Bernd Schmidt + + 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 PR tree-optimization/56541 diff --git a/gcc/df-scan.c b/gcc/df-scan.c index e6d01d60082..19d8e0f0eeb 100644 --- a/gcc/df-scan.c +++ b/gcc/df-scan.c @@ -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. */ diff --git a/gcc/hard-reg-set.h b/gcc/hard-reg-set.h index 85541f7fda3..b94ebb3929f 100644 --- a/gcc/hard-reg-set.h +++ b/gcc/hard-reg-set.h @@ -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 \ diff --git a/gcc/ira.c b/gcc/ira.c index a38e67e0b7c..d383a551370 100644 --- 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 (); diff --git a/gcc/reginfo.c b/gcc/reginfo.c index ccf53bfbc1f..f4dac083045 100644 --- a/gcc/reginfo.c +++ b/gcc/reginfo.c @@ -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++) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6ce2c7e916c..bc7c93f5a5d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-05-03 Bernd Schmidt + + PR rtl-optimization/44281 + * gcc.target/i386/pr44281.c: New test. + 2016-05-03 bin cheng 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 index 00000000000..e8e9edef319 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr44281.c @@ -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 + +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; +}