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>
ipa_get_vector_of_formal_parms(tree fndecl)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>
ipa_get_vector_of_formal_parm_types(tree fntype)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
ipa_modify_formal_parameters(tree fndecl,ipa_parm_adjustment_vec adjustments)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     {
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 
238 void
ipa_modify_call_arguments(struct cgraph_edge * cs,gcall * stmt,ipa_parm_adjustment_vec adjustments)239 ipa_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 
483 static bool
index_in_adjustments_multiple_times_p(int base_index,ipa_parm_adjustment_vec adjustments)484 index_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 
510 ipa_parm_adjustment_vec
ipa_combine_adjustments(ipa_parm_adjustment_vec inner,ipa_parm_adjustment_vec outer)511 ipa_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 
592 static tree
get_ssa_base_param(tree t,bool ignore_default_def)593 get_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 
616 ipa_parm_adjustment *
ipa_get_adjustment_candidate(tree ** expr,bool * convert,ipa_parm_adjustment_vec adjustments,bool ignore_default_def)617 ipa_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 
673 bool
ipa_modify_expr(tree * expr,bool convert,ipa_parm_adjustment_vec adjustments)674 ipa_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 
713 void
ipa_dump_param_adjustments(FILE * file,ipa_parm_adjustment_vec adjustments,tree fndecl)714 ipa_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