[C++/cgraph] Middle-end thunk support
Martin Jambor
mjambor@suse.cz
Wed Nov 25 14:00:00 GMT 2009
Hi,
On Sun, Nov 22, 2009 at 07:01:11PM +0100, Jan Hubicka wrote:
> Hi,
> to avoid uncomplette transition, here is updated patch with generic
> thunk codegen. Thunks are now generated as lowered gimple functions.
> (it might be bit easier to adjust existing code to use C++ FE
> independent functions and gimplifier, but it seems cleaner at this
> stage to operate at gimple. Plus I seem to generate more optimized IL
> saving some instructions even when thunks are optimized with -O2)
Nice. Just three rather minor comments:
> Index: cgraph.c
> ===================================================================
> *** cgraph.c (revision 154387)
> --- cgraph.c (working copy)
...
> *************** dump_cgraph_node (FILE *f, struct cgraph
> *** 1646,1651 ****
> --- 1680,1705 ----
> fprintf(f, "(can throw external) ");
> }
> fprintf (f, "\n");
> +
> + if (node->same_body)
> + {
> + struct cgraph_node *n;
> + fprintf (f, " aliases & thunks:");
> + for (n = node->same_body; n; n = n->next)
> + {
> + fprintf (f, " %s", cgraph_node_name (n));
Can you please dump also the UID like you do everywhere else? With
long C++ names, uids are the only hope to quickly identify the nodes I
am after.
> + if (n->thunk.thunk_p)
> + {
> + fprintf (f, " (thunk of %s fixed ofset %i virtual value %i has virtual offset %i",
> + lang_hooks.decl_printable_name (n->thunk.alias, 2),
> + (int)n->thunk.fixed_offset,
> + (int)n->thunk.virtual_value,
> + (int)n->thunk.virtual_offset_p);
> + fprintf (f, ")");
> + }
> + }
> + fprintf (f, "\n");
> + }
> }
...
>
>
> Index: cgraphunit.c
> ===================================================================
> *** cgraphunit.c (revision 154387)
> --- cgraphunit.c (working copy)
...
> + static tree
> + thunk_adjust (gimple_stmt_iterator * bsi,
> + tree ptr, bool this_adjusting,
> + HOST_WIDE_INT fixed_offset, tree virtual_offset)
> + {
> + gimple stmt;
> + tree ret;
> +
> + if (this_adjusting)
> + {
> + stmt = gimple_build_assign (ptr,
> + fold_build2_loc (input_location,
> + POINTER_PLUS_EXPR,
> + TREE_TYPE (ptr), ptr,
> + size_int (fixed_offset)));
> + gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
> + }
> +
> + /* If there's a virtual offset, look up that value in the vtable and
> + adjust the pointer again. */
> + if (virtual_offset)
> + {
> + tree vtabletmp;
> + tree vtabletmp2;
> + tree vtabletmp3;
> + tree vtable_entry_type;
> + tree offsettmp;
> +
> + tree vfunc_type = make_node (FUNCTION_TYPE);
> + TREE_TYPE (vfunc_type) = integer_type_node;
> + TYPE_ARG_TYPES (vfunc_type) = NULL_TREE;
> + layout_type (vfunc_type);
> +
> + vtable_entry_type = build_pointer_type (vfunc_type);
> +
> + vtabletmp =
> + create_tmp_var (build_pointer_type
> + (build_pointer_type (vtable_entry_type)), "vptr");
> +
> + /* The vptr is always at offset zero in the object. */
> + stmt = gimple_build_assign (vtabletmp,
> + build1 (NOP_EXPR, TREE_TYPE (vtabletmp),
> + ptr));
> + gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
> + mark_symbols_for_renaming (stmt);
> + find_referenced_vars_in (stmt);
> +
> + /* Form the vtable address. */
> + vtabletmp2 = create_tmp_var (TREE_TYPE (TREE_TYPE (vtabletmp)),
> + "vtableaddr");
> + stmt = gimple_build_assign (vtabletmp2,
> + build1 (INDIRECT_REF,
> + TREE_TYPE (vtabletmp2), vtabletmp));
> + gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
> + mark_symbols_for_renaming (stmt);
> + find_referenced_vars_in (stmt);
> +
> + /* Find the entry with the vcall offset. */
> + stmt = gimple_build_assign (vtabletmp2,
> + fold_build2_loc (input_location,
> + POINTER_PLUS_EXPR,
> + TREE_TYPE (vtabletmp2),
> + vtabletmp2,
> + fold_convert (sizetype,
> + virtual_offset)));
> + gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
> +
> + /* Get the offset itself. */
> + vtabletmp3 = create_tmp_var (TREE_TYPE (TREE_TYPE (vtabletmp2)),
> + "vcalloffset");
> + stmt = gimple_build_assign (vtabletmp3,
> + build1 (INDIRECT_REF,
> + TREE_TYPE (vtabletmp3),
> + vtabletmp2));
> + gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
> + mark_symbols_for_renaming (stmt);
> + find_referenced_vars_in (stmt);
> +
> + /* Cast to sizetype. */
> + offsettmp = create_tmp_var (sizetype, "offset");
> + stmt = gimple_build_assign (offsettmp, fold_convert (sizetype, vtabletmp3));
> + gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
> + mark_symbols_for_renaming (stmt);
> + find_referenced_vars_in (stmt);
> +
> + /* Adjust the `this' pointer. */
> + ptr = fold_build2_loc (input_location,
> + POINTER_PLUS_EXPR, TREE_TYPE (ptr), ptr,
> + offsettmp);
> + }
> +
> + if (!this_adjusting)
> + /* Adjust the pointer by the constant. */
> + {
> + tree ptrtmp;
> +
> + if (TREE_CODE (ptr) == VAR_DECL)
> + ptrtmp = ptr;
> + else
> + {
> + ptrtmp = create_tmp_var (TREE_TYPE (ptr), "ptr");
> + stmt = gimple_build_assign (ptrtmp, ptr);
> + gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
> + mark_symbols_for_renaming (stmt);
> + find_referenced_vars_in (stmt);
> + }
I think that force_gimple_operand_gsi is what you want to use instead
of the whole if statement above.
> + ptr = fold_build2_loc (input_location,
> + POINTER_PLUS_EXPR, TREE_TYPE (ptrtmp), ptrtmp,
> + size_int (fixed_offset));
> + }
> +
> + /* Emit the statement and gimplify the adjustment expression. */
> + ret = create_tmp_var (TREE_TYPE (ptr), "adjusted_this");
> + stmt = gimple_build_assign (ret, ptr);
> + mark_symbols_for_renaming (stmt);
> + find_referenced_vars_in (stmt);
> + gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
> +
> + return ret;
> + }
...
> Index: ira.c
> ===================================================================
> *** ira.c (revision 154387)
> --- ira.c (working copy)
> *************** ira (FILE *f)
> *** 3172,3177 ****
> --- 3172,3178 ----
>
> ira_assert (current_loops == NULL);
> flow_loops_find (&ira_loops);
> + record_loop_exits ();
> current_loops = &ira_loops;
>
> if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
> *************** ira (FILE *f)
> *** 3215,3220 ****
> --- 3216,3222 ----
> df_analyze ();
>
> flow_loops_find (&ira_loops);
> + record_loop_exits ();
> current_loops = &ira_loops;
>
> setup_allocno_assignment_flags ();
These changes look rather unrelated and are not in the Changelog so I
guess it is also unintentional?
Thanks,
Martin
More information about the Gcc-patches
mailing list