From: Kyrylo Tkachov <[email protected]>

noce_try_sign_bit_splat has two arms that narrow the -1/0 splat down to a
constant, one for each orientation of the test.  They are twenty-five
identical lines apart from which of the two arm constants they use, including
the cost comparison that picks between a mask, a left shift and a right shift.

Move that into noce_splat_to_const and call it from both arms.  No functional
change.

gcc/ChangeLog:

        * ifcvt.cc (noce_splat_to_const): New function.
        (noce_try_sign_bit_splat): Use it for both orientations.

Signed-off-by: Kyrylo Tkachov <[email protected]>
---
 gcc/ifcvt.cc | 92 ++++++++++++++++++++++------------------------------
 1 file changed, 38 insertions(+), 54 deletions(-)

diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 67bd54e2f2e..fb3f507758a 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -1411,6 +1411,42 @@ noce_try_move (struct noce_if_info *if_info)
   return false;
 }
 
+/* TEMP holds an all-ones or all-zeros splat of a tested sign bit.  Return an
+   rtx that narrows it to VAL or zero, expanded into TARGET where possible, or
+   NULL_RTX if the expansion failed.
+
+   The obvious form is a mask, but since the value is known to be -1 or 0 a
+   shift is sometimes cheaper: a logical right shift constructs 2^n-1 and a
+   left shift constructs ~(2^n-1).  Some targets do not have efficient shifts,
+   so build the RTL for each applicable form and expand the cheapest.  */
+
+static rtx
+noce_splat_to_const (machine_mode mode, rtx temp, HOST_WIDE_INT val,
+                    rtx target)
+{
+  rtx and_form = gen_rtx_AND (mode, temp, GEN_INT (val));
+  rtx shift_left = gen_rtx_ASHIFT (mode, temp, GEN_INT (ctz_hwi (val)));
+  HOST_WIDE_INT rshift_count
+    = clz_hwi (val) & (GET_MODE_PRECISION (mode).to_constant () - 1);
+  rtx shift_right = gen_rtx_LSHIFTRT (mode, temp, GEN_INT (rshift_count));
+  bool speed_p = optimize_insn_for_speed_p ();
+
+  if (exact_log2 (val + 1) >= 0
+      && (rtx_cost (shift_right, mode, SET, 1, speed_p)
+         < rtx_cost (and_form, mode, SET, 1, speed_p)))
+    return expand_simple_binop (mode, LSHIFTRT, temp, GEN_INT (rshift_count),
+                               target, false, OPTAB_WIDEN);
+
+  if (exact_log2 (~val + 1) >= 0
+      && (rtx_cost (shift_left, mode, SET, 1, speed_p)
+         < rtx_cost (and_form, mode, SET, 1, speed_p)))
+    return expand_simple_binop (mode, ASHIFT, temp, GEN_INT (ctz_hwi (val)),
+                               target, false, OPTAB_WIDEN);
+
+  return expand_simple_binop (mode, AND, temp, GEN_INT (val), target, false,
+                             OPTAB_WIDEN);
+}
+
 /* If a sign bit test is selecting across constants, we may be able
    to generate efficient code utilizing the -1/0 result of a sign
    bit splat idiom.
@@ -1507,33 +1543,7 @@ noce_try_sign_bit_splat (struct noce_if_info *if_info)
            goto fail;
        }
 
-      /* Since we know the value is currently -1 or 0, some constants may
-        be more easily handled by shifting the value again.  A right
-        logical shift constructs 2^n-1 constants a left shift constructs
-        ~(2^n-1) constants.  Given some targets don't have efficient
-        shifts, generate the obvious RTL for both forms and select the
-        one with smaller cost.  */
-      rtx and_form = gen_rtx_AND (mode, temp, GEN_INT (val_a));
-      rtx shift_left = gen_rtx_ASHIFT (mode, temp, GEN_INT (ctz_hwi (val_a)));
-      HOST_WIDE_INT rshift_count
-       = (clz_hwi (val_a) & (GET_MODE_PRECISION (mode).to_constant() - 1));
-      rtx shift_right = gen_rtx_LSHIFTRT (mode, temp, GEN_INT (rshift_count));
-      bool speed_p = optimize_insn_for_speed_p ();
-      if (exact_log2 (val_a + 1) >= 0
-         && (rtx_cost (shift_right, mode, SET, 1, speed_p)
-             < rtx_cost (and_form, mode, SET, 1, speed_p)))
-       temp = expand_simple_binop (mode, LSHIFTRT, temp,
-                                   GEN_INT (rshift_count),
-                                   if_info->x, false, OPTAB_WIDEN);
-      else if (exact_log2 (~val_a + 1) >= 0
-              && (rtx_cost (shift_left, mode, SET, 1, speed_p)
-                  < rtx_cost (and_form, mode, SET, 1, speed_p)))
-       temp = expand_simple_binop (mode, ASHIFT, temp,
-                                   GEN_INT (ctz_hwi (val_a)),
-                                   if_info->x, false, OPTAB_WIDEN);
-      else
-       temp = expand_simple_binop (mode, AND, temp, GEN_INT (val_a),
-                                   if_info->x, false, OPTAB_WIDEN);
+      temp = noce_splat_to_const (mode, temp, val_a, if_info->x);
     }
   /* Same cases, but with the test or arms swapped.  These
      can be realized as well, though it typically costs
@@ -1559,33 +1569,7 @@ noce_try_sign_bit_splat (struct noce_if_info *if_info)
            goto fail;
        }
 
-      /* Since we know the value is currently -1 or 0, some constants may
-        be more easily handled by shifting the value again.  A right
-        logical shift constructs 2^n-1 constants a left shift constructs
-        ~(2^n-1) constants.  Given some targets don't have efficient
-        shifts, generate the obvious RTL for both forms and select the
-        one with smaller cost.  */
-      rtx and_form = gen_rtx_AND (mode, temp, GEN_INT (val_b));
-      rtx shift_left = gen_rtx_ASHIFT (mode, temp, GEN_INT (ctz_hwi (val_b)));
-      HOST_WIDE_INT rshift_count
-       = (clz_hwi (val_b) & (GET_MODE_PRECISION (mode).to_constant() - 1));
-      rtx shift_right = gen_rtx_LSHIFTRT (mode, temp, GEN_INT (rshift_count));
-      bool speed_p = optimize_insn_for_speed_p ();
-      if (exact_log2 (val_b + 1) >= 0
-         && (rtx_cost (shift_right, mode, SET, 1, speed_p)
-             < rtx_cost (and_form, mode, SET, 1, speed_p)))
-       temp = expand_simple_binop (mode, LSHIFTRT, temp,
-                                   GEN_INT (rshift_count),
-                                   if_info->x, false, OPTAB_WIDEN);
-      else if (exact_log2 (~val_b + 1) >= 0
-              && (rtx_cost (shift_left, mode, SET, 1, speed_p)
-                  < rtx_cost (and_form, mode, SET, 1, speed_p)))
-       temp = expand_simple_binop (mode, ASHIFT, temp,
-                                   GEN_INT (ctz_hwi (val_b)),
-                                   if_info->x, false, OPTAB_WIDEN);
-      else
-        temp = expand_simple_binop (mode, AND, temp, GEN_INT (val_b),
-                                   if_info->x, false, OPTAB_WIDEN);
+      temp = noce_splat_to_const (mode, temp, val_b, if_info->x);
     }
   /* Nothing worked.  */
   else
-- 
2.50.1 (Apple Git-155)

Reply via email to