summaryrefslogtreecommitdiffstats
path: root/gcc
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2022-04-12 23:34:48 +0200
committerPierre-Marie de Rodat <derodat@adacore.com>2022-05-19 14:05:33 +0000
commit9aa9ba95ea3d4800974135da85fd4d9cd310b69e (patch)
treeeba33c668f8d7fc1dd87ab2a9d8e80c1c1cd40b7 /gcc
parent[Ada] Do not give warnings for compiler-generated entities by default (diff)
downloadgcc-9aa9ba95ea3d4800974135da85fd4d9cd310b69e.tar.gz
gcc-9aa9ba95ea3d4800974135da85fd4d9cd310b69e.tar.bz2
gcc-9aa9ba95ea3d4800974135da85fd4d9cd310b69e.tar.xz
[Ada] Avoid copy operation for returns involving function calls
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ada/gcc-interface/decl.cc11
-rw-r--r--gcc/ada/gcc-interface/trans.cc42
2 files changed, 53 insertions, 0 deletions
diff --git a/gcc/ada/gcc-interface/decl.cc b/gcc/ada/gcc-interface/decl.cc
index 2d9b41f984c..50d17f75562 100644
--- a/gcc/ada/gcc-interface/decl.cc
+++ b/gcc/ada/gcc-interface/decl.cc
@@ -630,6 +630,17 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
630 break; 630 break;
631 631
632 case E_Constant: 632 case E_Constant:
633 /* If this is a constant related to a return in a function returning by
634 invisible reference without expression, get the return object. */
635 if (Is_Related_To_Func_Return (gnat_entity)
636 && current_function_decl
637 && TREE_ADDRESSABLE (TREE_TYPE (current_function_decl))
638 && !gnu_expr)
639 {
640 gnu_decl = DECL_RESULT (current_function_decl);
641 break;
642 }
643
633 /* Ignore constant definitions already marked with the error node. See 644 /* Ignore constant definitions already marked with the error node. See
634 the N_Object_Declaration case of gnat_to_gnu for the rationale. */ 645 the N_Object_Declaration case of gnat_to_gnu for the rationale. */
635 if (definition 646 if (definition
diff --git a/gcc/ada/gcc-interface/trans.cc b/gcc/ada/gcc-interface/trans.cc
index 3e8842f4a92..e80200ee46a 100644
--- a/gcc/ada/gcc-interface/trans.cc
+++ b/gcc/ada/gcc-interface/trans.cc
@@ -5281,6 +5281,15 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
5281 && return_slot_opt_for_pure_call_p (gnu_target, gnu_call)) 5281 && return_slot_opt_for_pure_call_p (gnu_target, gnu_call))
5282 op_code = INIT_EXPR; 5282 op_code = INIT_EXPR;
5283 5283
5284 /* If this is the initialization of a return object in a function
5285 returning by invisible reference, we can always use the return
5286 slot optimization. */
5287 else if (TREE_CODE (gnu_target) == INDIRECT_REF
5288 && TREE_CODE (TREE_OPERAND (gnu_target, 0)) == RESULT_DECL
5289 && current_function_decl
5290 && TREE_ADDRESSABLE (TREE_TYPE (current_function_decl)))
5291 op_code = INIT_EXPR;
5292
5284 else 5293 else
5285 op_code = MODIFY_EXPR; 5294 op_code = MODIFY_EXPR;
5286 5295
@@ -6380,6 +6389,39 @@ gnat_to_gnu (Node_Id gnat_node)
6380 || Is_Concurrent_Type (Etype (gnat_temp)))) 6389 || Is_Concurrent_Type (Etype (gnat_temp))))
6381 break; 6390 break;
6382 6391
6392 /* If this is a constant related to a return initialized by a reference
6393 to a function call in a function returning by invisible reference:
6394
6395 type Ann is access all Result_Type;
6396 Rnn : constant Ann := Func'reference;
6397 [...]
6398 return Rnn.all;
6399
6400 then elide the temporary by forwarding the return object to Func:
6401
6402 *<retval> = Func (); [return slot optimization]
6403 [...]
6404 return <retval>;
6405
6406 That's necessary if the result type needs finalization because the
6407 temporary would never be adjusted as Expand_Simple_Function_Return
6408 also elides the temporary in this case. */
6409 if (Ekind (gnat_temp) == E_Constant
6410 && Is_Related_To_Func_Return (gnat_temp)
6411 && Nkind (Expression (gnat_node)) == N_Reference
6412 && Nkind (Prefix (Expression (gnat_node))) == N_Function_Call
6413 && current_function_decl
6414 && TREE_ADDRESSABLE (TREE_TYPE (current_function_decl)))
6415 {
6416 gnu_result = gnat_to_gnu_entity (gnat_temp, NULL_TREE, true);
6417 gnu_result = build_unary_op (INDIRECT_REF, NULL_TREE, gnu_result);
6418 gnu_result
6419 = Call_to_gnu (Prefix (Expression (gnat_node)),
6420 &gnu_result_type, gnu_result,
6421 NOT_ATOMIC, false);
6422 break;
6423 }
6424
6383 if (Present (Expression (gnat_node)) 6425 if (Present (Expression (gnat_node))
6384 && !(kind == N_Object_Declaration && No_Initialization (gnat_node)) 6426 && !(kind == N_Object_Declaration && No_Initialization (gnat_node))
6385 && (!type_annotate_only 6427 && (!type_annotate_only