--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
+
+extern void abort (void);
+
+typedef union tree_node *tree;
+union tree_node
+{
+ int code;
+ tree chain;
+ int omp_code;
+}
+bitmap_head;
+
+extern int c_omp_predetermined_sharing (tree);
+
+tree
+c_finish_omp_clauses (tree clauses)
+{
+ tree c, t, *pc = &clauses;
+ for (pc = &clauses, c = clauses; c; c = *pc)
+ {
+ unsigned char remove = 0;
+ switch (((c->omp_code)))
+ {
+ case 1:
+ if (t->code != 42)
+ remove = 1;
+ switch (c_omp_predetermined_sharing (t))
+ {
+ case 2:
+ abort ();
+ }
+ }
+ if (remove)
+ *pc = c->chain;
+ }
+}
+
+/* There are 3 FSM jump threading opportunities, two of which will
+ get cancelled. */
+/* { dg-final { scan-tree-dump-times "Registering FSM" 3 "vrp1"} } */
+/* { dg-final { scan-tree-dump-times "Cancelling FSM" 2 "vrp1"} } */
valid_jump_thread_path (vec<jump_thread_edge *> *path)
{
unsigned len = path->length ();
- bool multiway_branch = false;
+ bool threaded_multiway_branch = false;
+ bool multiway_branch_in_path = false;
bool threaded_through_latch = false;
/* Check that the path is connected and see if there's a multi-way
- branch on the path. */
+ branch on the path and whether or not a multi-way branch
+ is threaded. */
for (unsigned int j = 0; j < len - 1; j++)
{
edge e = (*path)[j]->e;
threaded_through_latch = true;
gimple *last = last_stmt (e->dest);
- multiway_branch |= (last && gimple_code (last) == GIMPLE_SWITCH);
+ if (j == len - 2)
+ threaded_multiway_branch
+ |= (last && gimple_code (last) == GIMPLE_SWITCH);
+ else
+ multiway_branch_in_path
+ |= (last && gimple_code (last) == GIMPLE_SWITCH);
}
/* If we are trying to thread through the loop latch to a block in the
irreducible loop. We avoid that unless the jump thread has a multi-way
branch, in which case we have deemed it worth losing other
loop optimizations later if we can eliminate the multi-way branch. */
- if (!multiway_branch && threaded_through_latch)
- return false;
+ if (!threaded_multiway_branch && threaded_through_latch)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file,
+ "Thread through latch without threading a multiway "
+ "branch.\n");
+ dump_jump_thread_path (dump_file, *path, false);
+ }
+ return false;
+ }
+
+ /* When there is a multi-way branch on the path, then threading can
+ explode the CFG due to duplicating the edges for that multi-way
+ branch. So like above, only allow a multi-way branch on the path
+ if we actually thread a multi-way branch. */
+ if (!threaded_multiway_branch && multiway_branch_in_path)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file,
+ "Thread through multiway branch without threading "
+ "a multiway branch.\n");
+ dump_jump_thread_path (dump_file, *path, false);
+ }
+ return false;
+ }
return true;
}
/* Do not jump-thread twice from the same block. */
if (bitmap_bit_p (threaded_blocks, entry->src->index)
- /* Verify that the jump thread path is still valid: a
- previous jump-thread may have changed the CFG, and
- invalidated the current path or the requested jump
- thread might create irreducible loops which should
- generally be avoided. */
+ /* We may not want to realize this jump thread path
+ for various reasons. So check it first. */
|| !valid_jump_thread_path (path))
{
/* Remove invalid FSM jump-thread paths. */