From 0e3acbe69c82973e886682c25531ecc05a29e71f Mon Sep 17 00:00:00 2001 From: Gary Oblock Date: Mon, 8 Jun 2020 20:46:26 -0700 Subject: Trasnsformations stub in place and malloc in development. --- gcc/ipa-str-reorg-instance-interleave.c | 610 +++++++++++++++++--------------- gcc/ipa-structure-reorg.c | 59 ++- gcc/ipa-structure-reorg.h | 4 +- 3 files changed, 344 insertions(+), 329 deletions(-) diff --git a/gcc/ipa-str-reorg-instance-interleave.c b/gcc/ipa-str-reorg-instance-interleave.c index fd87336152d..d2eaa0fa4c7 100644 --- a/gcc/ipa-str-reorg-instance-interleave.c +++ b/gcc/ipa-str-reorg-instance-interleave.c @@ -40,6 +40,9 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "stor-layout.h" #include "diagnostic-core.h" +#include "ssa.h" +#include "tree-ssanames.h" +#include "cfghooks.h" static void str_reorg_instance_interleave_qual_part ( Info *); static void str_reorg_instance_interleave_type_part ( Info *); @@ -100,7 +103,7 @@ str_reorg_instance_interleave_trans ( Info *info) if ( ri != NULL ) { enum ReorgTransformation trans = - reorg_recognize ( stmt, info); + reorg_recognize ( stmt, node, info); // print out trans and stmt if dumping if ( info->show_transforms ) { @@ -288,306 +291,329 @@ str_reorg_instance_interleave_trans ( Info *info) // Not needed for single pool. break; case ReorgT_Malloc: - DEBUG_L("ReorgT_Malloc\n"); - /* - // Note, unlike other simpler transformations, - // this must build new basic blocks to add new - // gimple to and use a phi for the final result. - // See appendix on malloc transformation for - // each comment starting with "FROM." - ReorgType_t *ri = contains_a_reorgtype( stmt, info); - // FROM len = val/size - tree arg = gimple_call_arg( stmt, 0); - len is new SSA - tree val = gimple_call_lhs( stmt); - gcc_assert( TREE_CODE( TREE_TYPE(val)) == INDIRECT_REF); - tree size = TYPE_SIZE_UNIT( TREE_TYPE( TREE_TYPE( val))); - // FROM len = val/size (insert before stmt) - gimple_stmt_iterator *gsi = gsi_for_stmt( stmt); - gimple *glen = - gimple_build_assign( - len, - TRUNC_DIV_EXPR, - val, - size, - NULL_TREE, NULL_TREE); - gsi_insert_before( gsi, glen, GSI_SAME_STMT); - // Note in other places in this doc this would - // be "insert glen before stmt" instead of this but - // here we need to create new basic blocks. - // FROM edge = split this block after stmt - edge new_edge = split_edge( bb, stmt); - // FROM before_bb = edge->src // same as this bb - before_bb = edge->src; - // FROM after_bb = edge->dest - after_bb = edge->dest; - // FROM delete edge - remove_edge( e); - // FROM prev_bb = before_bb - prev_bb = before_bb; - // FROM prev_ok_field is new label - tree prev_ok_field_L = - create_artificial_label( UNKNOWN_LOCATION); - // FROM after_label is new label - tree after_label_L = - create_artificial_label( UNKNOWN_LOCATION); - // FROM add goto for prev_ok_field to end of before_bb - gimple *goto_pof = gimple_build_goto( prev_ok_field_L); - gsi_insert_before( gsi, *goto_pof, GSI_SAME_STMT); - // FROM failure_bb = create_empty_block(prev_bb) - basic_block failure_bb = create_empty_block( prev_bb); - // FROM make_edge( failure_bb, after_bb, EDGE_FALLTHRU); - edge failure_edge = make_edge( failure_bb, - after_bb, EDGE_FALLTHRU); - // FROM bad_field is new label - tree bad_field_L = - create_artificial_label( UNKNOWN_LOCATION); - // FROM delete stmt - gsi_remove( gsi, true); - - // code in failure_bb - // - // FROM fail_val is new SSA - tree return_type = TREE_TYPE( arg); - tree fail_val = - make_temp_ssa_name( return_type, NULL, "fail_val") - // FROM gsi = gsi_start_bb( failure_bb) - gsi = gsi_start_bb( failure_bb); - // FROM gsi_insert_after( &gsi, "goto after_label") - gimple *goto_al = gimple_build_goto( after_label_L); - gsi_insert_after( &gsi, goto_al); - // (per field) { - tree field; - tree reorg_type = ri->gcc_type; - tree fndecl_free = builtin_decl_explicit( BUILT_IN_FREE); - tree base = ri->clone; - for( field = TYPE_FIELDS( reorg_type); - field; - field = DECL_CHAIN( field)) { - // FROM gsi_insert_after( &gsi, "base.field = 0") - tree lhs_ass = - build3( COMPONENT_REF, ptr_type_node, base, field, NULL_TREE); - gimple *gzero = gimple_build_assign( lhs_ass, null_pointer_node); - gsi_insert_after( &gsi, gzero); - - // FROM gsi_insert_after( &gsi, "free(field)") - tree to_free = - make_temp_ssa_name( type, NULL, "to_free") - gcall *free_call = gimple_build_call( fndecl_free, 1, to_free); - gsi_insert_after( &gsi, free_call); - tree rhs_ass = - build3( COMPONENT_REF, ptr_type_node, base, field, NULL_TREE); - gimple *gaddr2free = gimple_build_assign( to_free, rhs_ass); - gsi_insert_after( &gsi, gaddr2free); - } - // FROM gsi_insert_after( &gsi, "fail_val = minint") - gimple *gretnull = - gimple_build_assign( fail_val, - build_int_cst( - TYPE_MIN_VALUE( TREE_TYPE(fail_val)))); - gsi_insert_after( &gsi, gretnull); - // FROM gsi_insert_after( &gsi, bad_field ) - gimple gbad_field = gimple_build_label( bad_field_L); - gsi_insert_after( &gsi, gbad_field ); - - // loop setup trickery for gimple idioms - // - // FROM prev_order = failure_bb - prev_order = failure_bb; - // FROM prev_bb = before_bb - prev_bb = before_bb; + #if 0 + DEBUG_L("Transform ReorgT_Malloc\n"); + INDENT(2); + // Note, unlike other simpler transformations, + // this must build new basic blocks to add new + // gimple to and use a phi for the final result. + // See appendix on malloc transformation for + // each comment starting with "FROM." + ReorgType_t *ri = contains_a_reorgtype( stmt, info); + // FROM len = val/size + tree arg = gimple_call_arg( stmt, 0); + // TBD: len is new SSA + tree val = gimple_call_lhs( stmt); + gcc_assert( TREE_CODE( TREE_TYPE(val)) == INDIRECT_REF); + tree size = TYPE_SIZE_UNIT( TREE_TYPE( TREE_TYPE( val))); + // FROM len = val/size (insert before stmt) <== maybe arg/size + tree len = + make_temp_ssa_name( sizetype, NULL, "fail_val"); + gimple_stmt_iterator gsi = gsi_for_stmt( stmt); + //gimple *glen = + // gimple_build_assign ( len, TRUNC_DIV_EXPR, val, size); + gimple *glen = + gimple_build_assign ( len, TRUNC_DIV_EXPR, arg, size); + gsi_insert_before( &gsi, glen, GSI_SAME_STMT); + // Note in other places in this doc this would + // be "insert glen before stmt" instead of this but + // here we need to create new basic blocks. + // FROM edge = split this block after stmt + edge new_edge = split_block ( bb, stmt); + // FROM before_bb = edge->src // same as this bb + basic_block before_bb = new_edge->src; // + // FROM after_bb = edge->dest + basic_block after_bb = new_edge->dest; + // FROM delete edge + remove_edge ( new_edge); + // FROM prev_bb = before_bb + basic_block prev_bb = before_bb; + // FROM prev_ok_field is new label + tree prev_ok_field_L = + create_artificial_label ( UNKNOWN_LOCATION); + // FROM after_label is new label + tree after_label_L = + create_artificial_label ( UNKNOWN_LOCATION); + // FROM add goto for prev_ok_field to end of before_bb + gimple *goto_pof = gimple_build_goto ( prev_ok_field_L); + gsi_insert_before ( &gsi, goto_pof, GSI_SAME_STMT); // TBD insert after??? + // FROM failure_bb = create_empty_block(prev_bb) + basic_block failure_bb = create_empty_bb ( prev_bb); + // FROM make_edge( failure_bb, after_bb, EDGE_FALLTHRU); + edge failure_edge = make_edge ( failure_bb, + after_bb, EDGE_FALLTHRU); + // FROM bad_field is new label + tree bad_field_L = + create_artificial_label ( UNKNOWN_LOCATION); + // FROM delete stmt + gsi_remove ( &gsi, true); - // Generate all the real allocation code - tree fndecl_malloc = builtin_decl_explicit( BUILT_IN_MALLOC); - tree base = ri->clone; - // FROM (for fields) { - for( field = TYPE_FIELDS( reorg_type); - field; - field = DECL_CHAIN( field)) { - // FROM res is new SSA - // Note, alternative code would substitute ptr_type_node - // for null_pointer_node. - tree res = - make_temp_ssa_name( null_pointer_node, NULL, "res") - // FROM new_bb = create_empty_block(prev_order); - basic_block new_bb = create_empty_block( prev_order); - // FROM gsi = gsi_start_bb( new_bb) - gimple_stmt_iterator gsi = gsi_start_bb( new_bb); - // FROM set imm dom new_bb as prev_bb - set_immediate_dominator( CDI_DOMINATORS, new_bb, prev_bb); - // FROM make_edge( prev_bb, new_bb, EDGE_TRUE_VALUE); - make_edge( prev_bb, new_bb, EDGE_TRUE_VALUE); - // FROM make_edge( new_bb, failure_bb, EDGE_FALSE_VALUE); - make_edge( new_bb, failure_bb, EDGE_FALSE_VALUE); - // FROM new_ok_field is new label - tree new_ok_field_L = - create_artificial_label( UNKNOWN_LOCATION); - // FROM gsi_insert_after( &gsi, "if( res NE NULL ) - // goto new_ok_field; - // goto bad_field") - tree res = - make_temp_ssa_name( pointer_type_node, NULL, "res") - gimple *gcond = - gimple_build_cond( NE_EXPR, res, null_pointer_node, - new_ok_field_L, bad_field_L); - gsi_insert_after( &gsi, gcond); - // FROM gsi_insert_after( &gsi, "base.field = res") - tree lhs_ass = - build3( COMPONENT_REF, ptr_type_node, base, field, NULL_TREE); - gimple *gset_field = gimple_build_assign( lhs_ass, res); - gsi_insert_after( &gsi, gset_field); + // code in failure_bb + // + // FROM fail_val is new SSA + tree return_type = TREE_TYPE ( arg); + tree fail_val = + make_temp_ssa_name ( return_type, NULL, "fail_val"); + // FROM gsi = gsi_start_bb ( failure_bb) + gsi = gsi_start_bb ( failure_bb); + // FROM gsi_insert_after ( &gsi, "goto after_label") + gimple *goto_al = gimple_build_goto ( after_label_L); + gsi_insert_after ( &gsi, goto_al, GSI_SAME_STMT); + // (per field) { + tree field; + tree reorg_type = ri->gcc_type; // is this useful here? + tree reorg_pointer_type = ri->pointer_rep; + tree fndecl_free = builtin_decl_explicit( BUILT_IN_FREE); + tree base = ri->clone; + for( field = TYPE_FIELDS( reorg_type); + field; + field = DECL_CHAIN( field)) { + // FROM gsi_insert_after( &gsi, "base.field = 0") + tree lhs_ass = + build3( COMPONENT_REF, ptr_type_node, base, field, NULL_TREE); + gimple *gzero = gimple_build_assign( lhs_ass, null_pointer_node); + gsi_insert_after( &gsi, gzero, GSI_SAME_STMT); - // FROM gsi_insert_after( &gsi, "res = malloc( mem_size)") - // The alternative to sizetype are long_integer_type_node - // and integer_type_node. - tree mem_size = - make_temp_ssa_name( sizetype, NULL, "mem_size"); - gcall *malloc_call = gimple_build_call( fndecl_malloc, 1, mem_size); - gimple_call_set_lhs( malloc_call, res); - gsi_insert_after( &gsi, malloc_call); - // FROM gsi_insert_after( &gsi, "mem_size = len * field_size") - gimple *gsize = - gimple_build_assign( mem_size, MULT_EXPR, TYPE_SIZE(field), - len, NULL_TREE, NULL_TREE); - gsi_insert_after( &gsi, gsize); - // FROM gsi_insert_after( &gsi, prev_ok_field) - gimple gprev_ok_field = gimple_build_label( prev_ok_field_L); - gsi_insert_after( &gsi, gprev_ok_field_L ); - // FROM prev_bb = new_bb - prev_bb = new_bb; - // FROM prev_order = new_bb - prev_order = new_bb; - // FROM prev_ok_field = new_ok_field - prev_ok_field_L = new_ok_field_L; - } - - // create basic block for success - // - // FROM success_bb = create_empty_block(prev_bb_order); - success_bb = create_empty_block(prev_bb_order); - // FROM set imm dom success_bb as prev_bb - set_immediate_dominator( CDI_DOMINATORS, success_bb, prev_bb); - // FROM make_edge( prev_bb, success_bb, EDGE_TRUE_VALUE); - make_edge( prev_bb, success_bb, EDGE_TRUE_VALUE); - // FROM make_edge( success_bb, after_bb, EDGE_TRUE_VALUE); - edge success_edge = make_edge( success_bb, after_bb, EDGE_TRUE_VALUE); + // FROM gsi_insert_after( &gsi, "free(field)") + // TBD -- I'm + tree to_free = + make_temp_ssa_name( reorg_pointer_type, NULL, "to_free"); + gcall *free_call = gimple_build_call( fndecl_free, 1, to_free); + gsi_insert_after( &gsi, free_call, GSI_SAME_STMT); + tree rhs_ass = + build3( COMPONENT_REF, ptr_type_node, base, field, NULL_TREE); + gimple *gaddr2free = gimple_build_assign( to_free, rhs_ass); + gsi_insert_after( &gsi, gaddr2free, GSI_SAME_STMT); + } + // FROM gsi_insert_after( &gsi, "fail_val = minint") + gimple *gretnull = + gimple_build_assign ( fail_val, + build_int_cst ( size_type_node, + TYPE_MIN_VALUE ( TREE_TYPE ( fail_val)))); + gsi_insert_after( &gsi, gretnull, GSI_SAME_STMT); + // FROM gsi_insert_after( &gsi, bad_field ) + gimple *gbad_field = gimple_build_label( bad_field_L); + gsi_insert_after( &gsi, gbad_field, GSI_SAME_STMT); + + // loop setup trickery for gimple idioms + // + // FROM prev_order = failure_bb + basic_block prev_order = failure_bb; + // FROM prev_bb = before_bb + prev_bb = before_bb; + + // Generate all the real allocation code + tree fndecl_malloc = builtin_decl_explicit( BUILT_IN_MALLOC); + // This, after the following loop, will hold the start of the + // field related code. + tree new_ok_field_L; - // code in success_bb - // - // FROM success_val is new SSA - tree success_val = - make_temp_ssa_name( int_ptrsize_type, NULL, "success_val"); - // FROM gsi = gsi_start_bb( failure_bb) - gimple_stmt_iterator gsi = gsi_start_bb( failure_bb); - // FROM gsi_insert_after( &gsi, "goto after_label") - gimple *goto_al = gimple_build_goto( after_label_L); - gsi_insert_after( &gsi, goto_al); - // FROM gsi_insert_after( &gsi, "success_val = 0") - gimple *set_succ = - gimple_build_assign( success_val, build_int_cst( 0)); - gsi_insert_after( &gsi, set_succ); - // 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 ); + // FROM (for fields) { + for( field = TYPE_FIELDS( reorg_type); + field; + field = DECL_CHAIN( field)) + { + // FROM res is new SSA + // Note, alternative code would substitute ptr_type_node + // for null_pointer_node. + // This is probably a duplicate of the def of res below. + //tree res = + // make_temp_ssa_name( null_pointer_node, NULL, "res"); + // FROM new_bb = create_empty_block(prev_order); + basic_block new_bb = create_empty_bb ( prev_order); + // FROM gsi = gsi_start_bb( new_bb) + gimple_stmt_iterator gsi = gsi_start_bb ( new_bb); + // FROM set imm dom new_bb as prev_bb + set_immediate_dominator ( CDI_DOMINATORS, new_bb, prev_bb); + // FROM make_edge( prev_bb, new_bb, EDGE_TRUE_VALUE); + make_edge ( prev_bb, new_bb, EDGE_TRUE_VALUE); + // FROM make_edge( new_bb, failure_bb, EDGE_FALSE_VALUE); + make_edge ( new_bb, failure_bb, EDGE_FALSE_VALUE); + // FROM new_ok_field is new label + new_ok_field_L = + create_artificial_label ( UNKNOWN_LOCATION); + // FROM gsi_insert_after( &gsi, "if( res NE NULL ) + // goto new_ok_field; + // goto bad_field") + tree res = + make_temp_ssa_name ( ptr_type_node, NULL, "res"); + gimple *gcond = + gimple_build_cond ( NE_EXPR, res, null_pointer_node, + new_ok_field_L, bad_field_L); + gsi_insert_after ( &gsi, gcond, GSI_SAME_STMT); + // FROM gsi_insert_after( &gsi, "base.field = res") + tree lhs_ass = + build3( COMPONENT_REF, ptr_type_node, base, field, NULL_TREE); + gimple *gset_field = gimple_build_assign( lhs_ass, res); + gsi_insert_after( &gsi, gset_field, GSI_SAME_STMT); + + // FROM gsi_insert_after( &gsi, "res = malloc( mem_size)") + // The alternative to sizetype are long_integer_type_node + // and integer_type_node. + tree mem_size = + make_temp_ssa_name( sizetype, NULL, "mem_size"); + gcall *malloc_call = gimple_build_call( fndecl_malloc, 1, mem_size); + gimple_call_set_lhs( malloc_call, res); + gsi_insert_after( &gsi, malloc_call, GSI_SAME_STMT); + // FROM gsi_insert_after( &gsi, "mem_size = len * field_size") + //gimple *gsize = + // gimple_build_assign ( mem_size, MULT_EXPR, TYPE_SIZE(field), + // len, NULL_TREE, NULL_TREE); + gimple *gsize = + gimple_build_assign ( mem_size, + MULT_EXPR, + TYPE_SIZE ( field), + len); + gsi_insert_after( &gsi, gsize, GSI_SAME_STMT); + // FROM gsi_insert_after( &gsi, prev_ok_field) + gimple *gprev_ok_field = gimple_build_label ( prev_ok_field_L); + gsi_insert_after ( &gsi, gprev_ok_field, GSI_SAME_STMT); + // FROM prev_bb = new_bb + prev_bb = new_bb; + // FROM prev_order = new_bb + prev_order = new_bb; + // FROM prev_ok_field = new_ok_field + prev_ok_field_L = new_ok_field_L; + } - // add code to after_bb - // - // FROM gsi = gsi_start_bb( after_bb) - gimple_stmt_iterator gsi = gsi_start_bb( after_bb); - // FROM gsi_insert_after( &gsi, "lhs = "phi(success_val, fail_val) - gphi *der_phi = create_phi_node( lhs, after_bb); - add_phi_arg( der_phi, success_val, success_edge, UNKNOWN_LOCATION); - add_phi_arg( der_phi, fail_val, failure_edge, UNKNOWN_LOCATION); - - // FROM gsi_insert_after( &gsi, after_label) - gimple gafter_label = gimple_build_label( after_L); - gsi_insert_after( &gsi, gafter_label ); - */ + // create basic block for success + // + // FROM success_bb = create_empty_block(prev_bb_order); + basic_block success_bb = create_empty_bb ( prev_bb); + // FROM set imm dom success_bb as prev_bb + set_immediate_dominator ( CDI_DOMINATORS, success_bb, prev_bb); + // FROM make_edge( prev_bb, success_bb, EDGE_TRUE_VALUE); + make_edge ( prev_bb, success_bb, EDGE_TRUE_VALUE); + // FROM make_edge( success_bb, after_bb, EDGE_TRUE_VALUE); + edge success_edge = make_edge ( success_bb, after_bb, EDGE_TRUE_VALUE); + + // code in success_bb + // + // FROM success_val is new SSA + tree success_val = + make_temp_ssa_name( reorg_pointer_type, NULL, "success_val"); + // FROM gsi = gsi_start_bb( failure_bb) + // Reuse the same gsi??? Or create a new one??? + //gimple_stmt_iterator gsi = gsi_start_bb ( failure_bb); + gsi = gsi_start_bb ( failure_bb); + // FROM gsi_insert_after( &gsi, "goto after_label") + // Reuse goto_al + //gimple *goto_al = gimple_build_goto( after_label_L); + goto_al = gimple_build_goto( after_label_L); + gsi_insert_after( &gsi, goto_al, GSI_SAME_STMT); + // FROM gsi_insert_after( &gsi, "success_val = 0") + gimple *set_succ = + gimple_build_assign ( success_val, + build_int_cst ( reorg_pointer_type, 0)); + gsi_insert_after( &gsi, set_succ, GSI_SAME_STMT); + // 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 + // + // FROM gsi = gsi_start_bb( after_bb) + // Reuse gsi + //gimple_stmt_iterator gsi = gsi_start_bb( after_bb); + gsi = gsi_start_bb( after_bb); + // FROM gsi_insert_after( &gsi, "lhs = "phi(success_val, fail_val) + gphi *der_phi = create_phi_node( lhs, after_bb); + add_phi_arg( der_phi, success_val, success_edge, UNKNOWN_LOCATION); + add_phi_arg( der_phi, fail_val, failure_edge, UNKNOWN_LOCATION); + + // FROM gsi_insert_after( &gsi, after_label) + gimple gafter_label = gimple_build_label( after_L); + gsi_insert_after( &gsi, gafter_label, GSI_SAME_STMT); + #endif + INDENT(-2); break; case ReorgT_Calloc: DEBUG_L("ReorgT_Calloc\n"); /* - // This used to be almost a clone of the old version of - // the malloc code above and needs to transformed just like - // what was done above to malloc. - tree arg = gimple_call_arg( stmt, 0); - len is new SSA - tree val = gimple_call_lhs( stmt); - gcc_assert( TREE_CODE( TREE_TYPE(val)) == INDIRECT_REF); - tree size = TYPE_SIZE_UNIT( TREE_TYPE( TREE_TYPE( val))); - gimple *glen = - gimple_build_assign( - len, - TRUNC_DIV_EXPR, - val, - size, - NULL_TREE, NULL_TREE); - insert glen before stmt - tree lfial = create_artificial_label( UNKNOWN_LOCATION); - gimple *gfail = gimple_build_label( lfail); - tree lnotfial = create_artificial_label( UNKNOWN_LOCATION); - gimple *gnotfail = gimple_build_label( lnotfail); - tree base = ri->clone; - for each element of base { - // call malloc - tree lok = create_artificial_label( UNKNOWN_LOCATION); - gimple *glok = gimple_build_label( lok); - tree *fndecl = builtin_decl_explicit( BUILT_IN_MALLOC); - mem_size is new SSA - gimple *gsize = - gimple_build_assign( - mem_size, - MULT_EXPR, - TYPE_SIZE(element), - len, - NULL_TREE, NULL_TREE); - insert gsize before stmt - gcall *call = gimple_build_call( fndecl, 1, mem_size); - mres is new SSA - gimple_call_set_lhs( call, mres) - insert call before stmt - // Set element to return value of malloc. - // Note, the devil is in the details here. - gen concat( REORG_SP_PREFIX, - type_name( lhs) ).element <- mres - and insert before stmt - // gen test of return - gimple *gcond = - gimple_build_cond( EQ_EXPR, mres, - null_pointer_node, lfail, lok); - insert gcond before stmt - insert glok before stmt - // call memset - fndecl = builtin_decl_explicit( BUILT_IN_MEMSET); - call = - gimple_build_call( fndecl, 3, mres, int_node_zero, mem_size); - insert call before stmt - } + // This used to be almost a clone of the old version of + // the malloc code above and needs to transformed just like + // what was done above to malloc. + tree arg = gimple_call_arg( stmt, 0); + len is new SSA + tree val = gimple_call_lhs( stmt); + gcc_assert( TREE_CODE( TREE_TYPE(val)) == INDIRECT_REF); + tree size = TYPE_SIZE_UNIT( TREE_TYPE( TREE_TYPE( val))); + gimple *glen = + gimple_build_assign( + len, + TRUNC_DIV_EXPR, + val, + size, + NULL_TREE, NULL_TREE); + //insert glen before stmt + gimple_stmt_iterator stmt_gsi = gsi_for_stmt ( stmt); + gsi_link_before( stmt_gsi, glen, GSI_SAME_STMT); + tree lfial = create_artificial_label( UNKNOWN_LOCATION); + gimple *gfail = gimple_build_label( lfail); + tree lnotfial = create_artificial_label( UNKNOWN_LOCATION); + gimple *gnotfail = gimple_build_label( lnotfail); + tree base = ri->clone; + for (each element of base) // TBD <== + { + // call malloc + tree lok = create_artificial_label( UNKNOWN_LOCATION); + gimple *glok = gimple_build_label( lok); + tree *fndecl = builtin_decl_explicit( BUILT_IN_MALLOC); + mem_size is new SSA + gimple *gsize = + gimple_build_assign( + mem_size, + MULT_EXPR, + TYPE_SIZE(element), + len, + NULL_TREE, NULL_TREE); + insert gsize before stmt + gcall *call = gimple_build_call( fndecl, 1, mem_size); + mres is new SSA + gimple_call_set_lhs( call, mres) + insert call before stmt + // Set element to return value of malloc. + // Note, the devil is in the details here. + gen concat( REORG_SP_PREFIX, + type_name( lhs) ).element <- mres + and insert before stmt + // gen test of return + gimple *gcond = + gimple_build_cond( EQ_EXPR, mres, + null_pointer_node, lfail, lok); + insert gcond before stmt + insert glok before stmt + // call memset + fndecl = builtin_decl_explicit( BUILT_IN_MEMSET); + call = + gimple_build_call( fndecl, 3, mres, int_node_zero, mem_size); + insert call before stmt + } - // fake return value of zero - gimple *gretzero = - gimple_build_assign( lhs, - build_int_cst( - TYPE_MIN_VALUE( TREE_TYPE(lhs)), 0)); - insert gretzero before stmt - gimple *ggoto = gimple_build_goto( lnotfail); - insert ggoto before stmt - insert glab1 before stmt - for each element of base { - tree fndecl = builtin_decl_explicit( BUILT_IN_FREE); - gcall *call = gimple_build_call( fndecl, 1, element); - insert call before stmt - set element to null - } - // fake return value of null - gimple *gretnull = - gimple_build_assign( lhs, - build_int_cst( - TYPE_MIN_VALUE( TREE_TYPE(lhs)))); - insert gretnull before stmt - insert gnotfail before stmt - delete stmt - */ + // fake return value of zero + gimple *gretzero = + gimple_build_assign( lhs, + build_int_cst( + TYPE_MIN_VALUE( TREE_TYPE(lhs)), 0)); + insert gretzero before stmt + gimple *ggoto = gimple_build_goto( lnotfail); + insert ggoto before stmt + insert glab1 before stmt + for each element of base { + tree fndecl = builtin_decl_explicit( BUILT_IN_FREE); + gcall *call = gimple_build_call( fndecl, 1, element); + insert call before stmt + set element to null + } + // fake return value of null + gimple *gretnull = + gimple_build_assign( lhs, + build_int_cst( + TYPE_MIN_VALUE( TREE_TYPE(lhs)))); + insert gretnull before stmt + insert gnotfail before stmt + delete stmt + */ break; case ReorgT_Realloc: DEBUG_L("ReorgT_Realloc\n"); diff --git a/gcc/ipa-structure-reorg.c b/gcc/ipa-structure-reorg.c index 58e7578a8c8..68865afbb19 100644 --- a/gcc/ipa-structure-reorg.c +++ b/gcc/ipa-structure-reorg.c @@ -76,7 +76,7 @@ static void reorg_forbidden ( gimple *, Info *); //static ReorgTransformation reorg_recognize ( gimple *, Info *); //static bool is_reorg_type ( tree, Info *); //static tree base_type_of ( tree); -static bool is_user_function ( gimple *, Info *); +static bool is_user_function ( gimple *, cgraph_node *, Info *); static bool is_reorg_alloc_trigger ( gimple *); static ReorgType_t *find_struct_type_ptr_to_struct ( tree, Info *); //static ReorgType_t *get_reorgtype_info ( tree, Info *); @@ -917,7 +917,7 @@ transformation_legality ( Info *info) int num = num_reorgtypes ( stmt, info); if ( num != 0 ) { - if ( reorg_recognize( stmt, info) == Not_Supported ) + if ( reorg_recognize( stmt, node, info) == Not_Supported ) { int i; for ( i = 0; i < num; i++ ) @@ -1034,7 +1034,7 @@ undelete_reorgtype ( ReorgType_t *rt, Info *info ) } ReorgTransformation -reorg_recognize ( gimple *stmt, Info *info ) +reorg_recognize ( gimple *stmt, cgraph_node* node, Info_t *info ) { DEBUG_L ( "ReorgTransformation reorg_recognize for: "); DEBUG_F ( print_gimple_stmt, stderr, stmt, 0); @@ -1115,6 +1115,7 @@ reorg_recognize ( gimple *stmt, Info *info ) INDENT(-4); switch ( recognize_op( rhs, info) ) { + case ReorgOpT_Scalar: // "z" case ReorgOpT_Temp: // "t" case ReorgOpT_Indirect: // "a->f" case ReorgOpT_AryDir: // "x[i].f" @@ -1190,13 +1191,15 @@ reorg_recognize ( gimple *stmt, Info *info ) { DEBUG_L("GIMPLE_COND:\n"); INDENT(-2); - tree op1 = gimple_assign_rhs1 ( stmt); - tree op2 = gimple_assign_rhs2( stmt); + //tree op1 = gimple_assign_rhs1 ( stmt); + //tree op2 = gimple_assign_rhs2( stmt); + tree op1 = gimple_cond_lhs ( stmt); + tree op2 = gimple_cond_rhs ( stmt); enum tree_code cond_code = gimple_cond_code (stmt); - // TBD The parenthesis where a disaster here in the HL Design so + // TBD The parenthesis were a disaster here in the HL Design so // double check this! bool zero_case = - ( POINTER_TYPE_P ( TREE_TYPE ( op1)) && integer_zerop ( op2)) + ( POINTER_TYPE_P ( TREE_TYPE ( op1)) && integer_zerop ( op2)) || ( POINTER_TYPE_P ( TREE_TYPE ( op2)) && integer_zerop ( op1)); switch ( cond_code ) { @@ -1219,6 +1222,10 @@ reorg_recognize ( gimple *stmt, Info *info ) case GIMPLE_CALL: { 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); if ( gimple_call_builtin_p( stmt, BUILT_IN_CALLOC ) ) return ReorgT_Calloc; if ( gimple_call_builtin_p( stmt, BUILT_IN_MALLOC ) ) return ReorgT_Malloc; @@ -1230,7 +1237,7 @@ reorg_recognize ( gimple *stmt, Info *info ) // transformation is meaningless but the type still needs to be // adjusted (does transform really do this?) - if ( is_user_function ( stmt, info) ) + if ( is_user_function ( stmt, node, info) ) { return ReorgT_UserFunc; } @@ -1253,35 +1260,15 @@ reorg_recognize ( gimple *stmt, Info *info ) } static bool -is_user_function ( gimple *call_stmt, Info *info) +is_user_function ( gimple *call_stmt, cgraph_node* node, Info *info) { - tree fndecl = gimple_call_fndecl ( call_stmt); - - DEBUG_L("is_user_function: decl in: %p,", fndecl); - DEBUG_F( print_generic_decl, stderr, fndecl, (dump_flags_t)-1); - DEBUG("\n"); - INDENT(2); - - gcc_assert ( fndecl); - - cgraph_node* node; - bool ret_val = false; - FOR_EACH_FUNCTION_WITH_GIMPLE_BODY ( node) - { - DEBUG_L("decl %p,", node->decl); - DEBUG_F( print_generic_decl, stderr, node->decl, (dump_flags_t)-1); - DEBUG("\n"); - - if ( node->decl == fndecl ) - { - ret_val = true; - break; - } - } - - INDENT(-2); - return true; // <==== Evil work around!!!!!! - return ret_val; + // I'm not 100% sure this is a great idea but it means that + // if we know nothing about the contents of a function + // then it shouldn't be considered a user written function + // that is part of our program. + struct cgraph_edge *ce; + ce = node->get_edge ( call_stmt); + return ce->callee->has_gimple_body_p(); } void diff --git a/gcc/ipa-structure-reorg.h b/gcc/ipa-structure-reorg.h index 6864caf27a3..509597ca85f 100644 --- a/gcc/ipa-structure-reorg.h +++ b/gcc/ipa-structure-reorg.h @@ -212,7 +212,9 @@ extern void clear_deleted_types( Info *); extern void restore_deleted_types ( Info *); extern void remove_deleted_types ( Info *, ReorgFn); extern enum ReorgOpTrans recognize_op ( tree, Info_t *); -extern ReorgTransformation reorg_recognize ( gimple *, Info_t *); +extern ReorgTransformation reorg_recognize ( gimple *, + cgraph_node *, + Info_t *); extern ReorgType_t *get_reorgtype_info ( tree, Info_t *); extern ReorgType_t *contains_a_reorgtype ( gimple *, Info *); extern bool is_reorg_type ( tree, Info_t *); -- cgit v1.2.3