On Fri, Jan 03, 2025 at 10:46:18PM +0100, Jakub Jelinek wrote: > Hi! > > As suggested by Richi in the PR, the following patch will fail to DCE > allocation calls if they have constant size which is too large (over > PTRDIFF_MAX), or for the case of calloc, if either of the arguments > is too large (in that case in theory the call could succeed if the other > argument is variable zero but who cares) or if both are constant and > their product overflows or is above PTRDIFF_MAX. > > This will make some pedantic conformance tests happy, though if one > hides the size one will still need to use -fno-malloc-dce or obfuscate even > the malloc etc. uses. If the size is constant and too large, it isn't worth > trying to optimize it. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2025-01-03 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/118224 > * tree-ssa-dce.cc (is_removable_allocation_p): Don't return true > for allocations with constant size argument larger than PTRDIFF_MAX > or for calloc with one of the arguments constant larger than > PTRDIFF_MAX or their product known constant above PTRDIFF_MAX. > Fix comment typos, furhter -> further and then -> than. > * lto-section-in.cc (lto_free_function_in_decl_state_for_node): > Fix comment typo, furhter -> further. > > * gcc.dg/pr118224.c: New test. > * c-c++-common/ubsan/vla-1.c (bar): Use noipa attribute instead > of noinline, noclone. > > --- gcc/tree-ssa-dce.cc.jj 2025-01-02 11:23:26.890372040 +0100 > +++ gcc/tree-ssa-dce.cc 2025-01-03 20:01:33.074172650 +0100 > @@ -243,38 +243,101 @@ mark_operand_necessary (tree op) > > /* Return true if STMT is a call to allocation function that can be > optimized out if the memory block is never used for anything else > - then NULL pointer check or free. > - If NON_NULL_CHECK is false, we can furhter assume that return value > - is never checked to be non-NULL. */ > + than NULL pointer check or free. > + If NON_NULL_CHECK is false, we can further assume that return value > + is never checked to be non-NULL. > + Don't return true if it is called with constant size (or sizes for calloc) > + and the size is excessively large (larger than PTRDIFF_MAX, for calloc > + either argument larger than PTRDIFF_MAX or both constant and their product > + larger than PTRDIFF_MAX). */ > > static bool > is_removable_allocation_p (gcall *stmt, bool non_null_check) > { > - tree callee = gimple_call_fndecl (stmt); > + int arg = -1; > + tree callee = gimple_call_fndecl (stmt), a1, a2; > if (callee != NULL_TREE > && fndecl_built_in_p (callee, BUILT_IN_NORMAL)) > switch (DECL_FUNCTION_CODE (callee)) > { > case BUILT_IN_MALLOC: > + arg = 1; > + goto do_malloc; > case BUILT_IN_ALIGNED_ALLOC: > + arg = 2; > + goto do_malloc; > case BUILT_IN_CALLOC: > + arg = 3; > + goto do_malloc; > CASE_BUILT_IN_ALLOCA: > + arg = 1; > + goto do_malloc; > case BUILT_IN_STRDUP: > case BUILT_IN_STRNDUP: > - return non_null_check ? flag_malloc_dce > 1 : flag_malloc_dce; > + arg = 0; > + /* FALLTHRU */ > + do_malloc: > + if (non_null_check) > + { > + if (flag_malloc_dce <= 1) > + return false; > + } > + else if (!flag_malloc_dce) > + return false; > + break; > > case BUILT_IN_GOMP_ALLOC: > - return true; > + arg = 2; > + break; > > default:; > } > > - if (callee != NULL_TREE > + if (arg == -1 > + && callee != NULL_TREE > && flag_allocation_dce > && gimple_call_from_new_or_delete (stmt) > && DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee)) > - return true; > - return false; > + arg = 1; > + > + switch (arg) > + { > + case -1: > + return false; > + case 0: > + return true; > + case 1: > + case 2: > + if (gimple_call_num_args (stmt) < (unsigned) arg) > + return false; > + a1 = gimple_call_arg (stmt, arg - 1); > + if (tree_fits_uhwi_p (a1) > + && (tree_to_uhwi (a1) > + > tree_to_uhwi (TYPE_MAX_VALUE (ptrdiff_type_node)))) > + return false; > + return true; > + case 3: > + if (gimple_call_num_args (stmt) < 2) > + return false; > + a1 = gimple_call_arg (stmt, 0); > + a2 = gimple_call_arg (stmt, 1); > + if (tree_fits_uhwi_p (a1) > + && (tree_to_uhwi (a1) > + > tree_to_uhwi (TYPE_MAX_VALUE (ptrdiff_type_node)))) > + return false; > + if (tree_fits_uhwi_p (a2) > + && (tree_to_uhwi (a2) > + > tree_to_uhwi (TYPE_MAX_VALUE (ptrdiff_type_node)))) > + return false; > + if (TREE_CODE (a1) == INTEGER_CST > + && TREE_CODE (a2) == INTEGER_CST > + && (wi::to_widest (a1) + wi::to_widest (a2)
Hi Jakub, Shouldn't the two "calloc" arguments be multiplied here, instead of added? Regards, Dimitar > + > tree_to_uhwi (TYPE_MAX_VALUE (ptrdiff_type_node)))) > + return false; > + return true; > + default: > + gcc_unreachable (); > + } > } >