]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ipa-param-manipulation.c
Use checking forms of DECL_FUNCTION_CODE (PR 91421)
[thirdparty/gcc.git] / gcc / ipa-param-manipulation.c
1 /* Manipulation of formal and actual parameters of functions and function
2 calls.
3 Copyright (C) 2017-2019 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
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
10 version.
11
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
15 for more details.
16
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/>. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "backend.h"
25 #include "rtl.h"
26 #include "tree.h"
27 #include "gimple.h"
28 #include "ssa.h"
29 #include "cgraph.h"
30 #include "fold-const.h"
31 #include "stor-layout.h"
32 #include "gimplify.h"
33 #include "gimple-iterator.h"
34 #include "gimplify-me.h"
35 #include "tree-dfa.h"
36 #include "ipa-param-manipulation.h"
37 #include "print-tree.h"
38 #include "gimple-pretty-print.h"
39 #include "builtins.h"
40
41 /* Return a heap allocated vector containing formal parameters of FNDECL. */
42
43 vec<tree>
44 ipa_get_vector_of_formal_parms (tree fndecl)
45 {
46 vec<tree> args;
47 int count;
48 tree parm;
49
50 gcc_assert (!flag_wpa);
51 count = 0;
52 for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
53 count++;
54
55 args.create (count);
56 for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
57 args.quick_push (parm);
58
59 return args;
60 }
61
62 /* Return a heap allocated vector containing types of formal parameters of
63 function type FNTYPE. */
64
65 vec<tree>
66 ipa_get_vector_of_formal_parm_types (tree fntype)
67 {
68 vec<tree> types;
69 int count = 0;
70 tree t;
71
72 for (t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t))
73 count++;
74
75 types.create (count);
76 for (t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t))
77 types.quick_push (TREE_VALUE (t));
78
79 return types;
80 }
81
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
85 base_index field. */
86
87 void
88 ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments)
89 {
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);
93
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);
97 bool last_parm_void;
98 vec<tree> otypes;
99 if (care_for_types)
100 {
101 last_parm_void = (TREE_VALUE (tree_last (old_arg_types))
102 == void_type_node);
103 otypes = ipa_get_vector_of_formal_parm_types (orig_type);
104 if (last_parm_void)
105 gcc_assert (oparms.length () + 1 == otypes.length ());
106 else
107 gcc_assert (oparms.length () == otypes.length ());
108 }
109 else
110 {
111 last_parm_void = false;
112 otypes.create (0);
113 }
114
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++)
119 {
120 struct ipa_parm_adjustment *adj;
121 gcc_assert (link);
122
123 adj = &adjustments[i];
124 tree parm;
125 if (adj->op == IPA_PARM_OP_NEW)
126 parm = NULL;
127 else
128 parm = oparms[adj->base_index];
129 adj->base = parm;
130
131 if (adj->op == IPA_PARM_OP_COPY)
132 {
133 if (care_for_types)
134 new_arg_types = tree_cons (NULL_TREE, otypes[adj->base_index],
135 new_arg_types);
136 *link = parm;
137 link = &DECL_CHAIN (parm);
138 }
139 else if (adj->op != IPA_PARM_OP_REMOVE)
140 {
141 tree new_parm;
142 tree ptype;
143
144 if (adj->by_ref)
145 ptype = build_pointer_type (adj->type);
146 else
147 {
148 ptype = adj->type;
149 if (is_gimple_reg_type (ptype)
150 && TYPE_MODE (ptype) != BLKmode)
151 {
152 unsigned malign = GET_MODE_ALIGNMENT (TYPE_MODE (ptype));
153 if (TYPE_ALIGN (ptype) != malign)
154 ptype = build_aligned_type (ptype, malign);
155 }
156 }
157
158 if (care_for_types)
159 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
160
161 new_parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL_TREE,
162 ptype);
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);
171
172 if (adj->op == IPA_PARM_OP_NEW)
173 adj->base = NULL;
174 else
175 adj->base = parm;
176 adj->new_decl = new_parm;
177
178 *link = new_parm;
179 link = &DECL_CHAIN (new_parm);
180 }
181 }
182
183 *link = NULL_TREE;
184
185 tree new_reversed = NULL;
186 if (care_for_types)
187 {
188 new_reversed = nreverse (new_arg_types);
189 if (last_parm_void)
190 {
191 if (new_reversed)
192 TREE_CHAIN (new_arg_types) = void_list_node;
193 else
194 new_reversed = void_list_node;
195 }
196 }
197
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
202 instead. */
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))
207 {
208 new_type = build_distinct_type_copy (orig_type);
209 TYPE_ARG_TYPES (new_type) = new_reversed;
210 }
211 else
212 {
213 new_type
214 = build_distinct_type_copy (build_function_type (TREE_TYPE (orig_type),
215 new_reversed));
216 TYPE_CONTEXT (new_type) = TYPE_CONTEXT (orig_type);
217 DECL_VINDEX (fndecl) = NULL_TREE;
218 }
219
220 /* When signature changes, we need to clear builtin info. */
221 if (fndecl_built_in_p (fndecl))
222 set_decl_built_in_function (fndecl, NOT_BUILT_IN, 0);
223
224 TREE_TYPE (fndecl) = new_type;
225 DECL_VIRTUAL_P (fndecl) = 0;
226 DECL_LANG_SPECIFIC (fndecl) = NULL;
227 otypes.release ();
228 oparms.release ();
229 }
230
231 /* Modify actual arguments of a function call CS as indicated in ADJUSTMENTS.
232 If this is a directly recursive call, CS must be NULL. Otherwise it must
233 contain the corresponding call graph edge. */
234
235 void
236 ipa_modify_call_arguments (struct cgraph_edge *cs, gcall *stmt,
237 ipa_parm_adjustment_vec adjustments)
238 {
239 struct cgraph_node *current_node = cgraph_node::get (current_function_decl);
240 vec<tree> vargs;
241 vec<tree, va_gc> **debug_args = NULL;
242 gcall *new_stmt;
243 gimple_stmt_iterator gsi, prev_gsi;
244 tree callee_decl;
245 int i, len;
246
247 len = adjustments.length ();
248 vargs.create (len);
249 callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->decl;
250 current_node->remove_stmt_references (stmt);
251
252 gsi = gsi_for_stmt (stmt);
253 prev_gsi = gsi;
254 gsi_prev (&prev_gsi);
255 for (i = 0; i < len; i++)
256 {
257 struct ipa_parm_adjustment *adj;
258
259 adj = &adjustments[i];
260
261 if (adj->op == IPA_PARM_OP_COPY)
262 {
263 tree arg = gimple_call_arg (stmt, adj->base_index);
264
265 vargs.quick_push (arg);
266 }
267 else if (adj->op != IPA_PARM_OP_REMOVE)
268 {
269 tree expr, base, off;
270 location_t loc;
271 unsigned int deref_align = 0;
272 bool deref_base = false;
273
274 /* We create a new parameter out of the value of the old one, we can
275 do the following kind of transformations:
276
277 - A scalar passed by reference is converted to a scalar passed by
278 value. (adj->by_ref is false and the type of the original
279 actual argument is a pointer to a scalar).
280
281 - A part of an aggregate is passed instead of the whole aggregate.
282 The part can be passed either by value or by reference, this is
283 determined by value of adj->by_ref. Moreover, the code below
284 handles both situations when the original aggregate is passed by
285 value (its type is not a pointer) and when it is passed by
286 reference (it is a pointer to an aggregate).
287
288 When the new argument is passed by reference (adj->by_ref is true)
289 it must be a part of an aggregate and therefore we form it by
290 simply taking the address of a reference inside the original
291 aggregate. */
292
293 poly_int64 byte_offset = exact_div (adj->offset, BITS_PER_UNIT);
294 base = gimple_call_arg (stmt, adj->base_index);
295 loc = gimple_location (stmt);
296
297 if (TREE_CODE (base) != ADDR_EXPR
298 && POINTER_TYPE_P (TREE_TYPE (base)))
299 off = build_int_cst (adj->alias_ptr_type, byte_offset);
300 else
301 {
302 poly_int64 base_offset;
303 tree prev_base;
304 bool addrof;
305
306 if (TREE_CODE (base) == ADDR_EXPR)
307 {
308 base = TREE_OPERAND (base, 0);
309 addrof = true;
310 }
311 else
312 addrof = false;
313 prev_base = base;
314 base = get_addr_base_and_unit_offset (base, &base_offset);
315 /* Aggregate arguments can have non-invariant addresses. */
316 if (!base)
317 {
318 base = build_fold_addr_expr (prev_base);
319 off = build_int_cst (adj->alias_ptr_type, byte_offset);
320 }
321 else if (TREE_CODE (base) == MEM_REF)
322 {
323 if (!addrof)
324 {
325 deref_base = true;
326 deref_align = TYPE_ALIGN (TREE_TYPE (base));
327 }
328 off = build_int_cst (adj->alias_ptr_type,
329 base_offset + byte_offset);
330 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1),
331 off);
332 base = TREE_OPERAND (base, 0);
333 }
334 else
335 {
336 off = build_int_cst (adj->alias_ptr_type,
337 base_offset + byte_offset);
338 base = build_fold_addr_expr (base);
339 }
340 }
341
342 if (!adj->by_ref)
343 {
344 tree type = adj->type;
345 unsigned int align;
346 unsigned HOST_WIDE_INT misalign;
347
348 if (deref_base)
349 {
350 align = deref_align;
351 misalign = 0;
352 }
353 else
354 {
355 get_pointer_alignment_1 (base, &align, &misalign);
356 if (TYPE_ALIGN (type) > align)
357 align = TYPE_ALIGN (type);
358 }
359 misalign += (offset_int::from (wi::to_wide (off),
360 SIGNED).to_short_addr ()
361 * BITS_PER_UNIT);
362 misalign = misalign & (align - 1);
363 if (misalign != 0)
364 align = least_bit_hwi (misalign);
365 if (align < TYPE_ALIGN (type))
366 type = build_aligned_type (type, align);
367 base = force_gimple_operand_gsi (&gsi, base,
368 true, NULL, true, GSI_SAME_STMT);
369 expr = fold_build2_loc (loc, MEM_REF, type, base, off);
370 REF_REVERSE_STORAGE_ORDER (expr) = adj->reverse;
371 /* If expr is not a valid gimple call argument emit
372 a load into a temporary. */
373 if (is_gimple_reg_type (TREE_TYPE (expr)))
374 {
375 gimple *tem = gimple_build_assign (NULL_TREE, expr);
376 if (gimple_in_ssa_p (cfun))
377 {
378 gimple_set_vuse (tem, gimple_vuse (stmt));
379 expr = make_ssa_name (TREE_TYPE (expr), tem);
380 }
381 else
382 expr = create_tmp_reg (TREE_TYPE (expr));
383 gimple_assign_set_lhs (tem, expr);
384 gimple_set_location (tem, loc);
385 gsi_insert_before (&gsi, tem, GSI_SAME_STMT);
386 }
387 }
388 else
389 {
390 expr = fold_build2_loc (loc, MEM_REF, adj->type, base, off);
391 REF_REVERSE_STORAGE_ORDER (expr) = adj->reverse;
392 expr = build_fold_addr_expr (expr);
393 expr = force_gimple_operand_gsi (&gsi, expr,
394 true, NULL, true, GSI_SAME_STMT);
395 }
396 vargs.quick_push (expr);
397 }
398 if (adj->op != IPA_PARM_OP_COPY && MAY_HAVE_DEBUG_BIND_STMTS)
399 {
400 unsigned int ix;
401 tree ddecl = NULL_TREE, origin = DECL_ORIGIN (adj->base), arg;
402 gimple *def_temp;
403
404 arg = gimple_call_arg (stmt, adj->base_index);
405 if (!useless_type_conversion_p (TREE_TYPE (origin), TREE_TYPE (arg)))
406 {
407 if (!fold_convertible_p (TREE_TYPE (origin), arg))
408 continue;
409 arg = fold_convert_loc (gimple_location (stmt),
410 TREE_TYPE (origin), arg);
411 }
412 if (debug_args == NULL)
413 debug_args = decl_debug_args_insert (callee_decl);
414 for (ix = 0; vec_safe_iterate (*debug_args, ix, &ddecl); ix += 2)
415 if (ddecl == origin)
416 {
417 ddecl = (**debug_args)[ix + 1];
418 break;
419 }
420 if (ddecl == NULL)
421 {
422 ddecl = make_node (DEBUG_EXPR_DECL);
423 DECL_ARTIFICIAL (ddecl) = 1;
424 TREE_TYPE (ddecl) = TREE_TYPE (origin);
425 SET_DECL_MODE (ddecl, DECL_MODE (origin));
426
427 vec_safe_push (*debug_args, origin);
428 vec_safe_push (*debug_args, ddecl);
429 }
430 def_temp = gimple_build_debug_bind (ddecl, unshare_expr (arg), stmt);
431 gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
432 }
433 }
434
435 if (dump_file && (dump_flags & TDF_DETAILS))
436 {
437 fprintf (dump_file, "replacing stmt:");
438 print_gimple_stmt (dump_file, gsi_stmt (gsi), 0);
439 }
440
441 new_stmt = gimple_build_call_vec (callee_decl, vargs);
442 vargs.release ();
443 if (gimple_call_lhs (stmt))
444 gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
445
446 gimple_set_block (new_stmt, gimple_block (stmt));
447 if (gimple_has_location (stmt))
448 gimple_set_location (new_stmt, gimple_location (stmt));
449 gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
450 gimple_call_copy_flags (new_stmt, stmt);
451 if (gimple_in_ssa_p (cfun))
452 gimple_move_vops (new_stmt, stmt);
453
454 if (dump_file && (dump_flags & TDF_DETAILS))
455 {
456 fprintf (dump_file, "with stmt:");
457 print_gimple_stmt (dump_file, new_stmt, 0);
458 fprintf (dump_file, "\n");
459 }
460 gsi_replace (&gsi, new_stmt, true);
461 if (cs)
462 cs->set_call_stmt (new_stmt);
463 do
464 {
465 current_node->record_stmt_references (gsi_stmt (gsi));
466 gsi_prev (&gsi);
467 }
468 while (gsi_stmt (gsi) != gsi_stmt (prev_gsi));
469 }
470
471 /* Return true iff BASE_INDEX is in ADJUSTMENTS more than once. */
472
473 static bool
474 index_in_adjustments_multiple_times_p (int base_index,
475 ipa_parm_adjustment_vec adjustments)
476 {
477 int i, len = adjustments.length ();
478 bool one = false;
479
480 for (i = 0; i < len; i++)
481 {
482 struct ipa_parm_adjustment *adj;
483 adj = &adjustments[i];
484
485 if (adj->base_index == base_index)
486 {
487 if (one)
488 return true;
489 else
490 one = true;
491 }
492 }
493 return false;
494 }
495
496 /* Return adjustments that should have the same effect on function parameters
497 and call arguments as if they were first changed according to adjustments in
498 INNER and then by adjustments in OUTER. */
499
500 ipa_parm_adjustment_vec
501 ipa_combine_adjustments (ipa_parm_adjustment_vec inner,
502 ipa_parm_adjustment_vec outer)
503 {
504 int i, outlen = outer.length ();
505 int inlen = inner.length ();
506 int removals = 0;
507 ipa_parm_adjustment_vec adjustments, tmp;
508
509 tmp.create (inlen);
510 for (i = 0; i < inlen; i++)
511 {
512 struct ipa_parm_adjustment *n;
513 n = &inner[i];
514
515 if (n->op == IPA_PARM_OP_REMOVE)
516 removals++;
517 else
518 {
519 /* FIXME: Handling of new arguments are not implemented yet. */
520 gcc_assert (n->op != IPA_PARM_OP_NEW);
521 tmp.quick_push (*n);
522 }
523 }
524
525 adjustments.create (outlen + removals);
526 for (i = 0; i < outlen; i++)
527 {
528 struct ipa_parm_adjustment r;
529 struct ipa_parm_adjustment *out = &outer[i];
530 struct ipa_parm_adjustment *in = &tmp[out->base_index];
531
532 memset (&r, 0, sizeof (r));
533 gcc_assert (in->op != IPA_PARM_OP_REMOVE);
534 if (out->op == IPA_PARM_OP_REMOVE)
535 {
536 if (!index_in_adjustments_multiple_times_p (in->base_index, tmp))
537 {
538 r.op = IPA_PARM_OP_REMOVE;
539 adjustments.quick_push (r);
540 }
541 continue;
542 }
543 else
544 {
545 /* FIXME: Handling of new arguments are not implemented yet. */
546 gcc_assert (out->op != IPA_PARM_OP_NEW);
547 }
548
549 r.base_index = in->base_index;
550 r.type = out->type;
551
552 /* FIXME: Create nonlocal value too. */
553
554 if (in->op == IPA_PARM_OP_COPY && out->op == IPA_PARM_OP_COPY)
555 r.op = IPA_PARM_OP_COPY;
556 else if (in->op == IPA_PARM_OP_COPY)
557 r.offset = out->offset;
558 else if (out->op == IPA_PARM_OP_COPY)
559 r.offset = in->offset;
560 else
561 r.offset = in->offset + out->offset;
562 adjustments.quick_push (r);
563 }
564
565 for (i = 0; i < inlen; i++)
566 {
567 struct ipa_parm_adjustment *n = &inner[i];
568
569 if (n->op == IPA_PARM_OP_REMOVE)
570 adjustments.quick_push (*n);
571 }
572
573 tmp.release ();
574 return adjustments;
575 }
576
577 /* If T is an SSA_NAME, return NULL if it is not a default def or
578 return its base variable if it is. If IGNORE_DEFAULT_DEF is true,
579 the base variable is always returned, regardless if it is a default
580 def. Return T if it is not an SSA_NAME. */
581
582 static tree
583 get_ssa_base_param (tree t, bool ignore_default_def)
584 {
585 if (TREE_CODE (t) == SSA_NAME)
586 {
587 if (ignore_default_def || SSA_NAME_IS_DEFAULT_DEF (t))
588 return SSA_NAME_VAR (t);
589 else
590 return NULL_TREE;
591 }
592 return t;
593 }
594
595 /* Given an expression, return an adjustment entry specifying the
596 transformation to be done on EXPR. If no suitable adjustment entry
597 was found, returns NULL.
598
599 If IGNORE_DEFAULT_DEF is set, consider SSA_NAMEs which are not a
600 default def, otherwise bail on them.
601
602 If CONVERT is non-NULL, this function will set *CONVERT if the
603 expression provided is a component reference. ADJUSTMENTS is the
604 adjustments vector. */
605
606 ipa_parm_adjustment *
607 ipa_get_adjustment_candidate (tree **expr, bool *convert,
608 ipa_parm_adjustment_vec adjustments,
609 bool ignore_default_def)
610 {
611 if (TREE_CODE (**expr) == BIT_FIELD_REF
612 || TREE_CODE (**expr) == IMAGPART_EXPR
613 || TREE_CODE (**expr) == REALPART_EXPR)
614 {
615 *expr = &TREE_OPERAND (**expr, 0);
616 if (convert)
617 *convert = true;
618 }
619
620 poly_int64 offset, size, max_size;
621 bool reverse;
622 tree base
623 = get_ref_base_and_extent (**expr, &offset, &size, &max_size, &reverse);
624 if (!base || !known_size_p (size) || !known_size_p (max_size))
625 return NULL;
626
627 if (TREE_CODE (base) == MEM_REF)
628 {
629 offset += mem_ref_offset (base).force_shwi () * BITS_PER_UNIT;
630 base = TREE_OPERAND (base, 0);
631 }
632
633 base = get_ssa_base_param (base, ignore_default_def);
634 if (!base || TREE_CODE (base) != PARM_DECL)
635 return NULL;
636
637 struct ipa_parm_adjustment *cand = NULL;
638 unsigned int len = adjustments.length ();
639 for (unsigned i = 0; i < len; i++)
640 {
641 struct ipa_parm_adjustment *adj = &adjustments[i];
642
643 if (adj->base == base
644 && (known_eq (adj->offset, offset) || adj->op == IPA_PARM_OP_REMOVE))
645 {
646 cand = adj;
647 break;
648 }
649 }
650
651 if (!cand || cand->op == IPA_PARM_OP_COPY || cand->op == IPA_PARM_OP_REMOVE)
652 return NULL;
653 return cand;
654 }
655
656 /* If the expression *EXPR should be replaced by a reduction of a parameter, do
657 so. ADJUSTMENTS is a pointer to a vector of adjustments. CONVERT
658 specifies whether the function should care about type incompatibility the
659 current and new expressions. If it is false, the function will leave
660 incompatibility issues to the caller. Return true iff the expression
661 was modified. */
662
663 bool
664 ipa_modify_expr (tree *expr, bool convert,
665 ipa_parm_adjustment_vec adjustments)
666 {
667 struct ipa_parm_adjustment *cand
668 = ipa_get_adjustment_candidate (&expr, &convert, adjustments, false);
669 if (!cand)
670 return false;
671
672 tree src;
673 if (cand->by_ref)
674 {
675 src = build_simple_mem_ref (cand->new_decl);
676 REF_REVERSE_STORAGE_ORDER (src) = cand->reverse;
677 }
678 else
679 src = cand->new_decl;
680
681 if (dump_file && (dump_flags & TDF_DETAILS))
682 {
683 fprintf (dump_file, "About to replace expr ");
684 print_generic_expr (dump_file, *expr);
685 fprintf (dump_file, " with ");
686 print_generic_expr (dump_file, src);
687 fprintf (dump_file, "\n");
688 }
689
690 if (convert && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type))
691 {
692 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src);
693 *expr = vce;
694 }
695 else
696 *expr = src;
697 return true;
698 }
699
700 /* Dump the adjustments in the vector ADJUSTMENTS to dump_file in a human
701 friendly way, assuming they are meant to be applied to FNDECL. */
702
703 void
704 ipa_dump_param_adjustments (FILE *file, ipa_parm_adjustment_vec adjustments,
705 tree fndecl)
706 {
707 int i, len = adjustments.length ();
708 bool first = true;
709 vec<tree> parms = ipa_get_vector_of_formal_parms (fndecl);
710
711 fprintf (file, "IPA param adjustments: ");
712 for (i = 0; i < len; i++)
713 {
714 struct ipa_parm_adjustment *adj;
715 adj = &adjustments[i];
716
717 if (!first)
718 fprintf (file, " ");
719 else
720 first = false;
721
722 fprintf (file, "%i. base_index: %i - ", i, adj->base_index);
723 print_generic_expr (file, parms[adj->base_index]);
724 if (adj->base)
725 {
726 fprintf (file, ", base: ");
727 print_generic_expr (file, adj->base);
728 }
729 if (adj->new_decl)
730 {
731 fprintf (file, ", new_decl: ");
732 print_generic_expr (file, adj->new_decl);
733 }
734 if (adj->new_ssa_base)
735 {
736 fprintf (file, ", new_ssa_base: ");
737 print_generic_expr (file, adj->new_ssa_base);
738 }
739
740 if (adj->op == IPA_PARM_OP_COPY)
741 fprintf (file, ", copy_param");
742 else if (adj->op == IPA_PARM_OP_REMOVE)
743 fprintf (file, ", remove_param");
744 else
745 {
746 fprintf (file, ", offset ");
747 print_dec (adj->offset, file);
748 }
749 if (adj->by_ref)
750 fprintf (file, ", by_ref");
751 print_node_brief (file, ", type: ", adj->type, 0);
752 fprintf (file, "\n");
753 }
754 parms.release ();
755 }
756