This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Extend return by invisible reference mechanism


Hi,

in http://gcc.gnu.org/ml/gcc-patches/2006-06/msg01330.html Olivier submitted a 
patch to make it possible to force return by invisible reference, by setting 
DECL_BY_REFERENCE on the DECL_RESULT of the called function.  This works fine 
for direct calls, but there is no DECL_RESULT at hand for indirect calls.

As we would need to extend this mechanism to indirect calls, I'm proposing to 
replace it with a flag on the FUNCTION_TYPE instead, namely TREE_ADDRESSABLE.
This is modelled on the regular way of setting return by invisible reference, 
which is to set TREE_ADDRESSABLE on the return TYPE of the FUNCTION_TYPE.  As 
explained by Olivier, setting TREE_ADDRESSABLE on the return TYPE has other 
consequences that we don't necessarily want in Ada, hence this weaker form.

Tested on x86_64-suse-linux (in conjunction with the associated gigi patch).

The calls.c change is actually a no-op: if you pass a FUNCTION_DECL as fntype 
to aggregate_value_p, it will just reset fntype to its TREE_TYPE.

The gimplify.c change is slightly unrelated, but needed for the gigi patch.
It makes it possible to use the CALL_EXPR_RETURN_SLOT_OPTimization for calls 
to functions returning a type with non-fixed size, if the front-end thinks it 
is safe to do so.

All this stuff should only affect the Ada compiler.  OK for mainline?


2010-04-07  Eric Botcazou  <ebotcazou@adacore.com>

	* tree.h (TREE_ADDRESSABLE): Document its effect for function types.
	* calls.c (expand_call): Pass the function type to aggregate_value_p.
	* function.c (aggregate_value_p): Do not honor DECL_BY_REFERENCE on
	the target function of a CALL_EXPR.  Honor TREE_ADDRESSABLE on the
	function type instead.

	* gimplify.c (gimplify_modify_expr_rhs) <WITH_SIZE_EXPR>: New case.


-- 
Eric Botcazou
Index: tree.h
===================================================================
--- tree.h	(revision 157983)
+++ tree.h	(working copy)
@@ -1110,9 +1110,10 @@ extern void omp_clause_range_check_faile
    In CONSTRUCTOR nodes, it means object constructed must be in memory.
    In LABEL_DECL nodes, it means a goto for this label has been seen
    from a place outside all binding contours that restore stack levels.
-   In ..._TYPE nodes, it means that objects of this type must
-   be fully addressable.  This means that pieces of this
-   object cannot go into register parameters, for example.
+   In ..._TYPE nodes, it means that objects of this type must be fully
+   addressable.  This means that pieces of this object cannot go into
+   register parameters, for example.  If this a function type, this
+   means that the value must be returned in memory.
    In IDENTIFIER_NODEs, this means that some extern decl for this name
    had its address taken.  That matters for inline functions.  */
 #define TREE_ADDRESSABLE(NODE) ((NODE)->base.addressable_flag)
Index: function.c
===================================================================
--- function.c	(revision 157983)
+++ function.c	(working copy)
@@ -1857,11 +1857,7 @@ aggregate_value_p (const_tree exp, const
   rtx reg;
 
   const_tree type = (TYPE_P (exp)) ? exp : TREE_TYPE (exp);
-
-  /* DECL node associated with FNTYPE when relevant, which we might need to
-     check for by-invisible-reference returns, typically for CALL_EXPR input
-     EXPressions.  */
-  const_tree fndecl = NULL_TREE;
+  const_tree fndecl;
 
   if (fntype)
     switch (TREE_CODE (fntype))
@@ -1880,7 +1876,7 @@ aggregate_value_p (const_tree exp, const
       case METHOD_TYPE:
         break;
       case IDENTIFIER_NODE:
-	fntype = 0;
+	fntype = NULL_TREE;
 	break;
       default:
 	/* We don't expect other rtl types here.  */
@@ -1901,24 +1897,21 @@ aggregate_value_p (const_tree exp, const
       && DECL_BY_REFERENCE (exp))
     return 1;
 
-  /* If the EXPression is a CALL_EXPR, honor DECL_BY_REFERENCE set on the
-     called function RESULT_DECL, meaning the function returns in memory by
-     invisible reference.  This check lets front-ends not set TREE_ADDRESSABLE
-     on the function type, which used to be the way to request such a return
-     mechanism but might now be causing troubles at gimplification time if
-     temporaries with the function type need to be created.  */
-  if (TREE_CODE (exp) == CALL_EXPR && fndecl && DECL_RESULT (fndecl)
-      && DECL_BY_REFERENCE (DECL_RESULT (fndecl)))
+  /* Function types that are TREE_ADDRESSABLE force return in memory.  */
+  if (fntype && TREE_ADDRESSABLE (fntype))
     return 1;
 
-  if (targetm.calls.return_in_memory (type, fntype))
-    return 1;
   /* Types that are TREE_ADDRESSABLE must be constructed in memory,
      and thus can't be returned in registers.  */
   if (TREE_ADDRESSABLE (type))
     return 1;
+
   if (flag_pcc_struct_return && AGGREGATE_TYPE_P (type))
     return 1;
+
+  if (targetm.calls.return_in_memory (type, fntype))
+    return 1;
+
   /* Make sure we have suitable call-clobbered regs to return
      the value in; if not, we must return it in memory.  */
   reg = hard_function_value (type, 0, fntype, 0);
Index: gimplify.c
===================================================================
--- gimplify.c	(revision 157983)
+++ gimplify.c	(working copy)
@@ -4278,6 +4278,18 @@ gimplify_modify_expr_rhs (tree *expr_p,
 	ret = GS_UNHANDLED;
 	break;
 
+      case WITH_SIZE_EXPR:
+	/* Likewise for calls that return an aggregate of non-constant size,
+	   since we would not be able to generate a temporary at all.  */
+	if (TREE_CODE (TREE_OPERAND (*from_p, 0)) == CALL_EXPR)
+	  {
+	    *from_p = TREE_OPERAND (*from_p, 0);
+	    ret = GS_OK;
+	  }
+	else
+	  ret = GS_UNHANDLED;
+	break;
+
 	/* If we're initializing from a container, push the initialization
 	   inside it.  */
       case CLEANUP_POINT_EXPR:
Index: calls.c
===================================================================
--- calls.c	(revision 157983)
+++ calls.c	(working copy)
@@ -2089,7 +2089,7 @@ expand_call (tree exp, rtx target, int i
   /* Set up a place to return a structure.  */
 
   /* Cater to broken compilers.  */
-  if (aggregate_value_p (exp, (!fndecl ? fntype : fndecl)))
+  if (aggregate_value_p (exp, fntype))
     {
       /* This call returns a big structure.  */
       flags &= ~(ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]