Hi, one of the testcases from PR 118097 and the one from PR 118535 show that the fix to PR 118138 was incomplete. We must not only make sure that (intermediate) results of operations performed by IPA-CP are fold_converted to the type of the destination formal parameter but we also must decouple the these types from the ones in which operations are performed.
This patch does that, even though we do not store or stream the operation types, instead we simply limit ourselves to tcc_comparisons and operations for which the first operand and the result are of the same type as determined by expr_type_first_operand_type_p. If we wanted to go beyond these, we would indeed need to store/stream the respective operation type. ipa_value_from_jfunc needs an additional check that res_type is not NULL because it is not called just from within IPA-CP (where we know we have a destination lattice slot belonging to a defined parameter) but also from inlining, ipa-fnsummary and ipa-modref where it is used to examine a call to a function with variadic arguments and we do not have types for the unknown parameters. But we cannot really work with those or estimate any benefits when it comes to them, so ignoring them should be OK. Even after this patch, ipa_get_jf_arith_result has a parameter called res_type in which it performs operations for aggregate jump functions, where we do not allow type conversions when constucting the jump functions and the type is the type of the stored data. In GCC 16, we could relax this and allow conversions like for scalars. Bootstrapped, LTO-bootstrapped and tested on x86_64-linux. OK for master? Thanks, Honza gcc/ChangeLog: 2025-01-20 Martin Jambor <mjam...@suse.cz> PR ipa/118097 * ipa-cp.cc (ipa_get_jf_arith_result): Adjust comment. (ipa_get_jf_pass_through_result): Removed. (ipa_value_from_jfunc): Use directly ipa_get_jf_arith_result, do not specify operation type but make sure we check and possibly convert the result. (get_val_across_arith_op): Remove the last parameter, always pass NULL_TREE to ipa_get_jf_arith_result in its last argument. (propagate_vals_across_arith_jfunc): Do not pass res_type to get_val_across_arith_op. (propagate_vals_across_pass_through): Add checking assert that parm_type is not NULL. gcc/testsuite/ChangeLog: 2025-01-20 Martin Jambor <mjam...@suse.cz> PR ipa/118097 * gcc.dg/ipa/pr118097.c: New test. * gcc.dg/ipa/pr118535.c: Likewise. * gcc.dg/ipa/ipa-notypes-1.c: Likewise. --- gcc/ipa-cp.cc | 46 ++++++++++-------------- gcc/testsuite/gcc.dg/ipa/ipa-notypes-1.c | 17 +++++++++ gcc/testsuite/gcc.dg/ipa/pr118097.c | 23 ++++++++++++ gcc/testsuite/gcc.dg/ipa/pr118535.c | 17 +++++++++ 4 files changed, 75 insertions(+), 28 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/ipa/ipa-notypes-1.c create mode 100644 gcc/testsuite/gcc.dg/ipa/pr118097.c create mode 100644 gcc/testsuite/gcc.dg/ipa/pr118535.c diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc index d89324a0077..68959f2677b 100644 --- a/gcc/ipa-cp.cc +++ b/gcc/ipa-cp.cc @@ -1467,11 +1467,10 @@ ipacp_value_safe_for_type (tree param_type, tree value) return NULL_TREE; } -/* Return the result of a (possibly arithmetic) operation on the constant - value INPUT. OPERAND is 2nd operand for binary operation. RES_TYPE is - the type of the parameter to which the result is passed. Return - NULL_TREE if that cannot be determined or be considered an - interprocedural invariant. */ +/* Return the result of a (possibly arithmetic) operation on the constant value + INPUT. OPERAND is 2nd operand for binary operation. RES_TYPE is the type + in which any operation is to be performed. Return NULL_TREE if that cannot + be determined or be considered an interprocedural invariant. */ static tree ipa_get_jf_arith_result (enum tree_code opcode, tree input, tree operand, @@ -1513,21 +1512,6 @@ ipa_get_jf_arith_result (enum tree_code opcode, tree input, tree operand, return res; } -/* Return the result of a (possibly arithmetic) pass through jump function - JFUNC on the constant value INPUT. RES_TYPE is the type of the parameter - to which the result is passed. Return NULL_TREE if that cannot be - determined or be considered an interprocedural invariant. */ - -static tree -ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input, - tree res_type) -{ - return ipa_get_jf_arith_result (ipa_get_jf_pass_through_operation (jfunc), - input, - ipa_get_jf_pass_through_operand (jfunc), - res_type); -} - /* Return the result of an ancestor jump function JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be determined. */ @@ -1595,7 +1579,14 @@ ipa_value_from_jfunc (class ipa_node_params *info, struct ipa_jump_func *jfunc, return NULL_TREE; if (jfunc->type == IPA_JF_PASS_THROUGH) - return ipa_get_jf_pass_through_result (jfunc, input, parm_type); + { + if (!parm_type) + return NULL_TREE; + enum tree_code opcode = ipa_get_jf_pass_through_operation (jfunc); + tree op2 = ipa_get_jf_pass_through_operand (jfunc); + tree cstval = ipa_get_jf_arith_result (opcode, input, op2, NULL_TREE); + return ipacp_value_safe_for_type (parm_type, cstval); + } else return ipa_get_jf_ancestor_result (jfunc, input); } @@ -2120,15 +2111,13 @@ ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs, /* A helper function that returns result of operation specified by OPCODE on the value of SRC_VAL. If non-NULL, OPND1_TYPE is expected type for the value of SRC_VAL. If the operation is binary, OPND2 is a constant value - acting as its second operand. If non-NULL, RES_TYPE is expected type of - the result. */ + acting as its second operand. */ static tree get_val_across_arith_op (enum tree_code opcode, tree opnd1_type, tree opnd2, - ipcp_value<tree> *src_val, - tree res_type) + ipcp_value<tree> *src_val) { tree opnd1 = src_val->value; @@ -2137,7 +2126,7 @@ get_val_across_arith_op (enum tree_code opcode, && !useless_type_conversion_p (opnd1_type, TREE_TYPE (opnd1))) return NULL_TREE; - return ipa_get_jf_arith_result (opcode, opnd1, opnd2, res_type); + return ipa_get_jf_arith_result (opcode, opnd1, opnd2, NULL_TREE); } /* Propagate values through an arithmetic transformation described by a jump @@ -2213,7 +2202,7 @@ propagate_vals_across_arith_jfunc (cgraph_edge *cs, for (int j = 1; j < max_recursive_depth; j++) { tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2, - src_val, res_type); + src_val); cstval = ipacp_value_safe_for_type (res_type, cstval); if (!cstval) break; @@ -2238,7 +2227,7 @@ propagate_vals_across_arith_jfunc (cgraph_edge *cs, } tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2, - src_val, res_type); + src_val); cstval = ipacp_value_safe_for_type (res_type, cstval); if (cstval) ret |= dest_lat->add_value (cstval, cs, src_val, src_idx, @@ -2261,6 +2250,7 @@ propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc, ipcp_lattice<tree> *dest_lat, int src_idx, tree parm_type) { + gcc_checking_assert (parm_type); return propagate_vals_across_arith_jfunc (cs, ipa_get_jf_pass_through_operation (jfunc), NULL_TREE, diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-notypes-1.c b/gcc/testsuite/gcc.dg/ipa/ipa-notypes-1.c new file mode 100644 index 00000000000..e8f4adaed17 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/ipa-notypes-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +void some_memcpy(void *, long); +long bufused; +char buf, otest_s; +void otest(...) { + long slength; + some_memcpy(&buf + bufused, slength & otest_s); +} +int f, finish_root_table_fli2_1; +static void finish_root_table(char *lastname) { + for (;;) + if (finish_root_table_fli2_1) + otest(f, lastname); +} +void write_roots() { finish_root_table(""); } diff --git a/gcc/testsuite/gcc.dg/ipa/pr118097.c b/gcc/testsuite/gcc.dg/ipa/pr118097.c new file mode 100644 index 00000000000..772e83f3bf4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/pr118097.c @@ -0,0 +1,23 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fno-inline" } */ + +int a, b, c, *d = &a; +long e; +static long am (long f, int g) { + return g == 0 || f == 1 && g == 1 ?: f / g; +} +static void aq (unsigned f) +{ + c ^= e = am(~f, 1); + b = 7 - (e >= 1) - 33; + *d = b; +} + +int main() { + // am(1, 1); + aq(1); + if (a == 0xffffffffffffffe5) + ; + else + __builtin_abort(); +} diff --git a/gcc/testsuite/gcc.dg/ipa/pr118535.c b/gcc/testsuite/gcc.dg/ipa/pr118535.c new file mode 100644 index 00000000000..960ba4a5db2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/pr118535.c @@ -0,0 +1,17 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +int a, b, c, d, e, f, *g = &b; +static int h(int i) { return i < 0 || i > a ? 0 : i << a; } +static int j(unsigned short i) { + f = d == e; + *g = h(65535 ^ i); + return c; +} +int main() { + j(0); + h(0); + if (b != 0) + __builtin_abort(); + return 0; +} -- 2.47.1