1 /* Manipulation of formal and actual parameters of functions and function
3 Copyright (C) 2017 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
30 #include "fold-const.h"
31 #include "stor-layout.h"
33 #include "gimple-iterator.h"
34 #include "gimplify-me.h"
36 #include "ipa-param-manipulation.h"
37 #include "print-tree.h"
38 #include "gimple-pretty-print.h"
41 /* Return a heap allocated vector containing formal parameters of FNDECL. */
44 ipa_get_vector_of_formal_parms (tree fndecl
)
50 gcc_assert (!flag_wpa
);
52 for (parm
= DECL_ARGUMENTS (fndecl
); parm
; parm
= DECL_CHAIN (parm
))
56 for (parm
= DECL_ARGUMENTS (fndecl
); parm
; parm
= DECL_CHAIN (parm
))
57 args
.quick_push (parm
);
62 /* Return a heap allocated vector containing types of formal parameters of
63 function type FNTYPE. */
66 ipa_get_vector_of_formal_parm_types (tree fntype
)
72 for (t
= TYPE_ARG_TYPES (fntype
); t
; t
= TREE_CHAIN (t
))
76 for (t
= TYPE_ARG_TYPES (fntype
); t
; t
= TREE_CHAIN (t
))
77 types
.quick_push (TREE_VALUE (t
));
82 /* Modify the function declaration FNDECL and its type according to the plan in
83 ADJUSTMENTS. It also sets base fields of individual adjustments structures
84 to reflect the actual parameters being modified which are determined by the
88 ipa_modify_formal_parameters (tree fndecl
, ipa_parm_adjustment_vec adjustments
)
90 vec
<tree
> oparms
= ipa_get_vector_of_formal_parms (fndecl
);
91 tree orig_type
= TREE_TYPE (fndecl
);
92 tree old_arg_types
= TYPE_ARG_TYPES (orig_type
);
94 /* The following test is an ugly hack, some functions simply don't have any
95 arguments in their type. This is probably a bug but well... */
96 bool care_for_types
= (old_arg_types
!= NULL_TREE
);
101 last_parm_void
= (TREE_VALUE (tree_last (old_arg_types
))
103 otypes
= ipa_get_vector_of_formal_parm_types (orig_type
);
105 gcc_assert (oparms
.length () + 1 == otypes
.length ());
107 gcc_assert (oparms
.length () == otypes
.length ());
111 last_parm_void
= false;
115 int len
= adjustments
.length ();
116 tree
*link
= &DECL_ARGUMENTS (fndecl
);
117 tree new_arg_types
= NULL
;
118 for (int i
= 0; i
< len
; i
++)
120 struct ipa_parm_adjustment
*adj
;
123 adj
= &adjustments
[i
];
125 if (adj
->op
== IPA_PARM_OP_NEW
)
128 parm
= oparms
[adj
->base_index
];
131 if (adj
->op
== IPA_PARM_OP_COPY
)
134 new_arg_types
= tree_cons (NULL_TREE
, otypes
[adj
->base_index
],
137 link
= &DECL_CHAIN (parm
);
139 else if (adj
->op
!= IPA_PARM_OP_REMOVE
)
145 ptype
= build_pointer_type (adj
->type
);
149 if (is_gimple_reg_type (ptype
)
150 && TYPE_MODE (ptype
) != BLKmode
)
152 unsigned malign
= GET_MODE_ALIGNMENT (TYPE_MODE (ptype
));
153 if (TYPE_ALIGN (ptype
) != malign
)
154 ptype
= build_aligned_type (ptype
, malign
);
159 new_arg_types
= tree_cons (NULL_TREE
, ptype
, new_arg_types
);
161 new_parm
= build_decl (UNKNOWN_LOCATION
, PARM_DECL
, NULL_TREE
,
163 const char *prefix
= adj
->arg_prefix
? adj
->arg_prefix
: "SYNTH";
164 DECL_NAME (new_parm
) = create_tmp_var_name (prefix
);
165 DECL_ARTIFICIAL (new_parm
) = 1;
166 DECL_ARG_TYPE (new_parm
) = ptype
;
167 DECL_CONTEXT (new_parm
) = fndecl
;
168 TREE_USED (new_parm
) = 1;
169 DECL_IGNORED_P (new_parm
) = 1;
170 layout_decl (new_parm
, 0);
172 if (adj
->op
== IPA_PARM_OP_NEW
)
176 adj
->new_decl
= new_parm
;
179 link
= &DECL_CHAIN (new_parm
);
185 tree new_reversed
= NULL
;
188 new_reversed
= nreverse (new_arg_types
);
192 TREE_CHAIN (new_arg_types
) = void_list_node
;
194 new_reversed
= void_list_node
;
198 /* Use copy_node to preserve as much as possible from original type
199 (debug info, attribute lists etc.)
200 Exception is METHOD_TYPEs must have THIS argument.
201 When we are asked to remove it, we need to build new FUNCTION_TYPE
203 tree new_type
= NULL
;
204 if (TREE_CODE (orig_type
) != METHOD_TYPE
205 || (adjustments
[0].op
== IPA_PARM_OP_COPY
206 && adjustments
[0].base_index
== 0))
208 new_type
= build_distinct_type_copy (orig_type
);
209 TYPE_ARG_TYPES (new_type
) = new_reversed
;
214 = build_distinct_type_copy (build_function_type (TREE_TYPE (orig_type
),
216 TYPE_CONTEXT (new_type
) = TYPE_CONTEXT (orig_type
);
217 DECL_VINDEX (fndecl
) = NULL_TREE
;
220 /* When signature changes, we need to clear builtin info. */
221 if (DECL_BUILT_IN (fndecl
))
223 DECL_BUILT_IN_CLASS (fndecl
) = NOT_BUILT_IN
;
224 DECL_FUNCTION_CODE (fndecl
) = (enum built_in_function
) 0;
227 TREE_TYPE (fndecl
) = new_type
;
228 DECL_VIRTUAL_P (fndecl
) = 0;
229 DECL_LANG_SPECIFIC (fndecl
) = NULL
;
234 /* Modify actual arguments of a function call CS as indicated in ADJUSTMENTS.
235 If this is a directly recursive call, CS must be NULL. Otherwise it must
236 contain the corresponding call graph edge. */
239 ipa_modify_call_arguments (struct cgraph_edge
*cs
, gcall
*stmt
,
240 ipa_parm_adjustment_vec adjustments
)
242 struct cgraph_node
*current_node
= cgraph_node::get (current_function_decl
);
244 vec
<tree
, va_gc
> **debug_args
= NULL
;
246 gimple_stmt_iterator gsi
, prev_gsi
;
250 len
= adjustments
.length ();
252 callee_decl
= !cs
? gimple_call_fndecl (stmt
) : cs
->callee
->decl
;
253 current_node
->remove_stmt_references (stmt
);
255 gsi
= gsi_for_stmt (stmt
);
257 gsi_prev (&prev_gsi
);
258 for (i
= 0; i
< len
; i
++)
260 struct ipa_parm_adjustment
*adj
;
262 adj
= &adjustments
[i
];
264 if (adj
->op
== IPA_PARM_OP_COPY
)
266 tree arg
= gimple_call_arg (stmt
, adj
->base_index
);
268 vargs
.quick_push (arg
);
270 else if (adj
->op
!= IPA_PARM_OP_REMOVE
)
272 tree expr
, base
, off
;
274 unsigned int deref_align
= 0;
275 bool deref_base
= false;
277 /* We create a new parameter out of the value of the old one, we can
278 do the following kind of transformations:
280 - A scalar passed by reference is converted to a scalar passed by
281 value. (adj->by_ref is false and the type of the original
282 actual argument is a pointer to a scalar).
284 - A part of an aggregate is passed instead of the whole aggregate.
285 The part can be passed either by value or by reference, this is
286 determined by value of adj->by_ref. Moreover, the code below
287 handles both situations when the original aggregate is passed by
288 value (its type is not a pointer) and when it is passed by
289 reference (it is a pointer to an aggregate).
291 When the new argument is passed by reference (adj->by_ref is true)
292 it must be a part of an aggregate and therefore we form it by
293 simply taking the address of a reference inside the original
296 gcc_checking_assert (adj
->offset
% BITS_PER_UNIT
== 0);
297 base
= gimple_call_arg (stmt
, adj
->base_index
);
298 loc
= DECL_P (base
) ? DECL_SOURCE_LOCATION (base
)
299 : EXPR_LOCATION (base
);
301 if (TREE_CODE (base
) != ADDR_EXPR
302 && POINTER_TYPE_P (TREE_TYPE (base
)))
303 off
= build_int_cst (adj
->alias_ptr_type
,
304 adj
->offset
/ BITS_PER_UNIT
);
307 HOST_WIDE_INT base_offset
;
311 if (TREE_CODE (base
) == ADDR_EXPR
)
313 base
= TREE_OPERAND (base
, 0);
319 base
= get_addr_base_and_unit_offset (base
, &base_offset
);
320 /* Aggregate arguments can have non-invariant addresses. */
323 base
= build_fold_addr_expr (prev_base
);
324 off
= build_int_cst (adj
->alias_ptr_type
,
325 adj
->offset
/ BITS_PER_UNIT
);
327 else if (TREE_CODE (base
) == MEM_REF
)
332 deref_align
= TYPE_ALIGN (TREE_TYPE (base
));
334 off
= build_int_cst (adj
->alias_ptr_type
,
336 + adj
->offset
/ BITS_PER_UNIT
);
337 off
= int_const_binop (PLUS_EXPR
, TREE_OPERAND (base
, 1),
339 base
= TREE_OPERAND (base
, 0);
343 off
= build_int_cst (adj
->alias_ptr_type
,
345 + adj
->offset
/ BITS_PER_UNIT
);
346 base
= build_fold_addr_expr (base
);
352 tree type
= adj
->type
;
354 unsigned HOST_WIDE_INT misalign
;
363 get_pointer_alignment_1 (base
, &align
, &misalign
);
364 if (TYPE_ALIGN (type
) > align
)
365 align
= TYPE_ALIGN (type
);
367 misalign
+= (offset_int::from (wi::to_wide (off
),
368 SIGNED
).to_short_addr ()
370 misalign
= misalign
& (align
- 1);
372 align
= least_bit_hwi (misalign
);
373 if (align
< TYPE_ALIGN (type
))
374 type
= build_aligned_type (type
, align
);
375 base
= force_gimple_operand_gsi (&gsi
, base
,
376 true, NULL
, true, GSI_SAME_STMT
);
377 expr
= fold_build2_loc (loc
, MEM_REF
, type
, base
, off
);
378 REF_REVERSE_STORAGE_ORDER (expr
) = adj
->reverse
;
379 /* If expr is not a valid gimple call argument emit
380 a load into a temporary. */
381 if (is_gimple_reg_type (TREE_TYPE (expr
)))
383 gimple
*tem
= gimple_build_assign (NULL_TREE
, expr
);
384 if (gimple_in_ssa_p (cfun
))
386 gimple_set_vuse (tem
, gimple_vuse (stmt
));
387 expr
= make_ssa_name (TREE_TYPE (expr
), tem
);
390 expr
= create_tmp_reg (TREE_TYPE (expr
));
391 gimple_assign_set_lhs (tem
, expr
);
392 gsi_insert_before (&gsi
, tem
, GSI_SAME_STMT
);
397 expr
= fold_build2_loc (loc
, MEM_REF
, adj
->type
, base
, off
);
398 REF_REVERSE_STORAGE_ORDER (expr
) = adj
->reverse
;
399 expr
= build_fold_addr_expr (expr
);
400 expr
= force_gimple_operand_gsi (&gsi
, expr
,
401 true, NULL
, true, GSI_SAME_STMT
);
403 vargs
.quick_push (expr
);
405 if (adj
->op
!= IPA_PARM_OP_COPY
&& MAY_HAVE_DEBUG_STMTS
)
408 tree ddecl
= NULL_TREE
, origin
= DECL_ORIGIN (adj
->base
), arg
;
411 arg
= gimple_call_arg (stmt
, adj
->base_index
);
412 if (!useless_type_conversion_p (TREE_TYPE (origin
), TREE_TYPE (arg
)))
414 if (!fold_convertible_p (TREE_TYPE (origin
), arg
))
416 arg
= fold_convert_loc (gimple_location (stmt
),
417 TREE_TYPE (origin
), arg
);
419 if (debug_args
== NULL
)
420 debug_args
= decl_debug_args_insert (callee_decl
);
421 for (ix
= 0; vec_safe_iterate (*debug_args
, ix
, &ddecl
); ix
+= 2)
424 ddecl
= (**debug_args
)[ix
+ 1];
429 ddecl
= make_node (DEBUG_EXPR_DECL
);
430 DECL_ARTIFICIAL (ddecl
) = 1;
431 TREE_TYPE (ddecl
) = TREE_TYPE (origin
);
432 SET_DECL_MODE (ddecl
, DECL_MODE (origin
));
434 vec_safe_push (*debug_args
, origin
);
435 vec_safe_push (*debug_args
, ddecl
);
437 def_temp
= gimple_build_debug_bind (ddecl
, unshare_expr (arg
), stmt
);
438 gsi_insert_before (&gsi
, def_temp
, GSI_SAME_STMT
);
442 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
444 fprintf (dump_file
, "replacing stmt:");
445 print_gimple_stmt (dump_file
, gsi_stmt (gsi
), 0);
448 new_stmt
= gimple_build_call_vec (callee_decl
, vargs
);
450 if (gimple_call_lhs (stmt
))
451 gimple_call_set_lhs (new_stmt
, gimple_call_lhs (stmt
));
453 gimple_set_block (new_stmt
, gimple_block (stmt
));
454 if (gimple_has_location (stmt
))
455 gimple_set_location (new_stmt
, gimple_location (stmt
));
456 gimple_call_set_chain (new_stmt
, gimple_call_chain (stmt
));
457 gimple_call_copy_flags (new_stmt
, stmt
);
458 if (gimple_in_ssa_p (cfun
))
460 gimple_set_vuse (new_stmt
, gimple_vuse (stmt
));
461 if (gimple_vdef (stmt
))
463 gimple_set_vdef (new_stmt
, gimple_vdef (stmt
));
464 SSA_NAME_DEF_STMT (gimple_vdef (new_stmt
)) = new_stmt
;
468 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
470 fprintf (dump_file
, "with stmt:");
471 print_gimple_stmt (dump_file
, new_stmt
, 0);
472 fprintf (dump_file
, "\n");
474 gsi_replace (&gsi
, new_stmt
, true);
476 cs
->set_call_stmt (new_stmt
);
479 current_node
->record_stmt_references (gsi_stmt (gsi
));
482 while (gsi_stmt (gsi
) != gsi_stmt (prev_gsi
));
485 /* Return true iff BASE_INDEX is in ADJUSTMENTS more than once. */
488 index_in_adjustments_multiple_times_p (int base_index
,
489 ipa_parm_adjustment_vec adjustments
)
491 int i
, len
= adjustments
.length ();
494 for (i
= 0; i
< len
; i
++)
496 struct ipa_parm_adjustment
*adj
;
497 adj
= &adjustments
[i
];
499 if (adj
->base_index
== base_index
)
510 /* Return adjustments that should have the same effect on function parameters
511 and call arguments as if they were first changed according to adjustments in
512 INNER and then by adjustments in OUTER. */
514 ipa_parm_adjustment_vec
515 ipa_combine_adjustments (ipa_parm_adjustment_vec inner
,
516 ipa_parm_adjustment_vec outer
)
518 int i
, outlen
= outer
.length ();
519 int inlen
= inner
.length ();
521 ipa_parm_adjustment_vec adjustments
, tmp
;
524 for (i
= 0; i
< inlen
; i
++)
526 struct ipa_parm_adjustment
*n
;
529 if (n
->op
== IPA_PARM_OP_REMOVE
)
533 /* FIXME: Handling of new arguments are not implemented yet. */
534 gcc_assert (n
->op
!= IPA_PARM_OP_NEW
);
539 adjustments
.create (outlen
+ removals
);
540 for (i
= 0; i
< outlen
; i
++)
542 struct ipa_parm_adjustment r
;
543 struct ipa_parm_adjustment
*out
= &outer
[i
];
544 struct ipa_parm_adjustment
*in
= &tmp
[out
->base_index
];
546 memset (&r
, 0, sizeof (r
));
547 gcc_assert (in
->op
!= IPA_PARM_OP_REMOVE
);
548 if (out
->op
== IPA_PARM_OP_REMOVE
)
550 if (!index_in_adjustments_multiple_times_p (in
->base_index
, tmp
))
552 r
.op
= IPA_PARM_OP_REMOVE
;
553 adjustments
.quick_push (r
);
559 /* FIXME: Handling of new arguments are not implemented yet. */
560 gcc_assert (out
->op
!= IPA_PARM_OP_NEW
);
563 r
.base_index
= in
->base_index
;
566 /* FIXME: Create nonlocal value too. */
568 if (in
->op
== IPA_PARM_OP_COPY
&& out
->op
== IPA_PARM_OP_COPY
)
569 r
.op
= IPA_PARM_OP_COPY
;
570 else if (in
->op
== IPA_PARM_OP_COPY
)
571 r
.offset
= out
->offset
;
572 else if (out
->op
== IPA_PARM_OP_COPY
)
573 r
.offset
= in
->offset
;
575 r
.offset
= in
->offset
+ out
->offset
;
576 adjustments
.quick_push (r
);
579 for (i
= 0; i
< inlen
; i
++)
581 struct ipa_parm_adjustment
*n
= &inner
[i
];
583 if (n
->op
== IPA_PARM_OP_REMOVE
)
584 adjustments
.quick_push (*n
);
591 /* If T is an SSA_NAME, return NULL if it is not a default def or
592 return its base variable if it is. If IGNORE_DEFAULT_DEF is true,
593 the base variable is always returned, regardless if it is a default
594 def. Return T if it is not an SSA_NAME. */
597 get_ssa_base_param (tree t
, bool ignore_default_def
)
599 if (TREE_CODE (t
) == SSA_NAME
)
601 if (ignore_default_def
|| SSA_NAME_IS_DEFAULT_DEF (t
))
602 return SSA_NAME_VAR (t
);
609 /* Given an expression, return an adjustment entry specifying the
610 transformation to be done on EXPR. If no suitable adjustment entry
611 was found, returns NULL.
613 If IGNORE_DEFAULT_DEF is set, consider SSA_NAMEs which are not a
614 default def, otherwise bail on them.
616 If CONVERT is non-NULL, this function will set *CONVERT if the
617 expression provided is a component reference. ADJUSTMENTS is the
618 adjustments vector. */
620 ipa_parm_adjustment
*
621 ipa_get_adjustment_candidate (tree
**expr
, bool *convert
,
622 ipa_parm_adjustment_vec adjustments
,
623 bool ignore_default_def
)
625 if (TREE_CODE (**expr
) == BIT_FIELD_REF
626 || TREE_CODE (**expr
) == IMAGPART_EXPR
627 || TREE_CODE (**expr
) == REALPART_EXPR
)
629 *expr
= &TREE_OPERAND (**expr
, 0);
634 HOST_WIDE_INT offset
, size
, max_size
;
637 = get_ref_base_and_extent (**expr
, &offset
, &size
, &max_size
, &reverse
);
638 if (!base
|| size
== -1 || max_size
== -1)
641 if (TREE_CODE (base
) == MEM_REF
)
643 offset
+= mem_ref_offset (base
).to_short_addr () * BITS_PER_UNIT
;
644 base
= TREE_OPERAND (base
, 0);
647 base
= get_ssa_base_param (base
, ignore_default_def
);
648 if (!base
|| TREE_CODE (base
) != PARM_DECL
)
651 struct ipa_parm_adjustment
*cand
= NULL
;
652 unsigned int len
= adjustments
.length ();
653 for (unsigned i
= 0; i
< len
; i
++)
655 struct ipa_parm_adjustment
*adj
= &adjustments
[i
];
657 if (adj
->base
== base
658 && (adj
->offset
== offset
|| adj
->op
== IPA_PARM_OP_REMOVE
))
665 if (!cand
|| cand
->op
== IPA_PARM_OP_COPY
|| cand
->op
== IPA_PARM_OP_REMOVE
)
670 /* If the expression *EXPR should be replaced by a reduction of a parameter, do
671 so. ADJUSTMENTS is a pointer to a vector of adjustments. CONVERT
672 specifies whether the function should care about type incompatibility the
673 current and new expressions. If it is false, the function will leave
674 incompatibility issues to the caller. Return true iff the expression
678 ipa_modify_expr (tree
*expr
, bool convert
,
679 ipa_parm_adjustment_vec adjustments
)
681 struct ipa_parm_adjustment
*cand
682 = ipa_get_adjustment_candidate (&expr
, &convert
, adjustments
, false);
689 src
= build_simple_mem_ref (cand
->new_decl
);
690 REF_REVERSE_STORAGE_ORDER (src
) = cand
->reverse
;
693 src
= cand
->new_decl
;
695 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
697 fprintf (dump_file
, "About to replace expr ");
698 print_generic_expr (dump_file
, *expr
);
699 fprintf (dump_file
, " with ");
700 print_generic_expr (dump_file
, src
);
701 fprintf (dump_file
, "\n");
704 if (convert
&& !useless_type_conversion_p (TREE_TYPE (*expr
), cand
->type
))
706 tree vce
= build1 (VIEW_CONVERT_EXPR
, TREE_TYPE (*expr
), src
);
714 /* Dump the adjustments in the vector ADJUSTMENTS to dump_file in a human
715 friendly way, assuming they are meant to be applied to FNDECL. */
718 ipa_dump_param_adjustments (FILE *file
, ipa_parm_adjustment_vec adjustments
,
721 int i
, len
= adjustments
.length ();
723 vec
<tree
> parms
= ipa_get_vector_of_formal_parms (fndecl
);
725 fprintf (file
, "IPA param adjustments: ");
726 for (i
= 0; i
< len
; i
++)
728 struct ipa_parm_adjustment
*adj
;
729 adj
= &adjustments
[i
];
736 fprintf (file
, "%i. base_index: %i - ", i
, adj
->base_index
);
737 print_generic_expr (file
, parms
[adj
->base_index
]);
740 fprintf (file
, ", base: ");
741 print_generic_expr (file
, adj
->base
);
745 fprintf (file
, ", new_decl: ");
746 print_generic_expr (file
, adj
->new_decl
);
748 if (adj
->new_ssa_base
)
750 fprintf (file
, ", new_ssa_base: ");
751 print_generic_expr (file
, adj
->new_ssa_base
);
754 if (adj
->op
== IPA_PARM_OP_COPY
)
755 fprintf (file
, ", copy_param");
756 else if (adj
->op
== IPA_PARM_OP_REMOVE
)
757 fprintf (file
, ", remove_param");
759 fprintf (file
, ", offset %li", (long) adj
->offset
);
761 fprintf (file
, ", by_ref");
762 print_node_brief (file
, ", type: ", adj
->type
, 0);
763 fprintf (file
, "\n");