@@ -1429,14 +1429,26 @@ find_implicit_sets (void)
static int bypass_last_basic_block;
+/* Determine whether there is only one constant SRC rtx in the hash table
+ for REGNO. Here we assume that for the same hash value there won't be
+ more entries with the same SRC rtx. Return true if there is only one
+ constant, false otherwise. */
+
+static bool
+only_one_const_p (int regno)
+{
+ struct expr *set = lookup_set (regno, &set_hash_table);
+ return next_set (regno, set) == NULL;
+}
+
/* Find a set of REGNO to a constant that is available at the end of basic
block BB. Return NULL if no such set is found. Based heavily upon
find_avail_set. */
static struct expr *
-find_bypass_set (int regno, int bb)
+find_bypass_set (int regno, int bb, bool multiple_latches)
{
- struct expr *result = 0;
+ struct expr *result = NULL;
for (;;)
{
@@ -1450,9 +1462,15 @@ find_bypass_set (int regno, int bb)
set = next_set (regno, set);
}
- if (set == 0)
+ if (set == NULL)
break;
+ /* If there are more latch edges coming to the BB, we need to
+ make sure that for the same hash value there aren't
+ more constants. */
+ if (multiple_latches && !only_one_const_p (regno))
+ return NULL;
+
src = set->src;
if (cprop_constant_p (src))
result = set;
@@ -1502,6 +1520,7 @@ bypass_block (basic_block bb, rtx setcc,
int may_be_loop_header;
unsigned removed_p;
unsigned i;
+ unsigned n_latches;
edge_iterator ei;
insn = (setcc != NULL) ? setcc : jump;
@@ -1514,12 +1533,12 @@ bypass_block (basic_block bb, rtx setcc,
find_used_regs (&XEXP (note, 0), NULL);
may_be_loop_header = false;
+ n_latches = 0;
FOR_EACH_EDGE (e, ei, bb->preds)
if (e->flags & EDGE_DFS_BACK)
- {
- may_be_loop_header = true;
- break;
- }
+ n_latches++;
+
+ may_be_loop_header = n_latches > 0;
change = 0;
for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
@@ -1557,7 +1576,7 @@ bypass_block (basic_block bb, rtx setcc,
struct expr *set;
rtx src, new_rtx;
- set = find_bypass_set (regno, e->src->index);
+ set = find_bypass_set (regno, e->src->index, n_latches > 1);
if (! set)
continue;
@@ -0,0 +1,24 @@
+/* PR middle-end/54838 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-forward-propagate -ftracer" } */
+
+void bar (void);
+
+void
+foo (void *b, int *c)
+{
+again:
+ switch (*c)
+ {
+ case 1:
+ if (!b)
+ {
+ bar ();
+ return;
+ }
+ goto again;
+ case 3:
+ if (!b)
+ goto again;
+ }
+}