In r14-6418-gacbfb8b9495b, the detection of boolean range was moved
over to use gimple_zero_one_valued_p but now that we can use the full ranger
during expand, let's use that instead. Adds a new helper function called
expr_has_boolean_range.  This calls ssa_name_has_boolean_range when there
is an ssa name; otherwise checks the constant value for boolean[0,1].

An example is:
```
unsigned f(unsigned b, unsigned c, unsigned d)
{
  if (b <= 1)
    return b * c;
  return d;
}
```
Where before this would not try to expand as `c & -b` but we know that b has 
[0,1] range,
this will expand as `c & -b` for many targets.

Bootstrapped and tested on x86_64-linux-gnu.

gcc/ChangeLog:

        * expr.cc (expr_has_boolean_range): New function.
        (expand_expr_real_2): Use expr_has_boolean_range instead of
        gimple_zero_one_valued_p.
        * tree-ssanames.cc (ssa_name_has_boolean_range): Update to take
        a gimple STMT.
        * tree-ssanames.h (ssa_name_has_boolean_range): Update for the new
        argument and default to nullptr.

Signed-off-by: Andrew Pinski <[email protected]>
---
 gcc/expr.cc          | 28 +++++++++++++++++++++++++---
 gcc/tree-ssanames.cc |  8 ++++----
 gcc/tree-ssanames.h  |  2 +-
 3 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/gcc/expr.cc b/gcc/expr.cc
index 4a699101bb5..1528c2212c8 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -9802,6 +9802,29 @@ expand_expr_divmod (tree_code code, machine_mode mode, 
tree treeop0,
   return expand_divmod (mod_p, code, mode, op0, op1, target, unsignedp);
 }
 
+/* Return TRUE is OP, an EXP has a range of values [0..1], false
+   otherwise. This works for constants and ssa names, calling back into the 
ranger.  */
+static bool
+expr_has_boolean_range (tree exp, gimple *stmt)
+{
+  /* An integral type with a single bit of precision.  */
+  if (INTEGRAL_TYPE_P (TREE_TYPE (exp))
+      && TYPE_UNSIGNED (TREE_TYPE (exp))
+      && TYPE_PRECISION (TREE_TYPE (exp)) == 1)
+    return true;
+
+  /* Signed 1 bit integers are not boolean ranges. */
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
+      || TYPE_PRECISION (TREE_TYPE (exp)) <= 1)
+    return false;
+
+  if (TREE_CODE (exp) == SSA_NAME)
+    return ssa_name_has_boolean_range (exp, stmt);
+  if (TREE_CODE (exp) == INTEGER_CST)
+    return wi::leu_p (wi::to_wide (exp), 1);
+  return false;
+}
+
 rtx
 expand_expr_real_2 (const_sepops ops, rtx target, machine_mode tmode,
                    enum expand_modifier modifier)
@@ -10460,9 +10483,8 @@ expand_expr_real_2 (const_sepops ops, rtx target, 
machine_mode tmode,
       /* Expand X*Y as X&-Y when Y must be zero or one.  */
       if (SCALAR_INT_MODE_P (mode))
        {
-         bool gimple_zero_one_valued_p (tree, tree (*)(tree));
-         bool bit0_p = gimple_zero_one_valued_p (treeop0, nullptr);
-         bool bit1_p = gimple_zero_one_valued_p (treeop1, nullptr);
+         bool bit0_p = expr_has_boolean_range (treeop0, 
currently_expanding_gimple_stmt);
+         bool bit1_p = expr_has_boolean_range (treeop1, 
currently_expanding_gimple_stmt);
 
          /* Expand X*Y as X&Y when both X and Y must be zero or one.  */
          if (bit0_p && bit1_p)
diff --git a/gcc/tree-ssanames.cc b/gcc/tree-ssanames.cc
index b6ca8809dc9..dcf8da56272 100644
--- a/gcc/tree-ssanames.cc
+++ b/gcc/tree-ssanames.cc
@@ -611,15 +611,15 @@ get_known_nonzero_bits (const_tree name)
   return get_known_nonzero_bits_1 (name);
 }
 
-/* Return TRUE is OP, an SSA_NAME has a range of values [0..1], false
-   otherwise.
+/* Return TRUE is OP, an SSA_NAME has a range of values [0..1] at the
+   STMT, false otherwise.
 
    This can be because it is a boolean type, any unsigned integral
    type with a single bit of precision, or has known range of [0..1]
    via range analysis.  */
 
 bool
-ssa_name_has_boolean_range (tree op)
+ssa_name_has_boolean_range (tree op, gimple *stmt)
 {
   gcc_assert (TREE_CODE (op) == SSA_NAME);
 
@@ -636,7 +636,7 @@ ssa_name_has_boolean_range (tree op)
       && (TYPE_PRECISION (TREE_TYPE (op)) > 1))
     {
       int_range<2> r;
-      if (get_range_query (cfun)->range_of_expr (r, op)
+      if (get_range_query (cfun)->range_of_expr (r, op, stmt)
          && r == range_true_and_false (TREE_TYPE (op)))
        return true;
 
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index 7d2a8f94049..a6c603f8805 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -62,7 +62,7 @@ extern void set_nonzero_bits (tree, const wide_int &);
 extern void set_bitmask (tree, const wide_int &value, const wide_int &mask);
 extern wide_int get_nonzero_bits (const_tree);
 extern wide_int get_known_nonzero_bits (const_tree);
-extern bool ssa_name_has_boolean_range (tree);
+extern bool ssa_name_has_boolean_range (tree, gimple * = nullptr);
 extern void init_ssanames (struct function *, int);
 extern void fini_ssanames (struct function *);
 extern void ssanames_print_statistics (void);
-- 
2.43.0

Reply via email to