]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ipa-param-manipulation.c
PR c++/87554 - ICE with extern template and reference member.
[thirdparty/gcc.git] / gcc / ipa-param-manipulation.c
CommitLineData
ac762bff 1/* Manipulation of formal and actual parameters of functions and function
2 calls.
fbd26352 3 Copyright (C) 2017-2019 Free Software Foundation, Inc.
ac762bff 4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along 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
43vec<tree>
44ipa_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
65vec<tree>
66ipa_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
87void
88ipa_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. */
a0e9bfbb 221 if (fndecl_built_in_p (fndecl))
ac762bff 222 {
223 DECL_BUILT_IN_CLASS (fndecl) = NOT_BUILT_IN;
224 DECL_FUNCTION_CODE (fndecl) = (enum built_in_function) 0;
225 }
226
227 TREE_TYPE (fndecl) = new_type;
228 DECL_VIRTUAL_P (fndecl) = 0;
229 DECL_LANG_SPECIFIC (fndecl) = NULL;
230 otypes.release ();
231 oparms.release ();
232}
233
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. */
237
238void
239ipa_modify_call_arguments (struct cgraph_edge *cs, gcall *stmt,
240 ipa_parm_adjustment_vec adjustments)
241{
242 struct cgraph_node *current_node = cgraph_node::get (current_function_decl);
243 vec<tree> vargs;
244 vec<tree, va_gc> **debug_args = NULL;
245 gcall *new_stmt;
246 gimple_stmt_iterator gsi, prev_gsi;
247 tree callee_decl;
248 int i, len;
249
250 len = adjustments.length ();
251 vargs.create (len);
252 callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->decl;
253 current_node->remove_stmt_references (stmt);
254
255 gsi = gsi_for_stmt (stmt);
256 prev_gsi = gsi;
257 gsi_prev (&prev_gsi);
258 for (i = 0; i < len; i++)
259 {
260 struct ipa_parm_adjustment *adj;
261
262 adj = &adjustments[i];
263
264 if (adj->op == IPA_PARM_OP_COPY)
265 {
266 tree arg = gimple_call_arg (stmt, adj->base_index);
267
268 vargs.quick_push (arg);
269 }
270 else if (adj->op != IPA_PARM_OP_REMOVE)
271 {
272 tree expr, base, off;
273 location_t loc;
274 unsigned int deref_align = 0;
275 bool deref_base = false;
276
277 /* We create a new parameter out of the value of the old one, we can
278 do the following kind of transformations:
279
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).
283
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).
290
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
294 aggregate. */
295
3bed7476 296 poly_int64 byte_offset = exact_div (adj->offset, BITS_PER_UNIT);
ac762bff 297 base = gimple_call_arg (stmt, adj->base_index);
ccdd6f5c 298 loc = gimple_location (stmt);
ac762bff 299
300 if (TREE_CODE (base) != ADDR_EXPR
301 && POINTER_TYPE_P (TREE_TYPE (base)))
3bed7476 302 off = build_int_cst (adj->alias_ptr_type, byte_offset);
ac762bff 303 else
304 {
773078cb 305 poly_int64 base_offset;
ac762bff 306 tree prev_base;
307 bool addrof;
308
309 if (TREE_CODE (base) == ADDR_EXPR)
310 {
311 base = TREE_OPERAND (base, 0);
312 addrof = true;
313 }
314 else
315 addrof = false;
316 prev_base = base;
317 base = get_addr_base_and_unit_offset (base, &base_offset);
318 /* Aggregate arguments can have non-invariant addresses. */
319 if (!base)
320 {
321 base = build_fold_addr_expr (prev_base);
3bed7476 322 off = build_int_cst (adj->alias_ptr_type, byte_offset);
ac762bff 323 }
324 else if (TREE_CODE (base) == MEM_REF)
325 {
326 if (!addrof)
327 {
328 deref_base = true;
329 deref_align = TYPE_ALIGN (TREE_TYPE (base));
330 }
331 off = build_int_cst (adj->alias_ptr_type,
3bed7476 332 base_offset + byte_offset);
ac762bff 333 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1),
334 off);
335 base = TREE_OPERAND (base, 0);
336 }
337 else
338 {
339 off = build_int_cst (adj->alias_ptr_type,
3bed7476 340 base_offset + byte_offset);
ac762bff 341 base = build_fold_addr_expr (base);
342 }
343 }
344
345 if (!adj->by_ref)
346 {
347 tree type = adj->type;
348 unsigned int align;
349 unsigned HOST_WIDE_INT misalign;
350
351 if (deref_base)
352 {
353 align = deref_align;
354 misalign = 0;
355 }
356 else
357 {
358 get_pointer_alignment_1 (base, &align, &misalign);
359 if (TYPE_ALIGN (type) > align)
360 align = TYPE_ALIGN (type);
361 }
362 misalign += (offset_int::from (wi::to_wide (off),
363 SIGNED).to_short_addr ()
364 * BITS_PER_UNIT);
365 misalign = misalign & (align - 1);
366 if (misalign != 0)
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)))
377 {
378 gimple *tem = gimple_build_assign (NULL_TREE, expr);
379 if (gimple_in_ssa_p (cfun))
380 {
381 gimple_set_vuse (tem, gimple_vuse (stmt));
382 expr = make_ssa_name (TREE_TYPE (expr), tem);
383 }
384 else
385 expr = create_tmp_reg (TREE_TYPE (expr));
386 gimple_assign_set_lhs (tem, expr);
ccdd6f5c 387 gimple_set_location (tem, loc);
ac762bff 388 gsi_insert_before (&gsi, tem, GSI_SAME_STMT);
389 }
390 }
391 else
392 {
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);
398 }
399 vargs.quick_push (expr);
400 }
c64f38bf 401 if (adj->op != IPA_PARM_OP_COPY && MAY_HAVE_DEBUG_BIND_STMTS)
ac762bff 402 {
403 unsigned int ix;
404 tree ddecl = NULL_TREE, origin = DECL_ORIGIN (adj->base), arg;
405 gimple *def_temp;
406
407 arg = gimple_call_arg (stmt, adj->base_index);
408 if (!useless_type_conversion_p (TREE_TYPE (origin), TREE_TYPE (arg)))
409 {
410 if (!fold_convertible_p (TREE_TYPE (origin), arg))
411 continue;
412 arg = fold_convert_loc (gimple_location (stmt),
413 TREE_TYPE (origin), arg);
414 }
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)
418 if (ddecl == origin)
419 {
420 ddecl = (**debug_args)[ix + 1];
421 break;
422 }
423 if (ddecl == NULL)
424 {
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));
429
430 vec_safe_push (*debug_args, origin);
431 vec_safe_push (*debug_args, ddecl);
432 }
433 def_temp = gimple_build_debug_bind (ddecl, unshare_expr (arg), stmt);
434 gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
435 }
436 }
437
438 if (dump_file && (dump_flags & TDF_DETAILS))
439 {
440 fprintf (dump_file, "replacing stmt:");
441 print_gimple_stmt (dump_file, gsi_stmt (gsi), 0);
442 }
443
444 new_stmt = gimple_build_call_vec (callee_decl, vargs);
445 vargs.release ();
446 if (gimple_call_lhs (stmt))
447 gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
448
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))
455 {
456 gimple_set_vuse (new_stmt, gimple_vuse (stmt));
457 if (gimple_vdef (stmt))
458 {
459 gimple_set_vdef (new_stmt, gimple_vdef (stmt));
460 SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
461 }
462 }
463
464 if (dump_file && (dump_flags & TDF_DETAILS))
465 {
466 fprintf (dump_file, "with stmt:");
467 print_gimple_stmt (dump_file, new_stmt, 0);
468 fprintf (dump_file, "\n");
469 }
470 gsi_replace (&gsi, new_stmt, true);
471 if (cs)
472 cs->set_call_stmt (new_stmt);
473 do
474 {
475 current_node->record_stmt_references (gsi_stmt (gsi));
476 gsi_prev (&gsi);
477 }
478 while (gsi_stmt (gsi) != gsi_stmt (prev_gsi));
479}
480
481/* Return true iff BASE_INDEX is in ADJUSTMENTS more than once. */
482
483static bool
484index_in_adjustments_multiple_times_p (int base_index,
485 ipa_parm_adjustment_vec adjustments)
486{
487 int i, len = adjustments.length ();
488 bool one = false;
489
490 for (i = 0; i < len; i++)
491 {
492 struct ipa_parm_adjustment *adj;
493 adj = &adjustments[i];
494
495 if (adj->base_index == base_index)
496 {
497 if (one)
498 return true;
499 else
500 one = true;
501 }
502 }
503 return false;
504}
505
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. */
509
510ipa_parm_adjustment_vec
511ipa_combine_adjustments (ipa_parm_adjustment_vec inner,
512 ipa_parm_adjustment_vec outer)
513{
514 int i, outlen = outer.length ();
515 int inlen = inner.length ();
516 int removals = 0;
517 ipa_parm_adjustment_vec adjustments, tmp;
518
519 tmp.create (inlen);
520 for (i = 0; i < inlen; i++)
521 {
522 struct ipa_parm_adjustment *n;
523 n = &inner[i];
524
525 if (n->op == IPA_PARM_OP_REMOVE)
526 removals++;
527 else
528 {
529 /* FIXME: Handling of new arguments are not implemented yet. */
530 gcc_assert (n->op != IPA_PARM_OP_NEW);
531 tmp.quick_push (*n);
532 }
533 }
534
535 adjustments.create (outlen + removals);
536 for (i = 0; i < outlen; i++)
537 {
538 struct ipa_parm_adjustment r;
539 struct ipa_parm_adjustment *out = &outer[i];
540 struct ipa_parm_adjustment *in = &tmp[out->base_index];
541
542 memset (&r, 0, sizeof (r));
543 gcc_assert (in->op != IPA_PARM_OP_REMOVE);
544 if (out->op == IPA_PARM_OP_REMOVE)
545 {
546 if (!index_in_adjustments_multiple_times_p (in->base_index, tmp))
547 {
548 r.op = IPA_PARM_OP_REMOVE;
549 adjustments.quick_push (r);
550 }
551 continue;
552 }
553 else
554 {
555 /* FIXME: Handling of new arguments are not implemented yet. */
556 gcc_assert (out->op != IPA_PARM_OP_NEW);
557 }
558
559 r.base_index = in->base_index;
560 r.type = out->type;
561
562 /* FIXME: Create nonlocal value too. */
563
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;
570 else
571 r.offset = in->offset + out->offset;
572 adjustments.quick_push (r);
573 }
574
575 for (i = 0; i < inlen; i++)
576 {
577 struct ipa_parm_adjustment *n = &inner[i];
578
579 if (n->op == IPA_PARM_OP_REMOVE)
580 adjustments.quick_push (*n);
581 }
582
583 tmp.release ();
584 return adjustments;
585}
586
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. */
591
592static tree
593get_ssa_base_param (tree t, bool ignore_default_def)
594{
595 if (TREE_CODE (t) == SSA_NAME)
596 {
597 if (ignore_default_def || SSA_NAME_IS_DEFAULT_DEF (t))
598 return SSA_NAME_VAR (t);
599 else
600 return NULL_TREE;
601 }
602 return t;
603}
604
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.
608
609 If IGNORE_DEFAULT_DEF is set, consider SSA_NAMEs which are not a
610 default def, otherwise bail on them.
611
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. */
615
616ipa_parm_adjustment *
617ipa_get_adjustment_candidate (tree **expr, bool *convert,
618 ipa_parm_adjustment_vec adjustments,
619 bool ignore_default_def)
620{
621 if (TREE_CODE (**expr) == BIT_FIELD_REF
622 || TREE_CODE (**expr) == IMAGPART_EXPR
623 || TREE_CODE (**expr) == REALPART_EXPR)
624 {
625 *expr = &TREE_OPERAND (**expr, 0);
626 if (convert)
627 *convert = true;
628 }
629
f3c2a387 630 poly_int64 offset, size, max_size;
ac762bff 631 bool reverse;
632 tree base
633 = get_ref_base_and_extent (**expr, &offset, &size, &max_size, &reverse);
f3c2a387 634 if (!base || !known_size_p (size) || !known_size_p (max_size))
ac762bff 635 return NULL;
636
637 if (TREE_CODE (base) == MEM_REF)
638 {
90ca1268 639 offset += mem_ref_offset (base).force_shwi () * BITS_PER_UNIT;
ac762bff 640 base = TREE_OPERAND (base, 0);
641 }
642
643 base = get_ssa_base_param (base, ignore_default_def);
644 if (!base || TREE_CODE (base) != PARM_DECL)
645 return NULL;
646
647 struct ipa_parm_adjustment *cand = NULL;
648 unsigned int len = adjustments.length ();
649 for (unsigned i = 0; i < len; i++)
650 {
651 struct ipa_parm_adjustment *adj = &adjustments[i];
652
653 if (adj->base == base
3bed7476 654 && (known_eq (adj->offset, offset) || adj->op == IPA_PARM_OP_REMOVE))
ac762bff 655 {
656 cand = adj;
657 break;
658 }
659 }
660
661 if (!cand || cand->op == IPA_PARM_OP_COPY || cand->op == IPA_PARM_OP_REMOVE)
662 return NULL;
663 return cand;
664}
665
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
671 was modified. */
672
673bool
674ipa_modify_expr (tree *expr, bool convert,
675 ipa_parm_adjustment_vec adjustments)
676{
677 struct ipa_parm_adjustment *cand
678 = ipa_get_adjustment_candidate (&expr, &convert, adjustments, false);
679 if (!cand)
680 return false;
681
682 tree src;
683 if (cand->by_ref)
684 {
685 src = build_simple_mem_ref (cand->new_decl);
686 REF_REVERSE_STORAGE_ORDER (src) = cand->reverse;
687 }
688 else
689 src = cand->new_decl;
690
691 if (dump_file && (dump_flags & TDF_DETAILS))
692 {
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");
698 }
699
700 if (convert && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type))
701 {
702 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src);
703 *expr = vce;
704 }
705 else
706 *expr = src;
707 return true;
708}
709
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. */
712
713void
714ipa_dump_param_adjustments (FILE *file, ipa_parm_adjustment_vec adjustments,
715 tree fndecl)
716{
717 int i, len = adjustments.length ();
718 bool first = true;
719 vec<tree> parms = ipa_get_vector_of_formal_parms (fndecl);
720
721 fprintf (file, "IPA param adjustments: ");
722 for (i = 0; i < len; i++)
723 {
724 struct ipa_parm_adjustment *adj;
725 adj = &adjustments[i];
726
727 if (!first)
728 fprintf (file, " ");
729 else
730 first = false;
731
732 fprintf (file, "%i. base_index: %i - ", i, adj->base_index);
733 print_generic_expr (file, parms[adj->base_index]);
734 if (adj->base)
735 {
736 fprintf (file, ", base: ");
737 print_generic_expr (file, adj->base);
738 }
739 if (adj->new_decl)
740 {
741 fprintf (file, ", new_decl: ");
742 print_generic_expr (file, adj->new_decl);
743 }
744 if (adj->new_ssa_base)
745 {
746 fprintf (file, ", new_ssa_base: ");
747 print_generic_expr (file, adj->new_ssa_base);
748 }
749
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");
754 else
3bed7476 755 {
756 fprintf (file, ", offset ");
757 print_dec (adj->offset, file);
758 }
ac762bff 759 if (adj->by_ref)
760 fprintf (file, ", by_ref");
761 print_node_brief (file, ", type: ", adj->type, 0);
762 fprintf (file, "\n");
763 }
764 parms.release ();
765}
766