aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-range-fold.cc
diff options
context:
space:
mode:
authorAndrew MacLeod <amacleod@redhat.com>2021-08-24 12:13:24 -0400
committerAndrew MacLeod <amacleod@redhat.com>2021-09-20 16:32:35 -0400
commit73cf73af2392e00917de042a4692f6a0b6329ee8 (patch)
tree6cd6cfb9b9569ddf87064cc4563655b74efd3135 /gcc/gimple-range-fold.cc
parent5d110fe90afcd850ea21aee6429f22edd6b1b592 (diff)
downloadgcc-73cf73af2392e00917de042a4692f6a0b6329ee8.zip
gcc-73cf73af2392e00917de042a4692f6a0b6329ee8.tar.gz
gcc-73cf73af2392e00917de042a4692f6a0b6329ee8.tar.bz2
Use EDGE_EXECUTABLE in ranger and return UNDEFINED for those edges.
If an incoming edge is UNDEFINED, don't process it. Track if other edges equate to a single value, and add an equivalence if appropriate. gcc/ * gimple-range-fold.cc (fold_using_range::range_of_phi): Ignore undefined edges, apply an equivalence if appropriate. * gimple-range-gori.cc (gori_compute::outgoing_edge_range_p): Return UNDEFINED if EDGE_EXECUTABLE is not set. * gimple-range.cc (gimple_ranger::gimple_ranger): Set all edges as EXECUTABLE upon startup. (gimple_ranger::range_on_edge): Return UNDEFINED for edges without EDGE_EXECUTABLE set. * vr-values.c (set_and_propagate_unexecutable): New. (simplify_using_ranges::fold_cond): Call set_and_propagate. (simplify_using_ranges::simplify_switch_using_ranges): Ditto. * vr-values.h: Add prototype. gcc/testsuite/ * gcc.dg/tree-ssa/evrp-ignore.c: New.
Diffstat (limited to 'gcc/gimple-range-fold.cc')
-rw-r--r--gcc/gimple-range-fold.cc47
1 files changed, 40 insertions, 7 deletions
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 997d02d..80cc5c0 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -760,6 +760,10 @@ fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src)
if (!type)
return false;
+ // Track if all executable arguments are the same.
+ tree single_arg = NULL_TREE;
+ bool seen_arg = false;
+
// Start with an empty range, unioning in each argument's range.
r.set_undefined ();
for (x = 0; x < gimple_phi_num_args (phi); x++)
@@ -767,19 +771,48 @@ fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src)
tree arg = gimple_phi_arg_def (phi, x);
edge e = gimple_phi_arg_edge (phi, x);
- // Register potential dependencies for stale value tracking.
- if (gimple_range_ssa_p (arg) && src.gori ())
- src.gori ()->register_dependency (phi_def, arg);
-
// Get the range of the argument on its edge.
src.get_phi_operand (arg_range, arg, e);
- // If we're recomputing the argument elsewhere, try to refine it.
- r.union_ (arg_range);
+
+ if (!arg_range.undefined_p ())
+ {
+ // Register potential dependencies for stale value tracking.
+ r.union_ (arg_range);
+ if (gimple_range_ssa_p (arg) && src.gori ())
+ src.gori ()->register_dependency (phi_def, arg);
+
+ // Track if all arguments are the same.
+ if (!seen_arg)
+ {
+ seen_arg = true;
+ single_arg = arg;
+ }
+ else if (single_arg != arg)
+ single_arg = NULL_TREE;
+ }
+
// Once the value reaches varying, stop looking.
- if (r.varying_p ())
+ if (r.varying_p () && single_arg == NULL_TREE)
break;
}
+ // If the PHI boils down to a single effective argument, look at it.
+ if (single_arg)
+ {
+ // Symbolic arguments are equivalences.
+ if (gimple_range_ssa_p (single_arg))
+ src.register_relation (phi, EQ_EXPR, phi_def, single_arg);
+ else if (src.get_operand (arg_range, single_arg)
+ && arg_range.singleton_p ())
+ {
+ // Numerical arguments that are a constant can be returned as
+ // the constant. This can help fold later cases where even this
+ // constant might have been UNDEFINED via an unreachable edge.
+ r = arg_range;
+ return true;
+ }
+ }
+
// If SCEV is available, query if this PHI has any knonwn values.
if (scev_initialized_p () && !POINTER_TYPE_P (TREE_TYPE (phi_def)))
{