diff options
| author | Andrew Pinski <andrew.pinski@oss.qualcomm.com> | 2025-10-26 12:21:08 -0700 |
|---|---|---|
| committer | Andrew Pinski <andrew.pinski@oss.qualcomm.com> | 2025-10-27 16:09:07 -0700 |
| commit | 89f8c4709446f4b16fe88ac25cfef7fa9a73f296 (patch) | |
| tree | e364243039da9ed8fb3e374d434e757f2502de75 | |
| parent | 2f7edefc54e6967168c3cce3a4347cc0bc6a8155 (diff) | |
| download | gcc-89f8c4709446f4b16fe88ac25cfef7fa9a73f296.zip gcc-89f8c4709446f4b16fe88ac25cfef7fa9a73f296.tar.gz gcc-89f8c4709446f4b16fe88ac25cfef7fa9a73f296.tar.bz2 | |
expand: Move the [0,1] detection for a*b to use the ranger
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 <andrew.pinski@oss.qualcomm.com>
| -rw-r--r-- | gcc/expr.cc | 28 | ||||
| -rw-r--r-- | gcc/tree-ssanames.cc | 8 | ||||
| -rw-r--r-- | gcc/tree-ssanames.h | 2 |
3 files changed, 30 insertions, 8 deletions
diff --git a/gcc/expr.cc b/gcc/expr.cc index 4a69910..7d84ad9 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 if 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 b6ca880..dcf8da5 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 7d2a8f9..a6c603f 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); |
