summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Oblock <gary@amperecomputing.com>2020-09-24 21:17:52 -0700
committerGary Oblock <gary@amperecomputing.com>2020-09-24 21:17:52 -0700
commitda7f413db3ef1c74549329a202aec1d4e5ad950c (patch)
tree660f8cb52d85e08ac3fd7ec87a2f1600b60ead12
parent24ccc02f2498bbe0d4ecb2ec8c5ff7f71277bf7a (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.c376
-rw-r--r--gcc/ipa-structure-reorg.c192
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);