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;

Reply via email to