Range on exit was not ding the right thing when a basic block contained no statements other than a PHI node.

Rather than returning the value of the PHI, it was instead asking for range-on-entry for the phi, which  would trigger a walk back to the top of the CFG looking for the definition. When it didnt find it, it would then default to the global-value calculation. So it ended up with the right value, but it does a lot of unnecessary work and put entries in the on-entry cache that don't need to be there.

Bootstraps on  x86_64-pc-linux-gnu with no testsuite regressions.

Pushed.

Andrew


commit c0c25d1052950cecbf4488b7f76d41952672414a
Author: Andrew MacLeod <amacl...@redhat.com>
Date:   Mon Apr 26 19:23:25 2021 -0400

    Fix range_on_exit for PHI stmts when there are no other stmts in the block.
    
    last_stmt(bb) returns NULL for blocks which only have PHI stmts, and
    range_on_exit would trigger a cache fill all the way to the top of the
    program for the SSA_NAME.
    
            * gimple-range.cc (gimple_ranger::range_on_exit): Handle block with
            only PHI nodes better.

diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index 6158a754dd6..e94bb355de3 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -1003,14 +1003,23 @@ gimple_ranger::range_on_exit (irange &r, basic_block bb, tree name)
   gcc_checking_assert (bb != EXIT_BLOCK_PTR_FOR_FN (cfun));
   gcc_checking_assert (gimple_range_ssa_p (name));
 
-  gimple *s = last_stmt (bb);
-  // If there is no statement in the block and this isn't the entry
-  // block, go get the range_on_entry for this block.  For the entry
-  // block, a NULL stmt will return the global value for NAME.
-  if (!s && bb != ENTRY_BLOCK_PTR_FOR_FN (cfun))
-    range_on_entry (r, bb, name);
-  else
+  gimple *s = SSA_NAME_DEF_STMT (name);
+  basic_block def_bb = gimple_bb (s);
+  // If this is not the definition block, get the range on the last stmt in
+  // the block... if there is one.
+  if (def_bb != bb)
+    s = last_stmt (bb);
+  // If there is no statement provided, get the range_on_entry for this block.
+  if (s)
     range_of_expr (r, name, s);
+  else
+    {
+      range_on_entry (r, bb, name);
+      // See if there was a deref in this block, if applicable
+      if (!cfun->can_throw_non_call_exceptions && r.varying_p () &&
+	  m_cache.m_non_null.non_null_deref_p (name, bb))
+	r = range_nonzero (TREE_TYPE (name));
+    }
   gcc_checking_assert (r.undefined_p ()
 		       || range_compatible_p (r.type (), TREE_TYPE (name)));
 }

Reply via email to