diff options
Diffstat (limited to 'gcc/lra-constraints.c')
-rw-r--r-- | gcc/lra-constraints.c | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 7764f29f477..2c27f1abfe4 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -855,10 +855,11 @@ narrow_reload_pseudo_class (rtx reg, enum reg_class cl) numbers with end marker -1) with reg class GOAL_CLASS. Add input and output reloads correspondingly to the lists *BEFORE and *AFTER. OUT might be negative. In this case we generate input reloads for - matched input operands INS. */ + matched input operands INS. EARLY_CLOBBER_P is a flag that the + output operand is early clobbered for chosen alternative. */ static void match_reload (signed char out, signed char *ins, enum reg_class goal_class, - rtx_insn **before, rtx_insn **after) + rtx_insn **before, rtx_insn **after, bool early_clobber_p) { int i, in; rtx new_in_reg, new_out_reg, reg; @@ -939,17 +940,19 @@ match_reload (signed char out, signed char *ins, enum reg_class goal_class, have a situation like "a <- a op b", where the constraints force the second input operand ("b") to match the output operand ("a"). "b" must then be copied into a new register - so that it doesn't clobber the current value of "a". */ + so that it doesn't clobber the current value of "a". + + We can not use the same value if the output pseudo is + early clobbered or the input pseudo is mentioned in the + output, e.g. as an address part in memory, because + output reload will actually extend the pseudo liveness. + We don't care about eliminable hard regs here as we are + interesting only in pseudos. */ new_in_reg = new_out_reg - = (ins[1] < 0 && REG_P (in_rtx) + = (! early_clobber_p && ins[1] < 0 && REG_P (in_rtx) && (int) REGNO (in_rtx) < lra_new_regno_start && find_regno_note (curr_insn, REG_DEAD, REGNO (in_rtx)) - /* We can not use the same value if the pseudo is mentioned - in the output, e.g. as an address part in memory, - becuase output reload will actually extend the pseudo - liveness. We don't care about eliminable hard regs here - as we are interesting only in pseudos. */ && (out < 0 || regno_use_in (REGNO (in_rtx), out_rtx) == NULL_RTX) ? lra_create_new_reg (inmode, in_rtx, goal_class, "") : lra_create_new_reg_with_unique_value (outmode, out_rtx, @@ -3867,13 +3870,18 @@ curr_insn_transform (bool check_only_p) match_inputs[0] = i; match_inputs[1] = -1; match_reload (goal_alt_matched[i][0], match_inputs, - goal_alt[i], &before, &after); + goal_alt[i], &before, &after, + curr_static_id->operand_alternative + [goal_alt_number * n_operands + goal_alt_matched[i][0]] + .earlyclobber); } else if (curr_static_id->operand[i].type == OP_OUT && (curr_static_id->operand[goal_alt_matched[i][0]].type == OP_IN)) /* Generate reloads for output and matched inputs. */ - match_reload (i, goal_alt_matched[i], goal_alt[i], &before, &after); + match_reload (i, goal_alt_matched[i], goal_alt[i], &before, &after, + curr_static_id->operand_alternative + [goal_alt_number * n_operands + i].earlyclobber); else if (curr_static_id->operand[i].type == OP_IN && (curr_static_id->operand[goal_alt_matched[i][0]].type == OP_IN)) @@ -3883,7 +3891,7 @@ curr_insn_transform (bool check_only_p) for (j = 0; (k = goal_alt_matched[i][j]) >= 0; j++) match_inputs[j + 1] = k; match_inputs[j + 1] = -1; - match_reload (-1, match_inputs, goal_alt[i], &before, &after); + match_reload (-1, match_inputs, goal_alt[i], &before, &after, false); } else /* We must generate code in any case when function |