return false;
}
-// Compute the imports to the path ending in EXIT. These are
+// Compute the imports to PATH. These are
// essentially the SSA names used to calculate the final conditional
// along the path.
//
// we can solve.
void
-path_range_query::compute_imports (bitmap imports, basic_block exit)
+path_range_query::compute_imports (bitmap imports, const vec<basic_block> &path)
{
// Start with the imports from the exit block...
+ basic_block exit = path[0];
gori_compute &gori = m_ranger->gori ();
bitmap r_imports = gori.imports (exit);
bitmap_copy (imports, r_imports);
tree arg = gimple_phi_arg (phi, i)->def;
if (TREE_CODE (arg) == SSA_NAME
- && m_path.contains (e->src)
+ && path.contains (e->src)
&& bitmap_set_bit (imports, SSA_NAME_VERSION (arg)))
worklist.safe_push (arg);
}
}
// Exported booleans along the path, may help conditionals.
if (m_resolve)
- for (i = 0; i < m_path.length (); ++i)
+ for (i = 0; i < path.length (); ++i)
{
- basic_block bb = m_path[i];
+ basic_block bb = path[i];
tree name;
FOR_EACH_GORI_EXPORT_NAME (gori, bb, name)
if (TREE_CODE (TREE_TYPE (name)) == BOOLEAN_TYPE)
if (imports)
bitmap_copy (m_imports, imports);
else
- compute_imports (m_imports, exit_bb ());
+ compute_imports (m_imports, m_path);
if (m_resolve)
get_path_oracle ()->reset_path ();
void
path_range_query::compute_outgoing_relations (basic_block bb, basic_block next)
{
- gimple *stmt = last_stmt (bb);
-
- if (stmt
- && gimple_code (stmt) == GIMPLE_COND
- && (import_p (gimple_cond_lhs (stmt))
- || import_p (gimple_cond_rhs (stmt))))
+ if (gcond *cond = safe_dyn_cast <gcond *> (last_stmt (bb)))
{
int_range<2> r;
- gcond *cond = as_a<gcond *> (stmt);
edge e0 = EDGE_SUCC (bb, 0);
edge e1 = EDGE_SUCC (bb, 1);
void compute_ranges (const vec<basic_block> &,
const bitmap_head *imports = NULL);
void compute_ranges (edge e);
- void compute_imports (bitmap imports, basic_block exit);
+ void compute_imports (bitmap imports, const vec<basic_block> &);
bool range_of_expr (vrange &r, tree name, gimple * = NULL) override;
bool range_of_stmt (vrange &r, gimple *, tree name = NULL) override;
bool unreachable_path_p ();
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-threadfull1-stats" } */
+
+void foo (int nest, int print_nest)
+{
+ _Bool t0 = nest != 0;
+ _Bool t1 = nest == print_nest;
+ _Bool t2 = t0 & t1;
+ if (t2)
+ __builtin_puts ("x");
+ nest++;
+ if (nest > 2)
+ __builtin_abort ();
+ if (print_nest == nest)
+ __builtin_puts ("y");
+}
+
+/* We should be able to thread (t2) to !(print_nest == nest) using the
+ nest == print_nest relation implied by the entry block. */
+/* { dg-final { scan-tree-dump "Jumps threaded: 1" "threadfull1" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-threadfull1-stats" } */
+
+struct S;
+struct S { struct S *next; };
+int foo (struct S *chain, _Bool is_ctor, _Bool is_dtor)
+{
+ int num_args = 0;
+ if (chain) /* A */
+ {
+ do {
+ num_args++;
+ chain = chain->next;
+ if (!chain)
+ break;
+ } while (1);
+ }
+ if (is_ctor)
+ num_args++; /* B */
+ if (is_dtor)
+ num_args++;
+ else
+ {
+ if (num_args > 2) /* C */
+ __builtin_puts ("x");
+ }
+ return num_args;
+}
+
+/* We want to thread both paths from A with NULL chain to C, the one through
+ B and one around it.
+ ??? Ideally we'd thread one "path" containing the half-diamond with B. */
+/* { dg-final { scan-tree-dump "Jumps threaded: 2" "threadfull1" { xfail *-*-* } } } */