Hi, originally, we did not stream any formal parameter types into WPA and were generally very conservative when it came to type mismatches in IPA-CP. Over the time, mismatches that happen in code and blew up in WPA made us be much more resilient and also stream the types of the parameters which we now use commonly.
With that information, we can skip conversions when looking at the IL from which we build jump functions because we can check that they are indeed OK and emulate them with fold_convert or, if not, at least deal with the undefined behavior input gracefully. With this change, we can nicely propagate non-NULLness in IPA-VR as demonstrated with the new test case. I have gone through all other uses of (all components of) jump functions which could be affected by this and verified they do indeed check types and can handle mismatches. Bootstrapped and tested on x86_64-linux, the whole patch series has additionally passed LTO and profiled-LTO bootstrap on the same platform and a bootstrap and testsuite on ppc64-linux. Aarch64-linux bootstrap and testing is in progress. OK for master is that passes too? Thanks, Martin gcc/ChangeLog: 2024-11-01 Martin Jambor <mjam...@suse.cz> * ipa-prop.cc (skip_a_conversion_op): New function. (ipa_compute_jump_functions_for_edge): Use it. gcc/testsuite/ChangeLog: 2024-11-01 Martin Jambor <mjam...@suse.cz> * gcc.dg/ipa/vrp9.c: New test. --- gcc/ipa-prop.cc | 20 ++++++++++++++ gcc/testsuite/gcc.dg/ipa/vrp9.c | 48 +++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/ipa/vrp9.c diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index db8eda8c361..9bd2e4bc60c 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -2305,6 +2305,25 @@ ipa_set_jfunc_vr (ipa_jump_func *jf, const ipa_vr &vr) ipa_set_jfunc_vr (jf, tmp); } + +/* If T is an SSA_NAME that is a result of a simple type conversion statement, + return the operand of that conversion, otherwise treturn T. */ + +static tree +skip_a_conversion_op (tree t) +{ + if (TREE_CODE (t) != SSA_NAME + || SSA_NAME_IS_DEFAULT_DEF (t)) + return t; + + gimple *def = SSA_NAME_DEF_STMT (t); + if (!is_gimple_assign (def) + || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def))) + return t; + + return gimple_assign_rhs1 (def); +} + /* Compute jump function for all arguments of callsite CS and insert the information in the jump_functions array in the ipa_edge_args corresponding to this callsite. */ @@ -2409,6 +2428,7 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, gcc_assert (!jfunc->m_vr); } + arg = skip_a_conversion_op (arg); if (is_gimple_ip_invariant (arg) || (VAR_P (arg) && is_global_var (arg) diff --git a/gcc/testsuite/gcc.dg/ipa/vrp9.c b/gcc/testsuite/gcc.dg/ipa/vrp9.c new file mode 100644 index 00000000000..461a2e757d2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/vrp9.c @@ -0,0 +1,48 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int some_f1 (int); +int some_f2 (int); +int some_f3 (int); + +void remove_this_call (); + +int g; + +static int __attribute__((noinline)) +bar (int p) +{ + if (p) + remove_this_call (); + return g++; +} + +static int __attribute__((noinline)) +foo (int (*f)(int)) +{ + return bar (f == (void *)0); +} + +int +baz1 (void) +{ + int (*f)(int); + if (g) + f = some_f1; + else + f = some_f2; + return foo (f); +} + +int +baz2 (void) +{ + int (*f)(int); + if (g) + f = some_f2; + else + f = some_f3; + return foo (f); +} + +/* { dg-final { scan-tree-dump-not "remove_this_call" "optimized" } } */ -- 2.47.0