ipa-param-manipulation.c revision 1.1.1.2
1/* Manipulation of formal and actual parameters of functions and function
2   calls.
3   Copyright (C) 2017-2019 Free Software Foundation, Inc.
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.  */
221  if (fndecl_built_in_p (fndecl))
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
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);
299
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);
303	  else
304	    {
305	      poly_int64 base_offset;
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);
322		  off = build_int_cst (adj->alias_ptr_type, byte_offset);
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,
332				       base_offset + byte_offset);
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,
340				       base_offset + byte_offset);
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);
387		  gimple_set_location (tem, loc);
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	}
401      if (adj->op != IPA_PARM_OP_COPY && MAY_HAVE_DEBUG_BIND_STMTS)
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
630  poly_int64 offset, size, max_size;
631  bool reverse;
632  tree base
633    = get_ref_base_and_extent (**expr, &offset, &size, &max_size, &reverse);
634  if (!base || !known_size_p (size) || !known_size_p (max_size))
635    return NULL;
636
637  if (TREE_CODE (base) == MEM_REF)
638    {
639      offset += mem_ref_offset (base).force_shwi () * BITS_PER_UNIT;
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
654	  && (known_eq (adj->offset, offset) || adj->op == IPA_PARM_OP_REMOVE))
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
755	{
756	  fprintf (file, ", offset ");
757	  print_dec (adj->offset, file);
758	}
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
767