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

Reply via email to