[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