On Wed, 6 Nov 2024, Jan Hubicka wrote:
> Hi,
> this is updated patch which adds -fmalloc-dce flag to control malloc/free
> removal. I ended up copying what -fallocation-dse does so -fmalloc-dce=1
> enables malloc/free removal provided return value is unused otherwise and
> -fmalloc-dce=2 allows additional NULL pointer checks which it folds to
> non-NULL
> direction.
>
> I also added compensation for the gcc.dg/analyzer/pr101837.c testcase and
> added testcase that std::nothrow variant of operator new is now optimized way.
>
> With the -fmalloc-dce=n I can also add a level which emits runtime check for
> half
> of address space and calloc overflow if it seems useful, but perhaps
> incrementally. Adding size parameter tracking is not that hard (I posted WIP
> patch for that).
>
> Bootstrapped/regtested x86_64-linux, OK?
>
> * common.opt: Add -fmalloc-dce.
> * doc/invoke.texi: Document it; also add missing -flifetime-dse entry.
> * tree-ssa-dce.cc (is_removable_allocation_p): Break out from
> ...
> (mark_stmt_if_obviously_necessary): ... here; also check that
> operator new satisfies gimple_call_from_new_or_delete.
> (checks_return_value_of_removable_allocation_p): New Function.
> (mark_all_reaching_defs_necessary_1): add missing case ofr
for
> STRDUP and STRNDUP
> (propagate_necessity): Use is_removable_allocation_p and
> checks_return_value_of_removable_allocation_p.
> (eliminate_unnecessary_stmts): Update conditionals that use
> removed allocation; use is_removable_allocation_p.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/cdce3.C: Disable allocation dce.
> * g++.dg/tree-ssa/pr19476-1.C: Likewise.
> * g++.dg/tree-ssa/pr19476-2.C: Likewise.
> * g++.dg/tree-ssa/pr19476-3.C: Likewise.
> * g++.dg/tree-ssa/pr19476-4.C: Likewise.
> * gcc.dg/analyzer/pr101837.c: Disable malloc dce.
> * gcc.dg/tree-ssa/pr19831-3.c: Update.
> * gfortran.dg/pr68078.f90: Disable malloc DCE.
> * g++.dg/tree-ssa/dce-1.C: New test.
>
> diff --git a/gcc/common.opt b/gcc/common.opt
> index 0b1f1ec26e1..1a79f71789e 100644
> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -2282,6 +2282,13 @@ fmax-errors=
> Common Joined RejectNegative UInteger Var(flag_max_errors)
> -fmax-errors=<number> Maximum number of errors to report.
>
> +fmalloc-dce
> +Common Var(flag_malloc_dce,2) Init(2) Optimization
> +Allow removal of malloc and free pairs when allocated block is unused
> +
> +fmalloc-dce=
> +Common Joined RejectNegative UInteger Var(flag_malloc_dse) Optimization
> IntegerRange(0, 2)
> +
> fmem-report
> Common Var(mem_report)
> Report on permanent memory allocation.
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 7146163d66d..ba69ebe591c 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -585,7 +585,7 @@ Objective-C and Objective-C++ Dialects}.
> -fipa-bit-cp -fipa-vrp -fipa-pta -fipa-profile -fipa-pure-const
> -fipa-reference -fipa-reference-addressable
> -fipa-stack-alignment -fipa-icf -fira-algorithm=@var{algorithm}
> --flate-combine-instructions -flive-patching=@var{level}
> +-flate-combine-instructions -flifetime-dse -flive-patching=@var{level}
> -fira-region=@var{region} -fira-hoist-pressure
> -fira-loop-pressure -fno-ira-share-save-slots
> -fno-ira-share-spill-slots
> @@ -595,7 +595,7 @@ Objective-C and Objective-C++ Dialects}.
> -floop-block -floop-interchange -floop-strip-mine
> -floop-unroll-and-jam -floop-nest-optimize
> -floop-parallelize-all -flra-remat -flto -flto-compression-level
> --flto-partition=@var{alg} -fmerge-all-constants
> +-flto-partition=@var{alg} -fmalloc-dce -fmerge-all-constants
> -fmerge-constants -fmodulo-sched -fmodulo-sched-allow-regmoves
> -fmove-loop-invariants -fmove-loop-stores -fno-branch-count-reg
> -fno-defer-pop -fno-fp-int-builtin-inexact -fno-function-cse
> @@ -14568,8 +14568,12 @@ affected by @option{-flimit-function-alignment}
>
>
> @opindex fno-allocation-dce
> +@opindex fallocation-dce
> @item -fno-allocation-dce
> -Do not remove unused C++ allocations in dead code elimination.
> +Do not remove unused C++ allocations (using operator @code{new} and operator
> @code{delete})
> +in dead code elimination.
> +
> +See also @option{-fmalloc-dce}.
>
> @opindex fallow-store-data-races
> @item -fallow-store-data-races
> @@ -15442,6 +15446,18 @@ number of iterations).
>
> Enabled by @option{-O3}, @option{-fprofile-use}, and @option{-fauto-profile}.
>
> +@opindex fno-malloc-dce
> +@opindex fmalloc-dce
> +@item -fmalloc-dce
> +Control whether @code{malloc} (and its variatns such as @code{calloc} or
variants
> +@code{strdup}), can be optimized away provided its return value is only used
> +as a parameter of @code{free} call or compared with @code{NULL}. If
> +@option{-fmalloc-dce=1} is used, only calls to @code{free} are allowed while
> +with @option{-fmalloc-dce=2} also comparsions with @code{NULL} pointer are
> +considered safe to remove.
> +
> +The default is @option{-fmalloc-dce=2}. See also @option{-fallocation-dce}.
> +
> @opindex fmove-loop-invariants
> @item -fmove-loop-invariants
> Enables the loop invariant motion pass in the RTL loop optimizer. Enabled
> diff --git a/gcc/testsuite/g++.dg/cdce3.C b/gcc/testsuite/g++.dg/cdce3.C
> index 2543317f6b2..9aecf58a8b8 100644
> --- a/gcc/testsuite/g++.dg/cdce3.C
> +++ b/gcc/testsuite/g++.dg/cdce3.C
> @@ -1,6 +1,6 @@
> /* { dg-do run } */
> /* { dg-require-effective-target c99_runtime } */
> -/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -lm" } */
> +/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -lm
> -fno-allocation-dce" } */
> /* { dg-additional-options "-DLARGE_LONG_DOUBLE" { target large_long_double
> } } */
> /* { dg-additional-options "-DGNU_EXTENSION" { target pow10 } } */
> /* { dg-add-options ieee } */
> diff --git a/gcc/testsuite/g++.dg/tree-ssa/dce-1.C
> b/gcc/testsuite/g++.dg/tree-ssa/dce-1.C
> new file mode 100644
> index 00000000000..1d5115ccb14
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/tree-ssa/dce-1.C
> @@ -0,0 +1,9 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +#include <new>
> +void test ()
> +{
> + int *a = new (std::nothrow) int;
> + delete a;
> +}
> +/* { dg-final { scan-tree-dump-not "operator new" "optimized" } } */
> diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr19476-1.C
> b/gcc/testsuite/g++.dg/tree-ssa/pr19476-1.C
> index 25867185648..d17be88642f 100644
> --- a/gcc/testsuite/g++.dg/tree-ssa/pr19476-1.C
> +++ b/gcc/testsuite/g++.dg/tree-ssa/pr19476-1.C
> @@ -1,5 +1,5 @@
> /* { dg-do compile } */
> -/* { dg-options "-O -fdump-tree-dom2 -fdelete-null-pointer-checks" } */
> +/* { dg-options "-O -fdump-tree-dom2 -fdelete-null-pointer-checks
> -fno-allocation-dce" } */
> /* { dg-skip-if "" keeps_null_pointer_checks } */
>
> // See pr19476-5.C for a version without including <new>.
> diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr19476-2.C
> b/gcc/testsuite/g++.dg/tree-ssa/pr19476-2.C
> index 0f657d5bd0c..aab7d04ab92 100644
> --- a/gcc/testsuite/g++.dg/tree-ssa/pr19476-2.C
> +++ b/gcc/testsuite/g++.dg/tree-ssa/pr19476-2.C
> @@ -1,5 +1,5 @@
> /* { dg-do compile } */
> -/* { dg-options "-O2 -fdump-tree-optimized -fdelete-null-pointer-checks" } */
> +/* { dg-options "-O2 -fdump-tree-optimized -fdelete-null-pointer-checks
> -fno-allocation-dce" } */
> /* { dg-skip-if "" keeps_null_pointer_checks } */
>
> #include <new>
> diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr19476-3.C
> b/gcc/testsuite/g++.dg/tree-ssa/pr19476-3.C
> index fd5117fceb8..0894178c470 100644
> --- a/gcc/testsuite/g++.dg/tree-ssa/pr19476-3.C
> +++ b/gcc/testsuite/g++.dg/tree-ssa/pr19476-3.C
> @@ -1,5 +1,5 @@
> /* { dg-do compile } */
> -/* { dg-options "-O3 -fcheck-new -fdump-tree-optimized" } */
> +/* { dg-options "-O3 -fcheck-new -fdump-tree-optimized -fno-allocation-dce"
> } */
>
> #include <new>
>
> diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr19476-4.C
> b/gcc/testsuite/g++.dg/tree-ssa/pr19476-4.C
> index 5f137391cc6..e5c216a64fa 100644
> --- a/gcc/testsuite/g++.dg/tree-ssa/pr19476-4.C
> +++ b/gcc/testsuite/g++.dg/tree-ssa/pr19476-4.C
> @@ -1,5 +1,5 @@
> /* { dg-do compile } */
> -/* { dg-options "-O3 -fno-delete-null-pointer-checks -fdump-tree-optimized"
> } */
> +/* { dg-options "-O3 -fno-delete-null-pointer-checks -fdump-tree-optimized
> -fno-allocation-dce" } */
>
> #include <new>
>
> diff --git a/gcc/testsuite/gcc.dg/analyzer/pr101837.c
> b/gcc/testsuite/gcc.dg/analyzer/pr101837.c
> index f99374df604..1a1f7f63637 100644
> --- a/gcc/testsuite/gcc.dg/analyzer/pr101837.c
> +++ b/gcc/testsuite/gcc.dg/analyzer/pr101837.c
> @@ -1,4 +1,4 @@
> -/* { dg-additional-options "-O3 -fsanitize=undefined" } */
> +/* { dg-additional-options "-O3 -fsanitize=undefined -fno-malloc-dce" } */
>
> void memory_exhausted();
> void memcheck(void *ptr) {
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19831-3.c
> b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-3.c
> index f5cb72daa33..e6ae6582ab2 100644
> --- a/gcc/testsuite/gcc.dg/tree-ssa/pr19831-3.c
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-3.c
> @@ -29,10 +29,5 @@ void test6(void)
> Assume p was non-NULL for test2.
> For test5, it doesn't matter if p is NULL or non-NULL. */
>
> -/* { dg-final { scan-tree-dump-times "free" 0 "optimized" { xfail *-*-* } }
> } */
> -/* { dg-final { scan-tree-dump-times "malloc" 0 "optimized" { xfail *-*-* }
> } } */
> -
> -/* But make sure we don't partially optimize for now. */
> -
> -/* { dg-final { scan-tree-dump-times "free" 3 "optimized" } } */
> -/* { dg-final { scan-tree-dump-times "malloc" 3 "optimized" } } */
> +/* { dg-final { scan-tree-dump-times "free" 0 "optimized" } } */
> +/* { dg-final { scan-tree-dump-times "malloc" 0 "optimized" } } */
> diff --git a/gcc/testsuite/gfortran.dg/pr68078.f90
> b/gcc/testsuite/gfortran.dg/pr68078.f90
> index ebe26d55d2b..6494aa62362 100644
> --- a/gcc/testsuite/gfortran.dg/pr68078.f90
> +++ b/gcc/testsuite/gfortran.dg/pr68078.f90
> @@ -1,4 +1,6 @@
> ! { dg-do run { target i?86-*-linux* x86_64-*-linux* } }
> +! disable DCE so the allocations are not optimized away
> +! { dg-additional-options "-fno-malloc-dce" }
> ! { dg-additional-sources set_vm_limit.c }
> !
> ! This test calls set_vm_limit to set an artificially low address space
> diff --git a/gcc/tree-ssa-dce.cc b/gcc/tree-ssa-dce.cc
> index c44eff35b84..f4807adb926 100644
> --- a/gcc/tree-ssa-dce.cc
> +++ b/gcc/tree-ssa-dce.cc
> @@ -240,6 +240,60 @@ mark_operand_necessary (tree op)
> worklist.safe_push (stmt);
> }
>
> +/* 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. */
> +
> +static bool
> +is_removable_allocation_p (gcall *stmt, bool non_null_check)
> +{
> + tree callee = gimple_call_fndecl (stmt);
> + if (callee != NULL_TREE
> + && fndecl_built_in_p (callee, BUILT_IN_NORMAL))
> + switch (DECL_FUNCTION_CODE (callee))
> + {
> + case BUILT_IN_MALLOC:
> + case BUILT_IN_ALIGNED_ALLOC:
> + case BUILT_IN_CALLOC:
> + CASE_BUILT_IN_ALLOCA:
> + case BUILT_IN_STRDUP:
> + case BUILT_IN_STRNDUP:
> + return non_null_check ? flag_malloc_dce > 1 : flag_malloc_dce;
> +
> + case BUILT_IN_GOMP_ALLOC:
> + return true;
> +
> + default:;
> + }
> +
> + if (callee != NULL_TREE
> + && flag_allocation_dce
> + && gimple_call_from_new_or_delete (stmt)
> + && DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee))
> + return true;
> + return false;
> +}
> +
> +/* Return true if STMT is a conditional
> + if (ptr != NULL)
> + where ptr was returned by a removable allocation function. */
> +
> +static bool
> +checks_return_value_of_removable_allocation_p (gimple *stmt)
> +{
> + gcall *def_stmt;
> + return gimple_code (stmt) == GIMPLE_COND
> + && (gimple_cond_code (stmt) == EQ_EXPR
> + || gimple_cond_code (stmt) == NE_EXPR)
> + && integer_zerop (gimple_cond_rhs (stmt))
> + && TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME
> + && (def_stmt = dyn_cast <gcall *>
> + (SSA_NAME_DEF_STMT (gimple_cond_lhs (stmt))))
> + && is_removable_allocation_p (def_stmt, true);
> +}
> +
>
> /* Mark STMT as necessary if it obviously is. Add it to the worklist if
> it can make other statements necessary.
> @@ -271,38 +325,23 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool
> aggressive)
>
> case GIMPLE_CALL:
> {
> + gcall *call = as_a <gcall *> (stmt);
> +
> /* Never elide a noreturn call we pruned control-flow for. */
> - if ((gimple_call_flags (stmt) & ECF_NORETURN)
> - && gimple_call_ctrl_altering_p (stmt))
> + if ((gimple_call_flags (call) & ECF_NORETURN)
> + && gimple_call_ctrl_altering_p (call))
> {
> - mark_stmt_necessary (stmt, true);
> + mark_stmt_necessary (call, true);
> return;
> }
>
> - tree callee = gimple_call_fndecl (stmt);
> - if (callee != NULL_TREE
> - && fndecl_built_in_p (callee, BUILT_IN_NORMAL))
> - switch (DECL_FUNCTION_CODE (callee))
> - {
> - case BUILT_IN_MALLOC:
> - case BUILT_IN_ALIGNED_ALLOC:
> - case BUILT_IN_CALLOC:
> - CASE_BUILT_IN_ALLOCA:
> - case BUILT_IN_STRDUP:
> - case BUILT_IN_STRNDUP:
> - case BUILT_IN_GOMP_ALLOC:
> - return;
> -
> - default:;
> - }
>
> - if (callee != NULL_TREE
> - && flag_allocation_dce
> - && DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee))
> + if (is_removable_allocation_p (call, false))
> return;
>
> +
> /* For __cxa_atexit calls, don't mark as necessary right away. */
> - if (is_removable_cxa_atexit_call (stmt))
> + if (is_removable_cxa_atexit_call (call))
> return;
>
> /* IFN_GOACC_LOOP calls are necessary in that they are used to
> @@ -311,9 +350,9 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool
> aggressive)
> survive from aggressive loop removal for it has loop exit and
> is assumed to be finite. Therefore, we need to explicitly mark
> these calls. (An example is libgomp.oacc-c-c++-common/pr84955.c) */
> - if (gimple_call_internal_p (stmt, IFN_GOACC_LOOP))
> + if (gimple_call_internal_p (call, IFN_GOACC_LOOP))
> {
> - mark_stmt_necessary (stmt, true);
> + mark_stmt_necessary (call, true);
> return;
> }
> break;
> @@ -667,6 +706,8 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref
> ATTRIBUTE_UNUSED,
> case BUILT_IN_ALIGNED_ALLOC:
> case BUILT_IN_CALLOC:
> CASE_BUILT_IN_ALLOCA:
> + case BUILT_IN_STRDUP:
> + case BUILT_IN_STRNDUP:
> case BUILT_IN_FREE:
> case BUILT_IN_GOMP_ALLOC:
> case BUILT_IN_GOMP_FREE:
> @@ -891,19 +932,11 @@ propagate_necessity (bool aggressive)
> {
> tree ptr = gimple_call_arg (stmt, 0);
> gcall *def_stmt;
> - tree def_callee;
> /* If the pointer we free is defined by an allocation
> function do not add the call to the worklist. */
> if (TREE_CODE (ptr) == SSA_NAME
> && (def_stmt = dyn_cast <gcall *> (SSA_NAME_DEF_STMT (ptr)))
> - && (def_callee = gimple_call_fndecl (def_stmt))
> - && ((DECL_BUILT_IN_CLASS (def_callee) == BUILT_IN_NORMAL
> - && (DECL_FUNCTION_CODE (def_callee) ==
> BUILT_IN_ALIGNED_ALLOC
> - || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_MALLOC
> - || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_CALLOC
> - || DECL_FUNCTION_CODE (def_callee) ==
> BUILT_IN_GOMP_ALLOC))
> - || (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (def_callee)
> - && gimple_call_from_new_or_delete (def_stmt))))
> + && is_removable_allocation_p (def_stmt, false))
> {
> if (is_delete_operator
> && !valid_new_delete_pair_p (def_stmt, stmt))
> @@ -925,6 +958,9 @@ propagate_necessity (bool aggressive)
> }
> }
>
> + if (checks_return_value_of_removable_allocation_p (stmt))
> + continue;
> +
> FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
> mark_operand_necessary (use);
>
> @@ -1379,7 +1415,6 @@ eliminate_unnecessary_stmts (bool aggressive)
> basic_block bb;
> gimple_stmt_iterator gsi, psi;
> gimple *stmt;
> - tree call;
> auto_vec<edge> to_remove_edges;
>
> if (dump_file && (dump_flags & TDF_DETAILS))
> @@ -1448,6 +1483,23 @@ eliminate_unnecessary_stmts (bool aggressive)
> gimple_set_plf (stmt, STMT_NECESSARY, false);
> }
> }
> + /* Conditional checking that return value of allocation is non-NULL
> + can be turned to constant if the allocation itself
> + is unnecesary. */
> + if (gimple_plf (stmt, STMT_NECESSARY)
> + && gimple_code (stmt) == GIMPLE_COND
> + && TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME)
> + {
> + gimple *def_stmt = SSA_NAME_DEF_STMT (gimple_cond_lhs (stmt));
> + if (!gimple_nop_p (def_stmt)
> + && !gimple_plf (def_stmt, STMT_NECESSARY))
> + {
> + gcc_checking_assert
> + (checks_return_value_of_removable_allocation_p (stmt));
> + gimple_cond_set_lhs (as_a <gcond *>(stmt), integer_one_node);
please use a correctly typed constant, use build_one_cst (TREE_TYPE
(gimple_cond_rhs (stmt))) for example. Alternatively use
gimple_cond_make_{false,true} (based on gimple_cond_code) or
also set rhs, to integer_zero_node.
OK with those changes.
It warrants a changes.html entry.
Thanks,
Richard.
> + update_stmt (stmt);
> + }
> + }
>
> /* If GSI is not necessary then remove it. */
> if (!gimple_plf (stmt, STMT_NECESSARY))
> @@ -1482,11 +1534,11 @@ eliminate_unnecessary_stmts (bool aggressive)
> remove_dead_stmt (&gsi, bb, to_remove_edges);
> continue;
> }
> - else if (is_gimple_call (stmt))
> + else if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
> {
> - tree name = gimple_call_lhs (stmt);
> + tree name = gimple_call_lhs (call_stmt);
>
> - notice_special_calls (as_a <gcall *> (stmt));
> + notice_special_calls (call_stmt);
>
> /* When LHS of var = call (); is dead, simplify it into
> call (); saving one operand. */
> @@ -1496,36 +1548,30 @@ eliminate_unnecessary_stmts (bool aggressive)
> /* Avoid doing so for allocation calls which we
> did not mark as necessary, it will confuse the
> special logic we apply to malloc/free pair removal. */
> - && (!(call = gimple_call_fndecl (stmt))
> - || ((DECL_BUILT_IN_CLASS (call) != BUILT_IN_NORMAL
> - || (DECL_FUNCTION_CODE (call) !=
> BUILT_IN_ALIGNED_ALLOC
> - && DECL_FUNCTION_CODE (call) != BUILT_IN_MALLOC
> - && DECL_FUNCTION_CODE (call) != BUILT_IN_CALLOC
> - && !ALLOCA_FUNCTION_CODE_P
> - (DECL_FUNCTION_CODE (call))))
> - && !DECL_IS_REPLACEABLE_OPERATOR_NEW_P (call))))
> + && !is_removable_allocation_p (call_stmt, false))
> {
> something_changed = true;
> if (dump_file && (dump_flags & TDF_DETAILS))
> {
> fprintf (dump_file, "Deleting LHS of call: ");
> - print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
> + print_gimple_stmt (dump_file, call_stmt, 0, TDF_SLIM);
> fprintf (dump_file, "\n");
> }
>
> - gimple_call_set_lhs (stmt, NULL_TREE);
> - maybe_clean_or_replace_eh_stmt (stmt, stmt);
> - update_stmt (stmt);
> + gimple_call_set_lhs (call_stmt, NULL_TREE);
> + maybe_clean_or_replace_eh_stmt (call_stmt, call_stmt);
> + update_stmt (call_stmt);
> release_ssa_name (name);
>
> /* GOMP_SIMD_LANE (unless three argument) or ASAN_POISON
> without lhs is not needed. */
> - if (gimple_call_internal_p (stmt))
> - switch (gimple_call_internal_fn (stmt))
> + if (gimple_call_internal_p (call_stmt))
> + switch (gimple_call_internal_fn (call_stmt))
> {
> case IFN_GOMP_SIMD_LANE:
> - if (gimple_call_num_args (stmt) >= 3
> - && !integer_nonzerop (gimple_call_arg (stmt, 2)))
> + if (gimple_call_num_args (call_stmt) >= 3
> + && !integer_nonzerop
> + (gimple_call_arg (call_stmt, 2)))
> break;
> /* FALLTHRU */
> case IFN_ASAN_POISON:
> @@ -1535,8 +1581,8 @@ eliminate_unnecessary_stmts (bool aggressive)
> break;
> }
> }
> - else if (gimple_call_internal_p (stmt))
> - switch (gimple_call_internal_fn (stmt))
> + else if (gimple_call_internal_p (call_stmt))
> + switch (gimple_call_internal_fn (call_stmt))
> {
> case IFN_ADD_OVERFLOW:
> maybe_optimize_arith_overflow (&gsi, PLUS_EXPR);
> @@ -1548,11 +1594,11 @@ eliminate_unnecessary_stmts (bool aggressive)
> maybe_optimize_arith_overflow (&gsi, MULT_EXPR);
> break;
> case IFN_UADDC:
> - if (integer_zerop (gimple_call_arg (stmt, 2)))
> + if (integer_zerop (gimple_call_arg (call_stmt, 2)))
> maybe_optimize_arith_overflow (&gsi, PLUS_EXPR);
> break;
> case IFN_USUBC:
> - if (integer_zerop (gimple_call_arg (stmt, 2)))
> + if (integer_zerop (gimple_call_arg (call_stmt, 2)))
> maybe_optimize_arith_overflow (&gsi, MINUS_EXPR);
> break;
> default:
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)