This is the mail archive of the
mailing list for the GCC project.
[PATCH][RFA] Improvements to infer_nonnull_range
- From: Jeff Law <law at redhat dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 28 Oct 2013 23:02:44 -0600
- Subject: [PATCH][RFA] Improvements to infer_nonnull_range
- Authentication-results: sourceware.org; auth=none
Based on a suggestion from Marc, I want to use infer_nonnull_range in
the erroneous path isolation optimization.
In the process of doing that, I found a few deficiencies in
infer_nonnull_range that need to be addressed.
First, infer_nonnull_range_p doesn't infer ranges from a GIMPLE_RETURN
if the current function is marked as returns_nonnull. That's fixed in
the relatively obvious way.
Second, infer_nonnull_range_p, when presented with an arglist where the
non-null attribute applies to all pointer arguments, it won't bother to
determine if OP is actually one of the arguments :( It just assumes
that OP is in the argument list. Opps.
Third, I want to be able to call infer_nonnull_range with OP being 0B.
That lets me use infer_nonnull_range to look for explicit null pointer
dereferences, explicit uses of null in a return statement in functions
that can't return non-null and explicit uses of null arguments when
those arguments can't be null. Sadly, to make that work we need to use
operand_equal_p rather than simple pointer comparisons to see if OP
shows up in STMT.
Finally, for detecting explicit null pointers, infer_nonnull_range calls
count_ptr_derefs. count_ptr_derefs counts things in two ways. One with
a FOR_EACH_SSA_TREE_OPERAND, then again with simple walks of the tree
structures. Not surprisingly if we're looking for an explicit 0B, then
the loop over the operands finds nothing, but walking the tree
structures does. And the checking assert triggers. This change removes
the assert and instead sets *num_uses_p to a sane value.
I don't have testcases for this stuff that are independent of the
erroneous path isolation optimization. However, each is triggered by
tests I'll include in the the erroneous path isolation patch.
Bootstrapped and regression tested on x86_64-unknown-linux-gnu. OK for
* tree-ssa.c (count_ptr_derefs): Use operand_equal_p rather than
testing pointer equality. Remove invalid assert. Clamp minimum
value for *num_uses_p at *num_loads_p + *num_stores_p.
* tree-vrp.c (infer_nonnull_range): Verify OP is in the argument
list and the argument corresponding to OP is a pointer type.
Use operand_equal_p rather than pointer equality when testing
if OP is on the nonnull list. Handle GIMPLE_RETURN statements too.
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 0b743d1..d29665b 100644
@@ -265,7 +265,8 @@ count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
- if (TREE_CODE (*tp) == MEM_REF && TREE_OPERAND (*tp, 0) == count_p->ptr)
+ if (TREE_CODE (*tp) == MEM_REF
+ && operand_equal_p (TREE_OPERAND (*tp, 0), count_p->ptr, 0))
@@ -326,7 +327,11 @@ count_uses_and_derefs (tree ptr, gimple stmt, unsigned *num_uses_p,
*num_loads_p = count.num_loads;
- gcc_assert (*num_uses_p >= *num_loads_p + *num_stores_p);
+ /* This can happen if PTR refers to something other than an SSA_NAME.
+ In that case we will find no uses as the FOR_EACH_SSA_TREE_OPERAND
+ only iterates over the SSA_NAMEs in a statement. */
+ if (*num_uses_p < *num_loads_p + *num_stores_p)
+ *num_uses_p = *num_loads_p + *num_stores_p;
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index d3a07f3..bbcb34c 100644
@@ -4509,21 +4509,38 @@ infer_nonnull_range (gimple stmt, tree op)
/* If "nonnull" applies to all the arguments, then ARG
- is non-null. */
+ is non-null if it's in the argument list. */
if (TREE_VALUE (attrs) == NULL_TREE)
- return true;
+ for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
+ if (operand_equal_p (op, gimple_call_arg (stmt, i), 0)
+ && POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (stmt, i))))
+ return true;
+ return false;
/* Now see if op appears in the nonnull list. */
for (tree t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
int idx = TREE_INT_CST_LOW (TREE_VALUE (t)) - 1;
tree arg = gimple_call_arg (stmt, idx);
- if (op == arg)
+ if (operand_equal_p (op, arg, 0))
+ /* If this function is marked as returning non-null, then we can
+ infer OP is non-null if it is used in the return statement. */
+ if (gimple_code (stmt) == GIMPLE_RETURN
+ && gimple_return_retval (stmt)
+ && operand_equal_p (gimple_return_retval (stmt), op, 0)
+ && lookup_attribute ("returns_nonnull",
+ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
+ return true;