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;

Reply via email to