--- gcc/config/rs6000/rs6000.c | 3 ++ gcc/ira.c | 69 ++++++++++++++++++++++++++++++++++---- gcc/params.opt | 4 +++ 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 5ae40d6f4ce..eb9c4284f91 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -4852,6 +4852,9 @@ rs6000_option_override_internal (bool global_init_p) ap = __builtin_next_arg (0). */ if (DEFAULT_ABI != ABI_V4) targetm.expand_builtin_va_start = NULL; + + SET_OPTION_IF_UNSET (&global_options, &global_options_set, + param_ira_consider_dup_in_all_alts, 1); } rs6000_override_options_after_change (); diff --git a/gcc/ira.c b/gcc/ira.c index b93588d8a9f..beebee7499b 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -1937,10 +1939,16 @@ ira_get_dup_out_num (int op_num, alternative_mask alts) return -1; str = recog_data.constraints[op_num]; use_commut_op_p = false; + + rtx op = recog_data.operand[op_num]; + int op_no = reg_or_subregno (op); + enum reg_class op_pref_cl = reg_preferred_class (op_no); + machine_mode op_mode = GET_MODE (op); + for (;;) { - rtx op = recog_data.operand[op_num]; - + bool saw_reg_cstr = false; + for (curr_alt = 0, ignore_p = !TEST_BIT (alts, curr_alt), original = -1;;) { @@ -1963,9 +1971,25 @@ ira_get_dup_out_num (int op_num, alternative_mask alts) { enum constraint_num cn = lookup_constraint (str); enum reg_class cl = reg_class_for_constraint (cn); - if (cl != NO_REGS - && !targetm.class_likely_spilled_p (cl)) - goto fail; + if (cl != NO_REGS && !targetm.class_likely_spilled_p (cl)) + { + if (param_ira_consider_dup_in_all_alts + && op_pref_cl != NO_REGS) + { + /* If it's free to move from one preferred class to + the one without matching constraint, it doesn't + have to respect this constraint with costs. */ + if (cl != op_pref_cl + && (ira_reg_class_intersect[cl][op_pref_cl] + != NO_REGS) + && (ira_may_move_in_cost[op_mode][op_pref_cl][cl] + == 0)) + goto fail; + saw_reg_cstr = true; + } + else + goto fail; + } if (constraint_satisfied_p (op, cn)) goto fail; break; @@ -1979,7 +2003,40 @@ ira_get_dup_out_num (int op_num, alternative_mask alts) str = end; if (original != -1 && original != n) goto fail; - original = n; + if (param_ira_consider_dup_in_all_alts && saw_reg_cstr) + { + rtx out = recog_data.operand[n]; + if (!REG_P (out) + && (GET_CODE (out) != SUBREG + || !REG_P (SUBREG_REG (out)))) + goto fail; + int out_no = reg_or_subregno (out); + if (out_no >= FIRST_PSEUDO_REGISTER) + { + const char *out_alts = recog_data.constraints[n]; + int tot = curr_alt; + while (tot > 0) + { + if (out_alts[0] == ',') + tot--; + out_alts++; + } + enum reg_class out_cl = NO_REGS; + while (*out_alts != '\0' && *out_alts != ',') + { + enum constraint_num cn + = lookup_constraint (out_alts); + out_cl = reg_class_for_constraint (cn); + if (out_cl != NO_REGS) + break; + } + /* Respect this as it's for preferred rclass. */ + if (out_cl == op_pref_cl) + original = n; + } + } + else + original = n; continue; } } diff --git a/gcc/params.opt b/gcc/params.opt index 7c7aa78992a..7d9d3a5876d 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -326,6 +326,10 @@ Max size of conflict table in MB. Common Joined UInteger Var(param_ira_max_loops_num) Init(100) Param Optimization Max loops number for regional RA. +-param=ira-consider-dup-in-all-alts= +Common Joined UInteger Var(param_ira_consider_dup_in_all_alts) Init(0) IntegerRange(0, 1) Param Optimization +Control ira to continue to find matching constraint (duplicated operand number) even if it has encountered some contraint that has the appropriate register class, it will skip those alternatives whose constraint don't have the same register class as which the operand prefers. + -param=iv-always-prune-cand-set-bound= Common Joined UInteger Var(param_iv_always_prune_cand_set_bound) Init(10) Param Optimization If number of candidates in the set is smaller, we always try to remove unused ivs during its optimization. -- 2.17.1