]> gcc.gnu.org Git - gcc.git/commitdiff
[Ada] Avoid copy operation for returns involving function calls
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 12 Apr 2022 21:34:48 +0000 (23:34 +0200)
committerPierre-Marie de Rodat <derodat@adacore.com>
Thu, 19 May 2022 14:05:33 +0000 (14:05 +0000)
gcc/ada/

* gcc-interface/decl.cc (gnat_to_gnu_entity) <E_Constant>: Deal with
a constant related to a return in a function specially.
* gcc-interface/trans.cc (Call_to_gnu): Use return slot optimization
if the target is a return object.
(gnat_to_gnu) <N_Object_Declaration>: Deal with a constant related
to a return in a function specially.

gcc/ada/gcc-interface/decl.cc
gcc/ada/gcc-interface/trans.cc

index 2d9b41f984c4895011207ea2ba1a0c270ef35dfc..50d17f755622f9866deae72939a38cff4dff3849 100644 (file)
@@ -630,6 +630,17 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
       break;
 
     case E_Constant:
+      /* If this is a constant related to a return in a function returning by
+        invisible reference without expression, get the return object.  */
+      if (Is_Related_To_Func_Return (gnat_entity)
+         && current_function_decl
+         && TREE_ADDRESSABLE (TREE_TYPE (current_function_decl))
+         && !gnu_expr)
+       {
+         gnu_decl = DECL_RESULT (current_function_decl);
+         break;
+       }
+
       /* Ignore constant definitions already marked with the error node.  See
         the N_Object_Declaration case of gnat_to_gnu for the rationale.  */
       if (definition
index 3e8842f4a92ba331bb887389b3b8e74e9b8524ed..e80200ee46abb564c394a8c0483906f680cef24e 100644 (file)
@@ -5281,6 +5281,15 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
                   && return_slot_opt_for_pure_call_p (gnu_target, gnu_call))
            op_code = INIT_EXPR;
 
+         /* If this is the initialization of a return object in a function
+            returning by invisible reference, we can always use the return
+            slot optimization.  */
+         else if (TREE_CODE (gnu_target) == INDIRECT_REF
+                  && TREE_CODE (TREE_OPERAND (gnu_target, 0)) == RESULT_DECL
+                  && current_function_decl
+                  && TREE_ADDRESSABLE (TREE_TYPE (current_function_decl)))
+           op_code = INIT_EXPR;
+
          else
            op_code = MODIFY_EXPR;
 
@@ -6380,6 +6389,39 @@ gnat_to_gnu (Node_Id gnat_node)
              || Is_Concurrent_Type (Etype (gnat_temp))))
        break;
 
+      /* If this is a constant related to a return initialized by a reference
+        to a function call in a function returning by invisible reference:
+
+          type Ann is access all Result_Type;
+          Rnn : constant Ann := Func'reference;
+          [...]
+          return Rnn.all;
+
+        then elide the temporary by forwarding the return object to Func:
+
+          *<retval> = Func (); [return slot optimization]
+          [...]
+          return <retval>;
+
+        That's necessary if the result type needs finalization because the
+        temporary would never be adjusted as Expand_Simple_Function_Return
+        also elides the temporary in this case.  */
+      if (Ekind (gnat_temp) == E_Constant
+         && Is_Related_To_Func_Return (gnat_temp)
+         && Nkind (Expression (gnat_node)) == N_Reference
+         && Nkind (Prefix (Expression (gnat_node))) == N_Function_Call
+         && current_function_decl
+         && TREE_ADDRESSABLE (TREE_TYPE (current_function_decl)))
+       {
+         gnu_result = gnat_to_gnu_entity (gnat_temp, NULL_TREE, true);
+         gnu_result = build_unary_op (INDIRECT_REF, NULL_TREE, gnu_result);
+         gnu_result
+           = Call_to_gnu (Prefix (Expression (gnat_node)),
+                          &gnu_result_type, gnu_result,
+                          NOT_ATOMIC, false);
+         break;
+       }
+
       if (Present (Expression (gnat_node))
          && !(kind == N_Object_Declaration && No_Initialization (gnat_node))
          && (!type_annotate_only
This page took 0.078891 seconds and 5 git commands to generate.