https://gcc.gnu.org/g:d81e24bbb930e238305c42f1c1251947e1b35b6a
commit r16-3928-gd81e24bbb930e238305c42f1c1251947e1b35b6a Author: Eric Botcazou <ebotca...@adacore.com> Date: Wed Sep 17 11:31:17 2025 +0200 Preserve TREE_THIS_NOTRAP during inlining in more cases For parameters passed by reference, the Ada compiler sets TREE_THIS_NOTRAP on their dereference to prevent tree_could_trap_p from returning true and then causing a new basic block to be created for every access to them, given that in Ada the -fnon-call-exceptions flag is enabled by default. However, when the subprogram is inlined, this TREE_THIS_NOTRAP flag cannot be blindly preserved because the call may pass the dereference of a pointer as the argument: even if the compiler generates a check that the pointer is not null just before, preserving TREE_THIS_NOTRAP could cause an access to be hoisted before the check; therefore it gets cleared for parameters. Now that's suboptimal if the argument is a full object because accessing it through the dereference of the parameter cannot trap, which causes MEM_REFs of the form MEM_REF [&DECL] to be considered as trapping in the case where the nominal subtype of DECL is self-referential. gcc/ * tree-inline.cc (maybe_copy_this_notrap): New function. Also copy the TREE_THIS_NOTRAP flag for parameters when the argument is a full object and the parameter's type is self-referential. (remap_gimple_op_r): Call maybe_copy_this_notrap. (copy_tree_body_r): Likewise. Diff: --- gcc/tree-inline.cc | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc index 08e642178ba5..428cf55a2255 100644 --- a/gcc/tree-inline.cc +++ b/gcc/tree-inline.cc @@ -986,6 +986,30 @@ is_parm (tree decl) return (TREE_CODE (decl) == PARM_DECL); } +/* Copy the TREE_THIS_NOTRAP flag from OLD to T if it is appropriate to do so. + T and OLD must be both either INDIRECT_REF or MEM_REF. */ + +static void +maybe_copy_this_notrap (copy_body_data *id, tree t, tree old) +{ + gcc_assert (TREE_CODE (t) == TREE_CODE (old)); + + /* We cannot blindly propagate the TREE_THIS_NOTRAP flag if we have remapped + a parameter as the property might be valid only for the parameter itself, + typically when it is passed by reference. But we propagate the flag when + this is the dereference of an entire object done in a type that has self- + referential size, to avoid the static size check in tree_could_trap_p. */ + if (TREE_THIS_NOTRAP (old) + && (!is_parm (TREE_OPERAND (old, 0)) + || (!id->transform_parameter && is_parm (TREE_OPERAND (t, 0))) + || ((TREE_CODE (t) == INDIRECT_REF + || integer_zerop (TREE_OPERAND (t, 1))) + && TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR + && DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0)) + && type_contains_placeholder_p (TREE_TYPE (t))))) + TREE_THIS_NOTRAP (t) = 1; +} + /* Remap the dependence CLIQUE from the source to the destination function as specified in ID. */ @@ -1118,13 +1142,7 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data) = remap_dependence_clique (id, MR_DEPENDENCE_CLIQUE (old)); MR_DEPENDENCE_BASE (*tp) = MR_DEPENDENCE_BASE (old); } - /* We cannot propagate the TREE_THIS_NOTRAP flag if we have - remapped a parameter as the property might be valid only - for the parameter itself. */ - if (TREE_THIS_NOTRAP (old) - && (!is_parm (TREE_OPERAND (old, 0)) - || (!id->transform_parameter && is_parm (ptr)))) - TREE_THIS_NOTRAP (*tp) = 1; + maybe_copy_this_notrap (id, *tp, old); REF_REVERSE_STORAGE_ORDER (*tp) = REF_REVERSE_STORAGE_ORDER (old); *walk_subtrees = 0; return NULL; @@ -1352,13 +1370,7 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data) TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old); TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old); TREE_READONLY (*tp) = TREE_READONLY (old); - /* We cannot propagate the TREE_THIS_NOTRAP flag if we - have remapped a parameter as the property might be - valid only for the parameter itself. */ - if (TREE_THIS_NOTRAP (old) - && (!is_parm (TREE_OPERAND (old, 0)) - || (!id->transform_parameter && is_parm (ptr)))) - TREE_THIS_NOTRAP (*tp) = 1; + maybe_copy_this_notrap (id, *tp, old); } } *walk_subtrees = 0; @@ -1384,13 +1396,7 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data) = remap_dependence_clique (id, MR_DEPENDENCE_CLIQUE (old)); MR_DEPENDENCE_BASE (*tp) = MR_DEPENDENCE_BASE (old); } - /* We cannot propagate the TREE_THIS_NOTRAP flag if we have - remapped a parameter as the property might be valid only - for the parameter itself. */ - if (TREE_THIS_NOTRAP (old) - && (!is_parm (TREE_OPERAND (old, 0)) - || (!id->transform_parameter && is_parm (ptr)))) - TREE_THIS_NOTRAP (*tp) = 1; + maybe_copy_this_notrap (id, *tp, old); REF_REVERSE_STORAGE_ORDER (*tp) = REF_REVERSE_STORAGE_ORDER (old); *walk_subtrees = 0; return NULL;