aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2020-04-29 11:05:19 +0200
committerAldy Hernandez <aldyh@redhat.com>2020-04-29 11:06:32 +0200
commitd34a06eb10fc80e67b15524a3572f11a86e37e73 (patch)
tree97aa9ff188fd2ddf57baba5212816247bae15fbf
parentb1742cc9cae28ee3aad96a7f4510c1d08cd903b2 (diff)
downloadgcc-d34a06eb10fc80e67b15524a3572f11a86e37e73.zip
gcc-d34a06eb10fc80e67b15524a3572f11a86e37e73.tar.gz
gcc-d34a06eb10fc80e67b15524a3572f11a86e37e73.tar.bz2
Handle switches having a case pointing to the same destination as the default.
-rw-r--r--gcc/gimple-range-stmt.cc21
1 files changed, 13 insertions, 8 deletions
diff --git a/gcc/gimple-range-stmt.cc b/gcc/gimple-range-stmt.cc
index 4e48477..f94078c 100644
--- a/gcc/gimple-range-stmt.cc
+++ b/gcc/gimple-range-stmt.cc
@@ -83,11 +83,11 @@ gimple_range_adjustment (const gimple *stmt, irange &res)
// This function will calculate the "constant" range on edge E from
// switch SW returning it in R, and return the switch statement
-// itself. THis is currently not very efficent as the way we
+// itself. This is currently not very efficent as the way we
// represent switches in GIMPLE does not map well to this calculation.
static gimple *
-calc_single_range (irange &r, gswitch *sw, edge e)
+calc_range_for_switch_on_edge (irange &r, gswitch *sw, edge e)
{
unsigned x, lim;
lim = gimple_switch_num_labels (sw);
@@ -104,11 +104,12 @@ calc_single_range (irange &r, gswitch *sw, edge e)
if (lim > 1 && !types_compatible_p (type, case_type))
return NULL;
- if (e != gimple_switch_default_edge (cfun, sw))
+ edge default_edge = gimple_switch_default_edge (cfun, sw);
+ if (e != default_edge)
{
r.set_undefined ();
- // Loop through all the switches edges, ignoring the default edge.
- // unioning the ranges together.
+ // Union all the ranges for each switch edge, ignoring the
+ // default edge.
for (x = 1; x < lim; x++)
{
if (gimple_switch_edge (cfun, sw, x) != e)
@@ -124,10 +125,14 @@ calc_single_range (irange &r, gswitch *sw, edge e)
else
{
r.set_varying (type);
- // Loop through all the switches edges, ignoring the default edge.
- // intersecting the ranges not covered by the case.
+ // Loop through all the switches edges, ignoring the default
+ // edge, while intersecting the ranges not covered by the case.
for (x = 1; x < lim; x++)
{
+ // Some other edge could still point to the default edge
+ // destination. Ignore it.
+ if (gimple_switch_edge (cfun, sw, x) == default_edge)
+ continue;
tree low = CASE_LOW (gimple_switch_label (sw, x));
tree high = CASE_HIGH (gimple_switch_label (sw, x));
if (!high)
@@ -196,7 +201,7 @@ gimple_outgoing_edge_range_p (irange &r, edge e)
if (!irange::supports_type_p (type))
return NULL;
- return calc_single_range (r, sw, e);
+ return calc_range_for_switch_on_edge (r, sw, e);
}