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