1 /* Manipulation of formal and actual parameters of functions and function 2 calls. 3 Copyright (C) 2017-2018 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 (DECL_BUILT_IN (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 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 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 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 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 * 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 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 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