Hi, malloc_candidate_p() in ipa-pure-const misses detecting that a function is malloc-like if the return value is result of PHI and one of the arguments of PHI is 0. For example:
void g(unsigned n) { return (n) ? __builtin_malloc (n) : 0; } The reason is that the following check: if (TREE_CODE (arg) != SSA_NAME) DUMP_AND_RETURN ("phi arg is not SSA_NAME.") fails for arg with constant value 0 and malloc_candidate_p returns false. The patch simply skips the arg if it equals null_pointer_node. Does it look OK ? One concern I have is that with the patch, malloc_candidate_p will return true if all the args to PHI are NULL: retval = PHI<0, 0> return retval However I expect that PHI with all 0 args would be constant folded to 0 earlier, so this case shouldn't occur in practice ? Bootstrapped+tested on x86_64-unknown-linux-gnu. Cross-testing on arm*-*-* and aarch64*-*-* in progress. Thanks, Prathamesh
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c index 09ca3590039..0406d5588d2 100644 --- a/gcc/ipa-pure-const.c +++ b/gcc/ipa-pure-const.c @@ -910,7 +910,8 @@ malloc_candidate_p (function *fun, bool ipa) #define DUMP_AND_RETURN(reason) \ { \ if (dump_file && (dump_flags & TDF_DETAILS)) \ - fprintf (dump_file, "%s", (reason)); \ + fprintf (dump_file, "\n%s is not a malloc candidate, reason: %s\n", \ + (node->name()), (reason)); \ return false; \ } @@ -961,11 +962,14 @@ malloc_candidate_p (function *fun, bool ipa) for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i) { tree arg = gimple_phi_arg_def (phi, i); + if (arg == null_pointer_node) + continue; + if (TREE_CODE (arg) != SSA_NAME) - DUMP_AND_RETURN("phi arg is not SSA_NAME.") - if (!(arg == null_pointer_node || check_retval_uses (arg, phi))) - DUMP_AND_RETURN("phi arg has uses outside phi" - " and comparisons against 0.") + DUMP_AND_RETURN ("phi arg is not SSA_NAME."); + if (!check_retval_uses (arg, phi)) + DUMP_AND_RETURN ("phi arg has uses outside phi" + " and comparisons against 0.") gimple *arg_def = SSA_NAME_DEF_STMT (arg); gcall *call_stmt = dyn_cast<gcall *> (arg_def); diff --git a/gcc/testsuite/gcc.dg/ipa/pr83648.c b/gcc/testsuite/gcc.dg/ipa/pr83648.c new file mode 100644 index 00000000000..03b45de671b --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/pr83648.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-local-pure-const-details" } */ + +void *g(unsigned n) +{ + return n ? __builtin_malloc (n) : 0; +} + +/* { dg-final { scan-tree-dump "Function found to be malloc: g" "local-pure-const1" } } */