ipa: Type-convert constants in jump functions during inlining (PR124777)
Checks
| Context |
Check |
Description |
| linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Build passed
|
Commit Message
Hi,
PR 124777 revealed that update_jump_functions_after_inlining does not
properly fold_convert constants when it propagates them from constant
jump functions to formerly pass-through ones, leading to expectations
of wrong constants in parameters leading to inserting bogus
builtin_unreachables during inlining.
This patch fixes it by calling ipacp_value_safe_for_type which is what
IPA-CP uses during its propagation and moved handling of the case to a
separate function.
Bootstrapped and LTO-bootstrapped and tested on x86_64-linux. OK for
master?
Thanks,
Martin
gcc/ChangeLog:
2026-04-07 Martin Jambor <mjambor@suse.cz>
PR ipa/124777
* ipa-cp.h (ipacp_value_safe_for_type): Declare.
* ipa-cp.cc (ipacp_value_safe_for_type): Make public.
* ipa-prop.cc (ipa_set_jf_cst_copy): Fix comment.
(ipa_convert_prop_cst_jf): New function.
(update_jump_functions_after_inlining): Handle the constant to
pass-through case by calling ipa_convert_prop_cst_jf.
gcc/testsuite/ChangeLog:
2026-04-07 Martin Jambor <mjambor@suse.cz>
PR ipa/124777
* gcc.dg/ipa/pr124777.c: New test.
---
gcc/ipa-cp.cc | 2 +-
gcc/ipa-cp.h | 1 +
gcc/ipa-prop.cc | 44 +++++++++++++++++++++++------
gcc/testsuite/gcc.dg/ipa/pr124777.c | 38 +++++++++++++++++++++++++
4 files changed, 75 insertions(+), 10 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/ipa/pr124777.c
@@ -1544,7 +1544,7 @@ initialize_node_lattices (struct cgraph_node *node)
propagated to a parameter of type PARAM_TYPE, or return a fold-converted
VALUE to PARAM_TYPE if that is possible. Return NULL_TREE otherwise. */
-static tree
+tree
ipacp_value_safe_for_type (tree param_type, tree value)
{
if (!value)
@@ -323,6 +323,7 @@ bool ipa_vr_operation_and_type_effects (vrange &dst_vr,
const ipa_vr &src_vr,
enum tree_code operation,
tree dst_type, tree src_type);
+tree ipacp_value_safe_for_type (tree param_type, tree value);
@@ -680,8 +680,8 @@ ipa_set_jf_unknown (struct ipa_jump_func *jfunc)
jfunc->type = IPA_JF_UNKNOWN;
}
-/* Set JFUNC to be a copy of another jmp (to be used by jump function
- combination code). The two functions will share their rdesc. */
+/* Set DST to be a copy of another SRC. The two functions will share their
+ rdesc. */
static void
ipa_set_jf_cst_copy (struct ipa_jump_func *dst,
@@ -693,6 +693,36 @@ ipa_set_jf_cst_copy (struct ipa_jump_func *dst,
dst->value.constant = src->value.constant;
}
+/* Set DST to be a copy of another jump function SRC but possibly adjust it to
+ a new passed type PARM_TYPE. If the adjustment fails, the jump function can
+ end up being set to the unknown type. If the conversion is not necessary or
+ it succeeds and if the destination rdesc has not been already used, the two
+ functions will share their rdesc. */
+
+static void
+ipa_convert_prop_cst_jf (struct ipa_jump_func *dst,
+ struct ipa_jump_func *src,
+ tree parm_type)
+
+{
+ gcc_checking_assert (src->type == IPA_JF_CONST);
+ tree new_val = ipacp_value_safe_for_type (parm_type,
+ ipa_get_jf_constant (src));
+ if (new_val)
+ {
+ bool rd = ipa_get_jf_pass_through_refdesc_decremented (dst);
+
+ dst->type = IPA_JF_CONST;
+ dst->value.constant.value = new_val;
+ if (!rd)
+ dst->value.constant.rdesc = src->value.constant.rdesc;
+ else
+ ipa_zap_jf_refdesc (dst);
+ }
+ else
+ ipa_set_jf_unknown (dst);
+}
+
/* Set JFUNC to be a constant jmp function. */
static void
@@ -3863,13 +3893,9 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
ipa_set_jf_unknown (dst);
break;
case IPA_JF_CONST:
- {
- bool rd = ipa_get_jf_pass_through_refdesc_decremented (dst);
- ipa_set_jf_cst_copy (dst, src);
- if (rd)
- ipa_zap_jf_refdesc (dst);
- }
-
+ ipa_convert_prop_cst_jf (dst, src,
+ ipa_get_type (old_inline_root_info,
+ dst_fid));
break;
case IPA_JF_PASS_THROUGH:
new file mode 100644
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-early-inlining" } */
+
+int a;
+char b;
+void c() {
+ __builtin_exit(0);
+}
+
+typedef short (*t_d)(unsigned);
+
+static short __attribute__((noclone))
+d(unsigned f)
+{
+ if (f == (unsigned)(unsigned short)-1)
+ c ();
+ for (; a; a++)
+ ;
+}
+
+typedef short (*t_g)(unsigned, unsigned, unsigned short, t_d);
+
+static short __attribute__((noclone))
+g(unsigned f, unsigned h, unsigned short i, t_d p_d) {
+ if (f || h)
+ p_d(i);
+}
+
+static unsigned __attribute__((noclone))
+j(unsigned f, signed char h, t_d p_d, t_g p_g) {
+ p_g(b, 1, h, p_d);
+}
+
+int main() {
+ signed char e = -1;
+ j(0, e, d, g);
+ return 0;
+}