1 /* Manipulation of formal and actual parameters of functions and function
3 Copyright (C) 2017-2019 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 (fndecl_built_in_p (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 poly_int64 byte_offset
= exact_div (adj
->offset
, BITS_PER_UNIT
);
297 base
= gimple_call_arg (stmt
, adj
->base_index
);
298 loc
= gimple_location (stmt
);
300 if (TREE_CODE (base
) != ADDR_EXPR
301 && POINTER_TYPE_P (TREE_TYPE (base
)))
302 off
= build_int_cst (adj
->alias_ptr_type
, byte_offset
);
305 poly_int64 base_offset
;
309 if (TREE_CODE (base
) == ADDR_EXPR
)
311 base
= TREE_OPERAND (base
, 0);
317 base
= get_addr_base_and_unit_offset (base
, &base_offset
);
318 /* Aggregate arguments can have non-invariant addresses. */
321 base
= build_fold_addr_expr (prev_base
);
322 off
= build_int_cst (adj
->alias_ptr_type
, byte_offset
);
324 else if (TREE_CODE (base
) == MEM_REF
)
329 deref_align
= TYPE_ALIGN (TREE_TYPE (base
));
331 off
= build_int_cst (adj
->alias_ptr_type
,
332 base_offset
+ byte_offset
);
333 off
= int_const_binop (PLUS_EXPR
, TREE_OPERAND (base
, 1),
335 base
= TREE_OPERAND (base
, 0);
339 off
= build_int_cst (adj
->alias_ptr_type
,
340 base_offset
+ byte_offset
);
341 base
= build_fold_addr_expr (base
);
347 tree type
= adj
->type
;
349 unsigned HOST_WIDE_INT misalign
;
358 get_pointer_alignment_1 (base
, &align
, &misalign
);
359 if (TYPE_ALIGN (type
) > align
)
360 align
= TYPE_ALIGN (type
);
362 misalign
+= (offset_int::from (wi::to_wide (off
),
363 SIGNED
).to_short_addr ()
365 misalign
= misalign
& (align
- 1);
367 align
= least_bit_hwi (misalign
);
368 if (align
< TYPE_ALIGN (type
))
369 type
= build_aligned_type (type
, align
);
370 base
= force_gimple_operand_gsi (&gsi
, base
,
371 true, NULL
, true, GSI_SAME_STMT
);
372 expr
= fold_build2_loc (loc
, MEM_REF
, type
, base
, off
);
373 REF_REVERSE_STORAGE_ORDER (expr
) = adj
->reverse
;
374 /* If expr is not a valid gimple call argument emit
375 a load into a temporary. */
376 if (is_gimple_reg_type (TREE_TYPE (expr
)))
378 gimple
*tem
= gimple_build_assign (NULL_TREE
, expr
);
379 if (gimple_in_ssa_p (cfun
))
381 gimple_set_vuse (tem
, gimple_vuse (stmt
));
382 expr
= make_ssa_name (TREE_TYPE (expr
), tem
);
385 expr
= create_tmp_reg (TREE_TYPE (expr
));
386 gimple_assign_set_lhs (tem
, expr
);
387 gimple_set_location (tem
, loc
);
388 gsi_insert_before (&gsi
, tem
, GSI_SAME_STMT
);
393 expr
= fold_build2_loc (loc
, MEM_REF
, adj
->type
, base
, off
);
394 REF_REVERSE_STORAGE_ORDER (expr
) = adj
->reverse
;
395 expr
= build_fold_addr_expr (expr
);
396 expr
= force_gimple_operand_gsi (&gsi
, expr
,
397 true, NULL
, true, GSI_SAME_STMT
);
399 vargs
.quick_push (expr
);
401 if (adj
->op
!= IPA_PARM_OP_COPY
&& MAY_HAVE_DEBUG_BIND_STMTS
)
404 tree ddecl
= NULL_TREE
, origin
= DECL_ORIGIN (adj
->base
), arg
;
407 arg
= gimple_call_arg (stmt
, adj
->base_index
);
408 if (!useless_type_conversion_p (TREE_TYPE (origin
), TREE_TYPE (arg
)))
410 if (!fold_convertible_p (TREE_TYPE (origin
), arg
))
412 arg
= fold_convert_loc (gimple_location (stmt
),
413 TREE_TYPE (origin
), arg
);
415 if (debug_args
== NULL
)
416 debug_args
= decl_debug_args_insert (callee_decl
);
417 for (ix
= 0; vec_safe_iterate (*debug_args
, ix
, &ddecl
); ix
+= 2)
420 ddecl
= (**debug_args
)[ix
+ 1];
425 ddecl
= make_node (DEBUG_EXPR_DECL
);
426 DECL_ARTIFICIAL (ddecl
) = 1;
427 TREE_TYPE (ddecl
) = TREE_TYPE (origin
);
428 SET_DECL_MODE (ddecl
, DECL_MODE (origin
));
430 vec_safe_push (*debug_args
, origin
);
431 vec_safe_push (*debug_args
, ddecl
);
433 def_temp
= gimple_build_debug_bind (ddecl
, unshare_expr (arg
), stmt
);
434 gsi_insert_before (&gsi
, def_temp
, GSI_SAME_STMT
);
438 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
440 fprintf (dump_file
, "replacing stmt:");
441 print_gimple_stmt (dump_file
, gsi_stmt (gsi
), 0);
444 new_stmt
= gimple_build_call_vec (callee_decl
, vargs
);
446 if (gimple_call_lhs (stmt
))
447 gimple_call_set_lhs (new_stmt
, gimple_call_lhs (stmt
));
449 gimple_set_block (new_stmt
, gimple_block (stmt
));
450 if (gimple_has_location (stmt
))
451 gimple_set_location (new_stmt
, gimple_location (stmt
));
452 gimple_call_set_chain (new_stmt
, gimple_call_chain (stmt
));
453 gimple_call_copy_flags (new_stmt
, stmt
);
454 if (gimple_in_ssa_p (cfun
))
456 gimple_set_vuse (new_stmt
, gimple_vuse (stmt
));
457 if (gimple_vdef (stmt
))
459 gimple_set_vdef (new_stmt
, gimple_vdef (stmt
));
460 SSA_NAME_DEF_STMT (gimple_vdef (new_stmt
)) = new_stmt
;
464 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
466 fprintf (dump_file
, "with stmt:");
467 print_gimple_stmt (dump_file
, new_stmt
, 0);
468 fprintf (dump_file
, "\n");
470 gsi_replace (&gsi
, new_stmt
, true);
472 cs
->set_call_stmt (new_stmt
);
475 current_node
->record_stmt_references (gsi_stmt (gsi
));
478 while (gsi_stmt (gsi
) != gsi_stmt (prev_gsi
));
481 /* Return true iff BASE_INDEX is in ADJUSTMENTS more than once. */
484 index_in_adjustments_multiple_times_p (int base_index
,
485 ipa_parm_adjustment_vec adjustments
)
487 int i
, len
= adjustments
.length ();
490 for (i
= 0; i
< len
; i
++)
492 struct ipa_parm_adjustment
*adj
;
493 adj
= &adjustments
[i
];
495 if (adj
->base_index
== base_index
)
506 /* Return adjustments that should have the same effect on function parameters
507 and call arguments as if they were first changed according to adjustments in
508 INNER and then by adjustments in OUTER. */
510 ipa_parm_adjustment_vec
511 ipa_combine_adjustments (ipa_parm_adjustment_vec inner
,
512 ipa_parm_adjustment_vec outer
)
514 int i
, outlen
= outer
.length ();
515 int inlen
= inner
.length ();
517 ipa_parm_adjustment_vec adjustments
, tmp
;
520 for (i
= 0; i
< inlen
; i
++)
522 struct ipa_parm_adjustment
*n
;
525 if (n
->op
== IPA_PARM_OP_REMOVE
)
529 /* FIXME: Handling of new arguments are not implemented yet. */
530 gcc_assert (n
->op
!= IPA_PARM_OP_NEW
);
535 adjustments
.create (outlen
+ removals
);
536 for (i
= 0; i
< outlen
; i
++)
538 struct ipa_parm_adjustment r
;
539 struct ipa_parm_adjustment
*out
= &outer
[i
];
540 struct ipa_parm_adjustment
*in
= &tmp
[out
->base_index
];
542 memset (&r
, 0, sizeof (r
));
543 gcc_assert (in
->op
!= IPA_PARM_OP_REMOVE
);
544 if (out
->op
== IPA_PARM_OP_REMOVE
)
546 if (!index_in_adjustments_multiple_times_p (in
->base_index
, tmp
))
548 r
.op
= IPA_PARM_OP_REMOVE
;
549 adjustments
.quick_push (r
);
555 /* FIXME: Handling of new arguments are not implemented yet. */
556 gcc_assert (out
->op
!= IPA_PARM_OP_NEW
);
559 r
.base_index
= in
->base_index
;
562 /* FIXME: Create nonlocal value too. */
564 if (in
->op
== IPA_PARM_OP_COPY
&& out
->op
== IPA_PARM_OP_COPY
)
565 r
.op
= IPA_PARM_OP_COPY
;
566 else if (in
->op
== IPA_PARM_OP_COPY
)
567 r
.offset
= out
->offset
;
568 else if (out
->op
== IPA_PARM_OP_COPY
)
569 r
.offset
= in
->offset
;
571 r
.offset
= in
->offset
+ out
->offset
;
572 adjustments
.quick_push (r
);
575 for (i
= 0; i
< inlen
; i
++)
577 struct ipa_parm_adjustment
*n
= &inner
[i
];
579 if (n
->op
== IPA_PARM_OP_REMOVE
)
580 adjustments
.quick_push (*n
);
587 /* If T is an SSA_NAME, return NULL if it is not a default def or
588 return its base variable if it is. If IGNORE_DEFAULT_DEF is true,
589 the base variable is always returned, regardless if it is a default
590 def. Return T if it is not an SSA_NAME. */
593 get_ssa_base_param (tree t
, bool ignore_default_def
)
595 if (TREE_CODE (t
) == SSA_NAME
)
597 if (ignore_default_def
|| SSA_NAME_IS_DEFAULT_DEF (t
))
598 return SSA_NAME_VAR (t
);
605 /* Given an expression, return an adjustment entry specifying the
606 transformation to be done on EXPR. If no suitable adjustment entry
607 was found, returns NULL.
609 If IGNORE_DEFAULT_DEF is set, consider SSA_NAMEs which are not a
610 default def, otherwise bail on them.
612 If CONVERT is non-NULL, this function will set *CONVERT if the
613 expression provided is a component reference. ADJUSTMENTS is the
614 adjustments vector. */
616 ipa_parm_adjustment
*
617 ipa_get_adjustment_candidate (tree
**expr
, bool *convert
,
618 ipa_parm_adjustment_vec adjustments
,
619 bool ignore_default_def
)
621 if (TREE_CODE (**expr
) == BIT_FIELD_REF
622 || TREE_CODE (**expr
) == IMAGPART_EXPR
623 || TREE_CODE (**expr
) == REALPART_EXPR
)
625 *expr
= &TREE_OPERAND (**expr
, 0);
630 poly_int64 offset
, size
, max_size
;
633 = get_ref_base_and_extent (**expr
, &offset
, &size
, &max_size
, &reverse
);
634 if (!base
|| !known_size_p (size
) || !known_size_p (max_size
))
637 if (TREE_CODE (base
) == MEM_REF
)
639 offset
+= mem_ref_offset (base
).force_shwi () * BITS_PER_UNIT
;
640 base
= TREE_OPERAND (base
, 0);
643 base
= get_ssa_base_param (base
, ignore_default_def
);
644 if (!base
|| TREE_CODE (base
) != PARM_DECL
)
647 struct ipa_parm_adjustment
*cand
= NULL
;
648 unsigned int len
= adjustments
.length ();
649 for (unsigned i
= 0; i
< len
; i
++)
651 struct ipa_parm_adjustment
*adj
= &adjustments
[i
];
653 if (adj
->base
== base
654 && (known_eq (adj
->offset
, offset
) || adj
->op
== IPA_PARM_OP_REMOVE
))
661 if (!cand
|| cand
->op
== IPA_PARM_OP_COPY
|| cand
->op
== IPA_PARM_OP_REMOVE
)
666 /* If the expression *EXPR should be replaced by a reduction of a parameter, do
667 so. ADJUSTMENTS is a pointer to a vector of adjustments. CONVERT
668 specifies whether the function should care about type incompatibility the
669 current and new expressions. If it is false, the function will leave
670 incompatibility issues to the caller. Return true iff the expression
674 ipa_modify_expr (tree
*expr
, bool convert
,
675 ipa_parm_adjustment_vec adjustments
)
677 struct ipa_parm_adjustment
*cand
678 = ipa_get_adjustment_candidate (&expr
, &convert
, adjustments
, false);
685 src
= build_simple_mem_ref (cand
->new_decl
);
686 REF_REVERSE_STORAGE_ORDER (src
) = cand
->reverse
;
689 src
= cand
->new_decl
;
691 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
693 fprintf (dump_file
, "About to replace expr ");
694 print_generic_expr (dump_file
, *expr
);
695 fprintf (dump_file
, " with ");
696 print_generic_expr (dump_file
, src
);
697 fprintf (dump_file
, "\n");
700 if (convert
&& !useless_type_conversion_p (TREE_TYPE (*expr
), cand
->type
))
702 tree vce
= build1 (VIEW_CONVERT_EXPR
, TREE_TYPE (*expr
), src
);
710 /* Dump the adjustments in the vector ADJUSTMENTS to dump_file in a human
711 friendly way, assuming they are meant to be applied to FNDECL. */
714 ipa_dump_param_adjustments (FILE *file
, ipa_parm_adjustment_vec adjustments
,
717 int i
, len
= adjustments
.length ();
719 vec
<tree
> parms
= ipa_get_vector_of_formal_parms (fndecl
);
721 fprintf (file
, "IPA param adjustments: ");
722 for (i
= 0; i
< len
; i
++)
724 struct ipa_parm_adjustment
*adj
;
725 adj
= &adjustments
[i
];
732 fprintf (file
, "%i. base_index: %i - ", i
, adj
->base_index
);
733 print_generic_expr (file
, parms
[adj
->base_index
]);
736 fprintf (file
, ", base: ");
737 print_generic_expr (file
, adj
->base
);
741 fprintf (file
, ", new_decl: ");
742 print_generic_expr (file
, adj
->new_decl
);
744 if (adj
->new_ssa_base
)
746 fprintf (file
, ", new_ssa_base: ");
747 print_generic_expr (file
, adj
->new_ssa_base
);
750 if (adj
->op
== IPA_PARM_OP_COPY
)
751 fprintf (file
, ", copy_param");
752 else if (adj
->op
== IPA_PARM_OP_REMOVE
)
753 fprintf (file
, ", remove_param");
756 fprintf (file
, ", offset ");
757 print_dec (adj
->offset
, file
);
760 fprintf (file
, ", by_ref");
761 print_node_brief (file
, ", type: ", adj
->type
, 0);
762 fprintf (file
, "\n");