diff options
-rw-r--r-- | gcc/ira.cc | 21 | ||||
-rw-r--r-- | gcc/ira.h | 5 | ||||
-rw-r--r-- | gcc/lra-constraints.cc | 15 | ||||
-rw-r--r-- | gcc/testsuite/g++.target/i386/pr108711.C | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr103541.c | 14 |
5 files changed, 65 insertions, 10 deletions
@@ -3070,6 +3070,8 @@ validate_equiv_mem_from_store (rtx dest, const_rtx set ATTRIBUTE_UNUSED, info->equiv_mem_modified = true; } +static int equiv_init_varies_p (rtx x); + enum valid_equiv { valid_none, valid_combine, valid_reload }; /* Verify that no store between START and the death of REG invalidates @@ -3113,7 +3115,8 @@ validate_equiv_mem (rtx_insn *start, rtx reg, rtx memref) been changed and all hell breaks loose. */ ret = valid_combine; if (!MEM_READONLY_P (memref) - && !RTL_CONST_OR_PURE_CALL_P (insn)) + && (!RTL_CONST_OR_PURE_CALL_P (insn) + || equiv_init_varies_p (XEXP (memref, 0)))) return valid_none; } @@ -3414,6 +3417,7 @@ no_equiv (rtx reg, const_rtx store ATTRIBUTE_UNUSED, if (reg_equiv[regno].is_arg_equivalence) return; ira_reg_equiv[regno].defined_p = false; + ira_reg_equiv[regno].caller_save_p = false; ira_reg_equiv[regno].init_insns = NULL; for (; list; list = list->next ()) { @@ -3766,7 +3770,18 @@ update_equiv_regs (void) { replacement = copy_rtx (SET_SRC (set)); if (validity == valid_reload) - note = set_unique_reg_note (insn, REG_EQUIV, replacement); + { + note = set_unique_reg_note (insn, REG_EQUIV, replacement); + } + else + { + /* We still can use this equivalence for caller save + optimization in LRA. Mark this. */ + ira_reg_equiv[regno].caller_save_p = true; + ira_reg_equiv[regno].init_insns + = gen_rtx_INSN_LIST (VOIDmode, insn, + ira_reg_equiv[regno].init_insns); + } } } @@ -4156,7 +4171,7 @@ setup_reg_equiv (void) legitimate, we ignore such REG_EQUIV notes. */ if (memory_operand (x, VOIDmode)) { - ira_reg_equiv[i].defined_p = true; + ira_reg_equiv[i].defined_p = !ira_reg_equiv[i].caller_save_p; ira_reg_equiv[i].memory = x; continue; } @@ -175,8 +175,11 @@ extern struct target_ira *this_target_ira; /* Major structure describing equivalence info for a pseudo. */ struct ira_reg_equiv_s { - /* True if we can use this equivalence. */ + /* True if we can use this as a general equivalence. */ bool defined_p; + /* True if we can use this equivalence only for caller save/restore + location. */ + bool caller_save_p; /* True if the usage of the equivalence is profitable. */ bool profitable_p; /* Equiv. memory, constant, invariant, and initializing insns of diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc index 7bffbc0..dd4f68b 100644 --- a/gcc/lra-constraints.cc +++ b/gcc/lra-constraints.cc @@ -5771,14 +5771,17 @@ choose_split_class (enum reg_class allocno_class, return best_cl; } -/* Copy any equivalence information from ORIGINAL_REGNO to NEW_REGNO. - It only makes sense to call this function if NEW_REGNO is always - equal to ORIGINAL_REGNO. */ +/* Copy any equivalence information from ORIGINAL_REGNO to NEW_REGNO. It only + makes sense to call this function if NEW_REGNO is always equal to + ORIGINAL_REGNO. Set up defined_p flag when caller_save_p flag is set up and + CALL_SAVE_P is true. */ static void -lra_copy_reg_equiv (unsigned int new_regno, unsigned int original_regno) +lra_copy_reg_equiv (unsigned int new_regno, unsigned int original_regno, + bool call_save_p) { - if (!ira_reg_equiv[original_regno].defined_p) + if (!ira_reg_equiv[original_regno].defined_p + && !(call_save_p && ira_reg_equiv[original_regno].caller_save_p)) return; ira_expand_reg_equiv (); @@ -5958,7 +5961,7 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn, rematerializing the original value instead of spilling to the stack. */ if (!HARD_REGISTER_NUM_P (original_regno) && mode == PSEUDO_REGNO_MODE (original_regno)) - lra_copy_reg_equiv (new_regno, original_regno); + lra_copy_reg_equiv (new_regno, original_regno, call_save_p); lra_reg_info[new_regno].restore_rtx = regno_reg_rtx[original_regno]; bitmap_set_bit (&lra_split_regs, new_regno); if (to != NULL) diff --git a/gcc/testsuite/g++.target/i386/pr108711.C b/gcc/testsuite/g++.target/i386/pr108711.C new file mode 100644 index 0000000..0a223e0 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr108711.C @@ -0,0 +1,20 @@ +/* PR target/108711.C */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-exceptions" } */ +struct Expression_list { + Expression_list *copy(); +} vals_; +struct Parser_expression { + Parser_expression(); +}; +struct Composite_literal_expression : Parser_expression { + Composite_literal_expression(bool has_keys, Expression_list *, + bool all_are_names) + : has_keys_(has_keys), all_are_names_(all_are_names) {} + void do_copy(); + bool has_keys_; + bool all_are_names_; +}; +void Composite_literal_expression::do_copy() { + new Composite_literal_expression(has_keys_, vals_.copy(), all_are_names_); +} diff --git a/gcc/testsuite/gcc.target/i386/pr103541.c b/gcc/testsuite/gcc.target/i386/pr103541.c new file mode 100644 index 0000000..72b257d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr103541.c @@ -0,0 +1,14 @@ +/* PR rtl-optimization/103541 */ +/* { dg-do compile { target x86_64-*-* } } */ +/* { dg-options "-O2" } */ + +float a; +__attribute__((const)) float foo (float); + +float +test() +{ + return a + foo(a) + a; +} + +/* { dg-final { scan-assembler-not "\\\(%rsp\\\)" } } */ |