diff options
author | Gary Oblock <gary@amperecomputing.com> | 2020-09-24 21:17:52 -0700 |
---|---|---|
committer | Gary Oblock <gary@amperecomputing.com> | 2020-09-24 21:17:52 -0700 |
commit | da7f413db3ef1c74549329a202aec1d4e5ad950c (patch) | |
tree | 660f8cb52d85e08ac3fd7ec87a2f1600b60ead12 | |
parent | 24ccc02f2498bbe0d4ecb2ec8c5ff7f71277bf7a (diff) |
All the changes from the other branch plus a few changes to help
with the structure assignment transformation.
-rw-r--r-- | gcc/ipa-str-reorg-instance-interleave.c | 376 | ||||
-rw-r--r-- | gcc/ipa-structure-reorg.c | 192 |
2 files changed, 303 insertions, 265 deletions
diff --git a/gcc/ipa-str-reorg-instance-interleave.c b/gcc/ipa-str-reorg-instance-interleave.c index 3a64f26afd8..1d0213f1427 100644 --- a/gcc/ipa-str-reorg-instance-interleave.c +++ b/gcc/ipa-str-reorg-instance-interleave.c @@ -36,7 +36,6 @@ along with GCC; see the file COPYING3. If not see #include <set> #include "ipa-structure-reorg.h" #include "dumpfile.h" -#include "tree-cfg.h" #include "tree-pretty-print.h" #include "gimple-pretty-print.h" #include "langhooks.h" @@ -48,20 +47,22 @@ along with GCC; see the file COPYING3. If not see #include "cfghooks.h" #include "function.h" #include "cfgloop.h" +#include "wide-int.h" static void wrangle_ssa_type( tree, Info_t*); //static bool print_internals (gimple *, void *); static void str_reorg_instance_interleave_qual_part ( Info *); -static double cut_off_eq_single_pool( double); static void str_reorg_instance_interleave_type_part ( Info *); static void header ( bool); +static double cut_off_eq_single_pool( double); +static double alignment_effect( unsigned HOST_WIDE_INT); static void create_new_types ( Info_t *); static void create_a_new_type ( Info_t *, tree); static unsigned int reorg_perf_qual ( Info *); static tree find_coresponding_field ( tree, tree); static void remove_default_def ( tree, struct function *); static void set_lhs_for ( gimple *, tree); - +static basic_block make_bb ( char *, basic_block); // These are local to this file by design #define REORG_SP_PTR_PREFIX "_reorg_SP_ptr_type_" @@ -634,10 +635,6 @@ str_reorg_instance_interleave_trans ( Info *info) case ReorgT_Malloc: { DEBUG_L("Transform ReorgT_Malloc\n"); - - DEBUG_L("BEFORE MALLOC ===========================================\n"); - DEBUG_F( dump_function_to_file, func->decl, stderr, (dump_flags_t)0); - INDENT(2); // We need to use the user malloc function @@ -718,15 +715,9 @@ str_reorg_instance_interleave_trans ( Info *info) basic_block after_bb = new_edge->dest; remove_edge ( new_edge); basic_block prev_bb = before_bb; - - DEBUG_L("Before <bb %d>:\n", before_bb->index); - INDENT(4); - DEBUG_A("");DEBUG_F( print_gimple_stmt, stderr, gcast_arg, 0); - DEBUG_A("");DEBUG_F( print_gimple_stmt, stderr, glen, 0); - INDENT(-4); // FROM failure_bb = create_empty_block(prev_bb) - basic_block failure_bb = create_empty_bb ( prev_bb); + basic_block failure_bb = make_bb ( "failure_bb", prev_bb); // I need to set the count to zero and there doesn't // seem to be direct way of doing this... failure_bb->count = prev_bb->count - prev_bb->count; @@ -776,8 +767,6 @@ str_reorg_instance_interleave_trans ( Info *info) // This, after the following loop, will hold the start of the // field related code. - DEBUG_L("Field Allocation Blocks Follow:\n"); - INDENT(4); tree new_ok_field_L; // FROM (for fields) { @@ -786,7 +775,7 @@ str_reorg_instance_interleave_trans ( Info *info) field; field = DECL_CHAIN( field)) { - basic_block new_bb = create_empty_bb ( prev_order); + basic_block new_bb = make_bb ( "new_bb", prev_order); new_bb->count = prev_order->count; // Nope! Don't do this. //set_immediate_dominator ( CDI_DOMINATORS, new_bb, prev_bb); @@ -812,6 +801,7 @@ str_reorg_instance_interleave_trans ( Info *info) //DEBUG("\n"); gimple_stmt_iterator gsi = gsi_start_bb ( new_bb); + // Note, switching the order of edge creation and // setting dominator seems to make no difference // set edge probability and flags @@ -840,10 +830,6 @@ str_reorg_instance_interleave_trans ( Info *info) base, base_field, NULL_TREE); - DEBUG_A("Field "); - DEBUG_F(flexible_print, stderr, base_field, 0, (dump_flags_t)0); - DEBUG_A(", <bb %d>\n"); - //DEBUG_L("base: %p\n", base); //DEBUG_A(" base: "); //DEBUG_F(print_generic_expr, stderr, base, (dump_flags_t)0); @@ -945,20 +931,10 @@ str_reorg_instance_interleave_trans ( Info *info) gsi_insert_after ( &gsi, gcast_res, GSI_CONTINUE_LINKING); gsi_insert_after ( &gsi, gset_field, GSI_CONTINUE_LINKING); gsi_insert_after ( &gsi, gcond, GSI_CONTINUE_LINKING); - - INDENT(4); - DEBUG_A("");DEBUG_F( print_gimple_stmt, stderr, gfield_size, 0); - DEBUG_A("");DEBUG_F( print_gimple_stmt, stderr, gsize, 0); - DEBUG_A("");DEBUG_F( print_gimple_stmt, stderr, malloc_call, 0); - DEBUG_A("");DEBUG_F( print_gimple_stmt, stderr, gcast_res, 0); - DEBUG_A("");DEBUG_F( print_gimple_stmt, stderr, gset_field, 0); - DEBUG_A("");DEBUG_F( print_gimple_stmt, stderr, gcond, 0); - INDENT(-4); prev_bb = new_bb; prev_order = new_bb; } - INDENT(-4); // Loop cleaup fo failure code bb here. There is loop state // overhead having nothing to do with the transformation @@ -968,7 +944,7 @@ str_reorg_instance_interleave_trans ( Info *info) // create basic block for success // // FROM success_bb = create_empty_block(prev_bb_order); - basic_block success_bb = create_empty_bb ( prev_bb); + basic_block success_bb = make_bb ( "succ_bb", prev_bb); success_bb->count = prev_bb->count; // NOTE, it seems I shouldn't be attempting @@ -983,8 +959,7 @@ str_reorg_instance_interleave_trans ( Info *info) succ_to_after_e->count () = prev_bb->count; add_bb_to_loop ( success_bb, before_bb->loop_father); - // Code In success_bb - DEBUG_L("Success Code Here <bb %d>:\n", success_bb->index); + // code in success_bb // gcc_assert ( reorg_pointer_type); tree success_val = @@ -998,14 +973,12 @@ str_reorg_instance_interleave_trans ( Info *info) SSA_NAME_DEF_STMT ( success_val) = set_succ; gsi_insert_after( &gsi, set_succ, GSI_NEW_STMT); - DEBUG_F( print_gimple_stmt, stderr, set_succ, 0); // FROM gsi_insert_after( &gsi, new_ok_field ) //gimple *gnew_ok_field = gimple_build_label ( new_ok_field_L); //gsi_insert_after ( &gsi, gnew_ok_field, GSI_SAME_STMT); - - // Add Code To after_bb - DEBUG_L("After Code Here <bb %d>:\n", after_bb->index); + + // add code to after_bb // // FROM gsi = gsi_start_bb( after_bb) // Reuse gsi @@ -1030,7 +1003,6 @@ str_reorg_instance_interleave_trans ( Info *info) //gsi_insert_after( &gsi, gm_cast_phi_val, GSI_NEW_STMT); // TBD What does GSI_NEW_STMT do if the block isn't emply? gsi_insert_before( &gsi, gm_cast_phi_val, GSI_NEW_STMT); - DEBUG_F( print_gimple_stmt, stderr, gm_cast_phi_val, 0); //// FROM gsi_insert_after( &gsi, after_label) //gimple *gafter_label = gimple_build_label( after_label_L); @@ -1038,7 +1010,6 @@ str_reorg_instance_interleave_trans ( Info *info) // failure_bb code here - DEBUG_L("Failure Code Here <bb %d>:\n", failure_bb->index); // // FROM fail_val is new SSA @@ -1055,7 +1026,6 @@ str_reorg_instance_interleave_trans ( Info *info) SSA_NAME_DEF_STMT ( fail_val) = gretnull; gsi_insert_after( &gsi, gretnull, GSI_NEW_STMT); - DEBUG_F( print_gimple_stmt, stderr, gretnull, 0); for( field = TYPE_FIELDS( reorg_type); field; @@ -1078,7 +1048,6 @@ str_reorg_instance_interleave_trans ( Info *info) SSA_NAME_DEF_STMT ( m_to_free) = gaddr2free; gsi_insert_after( &gsi, gaddr2free, GSI_CONTINUE_LINKING); - DEBUG_F( print_gimple_stmt, stderr, gaddr2free, 0); gcc_assert ( ptr_type_node); tree m_cast2free = @@ -1089,11 +1058,9 @@ str_reorg_instance_interleave_trans ( Info *info) SSA_NAME_DEF_STMT ( m_cast2free) = gm_cast2free; gsi_insert_after( &gsi, gm_cast2free, GSI_CONTINUE_LINKING); - DEBUG_F( print_gimple_stmt, stderr, gm_cast2free, 0); gcall *free_call = gimple_build_call( fndecl_free, 1, m_cast2free); gsi_insert_after( &gsi, free_call, GSI_CONTINUE_LINKING); - DEBUG_F( print_gimple_stmt, stderr, free_call, 0); cgraph_node::get ( cfun->decl)-> create_edge ( cgraph_node::get_create ( fndecl_free), @@ -1108,7 +1075,6 @@ str_reorg_instance_interleave_trans ( Info *info) gimple *gzero = gimple_build_assign( lhs_ass, null_pointer_node); gsi_insert_after( &gsi, gzero, GSI_CONTINUE_LINKING); - DEBUG_F( print_gimple_stmt, stderr, free_call, 0); } //// FROM gsi_insert_after( &gsi, bad_field ) @@ -1117,10 +1083,6 @@ str_reorg_instance_interleave_trans ( Info *info) //DEBUG_F( print_program, PRINT_FORMAT, stderr, 4); } INDENT(-2); - - DEBUG_L("AFTER MALLOC ===========================================\n"); - DEBUG_F( dump_function_to_file, func->decl, stderr, (dump_flags_t)0); - break; case ReorgT_Calloc: // TBD @@ -1716,11 +1678,6 @@ str_reorg_instance_interleave_trans ( Info *info) } #endif - if ( dom_info_available_p ( CDI_DOMINATORS)) - { - free_dominance_info (CDI_DOMINATORS); - } - pop_cfun (); } @@ -1926,9 +1883,9 @@ str_reorg_instance_interleave_type_part ( Info *info) // Typse for performance qualification typedef struct reorg_bb_info reorg_bb_info_t; - struct reorg_bb_info { - basic_block *bb; - }; +struct reorg_bb_info { + basic_block *bb; +}; typedef struct perf_bb_info perf_bb_info_t; typedef struct acc_info acc_info_t; @@ -1945,9 +1902,9 @@ struct acc_info { int field_num; }; -struct perf_bb_info { +struct perf_loop_info { std::vector <var_info_t*> *vari; - basic_block *gcc_bb; + class loop *gcc_loop; }; static void account_for_use( tree, std::vector <acc_info_t> *); @@ -1956,6 +1913,7 @@ static bool is_array_access( tree); static unsigned int reorg_perf_qual ( Info *info) { + DEBUG_L("reorg_perf_qual:\n"); #if 1 // TBD use design in doc but mark ReorgTypes // (do_instance_interleave) that qualify instead of deleting them @@ -1990,169 +1948,177 @@ reorg_perf_qual ( Info *info) double cache_accesses_noreorg = 0.0; // Perf Analysis - DEBUG_A("Preformance Qualifiction\n"); struct cgraph_node *node; FOR_EACH_FUNCTION_WITH_GIMPLE_BODY ( node) { struct function *func = DECL_STRUCT_FUNCTION ( node->decl); + // Ulgy GCC idiom with global pointer to current function. + // However, the dominace calculations other things need it. push_cfun ( func); - DEBUG_A("Function: %s\n", lang_hooks.decl_printable_name ( func->decl, 2)); - - if (dom_info_available_p (CDI_DOMINATORS)) - free_dominance_info (CDI_DOMINATORS); - - calculate_dominance_info ( CDI_DOMINATORS); - + if ( dom_info_available_p ( CDI_DOMINATORS) ) + { + free_dominance_info ( CDI_DOMINATORS); + } + calculate_dominance_info (CDI_DOMINATORS); + // TBD + std::vector<perf_loop_info> loop_perf; + loop_perf.reserve ( number_of_loops ( func)); class loop *loop; FOR_EACH_LOOP_FN ( func, loop, LI_ONLY_INNERMOST ) { - DEBUG_A("For Loop with: "); - + loop_perf [ loop->num ].vari = new std::vector<var_info_t*>; // ??? + loop_perf [ loop->num ].gcc_loop = loop; size_t num_bbs = loop->num_nodes; basic_block *bbs = get_loop_body ( loop); + // TBD Stuff here + for ( unsigned i = 0; i < loop->num_nodes; i++) + { + basic_block bb = bbs [i]; + for ( auto gsi = gsi_start_bb ( bb); !gsi_end_p ( gsi); gsi_next ( &gsi) ) + { + gimple *stmt = gsi_stmt ( gsi); + if ( contains_a_reorgtype ( stmt, info) != NULL ) + { + DEBUG_A("examine: "); + DEBUG_F ( print_gimple_stmt, stderr, stmt, 0); + INDENT(4); + unsigned n_ops = gimple_num_ops( stmt); + tree op; + unsigned ith_op; + for ( ith_op = 0; i < n_ops; i++ ) + { + op = gimple_op ( stmt, ith_op); + ReorgType_t *tri = tree_contains_a_reorgtype (op, info); + if ( tri != NULL ) + { + DEBUG_A(""); + DEBUG_F(print_reorg, stderr, 0, tri); + DEBUG(", "); + DEBUG_F(flexible_print, stderr, op, 1, (dump_flags_t)0); + } + } + INDENT(-4); + + } + } + }continue; // Testing above here + // Obtain loop count by looking at all the block counts. unsigned max_count = 0; for ( unsigned i = 0; i < loop->num_nodes; i++) { basic_block bb = bbs [i]; max_count = MAX( max_count, bb->count.value ()); - DEBUG("BB%d, ",bb->index); } - DEBUG("\n"); DEBUG_L("max_count = %d, nb_iterations_estimate = %ld\n", max_count, loop->nb_iterations_estimate); // Originally this was done per bb but now it has to be per - // loop. TBD But perf_bb is per loop so we need something - // similar per loop. I suggest one vector per loop and the the - // information nor be persistent. - - std::vector <var_info_t*> pv; - - std::vector <acc_info_t> accinfo; - INDENT(4); - for ( unsigned i = 0; i < loop->num_nodes; i++) - { - basic_block bb = bbs [i]; - for ( auto gsi = gsi_start_bb ( bb); - !gsi_end_p ( gsi); - gsi_next ( &gsi) ) + // loop. TBD But perf_bb is per loop so we need something similar + // per loop. + + std::vector <var_info_t*> *pv = loop_perf [ loop->num].vari; + for ( auto pvi = pv->begin (); pvi != pv->end (); pvi++ ) + { // 676 + tree base_type = base_type_of( ( *pvi)->var->decl); + ReorgType_t *ri = get_reorgtype_info ( base_type, info); + // Reorg accounting + if( ri != NULL ) { - gimple *stmt = gsi_stmt ( gsi); - DEBUG_A(""); - DEBUG_F ( print_gimple_stmt, stderr, stmt, 0); - unsigned ith; - unsigned num_ops = gimple_num_ops ( stmt); - INDENT(4); - for ( ith = 0; ith < num_ops; ith++ ) + double reorg_nca = 0.0; + int fi; + tree field; + for( field = TYPE_FIELDS ( ri->gcc_type), fi = 0; + field; + field = DECL_CHAIN ( field), fi++ ) // 684 { - tree op = gimple_op ( stmt, ith); - if ( op == NULL ) continue; - DEBUG_A("op %p: ", op); - DEBUG_F( flexible_print, stderr, op, 1, (dump_flags_t)0); - #if 0 - if ( is_array_access( acc) ) + if ( bitmap_bit_p ( *(*pvi)->bits, fi) ) { - account_for_use( acc, &accinfo); + unsigned HOST_WIDE_INT fld_width = + tree_to_uhwi ( DECL_SIZE ( field)); + reorg_nca += max_count * alignment_effect ( fld_width); } - #endif } - INDENT(-4); - } - } - INDENT(-4); - - // Disable for a bit - #if 0 + ri->instance_interleave.reorg_perf += reorg_nca; + } // 699 - // Originally this was done per bb but now it has to be per - // loop. TBD But perf_bb is per loop so we need something - // similar per loop. I suggest one vector per loop and the the - // information nor be persistent. - //std::vector <var_info_t*> pv = bb->vari; - - for( auto pvi = pv->begin (); pvi != pv->end (); pv = pvi++ ) { // 676 - tree base_type = base_type_of( pvi->var->decl); - ReorgType_t *ri = get_reorgtype_info( base_type, info); - // Reorg accounting - if( ri != NULL ) { - double reorg_nca = 0.0; - int nf = number_of_fields_of( base_type); - int fi; - for( fi = 0; fi < nf; fi++ ) { // 684 - if( bitmap_bit_p( fi, pv->bits) ) { - int fld_width = field_width( base_type, fi); - reorg_nca += pvi->count * alignment_effect( fld_width); - } - } - ri->reorg_perf += reorg_nca; - } // 699 - - // regular accounting - double regular_nca = 0.0; - sbitmap *cache_model = sbitmap_alloc(1); - // TBD NOTE, pv steps on the pv above. - vector <var_info_t*> pv2 = perf_bb->vari; - for( auto pv2i = pv2->begin (); pv2i != pv2->end; pv2i++ ) { // 704 - tree base_type = base_type_of( pv2i->var->decl); - // create a tiny model of the cache big - // enough for this record. - int len = - ((length( base_type) + L1_CACHE_LINE_SIZE -1) - / - L1_CACHE_LINE_SIZE) - + - 1; - cache_model = sbitmap_resize( cache_model, len, 0); - int nf = number_of_fields_of( base_type); - int nrbo = number of record base offsets + // regular accounting + double regular_nca = 0.0; + sbitmap cache_model = sbitmap_alloc(1); + // TBD NOTE, pv steps on the pv above. + std::vector <var_info_t*> *pv2 = loop_perf[ loop->num].vari; + for( auto pv2i = pv2->begin (); pv2i != pv2->end (); pv2i++ ) { // 704 + tree base_type = base_type_of ( (*pv2i)->var->decl); + // create a tiny model of the cache big + // enough for this record. + unsigned HOST_WIDE_INT len = + (( tree_to_uhwi ( DECL_SIZE ( base_type)) + + + param_l1_cache_line_size -1) + / + param_l1_cache_line_size) + + + 1; + cache_model = sbitmap_resize( cache_model, (unsigned) len, 0); double accum = 0.0; - for( rboi = 0; rboi < nrbo; rboi++ ) { - base_offset = offset_for( rboi); - // Access accounting - int fi; - for( fi = 0; fi < nf; fi++ ) { - if( bitmap_bit_p( fi, pv2i->bits) ) { - int fld_width = field_width( base_type, fi); - int fld_offset = field_offset( base_type, fi); - int chari; - for( chari = 0; chari < fld_width; chari++ ) { - int loc = (chari + field_offset + base_offset) - / - L1_CACHE_LINE_SIZE; - bitmap_set_bit(cache_model, loc); - } + int nrbo = 0; + for ( auto field_ex = TYPE_FIELDS ( base_type); + field_ex; + field_ex = DECL_CHAIN ( field_ex) ) + { + nrbo++; + unsigned HOST_WIDE_INT base_offset = + tree_to_uhwi ( DECL_FIELD_OFFSET( field_ex)); + // Access accounting + int fi = 0; + for ( auto field = TYPE_FIELDS ( base_type); + field; + field = DECL_CHAIN ( field), fi++) + { + if ( bitmap_bit_p ( *(*pv2i)->bits, fi) ) + { + unsigned HOST_WIDE_INT fld_width, fld_offset; + fld_width = tree_to_uhwi ( DECL_SIZE ( field)); + fld_offset = tree_to_uhwi ( DECL_FIELD_OFFSET ( field)); + int chari; + for ( chari = 0; chari < fld_width; chari++ ) + { + int loc = (chari + fld_offset + base_offset) + / + param_l1_cache_line_size; + bitmap_set_bit ( cache_model, loc); + } + } + } + accum += bitmap_count_bits ( cache_model); + bitmap_clear ( cache_model); } - } - accum += popcount( cache_model); - bitmap_clear( cache_model); + regular_nca += accum / nrbo; + + } // 739 + sbitmap_free ( cache_model); + + if( ri != NULL ) { + ri->instance_interleave.regular_perf += regular_nca; + cache_accesses_noreorg += regular_nca; + } else { + cache_accesses += regular_nca; } - regular_nca += accum/nrbo; - - } // 739 - sbitmap_free( cache_model); - - if( ri != NULL ) { - ri->regular_perf += regular_nca; - cache_accesses_noreorg += regular_nca; - } else { - cache_accesses += regular_nca; - } - } // end for each prop_var 748 - - #endif + } // end for each prop_var 748 + + } // pop_cfun (); } + // TBD Somebody somewhere needs to compute: // reorg_perf // regular_perf // cache_accesses // cache_accesses_noreorg - #if 0 double total_cache_accesses = cache_accesses + cache_accesses_noreorg; @@ -2208,21 +2174,22 @@ reorg_perf_qual ( Info *info) { reorgi->do_instance_interleave = false; } - } - #endif + + free_dominance_info ( CDI_DOMINATORS); + #endif } -#define SINGLE_POOL_SLOPE \ -((SINGLE_POOL_RAW_DO_IT_ALWAYS - SINGLE_POOL_RAW_SKIP_IT) \ - / \ - (SINGLE_POOL_ABS_DO_IT_ALWAYS - SINGLE_POOL_ABS_SKIP_IT)) +#define SINGLE_POOL_SLOPE \ + ((SINGLE_POOL_RAW_DO_IT_ALWAYS - SINGLE_POOL_RAW_SKIP_IT) \ + / \ + (SINGLE_POOL_ABS_DO_IT_ALWAYS - SINGLE_POOL_ABS_SKIP_IT)) -#define SINGLE_POOL_INTERSECT \ -(SINGLE_POOL_RAW_SKIP_IT \ - - \ - SINGLE_POOL_SLOPE * SINGLE_POOL_ABS_SKIP_IT) +#define SINGLE_POOL_INTERSECT \ + (SINGLE_POOL_RAW_SKIP_IT \ + - \ + SINGLE_POOL_SLOPE * SINGLE_POOL_ABS_SKIP_IT) static double cut_off_eq_single_pool( double x) @@ -2230,6 +2197,21 @@ cut_off_eq_single_pool( double x) return SINGLE_POOL_SLOPE * x + SINGLE_POOL_INTERSECT; } +static double +alignment_effect( unsigned HOST_WIDE_INT width ) +{ + unsigned HOST_WIDE_INT times = param_l1_cache_line_size / width; // ?? + unsigned HOST_WIDE_INT rem = param_l1_cache_line_size % width; + if( rem == 0 ) { + return 1.0; + } + unsigned HOST_WIDE_INT m, n, g; + g = gcd( param_l1_cache_line_size, width); + m = param_l1_cache_line_size / g; + n = width / g; + return 1.0 + (n - 1.0)/m; +} + static void header ( bool initialize ) { @@ -2540,3 +2522,15 @@ remove_default_def ( tree default_def, struct function *func) } } } + +static basic_block +make_bb ( char *msg, basic_block prev_bb ) +{ + basic_block ret = create_empty_bb ( prev_bb); + DEBUG_A( "make_bb ( %s, <bb %d>/%p ): <bb %d>/%p, prev: <bb %d>/%p, next: <bb %d>/%p\n", + msg, prev_bb->index, prev_bb, + ret->index, ret, + ret->prev_bb->index, ret->prev_bb, + ret->next_bb->index, ret->next_bb); + return ret; +} diff --git a/gcc/ipa-structure-reorg.c b/gcc/ipa-structure-reorg.c index 9b3fdf95211..639a1e876f3 100644 --- a/gcc/ipa-structure-reorg.c +++ b/gcc/ipa-structure-reorg.c @@ -45,6 +45,8 @@ along with GCC; see the file COPYING3. If not see #include <map> #include <set> #include "ipa-structure-reorg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" static void setup_debug_flags ( Info *); @@ -260,7 +262,6 @@ final_debug_info ( Info *info) static unsigned int reorg_analysis ( Info *info) { - // TODO: // Gary, this main "analysis" method seems to have a lot of // instance interleave specific code. Shouldn't this method @@ -320,36 +321,62 @@ reorg_analysis ( Info *info) gsi_next ( &gsi) ) { gimple *stmt = gsi_stmt ( gsi); - //DEBUG_L ( ""); - //DEBUG_F ( print_gimple_stmt, stderr, stmt, 0); - //INDENT(2); + DEBUG_L ( ""); + DEBUG_F ( print_gimple_stmt, stderr, stmt, 0); + INDENT(2); if ( is_gimple_call ( stmt) ) { // next line has issues but the mechanism is sound tree t = *gimple_call_lhs_ptr ( stmt); - //DEBUG_A( "t %p\n", t); + DEBUG_A( "t %p\n", t); // Calls to a function returning void are skipped. if ( t != NULL ) { + DEBUG_A( "t: "); + DEBUG_F( flexible_print, stderr, t, 1, (dump_flags_t)0); tree type = TREE_TYPE( t); + DEBUG_A( "type: "); + DEBUG_F( flexible_print, stderr, type, 1, (dump_flags_t)0); //tree bt = base_type_of ( t); tree bt = base_type_of ( type); - if ( TREE_CODE( bt) != RECORD_TYPE ) + if ( TREE_CODE( bt) != RECORD_TYPE && TREE_CODE( bt) != VOID_TYPE) { - //DEBUG_A( "TREE_CODE( bt) == %s\n", code_str( TREE_CODE ( bt))); - //DEBUG_A(""); - //DEBUG_F( print_generic_expr, stderr, bt, (dump_flags_t)-1); - //INDENT(-2); + DEBUG_A( "TREE_CODE( bt) == %s\n", code_str( TREE_CODE ( bt))); + DEBUG_A(""); + DEBUG_F(flexible_print, stderr, bt, 1, (dump_flags_t)0); + INDENT(-2); continue; } + if ( TREE_CODE( bt) == VOID_TYPE ) + { + // find the use of lhs. If is an assign + // get use the base type of it's lhs. + // Otherwise never mind. + gimple *use_stmt; + use_operand_p immuse; + bool yup_a_use = single_imm_use ( t, &immuse, &use_stmt); + DEBUG_A("VOID case: %sa single imm use, ", yup_a_use ? "" : "not "); + DEBUG("%san assign\n", + yup_a_use && is_gimple_assign ( use_stmt) ? "" : "not "); + if ( TREE_CODE ( t) == SSA_NAME + && yup_a_use + && is_gimple_assign ( use_stmt) ) + { + tree use_lhs = gimple_assign_lhs ( use_stmt); + bt = base_type_of ( TREE_TYPE ( use_lhs)); + } + else + continue; + } + // find if in reorgtypes and get the info (in one call) ReorgType_t *ri = get_reorgtype_info ( bt, info); if ( ri != NULL && is_reorg_alloc_trigger ( stmt) ) { - //DEBUG_L( "Found allocaion: \n"); - //DEBUG_A( " Reorg: "); - //DEBUG_F( print_reorg, stderr, 0, ri); - //DEBUG("\n"); + DEBUG_L( "Found allocaion: \n"); + DEBUG_A( " Reorg: "); + DEBUG_F( print_reorg, stderr, 0, ri); + DEBUG("\n"); // TBD this needs to increment with the execution count // instead of one. I hope the build-in block count estimation // will work or a DIY solution might be called for. @@ -357,13 +384,13 @@ reorg_analysis ( Info *info) } } } - //INDENT(-2); + INDENT(-2); } } } - //DEBUG_L( "possible deletes:\n"); - //INDENT(2); + DEBUG_L( "possible deletes:\n"); + INDENT(2); // It's LOT more clear to use an iterator here TBD for ( int i = 0; i < info->reorg_type->size (); i++ ) { @@ -376,12 +403,13 @@ reorg_analysis ( Info *info) } // Note when multi-pools are enabled the test should be // "n == 0" but until then... + DEBUG_A("%d pools\n",n) if ( n != 1 ) { delete_reorgtype ( &(*(info->reorg_type))[i], info); } } - //INDENT(-2); + INDENT(-2); //DEBUG_L("after reorg_analysis\n"); remove_deleted_types ( info, &reorg_analysis_debug); @@ -817,7 +845,7 @@ disq_str_in_str_or_union_helper ( tree type, //tree base = base_type_of ( field_type); if ( TREE_CODE ( field_type) == RECORD_TYPE ) // base to field type { - //DEBUG( "RECORD\n"); + DEBUG( "RECORD\n"); ReorgType_t *rinfo = get_reorgtype_info ( field_type, info); // base to field type if ( rinfo != NULL ) @@ -1070,12 +1098,14 @@ modify_declarations ( Info *info) static void disqualify_all_reorgtypes_of ( gimple *stmt, int num, Info *info) { + DEBUG_L("disqualify %d reorgtypes of: ", num); + DEBUG_F ( print_gimple_stmt, stderr, stmt, 0); int i; for ( i = 0; i < num; i++ ) { ReorgType_t *reorg_type = - get_reorgtype( stmt, info, i); - delete_reorgtype( reorg_type, info); + get_reorgtype ( stmt, info, i); + delete_reorgtype ( reorg_type, info); } } @@ -1399,14 +1429,14 @@ modify_decl_core ( tree *location, Info *info) void delete_reorgtype ( ReorgType_t *rt, Info *info ) { - //DEBUG_L( "delete_reorgtype( %s ):", type_name_to_str( TYPE_NAME( rt->gcc_type))); + DEBUG_L( "delete_reorgtype( %s ):", type_name_to_str( TYPE_NAME( rt->gcc_type))); if ( !rt->delete_me ) { - //DEBUG( "TO DELETE\n"); + DEBUG( "TO DELETE\n"); info->num_deleted++; rt->delete_me = true; } else { - //DEBUG( "SKIP\n"); + DEBUG( "SKIP\n"); } } @@ -1427,28 +1457,28 @@ undelete_reorgtype ( ReorgType_t *rt, Info *info ) ReorgTransformation reorg_recognize ( gimple *stmt, cgraph_node* node, Info_t *info ) { - //DEBUG_L ( "ReorgTransformation reorg_recognize for: "); - //DEBUG_F ( print_gimple_stmt, stderr, stmt, 0); - //INDENT(2); + DEBUG_L ( "ReorgTransformation reorg_recognize for: "); + DEBUG_F ( print_gimple_stmt, stderr, stmt, 0); + INDENT(2); switch ( gimple_code( stmt) ) { case GIMPLE_ASSIGN: { - //DEBUG_L("GIMPLE_ASSIGN:\n"); + DEBUG_L("GIMPLE_ASSIGN:\n"); tree lhs = gimple_assign_lhs ( stmt); enum tree_code rhs_code = gimple_assign_rhs_code ( stmt); if ( gimple_assign_single_p ( stmt) ) { - //DEBUG_L("gimple_assign_single_p() = true\n"); - //INDENT(2); + DEBUG_L("gimple_assign_single_p() = true\n"); + INDENT(2); tree rhs = gimple_assign_rhs1 ( stmt); enum ReorgOpTrans lhs_op = recognize_op ( lhs, info); switch ( lhs_op ) { case ReorgOpT_Pointer: // "a" - //DEBUG_L("case ReorgOpT_Pointer\n"); - //INDENT(-4); + DEBUG_L("case ReorgOpT_Pointer\n"); + INDENT(-4); switch ( recognize_op ( rhs, info) ) { case ReorgOpT_Scalar: @@ -1467,19 +1497,25 @@ reorg_recognize ( gimple *stmt, cgraph_node* node, Info_t *info ) return Not_Supported; } case ReorgOpT_Struct: // "s" - //DEBUG_L("case ReorgOpT_Struct\n"); - //INDENT(-4); + DEBUG_L("case ReorgOpT_Struct\n"); + INDENT(-4); switch ( recognize_op ( rhs, info) ) { case ReorgOpT_Deref: // "*a" case ReorgOpT_Array: // "x[i]" + // Technically with a struct on both sides + // this could be ignored but it's + // better to do this at transform time. + // With the case commented out test_09_23 + // exposes a bug. + case ReorgOpT_Struct: // "s" return ReorgT_StrAssign; default: return Not_Supported; } case ReorgOpT_Deref: // "*a" - //DEBUG_L("case ReorgOpT_Deref\n"); - //INDENT(-4); + DEBUG_L("case ReorgOpT_Deref\n"); + INDENT(-4); switch ( recognize_op ( rhs, info) ) { case ReorgOpT_Deref: // "*a" @@ -1490,8 +1526,8 @@ reorg_recognize ( gimple *stmt, cgraph_node* node, Info_t *info ) return Not_Supported; } case ReorgOpT_Array: // "x[i]" - //DEBUG_L("case ReorgOpT_Array\n"); - //INDENT(-4); + DEBUG_L("case ReorgOpT_Array\n"); + INDENT(-4); switch ( recognize_op ( rhs, info) ) { case ReorgOpT_Struct: // "s" @@ -1503,8 +1539,8 @@ reorg_recognize ( gimple *stmt, cgraph_node* node, Info_t *info ) } case ReorgOpT_Temp: // t case ReorgOpT_Scalar: // "z" - //DEBUG_L("case ReorgOpT_%s\n", lhs_op == ReorgOpT_Temp ? "Temp" : "Scalar"); - //INDENT(-4); + DEBUG_L("case ReorgOpT_%s\n", lhs_op == ReorgOpT_Temp ? "Temp" : "Scalar"); + INDENT(-4); switch ( recognize_op( rhs, info) ) { case ReorgOpT_Scalar: // "z" @@ -1517,8 +1553,8 @@ reorg_recognize ( gimple *stmt, cgraph_node* node, Info_t *info ) } case ReorgOpT_Indirect: // "a->f" case ReorgOpT_AryDir: // "x[i].f" - //DEBUG_L("case ReorgOpT_%s\n", lhs_op == ReorgOpT_Indirect ? "Indirect" : "AryDir"); - //INDENT(-4); + DEBUG_L("case ReorgOpT_%s\n", lhs_op == ReorgOpT_Indirect ? "Indirect" : "AryDir"); + INDENT(-4); switch ( recognize_op ( rhs, info) ) { case ReorgOpT_Temp: // t @@ -1530,30 +1566,30 @@ reorg_recognize ( gimple *stmt, cgraph_node* node, Info_t *info ) return Not_Supported; } default: - //INDENT(-4); + INDENT(-4); return Not_Supported; } // switch ( recognize_op ( lhs, info) ) } else { - //DEBUG_L("gimple_assign_single_p() = false\n"); - //INDENT(2); + DEBUG_L("gimple_assign_single_p() = false\n"); + INDENT(2); tree op1 = gimple_assign_rhs1 ( stmt); tree op2 = gimple_assign_rhs2 ( stmt); - //DEBUG_L("op1 = %p, op2 = %p\n", op1, op2); - //DEBUG_A(""); - //DEBUG_F( print_generic_expr, stderr, op1, (dump_flags_t)-1); - //DEBUG("\n"); + DEBUG_L("op1 = %p, op2 = %p\n", op1, op2); + DEBUG_A(""); + DEBUG_F( print_generic_expr, stderr, op1, (dump_flags_t)-1); + DEBUG("\n"); if ( CONVERT_EXPR_CODE_P ( gimple_assign_rhs_code ( stmt))) { - //DEBUG_L("CONVERT_EXPR_CODE_P (...)\n"); - //INDENT(-4); + DEBUG_L("CONVERT_EXPR_CODE_P (...)\n"); + INDENT(-4); return ReorgT_Convert; } if ( gimple_assign_rhs3 ( stmt) != NULL ) { - //DEBUG_L("gimple_assign_rhs3 ( stmt) != NULL\n"); - //INDENT(-4); + DEBUG_L("gimple_assign_rhs3 ( stmt) != NULL\n"); + INDENT(-4); return Not_Supported; } @@ -1563,8 +1599,8 @@ reorg_recognize ( gimple *stmt, cgraph_node* node, Info_t *info ) ( (POINTER_TYPE_P ( TREE_TYPE( op1)) && integer_zerop ( op2)) || (POINTER_TYPE_P ( TREE_TYPE( op2)) && integer_zerop ( op1))) && ( integer_zerop ( op1) || integer_zerop ( op2) ); - //DEBUG_L("zero_case = %s\n", zero_case ? "true" : "false" ); - //INDENT(-4); + DEBUG_L("zero_case = %s\n", zero_case ? "true" : "false" ); + INDENT(-4); switch ( rhs_code ) { case POINTER_PLUS_EXPR: @@ -1622,12 +1658,12 @@ reorg_recognize ( gimple *stmt, cgraph_node* node, Info_t *info ) } case GIMPLE_CALL: { - //DEBUG_L("GIMPLE_CALL:\n"); + DEBUG_L("GIMPLE_CALL:\n"); struct cgraph_edge *edge = node->get_edge ( stmt); gcc_assert( edge); - //DEBUG_L("called function %s gimple_body\n", - // edge->callee->has_gimple_body_p() ? "has a" : "has no"); - //INDENT(-2); + DEBUG_L("called function %s gimple_body\n", + edge->callee->has_gimple_body_p() ? "has a" : "has no"); + INDENT(-2); if ( gimple_call_builtin_p( stmt, BUILT_IN_CALLOC ) ) return ReorgT_Calloc; if ( gimple_call_builtin_p( stmt, BUILT_IN_MALLOC ) ) return ReorgT_Malloc; if ( gimple_call_builtin_p( stmt, BUILT_IN_REALLOC) ) return ReorgT_Realloc; @@ -1647,15 +1683,15 @@ reorg_recognize ( gimple *stmt, cgraph_node* node, Info_t *info ) } break; case GIMPLE_RETURN: - //DEBUG_L("GIMPLE_RETURN:\n"); - //INDENT(-2); + DEBUG_L("GIMPLE_RETURN:\n"); + INDENT(-2); return ReorgT_Return; break; default: - //DEBUG_L ( "didn't support: "); - //DEBUG_F ( print_gimple_stmt, stderr, stmt, 0); - //DEBUG( "\n"); - //INDENT(-2); + DEBUG_L ( "didn't support: "); + DEBUG_F ( print_gimple_stmt, stderr, stmt, 0); + DEBUG( "\n"); + INDENT(-2); return Not_Supported; } } @@ -1762,43 +1798,51 @@ remove_deleted_types ( Info *info, ReorgFn reorg_fn) enum ReorgOpTrans recognize_op ( tree op, Info *info) { - //DEBUG_L("recognize_op: "); - //DEBUG_F( print_generic_expr, stderr, op, TDF_DETAILS); - //DEBUG("\n"); + DEBUG_L("recognize_op: "); + DEBUG_F( flexible_print, stderr, op, 1, TDF_DETAILS); enum tree_code op_code = TREE_CODE ( op); + DEBUG_A("opcode = %s\n", code_str( op_code)); if ( op_code == SSA_NAME ) { // We tried returning ReorgOpT_Scalar. // It caused an assertion failue because // it was incorrectly triggering the ReorgT_Ptr2Zero // case with a bogus RHS. - //DEBUG_L(" returns: ReorgOpT_Temp\n"); + DEBUG_L(" returns: ReorgOpT_Temp\n"); return ReorgOpT_Temp; } tree type = TREE_TYPE ( op); - if ( POINTER_TYPE_P (type) ) + if ( type != NULL && POINTER_TYPE_P (type) ) { - //DEBUG_L("POINTER_TYPE_P (type) = true\n"); + DEBUG_L("POINTER_TYPE_P (type) = true\n"); if ( is_reorg_type ( type, info) ) { - //DEBUG_L(" returns: ReorgOpT_Pointer\n"); + DEBUG_L(" returns: ReorgOpT_Pointer\n"); return ReorgOpT_Pointer; } else { // This would be for when // the field of a struct element // is a pointer that's not a reorg // point. I.e. ReorgT_ElemAssign. - //DEBUG_L(" returns: ReorgOpT_Scalar\n"); + DEBUG_L(" returns: ReorgOpT_Scalar\n"); return ReorgOpT_Scalar; } } + // This might not occur in practice if ( op_code == RECORD_TYPE ) { // The assumption here is that this // is a reorg type. - //DEBUG_L(" returns: ReorgOpT_Struct\n"); + DEBUG_L(" returns: ReorgOpT_Struct\n"); return ReorgOpT_Struct; } + if ( op_code == VAR_DECL ) + { + tree type = TREE_TYPE ( op); + DEBUG_L(" recursing on type :"); + DEBUG_F( flexible_print, stderr, type, 1, TDF_DETAILS); + return recognize_op ( type, info); + } tree inner_op = TREE_OPERAND( op, 0); tree inner_type = TREE_TYPE ( inner_op); enum tree_code inner_op_code = TREE_CODE ( inner_op); |