diff options
Diffstat (limited to 'gcc/ipa-structure-reorg.c')
-rw-r--r-- | gcc/ipa-structure-reorg.c | 250 |
1 files changed, 203 insertions, 47 deletions
diff --git a/gcc/ipa-structure-reorg.c b/gcc/ipa-structure-reorg.c index fbba1227d70..9ef52d37921 100644 --- a/gcc/ipa-structure-reorg.c +++ b/gcc/ipa-structure-reorg.c @@ -70,6 +70,10 @@ static bool reorg_legality ( Info *); static void reorg_common_middle_code ( Info *); static void modify_declarations ( Info *); static bool modify_func_decl_core ( struct function *, Info *); +static void adjust_result_decl ( struct function *); +static tree modify_func_type ( struct function *, Info *); +static bool needs_modification_p ( struct function *, Info *); +static int number_of_levels ( tree); //static void modify_decl_core ( tree *, Info *); static void reorg_forbidden ( gimple *, Info *); // Name changed and moved to its own file @@ -136,10 +140,10 @@ ipa_structure_reorg ( void) DEBUG_F( ssa_check, stderr, Show_everything, Do_not_fail, false, true); setup_debug_flags ( &info); - //initial_debug_info ( &info); + initial_debug_info ( &info); - DEBUG_L(""); - DEBUG_F( wolf_fence, &info); + //DEBUG_L(""); + //DEBUG_F( wolf_fence, &info); if ( !reorg_analysis ( &info) ) { @@ -150,8 +154,8 @@ ipa_structure_reorg ( void) bool qualified = reorg_qualification(&info); DEBUG_L("after reorg_qualification\n"); - DEBUG_L(""); - DEBUG_F(wolf_fence, &info); + //DEBUG_L(""); + //DEBUG_F(wolf_fence, &info); if ( qualified ) @@ -174,8 +178,8 @@ ipa_structure_reorg ( void) //DEBUG_L("before str_reorg_instance_interleave_qual\n"); str_reorg_instance_interleave_qual ( &info); //DEBUG_L("after str_reorg_instance_interleave_qual\n"); - DEBUG_L(""); - DEBUG_F(wolf_fence, &info); + //DEBUG_L(""); + //DEBUG_F(wolf_fence, &info); } @@ -187,8 +191,8 @@ ipa_structure_reorg ( void) reorg_common_middle_code( &info); // ??? might not amount to anything DEBUG_L("after reorg_common_middle_code\n"); - DEBUG_L(""); - DEBUG_F(wolf_fence, &info); + //DEBUG_L(""); + //DEBUG_F(wolf_fence, &info); if ( flag_ipa_structure_reorg || flag_ipa_dead_field_eliminate ) { @@ -981,18 +985,183 @@ modify_declarations ( Info *info) // NOTE, Call modufy_decl_core breaks hello world! // Modify the declaration of the function type itself. + // Note, create a new declaration if necessary. If this + // loop already created and the function is seen a second + // time reuse the previous one created. + + // Note, most of the function type stuff can use memoization but + // it's not worth doing unless it proves to be a significant + // performance issue. This is what fncache is all about. But it's + // used not to save time but to guarantee that if two functions have + // the same type before this exercise, their new types will be + // equal afterwards. + std::map <tree,tree> fncache; + struct cgraph_node *node; FOR_EACH_FUNCTION_WITH_GIMPLE_BODY ( node) + { struct function *func = DECL_STRUCT_FUNCTION ( node->decl); - push_cfun ( func); // Is push and necessary? + push_cfun ( func); // Is this necessary? + tree curr_func_type = TREE_TYPE ( func->decl); + + #if 0 modify_func_decl_core ( func, info); + #else + + // TBD Check cached function type. If the decl's type + // has been modified use the cached new type. + auto location = fncache.find ( curr_func_type); + tree old_ret_type = TREE_TYPE ( TREE_TYPE ( func->decl)); + if ( location != fncache.end () ) + { + TREE_TYPE ( func->decl) = location->second; + + // The function type can be cached but this must be created + // anew for any function who's return type has changed + if ( old_ret_type != TREE_TYPE ( TREE_TYPE ( func->decl)) ) + { + adjust_result_decl ( func); + } + + pop_cfun (); + continue; + } + + // check if funtion type needs modification. + if ( needs_modification_p ( func, info) ) + { + // Create new type and set the decl's type to it. + tree new_func_type = modify_func_type ( func, info); + + if ( old_ret_type != TREE_TYPE ( new_func_type)) + { + adjust_result_decl ( func); + } + + // Add the type to the cache. + fncache [ curr_func_type] = new_func_type; + } + #endif pop_cfun (); } // Note, do not relayout functions decls.... } +static void +adjust_result_decl ( struct function *func) +{ + tree func_decl = func->decl; + tree ret_type = TREE_TYPE ( TREE_TYPE ( func_decl)); + tree decl_result; + + decl_result = + build_decl ( DECL_SOURCE_LOCATION ( func_decl), + RESULT_DECL, NULL_TREE, ret_type); + DECL_RESULT ( func_decl) = decl_result; + DECL_CONTEXT ( decl_result) = func_decl; +} + + +static tree +modify_func_type ( struct function *func, Info *info ) +{ + tree func_type = TREE_TYPE ( func->decl); + DEBUG_L("old func_type = "); + DEBUG_F( flexible_print, stderr, func_type, 1, (dump_flags_t)0); + INDENT(4); + tree new_type; + tree func_ret_type = TREE_TYPE ( func_type); + tree base = base_type_of ( func_ret_type); + + ReorgType_t *ri = get_reorgtype_info ( base, info); + if ( ri != NULL ) + { + // TBD Do level based stuff here + if ( number_of_levels ( func_ret_type ) == 1 ) + { + func_ret_type = TYPE_MAIN_VARIANT ( ri->pointer_rep); + } + else + { + gcc_assert(0); + } + } + tree arg; + tree new_args = NULL_TREE; + //DEBUG_A("old arg = "); + //DEBUG_F( flexible_print, stderr, arg, 1, (dump_flags_t)0); + for ( arg = TYPE_ARG_TYPES ( func_type); + arg != NULL && arg != void_list_node; + arg = TREE_CHAIN ( arg)) + { + //DEBUG_L("arg: "); + //DEBUG_F( flexible_print, stderr, arg, 1, (dump_flags_t)0); + + tree type_of_arg = TREE_VALUE (arg); + //DEBUG_L("type_of_arg: "); + //DEBUG_F( flexible_print, stderr, type_of_arg, 1, (dump_flags_t)0); + base = base_type_of ( type_of_arg); + //DEBUG_L("base: "); + //DEBUG_F( flexible_print, stderr, base, 1, (dump_flags_t)0); + + tree new_arg_type; + ri = get_reorgtype_info ( base, info); + if ( ri != NULL ) + { + if ( number_of_levels ( type_of_arg ) == 1 ) + { + new_arg_type = TYPE_MAIN_VARIANT ( ri->pointer_rep); + } + else + { + gcc_assert(0); + } + } + else + { + new_arg_type = type_of_arg; + } + new_args = tree_cons ( NULL_TREE, new_arg_type, new_args); + //DEBUG_A("interim new_args = "); + //DEBUG_F( flexible_print, stderr, new_args, 1, (dump_flags_t)0); + } + //DEBUG_A("before reverse new_args = "); + //DEBUG_F( flexible_print, stderr, new_args, 1, (dump_flags_t)0); + tree last = new_args; + new_args = nreverse ( new_args); + TREE_CHAIN ( last) = void_list_node; + + DEBUG_A("new args = "); + DEBUG_F( flexible_print, stderr, new_args, 1, (dump_flags_t)0); + INDENT(-4); + + new_type = build_function_type ( func_ret_type, new_args); + DEBUG_L("new_type (func) = "); + DEBUG_F( flexible_print, stderr, new_type, 1, (dump_flags_t)0); + TREE_TYPE ( func->decl) = new_type; + return new_type; +} + +static bool +needs_modification_p ( struct function *func, Info *info ) +{ + tree func_type = TREE_TYPE ( func->decl); + tree ret_type = TREE_TYPE ( func_type); + tree base = base_type_of ( ret_type); + if ( get_reorgtype_info ( base, info) != NULL ) return true; + + tree arg; + for ( arg = TYPE_ARG_TYPES ( func_type); arg != NULL; arg = TREE_CHAIN ( arg)) + { + base = base_type_of ( ret_type); + if ( get_reorgtype_info ( base, info) != NULL ) return true; + } + + return false; +} + static int number_of_levels ( tree type) { @@ -1014,14 +1183,11 @@ modify_func_decl_core ( struct function *func, Info *info) //DEBUG_L("BEFORE modify_func_decl_core:\n"); //INDENT(4); //DEBUG_A("func->decl = %p, ", func->decl); - //DEBUG_F( flexible_print, stderr, func->decl, (dump_flags_t)0); - //DEBUG("\n"); + //DEBUG_F( flexible_print, stderr, func->decl, 1, (dump_flags_t)0); //DEBUG_A("TREE_TYPE (func->decl) = %p, ", TREE_TYPE (func->decl)); - //DEBUG_F( flexible_print, stderr, TREE_TYPE (func->decl), (dump_flags_t)0); - //DEBUG("\n"); + //DEBUG_F( flexible_print, stderr, TREE_TYPE (func->decl), 1, (dump_flags_t)0); //DEBUG_A("TREE_TYPE(TREE_TYPE (func->decl)) = %p, ", TREE_TYPE(TREE_TYPE (func->decl))); - //DEBUG_F( flexible_print, stderr, TREE_TYPE(TREE_TYPE (func->decl)), (dump_flags_t)0); - //DEBUG("\n"); + //DEBUG_F( flexible_print, stderr, TREE_TYPE(TREE_TYPE (func->decl)), 1, (dump_flags_t)0); // TBD Implement tree *func_type_loc = &(TREE_TYPE(TREE_TYPE (func->decl))); tree func_type = *func_type_loc; @@ -1035,12 +1201,9 @@ modify_func_decl_core ( struct function *func, Info *info) return false; } //DEBUG_A("pointer_rep = "); - //DEBUG_F( flexible_print, stderr, ri->pointer_rep, (dump_flags_t)0); - //DEBUG("\n"); + //DEBUG_F( flexible_print, stderr, ri->pointer_rep, 1, (dump_flags_t)0); //DEBUG_A("TYPE_MAIN_VARIANT( pointer_rep) = "); - //DEBUG_F( flexible_print, stderr, TYPE_MAIN_VARIANT( ri->pointer_rep),(dump_flags_t)0); - //DEBUG("\n"); - + //DEBUG_F( flexible_print, stderr, TYPE_MAIN_VARIANT( ri->pointer_rep), 1, (dump_flags_t)0); int levels = number_of_levels ( func_type); @@ -1064,14 +1227,11 @@ modify_func_decl_core ( struct function *func, Info *info) //DEBUG_L("AFTER modify_func_decl_core:\n"); //DEBUG_A("func->decl = %p, ", func->decl); - //DEBUG_F( flexible_print, stderr, func->decl, (dump_flags_t)0); - //DEBUG("\n"); + //DEBUG_F( flexible_print, stderr, func->decl, 1, (dump_flags_t)0); //DEBUG_A("TREE_TYPE (func->decl) = %p, ", TREE_TYPE (func->decl)); - //DEBUG_F( flexible_print, stderr, TREE_TYPE (func->decl), (dump_flags_t)0); - //DEBUG("\n"); + //DEBUG_F( flexible_print, stderr, TREE_TYPE (func->decl), 1, (dump_flags_t)0); //DEBUG_A("TREE_TYPE(TREE_TYPE (func->decl)) = %p, ", TREE_TYPE(TREE_TYPE (func->decl))); - //DEBUG_F( flexible_print, stderr, TREE_TYPE(TREE_TYPE (func->decl)), (dump_flags_t)0); - //DEBUG("\n"); + //DEBUG_F( flexible_print, stderr, TREE_TYPE(TREE_TYPE (func->decl)), 1, (dump_flags_t)0); //INDENT(-4); return true; @@ -1084,15 +1244,13 @@ bool modify_decl_core ( tree *location, Info *info) { //DEBUG_L("before modify_decl_core: "); - //DEBUG_F( flexible_print, stderr, *location, (dump_flags_t)0); - //DEBUG("\n"); + //DEBUG_F( flexible_print, stderr, *location, 1, (dump_flags_t)0); tree type = *location; //DEBUG_A("type = "); - //DEBUG_F( flexible_print, stderr, type, (dump_flags_t)0); + //DEBUG_F( flexible_print, stderr, type, 0, (dump_flags_t)0); tree base = base_type_of ( type); //DEBUG_A(", base = "); - //DEBUG_F( flexible_print, stderr, base, (dump_flags_t)0); - //DEBUG("\n"); + //DEBUG_F( flexible_print, stderr, base, 1, (dump_flags_t)0); ReorgType_t *ri = get_reorgtype_info ( base, info); if ( ri == NULL ) { @@ -1149,15 +1307,13 @@ bool modify_decl_core ( tree *location, Info *info) { //DEBUG_L("before modify_decl_core: "); - //DEBUG_F( flexible_print, stderr, *location, (dump_flags_t)0); - //DEBUG("\n"); + //DEBUG_F( flexible_print, stderr, *location, 1, (dump_flags_t)0); tree type = *location; //DEBUG_A("type = "); - //DEBUG_F( flexible_print, stderr, type, (dump_flags_t)0); + //DEBUG_F( flexible_print, stderr, type, 0, (dump_flags_t)0); tree base = base_type_of ( type); //DEBUG_A(", base = "); - //DEBUG_F( flexible_print, stderr, base, (dump_flags_t)0); - //DEBUG("\n"); + //DEBUG_F( flexible_print, stderr, base, 1, (dump_flags_t)0); ReorgType_t *ri = get_reorgtype_info ( base, info); if ( ri == NULL ) { @@ -1848,7 +2004,7 @@ get_reorgtype_info ( tree type, Info* info) // Remember, the same_type_p here is my own temporary hack. //DEBUG_L(""); //DEBUG_F( print_generic_expr, stderr, type, TDF_DETAILS); - // DEBUG("\n"); + //DEBUG("\n"); if ( same_type_p ( ri->gcc_type, type) ) { //DEBUG_A( " returns %p\n", &(*ri)); @@ -1910,16 +2066,13 @@ static tree detect_reorg_in_expr ( tree *tp, int *w_s, void *data) { //DEBUG_L("*tp = "); - //DEBUG_F( flexible_print, stderr, *tp, (dump_flags_t)0); - //DEBUG("\n") + //DEBUG_F( flexible_print, stderr, *tp, 1, (dump_flags_t)0); hidden_info_t *tre_hi = ( hidden_info_t *)data; //DEBUG_L("TREE_TYPE ( *tp) = "); - //DEBUG_F( flexible_print, stderr, TREE_TYPE ( *tp), (dump_flags_t)0); - //DEBUG("\n") + //DEBUG_F( flexible_print, stderr, TREE_TYPE ( *tp), 1, (dump_flags_t)0); tree operand = base_type_of ( TREE_TYPE ( *tp)); //DEBUG_L("operand = %p, ", operand); - DEBUG_F( flexible_print, stderr, operand, (dump_flags_t)0); - DEBUG("\n"); + DEBUG_F( flexible_print, stderr, operand, 1, (dump_flags_t)0); ReorgType_t *ri = get_reorgtype_info ( operand, tre_hi->info); if ( ri != NULL ) { @@ -2111,10 +2264,12 @@ print_program ( FILE *file, bool my_format, int leading_space, Info_t *info) struct function *func = DECL_STRUCT_FUNCTION ( node->decl); if ( my_format ) { + flexible_print ( file, TREE_TYPE( func->decl), 1, (dump_flags_t)0); print_function ( file, leading_space + 4, func); } else { + flexible_print ( file, TREE_TYPE( func->decl), 1, (dump_flags_t)0); dump_function_header ( file, func->decl, (dump_flags_t)0); dump_function_to_file ( func->decl, file, (dump_flags_t)0); } @@ -2471,7 +2626,7 @@ wolf_fence ( { if ( ssa_check ( stderr, Show_failures, Fail_1st_bad, false, false) ) { - fprintf ( stderr, "Wolf! : "); + fprintf ( stderr, "Wolf!\n"); gcc_assert (0); } @@ -2532,8 +2687,9 @@ ssa_check ( FILE *file, Display display, Failure failure, bool types, bool heade return failure != Do_not_fail && has_a_failure; } +#endif void -flexible_print( FILE *f, tree t, dump_flags_t d) +flexible_print( FILE *f, tree t, int nl, dump_flags_t d) { if ( DECL_P( t) ) { @@ -2543,8 +2699,8 @@ flexible_print( FILE *f, tree t, dump_flags_t d) { print_generic_expr(f,t,d); } + if ( nl ) fprintf ( f, "\n"); } -#endif //---------------- Pass Control Follows ---------------- |