Hi,
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 the TREE_THIS_NOTRAP flag could cause an access
to be hoisted before the check; therefore it gets cleared for parameters.
Now that's suboptimal if the argument is an object (DECL_P) 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.
Bootstrapped/regtested on x86-64/Linux, OK for the mainline?
2025-09-15 Eric Botcazou <ebotca...@adacore.com>
* tree-inline.cc (maybe_copy_this_notrap): New function. Copy the
TREE_THIS_NOTRAP flag for parameters if the argument is DECL_P.
(remap_gimple_op_r): Call maybe_copy_this_notrap.
(copy_tree_body_r): Likewise.
--
Eric Botcazou
diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc
index 08e642178ba..7555137420a 100644
--- a/gcc/tree-inline.cc
+++ b/gcc/tree-inline.cc
@@ -986,6 +986,26 @@ 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 can propagate the flag
+ if we know that the new pointer designates an object. */
+ if (TREE_THIS_NOTRAP (old)
+ && (!is_parm (TREE_OPERAND (old, 0))
+ || (!id->transform_parameter && is_parm (TREE_OPERAND (t, 0)))
+ || (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
+ && DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))))
+ TREE_THIS_NOTRAP (t) = 1;
+}
+
/* Remap the dependence CLIQUE from the source to the destination function
as specified in ID. */
@@ -1118,13 +1138,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 +1366,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 +1392,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;