If one of the to-be-converted SETs requires the original comparison (i.e. in order to generate a min/max insn) but no other insn after it does, we can omit creating temporaries, thus facilitating costing. --- gcc/ifcvt.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index d1e7db1ee27..3be5bb131df 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -3262,6 +3262,11 @@ noce_convert_multiple_sets (struct noce_if_info *if_info) need_cmov_or_rewire (then_bb, &need_no_cmov, &rewired_src); + int last_needs_comparison = -1; + bool second_try = false; + +restart: + FOR_BB_INSNS (then_bb, insn) { /* Skip over non-insns. */ @@ -3305,8 +3310,12 @@ noce_convert_multiple_sets (struct noce_if_info *if_info) Therefore we introduce a temporary every time we are about to overwrite a variable used in the check. Costing of a sequence with these is going to be inaccurate so only use temporaries when - needed. */ - if (reg_overlap_mentioned_p (target, cond)) + needed. + + If performing a second try, we know how many insns require a + temporary. For the last of these, we can omit creating one. */ + if (reg_overlap_mentioned_p (target, cond) + && (!second_try || count < last_needs_comparison)) temp = gen_reg_rtx (GET_MODE (target)); else temp = target; @@ -3389,6 +3398,8 @@ noce_convert_multiple_sets (struct noce_if_info *if_info) { seq = seq1; temp_dest = temp_dest1; + if (!second_try) + last_needs_comparison = count; } else if (seq2 != NULL_RTX) { @@ -3412,6 +3423,24 @@ noce_convert_multiple_sets (struct noce_if_info *if_info) unmodified_insns.safe_push (insn); } + /* If there are insns that overwrite part of the initial + comparison, we can still omit creating temporaries for + the last of them. + As the second try will always create a less expensive, + valid sequence, we do not need to compare and can discard + the first one. */ + if (!second_try && last_needs_comparison >= 0) + { + end_sequence (); + start_sequence (); + count = 0; + targets.truncate (0); + temporaries.truncate (0); + unmodified_insns.truncate (0); + second_try = true; + goto restart; + } + /* We must have seen some sort of insn to insert, otherwise we were given an empty BB to convert, and we can't handle that. */ gcc_assert (!unmodified_insns.is_empty ()); -- 2.31.1