+ c++;
+
+ adj = XALLOCAVEC (int, c);
+ for (i = 0; i < c; i++)
+ if (bitmap_bit_p (node->clone.combined_args_to_skip, i))
+ {
+ adj[i] = -1;
+ d++;
+ }
+ else
+ adj[i] = i - d;
+
+ for (v = aggval; v; v = v->next)
+ v->index = adj[v->index];
+}
+
+
+/* Function body transformation phase. */
+
+unsigned int
+ipcp_transform_function (struct cgraph_node *node)
+{
+ vec<ipa_param_descriptor_t> descriptors = vNULL;
+ struct param_analysis_info *parms_ainfo;
+ struct ipa_agg_replacement_value *aggval;
+ gimple_stmt_iterator gsi;
+ basic_block bb;
+ int param_count;
+ bool cfg_changed = false, something_changed = false;
+
+ gcc_checking_assert (cfun);
+ gcc_checking_assert (current_function_decl);
+
+ if (dump_file)
+ fprintf (dump_file, "Modification phase of node %s/%i\n",
+ cgraph_node_name (node), node->uid);
+
+ aggval = ipa_get_agg_replacements_for_node (node);
+ if (!aggval)
+ return 0;
+ param_count = count_formal_params (node->symbol.decl);
+ if (param_count == 0)
+ return 0;
+ adjust_agg_replacement_values (node, aggval);
+ if (dump_file)
+ ipa_dump_agg_replacement_values (dump_file, aggval);
+ parms_ainfo = XALLOCAVEC (struct param_analysis_info, param_count);
+ memset (parms_ainfo, 0, sizeof (struct param_analysis_info) * param_count);
+ descriptors.safe_grow_cleared (param_count);
+ ipa_populate_param_decls (node, descriptors);
+
+ FOR_EACH_BB (bb)
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ struct ipa_agg_replacement_value *v;
+ gimple stmt = gsi_stmt (gsi);
+ tree rhs, val, t;
+ HOST_WIDE_INT offset;
+ int index;
+ bool by_ref, vce;
+
+ if (!gimple_assign_load_p (stmt))
+ continue;
+ rhs = gimple_assign_rhs1 (stmt);
+ if (!is_gimple_reg_type (TREE_TYPE (rhs)))
+ continue;
+
+ vce = false;
+ t = rhs;
+ while (handled_component_p (t))
+ {
+ /* V_C_E can do things like convert an array of integers to one
+ bigger integer and similar things we do not handle below. */
+ if (TREE_CODE (rhs) == VIEW_CONVERT_EXPR)
+ {
+ vce = true;
+ break;
+ }
+ t = TREE_OPERAND (t, 0);
+ }
+ if (vce)
+ continue;
+
+ if (!ipa_load_from_parm_agg_1 (descriptors, parms_ainfo, stmt,
+ rhs, &index, &offset, &by_ref))
+ continue;
+ for (v = aggval; v; v = v->next)
+ if (v->index == index
+ && v->offset == offset)
+ break;
+ if (!v)
+ continue;
+
+ gcc_checking_assert (is_gimple_ip_invariant (v->value));
+ if (!useless_type_conversion_p (TREE_TYPE (rhs), TREE_TYPE (v->value)))
+ {
+ if (fold_convertible_p (TREE_TYPE (rhs), v->value))
+ val = fold_build1 (NOP_EXPR, TREE_TYPE (rhs), v->value);
+ else if (TYPE_SIZE (TREE_TYPE (rhs))
+ == TYPE_SIZE (TREE_TYPE (v->value)))
+ val = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (rhs), v->value);
+ else
+ {
+ if (dump_file)
+ {
+ fprintf (dump_file, " const ");
+ print_generic_expr (dump_file, v->value, 0);
+ fprintf (dump_file, " can't be converted to type of ");
+ print_generic_expr (dump_file, rhs, 0);
+ fprintf (dump_file, "\n");
+ }
+ continue;
+ }
+ }
+ else
+ val = v->value;
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Modifying stmt:\n ");
+ print_gimple_stmt (dump_file, stmt, 0, 0);
+ }
+ gimple_assign_set_rhs_from_tree (&gsi, val);
+ update_stmt (stmt);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "into:\n ");
+ print_gimple_stmt (dump_file, stmt, 0, 0);
+ fprintf (dump_file, "\n");
+ }
+
+ something_changed = true;
+ if (maybe_clean_eh_stmt (stmt)
+ && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
+ cfg_changed = true;
+ }
+
+ (*ipa_node_agg_replacements)[node->uid] = NULL;
+ free_parms_ainfo (parms_ainfo, param_count);
+ descriptors.release ();
+
+ if (!something_changed)
+ return 0;
+ else if (cfg_changed)
+ return TODO_update_ssa_only_virtuals | TODO_cleanup_cfg;