diff options
Diffstat (limited to 'src/cuda-sim/ptx_ir.cc')
| -rw-r--r-- | src/cuda-sim/ptx_ir.cc | 2478 |
1 files changed, 1287 insertions, 1191 deletions
diff --git a/src/cuda-sim/ptx_ir.cc b/src/cuda-sim/ptx_ir.cc index d8943d2..aa1c25a 100644 --- a/src/cuda-sim/ptx_ir.cc +++ b/src/cuda-sim/ptx_ir.cc @@ -1,5 +1,5 @@ // Copyright (c) 2009-2011, Tor M. Aamodt, Ali Bakhoda, Wilson W.L. Fung, -// George L. Yuan +// George L. Yuan // The University of British Columbia // All rights reserved. // @@ -8,1170 +8,1263 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this -// list of conditions and the following disclaimer in the documentation and/or -// other materials provided with the distribution. -// Neither the name of The University of British Columbia nor the names of its -// contributors may be used to endorse or promote products derived from this -// software without specific prior written permission. +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. Neither the name of +// The University of British Columbia nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. -#include "ptx_parser.h" #include "ptx_ir.h" -typedef void * yyscan_t; -#include "ptx.tab.h" -#include "opcodes.h" +#include "ptx_parser.h" +typedef void *yyscan_t; +#include <assert.h> #include <stdio.h> #include <stdlib.h> -#include <list> -#include <assert.h> #include <algorithm> +#include <list> #include "assert.h" +#include "opcodes.h" +#include "ptx.tab.h" -#include "cuda-sim.h" #include "../../libcuda/gpgpu_context.h" +#include "cuda-sim.h" #define STR_SIZE 1024 -const ptx_instruction* gpgpu_context::pc_to_instruction(unsigned pc) -{ - if( pc < s_g_pc_to_insn.size() ) - return s_g_pc_to_insn[pc]; - else - return NULL; +const ptx_instruction *gpgpu_context::pc_to_instruction(unsigned pc) { + if (pc < s_g_pc_to_insn.size()) + return s_g_pc_to_insn[pc]; + else + return NULL; } -unsigned symbol::get_uid() -{ - unsigned result = (gpgpu_ctx->symbol_sm_next_uid)++; - return result; +unsigned symbol::get_uid() { + unsigned result = (gpgpu_ctx->symbol_sm_next_uid)++; + return result; } -void symbol::add_initializer( const std::list<operand_info> &init ) -{ - m_initializer = init; +void symbol::add_initializer(const std::list<operand_info> &init) { + m_initializer = init; } -void symbol::print_info(FILE *fp) const -{ - fprintf(fp,"uid:%u, decl:%s, type:%p, ", m_uid, m_decl_location.c_str(), m_type ); - if( m_address_valid ) - fprintf(fp,"<address valid>, "); - if( m_is_label ) - fprintf(fp," is_label "); - if( m_is_shared ) - fprintf(fp," is_shared "); - if( m_is_const ) - fprintf(fp," is_const "); - if( m_is_global ) - fprintf(fp," is_global "); - if( m_is_local ) - fprintf(fp," is_local "); - if( m_is_tex ) - fprintf(fp," is_tex "); - if( m_is_func_addr ) - fprintf(fp," is_func_addr "); - if( m_function ) - fprintf(fp," %p ", m_function ); +void symbol::print_info(FILE *fp) const { + fprintf(fp, "uid:%u, decl:%s, type:%p, ", m_uid, m_decl_location.c_str(), + m_type); + if (m_address_valid) fprintf(fp, "<address valid>, "); + if (m_is_label) fprintf(fp, " is_label "); + if (m_is_shared) fprintf(fp, " is_shared "); + if (m_is_const) fprintf(fp, " is_const "); + if (m_is_global) fprintf(fp, " is_global "); + if (m_is_local) fprintf(fp, " is_local "); + if (m_is_tex) fprintf(fp, " is_tex "); + if (m_is_func_addr) fprintf(fp, " is_func_addr "); + if (m_function) fprintf(fp, " %p ", m_function); } -symbol_table::symbol_table() -{ - assert(0); -} +symbol_table::symbol_table() { assert(0); } -symbol_table::symbol_table( const char *scope_name, unsigned entry_point, symbol_table *parent, gpgpu_context* ctx ) -{ - gpgpu_ctx = ctx; - m_scope_name = std::string(scope_name); - m_reg_allocator=0; - m_shared_next = 0; - m_const_next = 0; - m_global_next = 0x100; - m_local_next = 0; - m_tex_next = 0; +symbol_table::symbol_table(const char *scope_name, unsigned entry_point, + symbol_table *parent, gpgpu_context *ctx) { + gpgpu_ctx = ctx; + m_scope_name = std::string(scope_name); + m_reg_allocator = 0; + m_shared_next = 0; + m_const_next = 0; + m_global_next = 0x100; + m_local_next = 0; + m_tex_next = 0; - //Jin: handle instruction group for cdp - m_inst_group_id = 0; + // Jin: handle instruction group for cdp + m_inst_group_id = 0; - m_parent = parent; - if ( m_parent ) { - m_shared_next = m_parent->m_shared_next; - m_global_next = m_parent->m_global_next; - } + m_parent = parent; + if (m_parent) { + m_shared_next = m_parent->m_shared_next; + m_global_next = m_parent->m_global_next; + } } -void symbol_table::set_name( const char *name ) -{ - m_scope_name = std::string(name); +void symbol_table::set_name(const char *name) { + m_scope_name = std::string(name); } -const ptx_version &symbol_table::get_ptx_version() const -{ - if( m_parent == NULL ) return m_ptx_version; - else return m_parent->get_ptx_version(); +const ptx_version &symbol_table::get_ptx_version() const { + if (m_parent == NULL) + return m_ptx_version; + else + return m_parent->get_ptx_version(); } -unsigned symbol_table::get_sm_target() const -{ - if( m_parent == NULL ) - return m_ptx_version.target(); - else return m_parent->get_sm_target(); +unsigned symbol_table::get_sm_target() const { + if (m_parent == NULL) + return m_ptx_version.target(); + else + return m_parent->get_sm_target(); } -void symbol_table::set_ptx_version( float ver, unsigned ext ) -{ - m_ptx_version = ptx_version(ver,ext); +void symbol_table::set_ptx_version(float ver, unsigned ext) { + m_ptx_version = ptx_version(ver, ext); } -void symbol_table::set_sm_target( const char *target, const char *ext, const char *ext2 ) -{ - m_ptx_version.set_target(target,ext,ext2); +void symbol_table::set_sm_target(const char *target, const char *ext, + const char *ext2) { + m_ptx_version.set_target(target, ext, ext2); } -symbol *symbol_table::lookup( const char *identifier ) -{ - std::string key(identifier); - std::map<std::string, symbol *>::iterator i = m_symbols.find(key); - if ( i != m_symbols.end() ) { - return i->second; - } - if ( m_parent ) { - return m_parent->lookup(identifier); - } - return NULL; +symbol *symbol_table::lookup(const char *identifier) { + std::string key(identifier); + std::map<std::string, symbol *>::iterator i = m_symbols.find(key); + if (i != m_symbols.end()) { + return i->second; + } + if (m_parent) { + return m_parent->lookup(identifier); + } + return NULL; } -symbol *symbol_table::add_variable( const char *identifier, const type_info *type, unsigned size, const char *filename, unsigned line ) -{ - char buf[1024]; - std::string key(identifier); - assert( m_symbols.find(key) == m_symbols.end() ); - snprintf(buf,1024,"%s:%u",filename,line); - symbol *s = new symbol(identifier,type,buf,size,gpgpu_ctx); - m_symbols[ key ] = s; +symbol *symbol_table::add_variable(const char *identifier, + const type_info *type, unsigned size, + const char *filename, unsigned line) { + char buf[1024]; + std::string key(identifier); + assert(m_symbols.find(key) == m_symbols.end()); + snprintf(buf, 1024, "%s:%u", filename, line); + symbol *s = new symbol(identifier, type, buf, size, gpgpu_ctx); + m_symbols[key] = s; - if ( type != NULL && type->get_key().is_global() ) { - m_globals.push_back(s); - } - if ( type != NULL && type->get_key().is_const() ) { - m_consts.push_back(s); - } + if (type != NULL && type->get_key().is_global()) { + m_globals.push_back(s); + } + if (type != NULL && type->get_key().is_const()) { + m_consts.push_back(s); + } - return s; + return s; } -void symbol_table::add_function( function_info *func, const char *filename, unsigned linenumber ) -{ - std::map<std::string, symbol *>::iterator i = m_symbols.find( func->get_name() ); - if( i != m_symbols.end() ) - return; - char buf[1024]; - snprintf(buf,1024,"%s:%u",filename,linenumber); - type_info *type = add_type( func ); - symbol *s = new symbol(func->get_name().c_str(),type,buf,0,gpgpu_ctx); - s->set_function(func); - m_symbols[ func->get_name() ] = s; +void symbol_table::add_function(function_info *func, const char *filename, + unsigned linenumber) { + std::map<std::string, symbol *>::iterator i = + m_symbols.find(func->get_name()); + if (i != m_symbols.end()) return; + char buf[1024]; + snprintf(buf, 1024, "%s:%u", filename, linenumber); + type_info *type = add_type(func); + symbol *s = new symbol(func->get_name().c_str(), type, buf, 0, gpgpu_ctx); + s->set_function(func); + m_symbols[func->get_name()] = s; } -//Jin: handle instruction group for cdp -symbol_table* symbol_table::start_inst_group() { - char inst_group_name[4096]; - snprintf(inst_group_name, 4096, "%s_inst_group_%u", m_scope_name.c_str(), m_inst_group_id); +// Jin: handle instruction group for cdp +symbol_table *symbol_table::start_inst_group() { + char inst_group_name[4096]; + snprintf(inst_group_name, 4096, "%s_inst_group_%u", m_scope_name.c_str(), + m_inst_group_id); + + // previous added + assert(m_inst_group_symtab.find(std::string(inst_group_name)) == + m_inst_group_symtab.end()); + symbol_table *sym_table = + new symbol_table(inst_group_name, 3 /*inst group*/, this, gpgpu_ctx); - //previous added - assert(m_inst_group_symtab.find(std::string(inst_group_name)) == m_inst_group_symtab.end()); - symbol_table *sym_table = new symbol_table(inst_group_name, 3/*inst group*/, this, gpgpu_ctx ); - - sym_table->m_global_next = m_global_next; - sym_table->m_shared_next = m_shared_next; - sym_table->m_local_next = m_local_next; - sym_table->m_reg_allocator = m_reg_allocator; - sym_table->m_tex_next = m_tex_next; - sym_table->m_const_next = m_const_next; + sym_table->m_global_next = m_global_next; + sym_table->m_shared_next = m_shared_next; + sym_table->m_local_next = m_local_next; + sym_table->m_reg_allocator = m_reg_allocator; + sym_table->m_tex_next = m_tex_next; + sym_table->m_const_next = m_const_next; - m_inst_group_symtab[std::string(inst_group_name)] = sym_table; + m_inst_group_symtab[std::string(inst_group_name)] = sym_table; - return sym_table; + return sym_table; } -symbol_table * symbol_table::end_inst_group() { - symbol_table * sym_table = m_parent; - - sym_table->m_global_next = m_global_next; - sym_table->m_shared_next = m_shared_next; - sym_table->m_local_next = m_local_next; - sym_table->m_reg_allocator = m_reg_allocator; - sym_table->m_tex_next = m_tex_next; - sym_table->m_const_next = m_const_next; - sym_table->m_inst_group_id++; +symbol_table *symbol_table::end_inst_group() { + symbol_table *sym_table = m_parent; - return sym_table; + sym_table->m_global_next = m_global_next; + sym_table->m_shared_next = m_shared_next; + sym_table->m_local_next = m_local_next; + sym_table->m_reg_allocator = m_reg_allocator; + sym_table->m_tex_next = m_tex_next; + sym_table->m_const_next = m_const_next; + sym_table->m_inst_group_id++; + + return sym_table; } -void register_ptx_function( const char *name, function_info *impl ); // either libcuda or libopencl +void register_ptx_function(const char *name, + function_info *impl); // either libcuda or libopencl -bool symbol_table::add_function_decl( const char *name, int entry_point, function_info **func_info, symbol_table **sym_table ) -{ - std::string key = std::string(name); - bool prior_decl = false; - if( m_function_info_lookup.find(key) != m_function_info_lookup.end() ) { - *func_info = m_function_info_lookup[key]; - prior_decl = true; - } else { - *func_info = new function_info(entry_point, gpgpu_ctx); - (*func_info)->set_name(name); - (*func_info)->set_maxnt_id(0); - m_function_info_lookup[key] = *func_info; - } +bool symbol_table::add_function_decl(const char *name, int entry_point, + function_info **func_info, + symbol_table **sym_table) { + std::string key = std::string(name); + bool prior_decl = false; + if (m_function_info_lookup.find(key) != m_function_info_lookup.end()) { + *func_info = m_function_info_lookup[key]; + prior_decl = true; + } else { + *func_info = new function_info(entry_point, gpgpu_ctx); + (*func_info)->set_name(name); + (*func_info)->set_maxnt_id(0); + m_function_info_lookup[key] = *func_info; + } - if( m_function_symtab_lookup.find(key) != m_function_symtab_lookup.end() ) { - assert( prior_decl ); - *sym_table = m_function_symtab_lookup[key]; - } else { - assert( !prior_decl ); - *sym_table = new symbol_table( "", entry_point, this, gpgpu_ctx ); - - // Initial setup code to support a register represented as "_". - // This register is used when an instruction operand is - // not read or written. However, the parser must recognize it - // as a legitimate register but we do not want to pass - // it to the micro-architectural register to the performance simulator. - // For this purpose we add a symbol to the symbol table but - // mark it as a non_arch_reg so it does not effect the performance sim. - type_info_key null_key( reg_space, 0, 0, 0, 0, 0 ); - null_key.set_is_non_arch_reg(); - // First param is null - which is bad. - // However, the first parameter is actually unread in the constructor... - // TODO - remove the symbol_table* from type_info - type_info* null_type_info = new type_info( NULL, null_key ); - symbol *null_reg = (*sym_table)->add_variable( "_", null_type_info, 0, "", 0 ); - null_reg->set_regno(0, 0); - - (*sym_table)->set_name(name); - (*func_info)->set_symtab(*sym_table); - m_function_symtab_lookup[key] = *sym_table; - assert( (*func_info)->get_symtab() == *sym_table ); - register_ptx_function(name,*func_info); - } - return prior_decl; + if (m_function_symtab_lookup.find(key) != m_function_symtab_lookup.end()) { + assert(prior_decl); + *sym_table = m_function_symtab_lookup[key]; + } else { + assert(!prior_decl); + *sym_table = new symbol_table("", entry_point, this, gpgpu_ctx); + + // Initial setup code to support a register represented as "_". + // This register is used when an instruction operand is + // not read or written. However, the parser must recognize it + // as a legitimate register but we do not want to pass + // it to the micro-architectural register to the performance simulator. + // For this purpose we add a symbol to the symbol table but + // mark it as a non_arch_reg so it does not effect the performance sim. + type_info_key null_key(reg_space, 0, 0, 0, 0, 0); + null_key.set_is_non_arch_reg(); + // First param is null - which is bad. + // However, the first parameter is actually unread in the constructor... + // TODO - remove the symbol_table* from type_info + type_info *null_type_info = new type_info(NULL, null_key); + symbol *null_reg = + (*sym_table)->add_variable("_", null_type_info, 0, "", 0); + null_reg->set_regno(0, 0); + + (*sym_table)->set_name(name); + (*func_info)->set_symtab(*sym_table); + m_function_symtab_lookup[key] = *sym_table; + assert((*func_info)->get_symtab() == *sym_table); + register_ptx_function(name, *func_info); + } + return prior_decl; } -function_info *symbol_table::lookup_function( std::string name ) -{ - std::string key = std::string(name); - std::map<std::string,function_info*>::iterator it = m_function_info_lookup.find(key); - assert ( it != m_function_info_lookup.end() ); - return it->second; +function_info *symbol_table::lookup_function(std::string name) { + std::string key = std::string(name); + std::map<std::string, function_info *>::iterator it = + m_function_info_lookup.find(key); + assert(it != m_function_info_lookup.end()); + return it->second; } -type_info *symbol_table::add_type( memory_space_t space_spec, int scalar_type_spec, int vector_spec, int alignment_spec, int extern_spec ) -{ - if( space_spec == param_space_unclassified ) - space_spec = param_space_local; - type_info_key t(space_spec,scalar_type_spec,vector_spec,alignment_spec,extern_spec,0); - type_info *pt; - pt = new type_info(this,t); - return pt; +type_info *symbol_table::add_type(memory_space_t space_spec, + int scalar_type_spec, int vector_spec, + int alignment_spec, int extern_spec) { + if (space_spec == param_space_unclassified) space_spec = param_space_local; + type_info_key t(space_spec, scalar_type_spec, vector_spec, alignment_spec, + extern_spec, 0); + type_info *pt; + pt = new type_info(this, t); + return pt; } -type_info *symbol_table::add_type( function_info *func ) -{ - type_info_key t; - type_info *pt; - t.set_is_func(); - pt = new type_info(this,t); - return pt; +type_info *symbol_table::add_type(function_info *func) { + type_info_key t; + type_info *pt; + t.set_is_func(); + pt = new type_info(this, t); + return pt; } -type_info *symbol_table::get_array_type( type_info *base_type, unsigned array_dim ) -{ - type_info_key t = base_type->get_key(); - t.set_array_dim(array_dim); - type_info *pt = new type_info(this,t); - //Where else is m_types being used? As of now, I dont find any use of it and causing seg fault. So disabling m_types. - //TODO: find where m_types can be used in future and solve the seg fault. - //pt = m_types[t] = new type_info(this,t); - return pt; +type_info *symbol_table::get_array_type(type_info *base_type, + unsigned array_dim) { + type_info_key t = base_type->get_key(); + t.set_array_dim(array_dim); + type_info *pt = new type_info(this, t); + // Where else is m_types being used? As of now, I dont find any use of it and + // causing seg fault. So disabling m_types. + // TODO: find where m_types can be used in future and solve the seg fault. + // pt = m_types[t] = new type_info(this,t); + return pt; } -void symbol_table::set_label_address( const symbol *label, unsigned addr ) -{ - std::map<std::string, symbol *>::iterator i=m_symbols.find(label->name()); - assert( i != m_symbols.end() ); - symbol *s = i->second; - s->set_label_address(addr); +void symbol_table::set_label_address(const symbol *label, unsigned addr) { + std::map<std::string, symbol *>::iterator i = m_symbols.find(label->name()); + assert(i != m_symbols.end()); + symbol *s = i->second; + s->set_label_address(addr); } -void symbol_table::dump() -{ - printf("\n\n"); - printf("Symbol table for \"%s\":\n", m_scope_name.c_str() ); - std::map<std::string, symbol *>::iterator i; - for( i=m_symbols.begin(); i!=m_symbols.end(); i++ ) { - printf("%30s : ", i->first.c_str() ); - if( i->second ) - i->second->print_info(stdout); - else - printf(" <no symbol object> "); - printf("\n"); - } - printf("\n"); +void symbol_table::dump() { + printf("\n\n"); + printf("Symbol table for \"%s\":\n", m_scope_name.c_str()); + std::map<std::string, symbol *>::iterator i; + for (i = m_symbols.begin(); i != m_symbols.end(); i++) { + printf("%30s : ", i->first.c_str()); + if (i->second) + i->second->print_info(stdout); + else + printf(" <no symbol object> "); + printf("\n"); + } + printf("\n"); } -unsigned operand_info::get_uid() -{ - unsigned result = (gpgpu_ctx->operand_info_sm_next_uid)++; - return result; +unsigned operand_info::get_uid() { + unsigned result = (gpgpu_ctx->operand_info_sm_next_uid)++; + return result; } -std::list<ptx_instruction*>::iterator function_info::find_next_real_instruction( std::list<ptx_instruction*>::iterator i) -{ - while( (i != m_instructions.end()) && (*i)->is_label() ) - i++; - return i; +std::list<ptx_instruction *>::iterator +function_info::find_next_real_instruction( + std::list<ptx_instruction *>::iterator i) { + while ((i != m_instructions.end()) && (*i)->is_label()) i++; + return i; } -void function_info::create_basic_blocks() -{ - std::list<ptx_instruction*> leaders; - std::list<ptx_instruction*>::iterator i, l; +void function_info::create_basic_blocks() { + std::list<ptx_instruction *> leaders; + std::list<ptx_instruction *>::iterator i, l; - // first instruction is a leader - i=m_instructions.begin(); - leaders.push_back(*i); - i++; - while( i!=m_instructions.end() ) { - ptx_instruction *pI = *i; - if( pI->is_label() ) { - leaders.push_back(pI); - i = find_next_real_instruction(++i); - } else { - switch( pI->get_opcode() ) { - case BRA_OP: case RET_OP: case EXIT_OP: case RETP_OP: case BREAK_OP: + // first instruction is a leader + i = m_instructions.begin(); + leaders.push_back(*i); + i++; + while (i != m_instructions.end()) { + ptx_instruction *pI = *i; + if (pI->is_label()) { + leaders.push_back(pI); + i = find_next_real_instruction(++i); + } else { + switch (pI->get_opcode()) { + case BRA_OP: + case RET_OP: + case EXIT_OP: + case RETP_OP: + case BREAK_OP: + i++; + if (i != m_instructions.end()) leaders.push_back(*i); + i = find_next_real_instruction(i); + break; + case CALL_OP: + case CALLP_OP: + if (pI->has_pred()) { + printf("GPGPU-Sim PTX: Warning found predicated call\n"); i++; - if( i != m_instructions.end() ) - leaders.push_back(*i); + if (i != m_instructions.end()) leaders.push_back(*i); i = find_next_real_instruction(i); - break; - case CALL_OP: case CALLP_OP: - if( pI->has_pred() ) { - printf("GPGPU-Sim PTX: Warning found predicated call\n"); - i++; - if( i != m_instructions.end() ) - leaders.push_back(*i); - i = find_next_real_instruction(i); - } else i++; - break; - default: + } else i++; - } - } - } + break; + default: + i++; + } + } + } - if( leaders.empty() ) { - printf("GPGPU-Sim PTX: Function \'%s\' has no basic blocks\n", m_name.c_str()); - return; - } + if (leaders.empty()) { + printf("GPGPU-Sim PTX: Function \'%s\' has no basic blocks\n", + m_name.c_str()); + return; + } - unsigned bb_id = 0; - l=leaders.begin(); - i=m_instructions.begin(); - m_basic_blocks.push_back( new basic_block_t(bb_id++,*find_next_real_instruction(i),NULL,1,0) ); - ptx_instruction *last_real_inst=*(l++); + unsigned bb_id = 0; + l = leaders.begin(); + i = m_instructions.begin(); + m_basic_blocks.push_back( + new basic_block_t(bb_id++, *find_next_real_instruction(i), NULL, 1, 0)); + ptx_instruction *last_real_inst = *(l++); - for( ; i!=m_instructions.end(); i++ ) { - ptx_instruction *pI = *i; - if( l != leaders.end() && *i == *l ) { - // found start of next basic block - m_basic_blocks.back()->ptx_end = last_real_inst; - if( find_next_real_instruction(i) != m_instructions.end() ) { // if not bogus trailing label - m_basic_blocks.push_back( new basic_block_t(bb_id++,*find_next_real_instruction(i),NULL,0,0) ); - last_real_inst = *find_next_real_instruction(i); - } - // start search for next leader - l++; + for (; i != m_instructions.end(); i++) { + ptx_instruction *pI = *i; + if (l != leaders.end() && *i == *l) { + // found start of next basic block + m_basic_blocks.back()->ptx_end = last_real_inst; + if (find_next_real_instruction(i) != + m_instructions.end()) { // if not bogus trailing label + m_basic_blocks.push_back(new basic_block_t( + bb_id++, *find_next_real_instruction(i), NULL, 0, 0)); + last_real_inst = *find_next_real_instruction(i); } - pI->assign_bb( m_basic_blocks.back() ); - if( !pI->is_label() ) last_real_inst = pI; - } - m_basic_blocks.back()->ptx_end = last_real_inst; - m_basic_blocks.push_back( /*exit basic block*/ new basic_block_t(bb_id,NULL,NULL,0,1) ); + // start search for next leader + l++; + } + pI->assign_bb(m_basic_blocks.back()); + if (!pI->is_label()) last_real_inst = pI; + } + m_basic_blocks.back()->ptx_end = last_real_inst; + m_basic_blocks.push_back( + /*exit basic block*/ new basic_block_t(bb_id, NULL, NULL, 0, 1)); } -void function_info::print_basic_blocks() -{ - printf("Printing basic blocks for function \'%s\':\n", m_name.c_str() ); - std::list<ptx_instruction*>::iterator ptx_itr; - unsigned last_bb=0; - for (ptx_itr = m_instructions.begin();ptx_itr != m_instructions.end(); ptx_itr++) { - if( (*ptx_itr)->get_bb() ) { - if( (*ptx_itr)->get_bb()->bb_id != last_bb ) { - printf("\n"); - last_bb = (*ptx_itr)->get_bb()->bb_id; - } - printf("bb_%02u\t: ", (*ptx_itr)->get_bb()->bb_id); - (*ptx_itr)->print_insn(); - printf("\n"); +void function_info::print_basic_blocks() { + printf("Printing basic blocks for function \'%s\':\n", m_name.c_str()); + std::list<ptx_instruction *>::iterator ptx_itr; + unsigned last_bb = 0; + for (ptx_itr = m_instructions.begin(); ptx_itr != m_instructions.end(); + ptx_itr++) { + if ((*ptx_itr)->get_bb()) { + if ((*ptx_itr)->get_bb()->bb_id != last_bb) { + printf("\n"); + last_bb = (*ptx_itr)->get_bb()->bb_id; } - } - printf("\nSummary of basic blocks for \'%s\':\n", m_name.c_str() ); - std::vector<basic_block_t*>::iterator bb_itr; - for (bb_itr = m_basic_blocks.begin();bb_itr != m_basic_blocks.end(); bb_itr++) { - printf("bb_%02u\t:", (*bb_itr)->bb_id); - if ((*bb_itr)->ptx_begin) - printf(" first: %s\t", ((*bb_itr)->ptx_begin)->get_opcode_cstr()); - else printf(" first: NULL\t"); - if ((*bb_itr)->ptx_end) { - printf(" last: %s\t", ((*bb_itr)->ptx_end)->get_opcode_cstr()); - } else printf(" last: NULL\t"); + printf("bb_%02u\t: ", (*ptx_itr)->get_bb()->bb_id); + (*ptx_itr)->print_insn(); printf("\n"); - } - printf("\n"); + } + } + printf("\nSummary of basic blocks for \'%s\':\n", m_name.c_str()); + std::vector<basic_block_t *>::iterator bb_itr; + for (bb_itr = m_basic_blocks.begin(); bb_itr != m_basic_blocks.end(); + bb_itr++) { + printf("bb_%02u\t:", (*bb_itr)->bb_id); + if ((*bb_itr)->ptx_begin) + printf(" first: %s\t", ((*bb_itr)->ptx_begin)->get_opcode_cstr()); + else + printf(" first: NULL\t"); + if ((*bb_itr)->ptx_end) { + printf(" last: %s\t", ((*bb_itr)->ptx_end)->get_opcode_cstr()); + } else + printf(" last: NULL\t"); + printf("\n"); + } + printf("\n"); } -void function_info::print_basic_block_links() -{ - printf("Printing basic blocks links for function \'%s\':\n", m_name.c_str() ); - std::vector<basic_block_t*>::iterator bb_itr; - for (bb_itr = m_basic_blocks.begin();bb_itr != m_basic_blocks.end(); bb_itr++) { - printf("ID: %d\t:", (*bb_itr)->bb_id); - if ( !(*bb_itr)->predecessor_ids.empty() ) { - printf("Predecessors:"); - std::set<int>::iterator p; - for (p= (*bb_itr)->predecessor_ids.begin();p != (*bb_itr)->predecessor_ids.end();p++) { - printf(" %d", *p); - } - printf("\t"); +void function_info::print_basic_block_links() { + printf("Printing basic blocks links for function \'%s\':\n", m_name.c_str()); + std::vector<basic_block_t *>::iterator bb_itr; + for (bb_itr = m_basic_blocks.begin(); bb_itr != m_basic_blocks.end(); + bb_itr++) { + printf("ID: %d\t:", (*bb_itr)->bb_id); + if (!(*bb_itr)->predecessor_ids.empty()) { + printf("Predecessors:"); + std::set<int>::iterator p; + for (p = (*bb_itr)->predecessor_ids.begin(); + p != (*bb_itr)->predecessor_ids.end(); p++) { + printf(" %d", *p); } - if ( !(*bb_itr)->successor_ids.empty() ) { - printf("Successors:"); - std::set<int>::iterator s; - for (s= (*bb_itr)->successor_ids.begin();s != (*bb_itr)->successor_ids.end();s++) { - printf(" %d", *s); - } + printf("\t"); + } + if (!(*bb_itr)->successor_ids.empty()) { + printf("Successors:"); + std::set<int>::iterator s; + for (s = (*bb_itr)->successor_ids.begin(); + s != (*bb_itr)->successor_ids.end(); s++) { + printf(" %d", *s); } - printf("\n"); - } + } + printf("\n"); + } } -operand_info* function_info::find_break_target( ptx_instruction * p_break_insn ) //find the target of a break instruction +operand_info *function_info::find_break_target( + ptx_instruction *p_break_insn) // find the target of a break instruction { - const basic_block_t *break_bb = p_break_insn->get_bb(); - // go through the dominator tree - for(const basic_block_t *p_bb = break_bb; - p_bb->immediatedominator_id != -1; - p_bb = m_basic_blocks[p_bb->immediatedominator_id]) - { - // reverse search through instructions in basic block for breakaddr instruction - unsigned insn_addr = p_bb->ptx_end->get_m_instr_mem_index(); - while (insn_addr >= p_bb->ptx_begin->get_m_instr_mem_index()) { - ptx_instruction *pI = m_instr_mem[insn_addr]; - insn_addr -= 1; - if (pI == NULL) continue; // temporary solution for variable size instructions - if (pI->get_opcode() == BREAKADDR_OP) { - return &(pI->dst()); - } + const basic_block_t *break_bb = p_break_insn->get_bb(); + // go through the dominator tree + for (const basic_block_t *p_bb = break_bb; p_bb->immediatedominator_id != -1; + p_bb = m_basic_blocks[p_bb->immediatedominator_id]) { + // reverse search through instructions in basic block for breakaddr + // instruction + unsigned insn_addr = p_bb->ptx_end->get_m_instr_mem_index(); + while (insn_addr >= p_bb->ptx_begin->get_m_instr_mem_index()) { + ptx_instruction *pI = m_instr_mem[insn_addr]; + insn_addr -= 1; + if (pI == NULL) + continue; // temporary solution for variable size instructions + if (pI->get_opcode() == BREAKADDR_OP) { + return &(pI->dst()); } - } + } + } - assert(0); + assert(0); - // lazy fallback: just traverse backwards? - for (int insn_addr = p_break_insn->get_m_instr_mem_index(); - insn_addr >= 0; insn_addr--) - { - ptx_instruction *pI = m_instr_mem[insn_addr]; - if (pI->get_opcode() == BREAKADDR_OP) { - return &(pI->dst()); - } - } + // lazy fallback: just traverse backwards? + for (int insn_addr = p_break_insn->get_m_instr_mem_index(); insn_addr >= 0; + insn_addr--) { + ptx_instruction *pI = m_instr_mem[insn_addr]; + if (pI->get_opcode() == BREAKADDR_OP) { + return &(pI->dst()); + } + } - return NULL; + return NULL; } -void function_info::connect_basic_blocks( ) //iterate across m_basic_blocks of function, connecting basic blocks together +void function_info::connect_basic_blocks() // iterate across m_basic_blocks of + // function, connecting basic blocks + // together { - std::vector<basic_block_t*>::iterator bb_itr; - std::vector<basic_block_t*>::iterator bb_target_itr; - basic_block_t* exit_bb = m_basic_blocks.back(); + std::vector<basic_block_t *>::iterator bb_itr; + std::vector<basic_block_t *>::iterator bb_target_itr; + basic_block_t *exit_bb = m_basic_blocks.back(); - //start from first basic block, which we know is the entry point - bb_itr = m_basic_blocks.begin(); - for (bb_itr = m_basic_blocks.begin();bb_itr != m_basic_blocks.end(); bb_itr++) { - ptx_instruction *pI = (*bb_itr)->ptx_end; - if ((*bb_itr)->is_exit) //reached last basic block, no successors to link - continue; - if (pI->get_opcode() == RETP_OP || pI->get_opcode() == RET_OP || pI->get_opcode() == EXIT_OP ) { - (*bb_itr)->successor_ids.insert(exit_bb->bb_id); - exit_bb->predecessor_ids.insert((*bb_itr)->bb_id); - if( pI->has_pred() ) { - printf("GPGPU-Sim PTX: Warning detected predicated return/exit.\n"); - // if predicated, add link to next block - unsigned next_addr = pI->get_m_instr_mem_index() + pI->inst_size(); - if( next_addr < m_instr_mem_size && m_instr_mem[next_addr] ) { - basic_block_t *next_bb = m_instr_mem[next_addr]->get_bb(); - (*bb_itr)->successor_ids.insert(next_bb->bb_id); - next_bb->predecessor_ids.insert((*bb_itr)->bb_id); - } - } - continue; - } else if (pI->get_opcode() == BRA_OP) { - //find successor and link that basic_block to this one - operand_info &target = pI->dst(); //get operand, e.g. target name - unsigned addr = labels[ target.name() ]; - ptx_instruction *target_pI = m_instr_mem[addr]; - basic_block_t *target_bb = target_pI->get_bb(); - (*bb_itr)->successor_ids.insert(target_bb->bb_id); - target_bb->predecessor_ids.insert((*bb_itr)->bb_id); - } + // start from first basic block, which we know is the entry point + bb_itr = m_basic_blocks.begin(); + for (bb_itr = m_basic_blocks.begin(); bb_itr != m_basic_blocks.end(); + bb_itr++) { + ptx_instruction *pI = (*bb_itr)->ptx_end; + if ((*bb_itr)->is_exit) // reached last basic block, no successors to link + continue; + if (pI->get_opcode() == RETP_OP || pI->get_opcode() == RET_OP || + pI->get_opcode() == EXIT_OP) { + (*bb_itr)->successor_ids.insert(exit_bb->bb_id); + exit_bb->predecessor_ids.insert((*bb_itr)->bb_id); + if (pI->has_pred()) { + printf("GPGPU-Sim PTX: Warning detected predicated return/exit.\n"); + // if predicated, add link to next block + unsigned next_addr = pI->get_m_instr_mem_index() + pI->inst_size(); + if (next_addr < m_instr_mem_size && m_instr_mem[next_addr]) { + basic_block_t *next_bb = m_instr_mem[next_addr]->get_bb(); + (*bb_itr)->successor_ids.insert(next_bb->bb_id); + next_bb->predecessor_ids.insert((*bb_itr)->bb_id); + } + } + continue; + } else if (pI->get_opcode() == BRA_OP) { + // find successor and link that basic_block to this one + operand_info &target = pI->dst(); // get operand, e.g. target name + unsigned addr = labels[target.name()]; + ptx_instruction *target_pI = m_instr_mem[addr]; + basic_block_t *target_bb = target_pI->get_bb(); + (*bb_itr)->successor_ids.insert(target_bb->bb_id); + target_bb->predecessor_ids.insert((*bb_itr)->bb_id); + } - if ( !(pI->get_opcode()==BRA_OP && (!pI->has_pred())) ) { - // if basic block does not end in an unpredicated branch, - // then next basic block is also successor - // (this is better than testing for .uni) - unsigned next_addr = pI->get_m_instr_mem_index() + pI->inst_size(); - basic_block_t *next_bb = m_instr_mem[next_addr]->get_bb(); - (*bb_itr)->successor_ids.insert(next_bb->bb_id); - next_bb->predecessor_ids.insert((*bb_itr)->bb_id); - } else - assert(pI->get_opcode() == BRA_OP); - } + if (!(pI->get_opcode() == BRA_OP && (!pI->has_pred()))) { + // if basic block does not end in an unpredicated branch, + // then next basic block is also successor + // (this is better than testing for .uni) + unsigned next_addr = pI->get_m_instr_mem_index() + pI->inst_size(); + basic_block_t *next_bb = m_instr_mem[next_addr]->get_bb(); + (*bb_itr)->successor_ids.insert(next_bb->bb_id); + next_bb->predecessor_ids.insert((*bb_itr)->bb_id); + } else + assert(pI->get_opcode() == BRA_OP); + } } -bool function_info::connect_break_targets() //connecting break instructions with proper targets +bool function_info::connect_break_targets() // connecting break instructions + // with proper targets { - std::vector<basic_block_t*>::iterator bb_itr; - std::vector<basic_block_t*>::iterator bb_target_itr; - bool modified = false; - - //start from first basic block, which we know is the entry point - bb_itr = m_basic_blocks.begin(); - for (bb_itr = m_basic_blocks.begin();bb_itr != m_basic_blocks.end(); bb_itr++) { - basic_block_t *p_bb = *bb_itr; - ptx_instruction *pI = p_bb->ptx_end; - if (p_bb->is_exit) //reached last basic block, no successors to link - continue; - if (pI->get_opcode() == BREAK_OP) { - // backup existing successor_ids for stability check - std::set<int> orig_successor_ids = p_bb->successor_ids; + std::vector<basic_block_t *>::iterator bb_itr; + std::vector<basic_block_t *>::iterator bb_target_itr; + bool modified = false; - // erase the previous linkage with old successors - for(std::set<int>::iterator succ_ids = p_bb->successor_ids.begin(); succ_ids != p_bb->successor_ids.end(); ++succ_ids) { - basic_block_t *successor_bb = m_basic_blocks[*succ_ids]; - successor_bb->predecessor_ids.erase(p_bb->bb_id); - } - p_bb->successor_ids.clear(); + // start from first basic block, which we know is the entry point + bb_itr = m_basic_blocks.begin(); + for (bb_itr = m_basic_blocks.begin(); bb_itr != m_basic_blocks.end(); + bb_itr++) { + basic_block_t *p_bb = *bb_itr; + ptx_instruction *pI = p_bb->ptx_end; + if (p_bb->is_exit) // reached last basic block, no successors to link + continue; + if (pI->get_opcode() == BREAK_OP) { + // backup existing successor_ids for stability check + std::set<int> orig_successor_ids = p_bb->successor_ids; - //find successor and link that basic_block to this one - //successor of a break is set by an preceeding breakaddr instruction - operand_info *target = find_break_target(pI); - unsigned addr = labels[ target->name() ]; - ptx_instruction *target_pI = m_instr_mem[addr]; - basic_block_t *target_bb = target_pI->get_bb(); - p_bb->successor_ids.insert(target_bb->bb_id); - target_bb->predecessor_ids.insert(p_bb->bb_id); + // erase the previous linkage with old successors + for (std::set<int>::iterator succ_ids = p_bb->successor_ids.begin(); + succ_ids != p_bb->successor_ids.end(); ++succ_ids) { + basic_block_t *successor_bb = m_basic_blocks[*succ_ids]; + successor_bb->predecessor_ids.erase(p_bb->bb_id); + } + p_bb->successor_ids.clear(); - if (pI->has_pred()) { - // predicated break - add link to next basic block - unsigned next_addr = pI->get_m_instr_mem_index() + pI->inst_size(); - basic_block_t *next_bb = m_instr_mem[next_addr]->get_bb(); - p_bb->successor_ids.insert(next_bb->bb_id); - next_bb->predecessor_ids.insert(p_bb->bb_id); - } + // find successor and link that basic_block to this one + // successor of a break is set by an preceeding breakaddr instruction + operand_info *target = find_break_target(pI); + unsigned addr = labels[target->name()]; + ptx_instruction *target_pI = m_instr_mem[addr]; + basic_block_t *target_bb = target_pI->get_bb(); + p_bb->successor_ids.insert(target_bb->bb_id); + target_bb->predecessor_ids.insert(p_bb->bb_id); - modified = modified || (orig_successor_ids != p_bb->successor_ids); + if (pI->has_pred()) { + // predicated break - add link to next basic block + unsigned next_addr = pI->get_m_instr_mem_index() + pI->inst_size(); + basic_block_t *next_bb = m_instr_mem[next_addr]->get_bb(); + p_bb->successor_ids.insert(next_bb->bb_id); + next_bb->predecessor_ids.insert(p_bb->bb_id); } - } - return modified; + modified = modified || (orig_successor_ids != p_bb->successor_ids); + } + } + + return modified; } -void function_info::do_pdom() -{ - create_basic_blocks(); - connect_basic_blocks(); - bool modified = false; - do { - find_dominators(); - find_idominators(); - modified = connect_break_targets(); - } while (modified == true); +void function_info::do_pdom() { + create_basic_blocks(); + connect_basic_blocks(); + bool modified = false; + do { + find_dominators(); + find_idominators(); + modified = connect_break_targets(); + } while (modified == true); - if ( g_debug_execution>=50 ) { - print_basic_blocks(); - print_basic_block_links(); - print_basic_block_dot(); - } - if ( g_debug_execution>=2 ) { - print_dominators(); - } - find_postdominators(); - find_ipostdominators(); - if ( g_debug_execution>=50 ) { - print_postdominators(); - print_ipostdominators(); - } - printf("GPGPU-Sim PTX: pre-decoding instructions for \'%s\'...\n", m_name.c_str() ); - for ( unsigned ii=0; ii < m_n; ii += m_instr_mem[ii]->inst_size() ) { // handle branch instructions - ptx_instruction *pI = m_instr_mem[ii]; - pI->pre_decode(); - } - printf("GPGPU-Sim PTX: ... done pre-decoding instructions for \'%s\'.\n", m_name.c_str() ); - fflush(stdout); - m_assembled = true; + if (g_debug_execution >= 50) { + print_basic_blocks(); + print_basic_block_links(); + print_basic_block_dot(); + } + if (g_debug_execution >= 2) { + print_dominators(); + } + find_postdominators(); + find_ipostdominators(); + if (g_debug_execution >= 50) { + print_postdominators(); + print_ipostdominators(); + } + printf("GPGPU-Sim PTX: pre-decoding instructions for \'%s\'...\n", + m_name.c_str()); + for (unsigned ii = 0; ii < m_n; + ii += m_instr_mem[ii]->inst_size()) { // handle branch instructions + ptx_instruction *pI = m_instr_mem[ii]; + pI->pre_decode(); + } + printf("GPGPU-Sim PTX: ... done pre-decoding instructions for \'%s\'.\n", + m_name.c_str()); + fflush(stdout); + m_assembled = true; } -void intersect( std::set<int> &A, const std::set<int> &B ) -{ - // return intersection of A and B in A - for( std::set<int>::iterator a=A.begin(); a!=A.end(); ) { - std::set<int>::iterator a_next = a; - a_next++; - if( B.find(*a) == B.end() ) { - A.erase(*a); - a = a_next; - } else - a++; - } +void intersect(std::set<int> &A, const std::set<int> &B) { + // return intersection of A and B in A + for (std::set<int>::iterator a = A.begin(); a != A.end();) { + std::set<int>::iterator a_next = a; + a_next++; + if (B.find(*a) == B.end()) { + A.erase(*a); + a = a_next; + } else + a++; + } } -bool is_equal( const std::set<int> &A, const std::set<int> &B ) -{ - if( A.size() != B.size() ) - return false; - for( std::set<int>::iterator b=B.begin(); b!=B.end(); b++ ) - if( A.find(*b) == A.end() ) - return false; - return true; +bool is_equal(const std::set<int> &A, const std::set<int> &B) { + if (A.size() != B.size()) return false; + for (std::set<int>::iterator b = B.begin(); b != B.end(); b++) + if (A.find(*b) == A.end()) return false; + return true; } -void print_set(const std::set<int> &A) -{ - std::set<int>::iterator a; - for (a= A.begin(); a != A.end(); a++) { - printf("%d ", (*a)); - } - printf("\n"); +void print_set(const std::set<int> &A) { + std::set<int>::iterator a; + for (a = A.begin(); a != A.end(); a++) { + printf("%d ", (*a)); + } + printf("\n"); } -void function_info::find_dominators( ) -{ - // find dominators using algorithm of Muchnick's Adv. Compiler Design & Implemmntation Fig 7.14 - printf("GPGPU-Sim PTX: Finding dominators for \'%s\'...\n", m_name.c_str() ); - fflush(stdout); - assert( m_basic_blocks.size() >= 2 ); // must have a distinquished entry block - std::vector<basic_block_t*>::iterator bb_itr = m_basic_blocks.begin(); - (*bb_itr)->dominator_ids.insert((*bb_itr)->bb_id); // the only dominator of the entry block is the entry - //copy all basic blocks to all dominator lists EXCEPT for the entry block - for (++bb_itr;bb_itr != m_basic_blocks.end(); bb_itr++) { - for (unsigned i = 0; i < m_basic_blocks.size(); i++) - (*bb_itr)->dominator_ids.insert(i); - } - bool change = true; - while (change) { - change = false; - for ( int h = 1/*skip entry*/; h < m_basic_blocks.size(); ++h ) { - assert( m_basic_blocks[h]->bb_id == (unsigned)h ); - std::set<int> T; - for (unsigned i=0;i< m_basic_blocks.size();i++) - T.insert(i); - for ( std::set<int>::iterator s = m_basic_blocks[h]->predecessor_ids.begin();s != m_basic_blocks[h]->predecessor_ids.end();s++) - intersect(T, m_basic_blocks[*s]->dominator_ids); - T.insert(h); - if (!is_equal(T, m_basic_blocks[h]->dominator_ids)) { - change = true; - m_basic_blocks[h]->dominator_ids = T; - } +void function_info::find_dominators() { + // find dominators using algorithm of Muchnick's Adv. Compiler Design & + // Implemmntation Fig 7.14 + printf("GPGPU-Sim PTX: Finding dominators for \'%s\'...\n", m_name.c_str()); + fflush(stdout); + assert(m_basic_blocks.size() >= 2); // must have a distinquished entry block + std::vector<basic_block_t *>::iterator bb_itr = m_basic_blocks.begin(); + (*bb_itr)->dominator_ids.insert( + (*bb_itr)->bb_id); // the only dominator of the entry block is the entry + // copy all basic blocks to all dominator lists EXCEPT for the entry block + for (++bb_itr; bb_itr != m_basic_blocks.end(); bb_itr++) { + for (unsigned i = 0; i < m_basic_blocks.size(); i++) + (*bb_itr)->dominator_ids.insert(i); + } + bool change = true; + while (change) { + change = false; + for (int h = 1 /*skip entry*/; h < m_basic_blocks.size(); ++h) { + assert(m_basic_blocks[h]->bb_id == (unsigned)h); + std::set<int> T; + for (unsigned i = 0; i < m_basic_blocks.size(); i++) T.insert(i); + for (std::set<int>::iterator s = + m_basic_blocks[h]->predecessor_ids.begin(); + s != m_basic_blocks[h]->predecessor_ids.end(); s++) + intersect(T, m_basic_blocks[*s]->dominator_ids); + T.insert(h); + if (!is_equal(T, m_basic_blocks[h]->dominator_ids)) { + change = true; + m_basic_blocks[h]->dominator_ids = T; } - } - //clean the basic block of dominators of it has no predecessors -- except for entry block - bb_itr = m_basic_blocks.begin(); - for (++bb_itr;bb_itr != m_basic_blocks.end(); bb_itr++) { - if ((*bb_itr)->predecessor_ids.empty()) - (*bb_itr)->dominator_ids.clear(); - } + } + } + // clean the basic block of dominators of it has no predecessors -- except for + // entry block + bb_itr = m_basic_blocks.begin(); + for (++bb_itr; bb_itr != m_basic_blocks.end(); bb_itr++) { + if ((*bb_itr)->predecessor_ids.empty()) (*bb_itr)->dominator_ids.clear(); + } } -void function_info::find_postdominators( ) -{ - // find postdominators using algorithm of Muchnick's Adv. Compiler Design & Implemmntation Fig 7.14 - printf("GPGPU-Sim PTX: Finding postdominators for \'%s\'...\n", m_name.c_str() ); - fflush(stdout); - assert( m_basic_blocks.size() >= 2 ); // must have a distinquished exit block - std::vector<basic_block_t*>::reverse_iterator bb_itr = m_basic_blocks.rbegin(); - (*bb_itr)->postdominator_ids.insert((*bb_itr)->bb_id); // the only postdominator of the exit block is the exit - for (++bb_itr;bb_itr != m_basic_blocks.rend();bb_itr++) { //copy all basic blocks to all postdominator lists EXCEPT for the exit block - for (unsigned i=0; i<m_basic_blocks.size(); i++) - (*bb_itr)->postdominator_ids.insert(i); - } - bool change = true; - while (change) { - change = false; - for ( int h = m_basic_blocks.size()-2/*skip exit*/; h >= 0 ; --h ) { - assert( m_basic_blocks[h]->bb_id == (unsigned)h ); - std::set<int> T; - for (unsigned i=0;i< m_basic_blocks.size();i++) - T.insert(i); - for ( std::set<int>::iterator s = m_basic_blocks[h]->successor_ids.begin();s != m_basic_blocks[h]->successor_ids.end();s++) - intersect(T, m_basic_blocks[*s]->postdominator_ids); - T.insert(h); - if (!is_equal(T,m_basic_blocks[h]->postdominator_ids)) { - change = true; - m_basic_blocks[h]->postdominator_ids = T; - } +void function_info::find_postdominators() { + // find postdominators using algorithm of Muchnick's Adv. Compiler Design & + // Implemmntation Fig 7.14 + printf("GPGPU-Sim PTX: Finding postdominators for \'%s\'...\n", + m_name.c_str()); + fflush(stdout); + assert(m_basic_blocks.size() >= 2); // must have a distinquished exit block + std::vector<basic_block_t *>::reverse_iterator bb_itr = + m_basic_blocks.rbegin(); + (*bb_itr)->postdominator_ids.insert( + (*bb_itr) + ->bb_id); // the only postdominator of the exit block is the exit + for (++bb_itr; bb_itr != m_basic_blocks.rend(); + bb_itr++) { // copy all basic blocks to all postdominator lists EXCEPT + // for the exit block + for (unsigned i = 0; i < m_basic_blocks.size(); i++) + (*bb_itr)->postdominator_ids.insert(i); + } + bool change = true; + while (change) { + change = false; + for (int h = m_basic_blocks.size() - 2 /*skip exit*/; h >= 0; --h) { + assert(m_basic_blocks[h]->bb_id == (unsigned)h); + std::set<int> T; + for (unsigned i = 0; i < m_basic_blocks.size(); i++) T.insert(i); + for (std::set<int>::iterator s = m_basic_blocks[h]->successor_ids.begin(); + s != m_basic_blocks[h]->successor_ids.end(); s++) + intersect(T, m_basic_blocks[*s]->postdominator_ids); + T.insert(h); + if (!is_equal(T, m_basic_blocks[h]->postdominator_ids)) { + change = true; + m_basic_blocks[h]->postdominator_ids = T; } - } + } + } } -void function_info::find_ipostdominators( ) -{ - // find immediate postdominator blocks, using algorithm of - // Muchnick's Adv. Compiler Design & Implemmntation Fig 7.15 - printf("GPGPU-Sim PTX: Finding immediate postdominators for \'%s\'...\n", m_name.c_str() ); - fflush(stdout); - assert( m_basic_blocks.size() >= 2 ); // must have a distinquished exit block - for (unsigned i=0; i<m_basic_blocks.size(); i++) { //initialize Tmp(n) to all pdoms of n except for n - m_basic_blocks[i]->Tmp_ids = m_basic_blocks[i]->postdominator_ids; - assert( m_basic_blocks[i]->bb_id == i ); - m_basic_blocks[i]->Tmp_ids.erase(i); - } - for ( int n = m_basic_blocks.size()-2; n >=0;--n) { - // point iterator to basic block before the exit - for( std::set<int>::iterator s=m_basic_blocks[n]->Tmp_ids.begin(); s != m_basic_blocks[n]->Tmp_ids.end(); s++ ) { - int bb_s = *s; - for( std::set<int>::iterator t=m_basic_blocks[n]->Tmp_ids.begin(); t != m_basic_blocks[n]->Tmp_ids.end(); ) { - std::set<int>::iterator t_next = t; t_next++; // might erase thing pointed to be t, invalidating iterator t - if( *s == *t ) { - t = t_next; - continue; - } - int bb_t = *t; - if( m_basic_blocks[bb_s]->postdominator_ids.find(bb_t) != m_basic_blocks[bb_s]->postdominator_ids.end() ) - m_basic_blocks[n]->Tmp_ids.erase(bb_t); - t = t_next; - } - } - } - unsigned num_ipdoms=0; - for ( int n = m_basic_blocks.size()-1; n >=0;--n) { - assert( m_basic_blocks[n]->Tmp_ids.size() <= 1 ); - // if the above assert fails we have an error in either postdominator - // computation, the flow graph does not have a unique exit, or some other error - if( !m_basic_blocks[n]->Tmp_ids.empty() ) { - m_basic_blocks[n]->immediatepostdominator_id = *m_basic_blocks[n]->Tmp_ids.begin(); - num_ipdoms++; +void function_info::find_ipostdominators() { + // find immediate postdominator blocks, using algorithm of + // Muchnick's Adv. Compiler Design & Implemmntation Fig 7.15 + printf("GPGPU-Sim PTX: Finding immediate postdominators for \'%s\'...\n", + m_name.c_str()); + fflush(stdout); + assert(m_basic_blocks.size() >= 2); // must have a distinquished exit block + for (unsigned i = 0; i < m_basic_blocks.size(); + i++) { // initialize Tmp(n) to all pdoms of n except for n + m_basic_blocks[i]->Tmp_ids = m_basic_blocks[i]->postdominator_ids; + assert(m_basic_blocks[i]->bb_id == i); + m_basic_blocks[i]->Tmp_ids.erase(i); + } + for (int n = m_basic_blocks.size() - 2; n >= 0; --n) { + // point iterator to basic block before the exit + for (std::set<int>::iterator s = m_basic_blocks[n]->Tmp_ids.begin(); + s != m_basic_blocks[n]->Tmp_ids.end(); s++) { + int bb_s = *s; + for (std::set<int>::iterator t = m_basic_blocks[n]->Tmp_ids.begin(); + t != m_basic_blocks[n]->Tmp_ids.end();) { + std::set<int>::iterator t_next = t; + t_next++; // might erase thing pointed to be t, invalidating iterator t + if (*s == *t) { + t = t_next; + continue; + } + int bb_t = *t; + if (m_basic_blocks[bb_s]->postdominator_ids.find(bb_t) != + m_basic_blocks[bb_s]->postdominator_ids.end()) + m_basic_blocks[n]->Tmp_ids.erase(bb_t); + t = t_next; } - } - assert( num_ipdoms == m_basic_blocks.size()-1 ); - // the exit node does not have an immediate post dominator, but everyone else should + } + } + unsigned num_ipdoms = 0; + for (int n = m_basic_blocks.size() - 1; n >= 0; --n) { + assert(m_basic_blocks[n]->Tmp_ids.size() <= 1); + // if the above assert fails we have an error in either postdominator + // computation, the flow graph does not have a unique exit, or some other + // error + if (!m_basic_blocks[n]->Tmp_ids.empty()) { + m_basic_blocks[n]->immediatepostdominator_id = + *m_basic_blocks[n]->Tmp_ids.begin(); + num_ipdoms++; + } + } + assert(num_ipdoms == m_basic_blocks.size() - 1); + // the exit node does not have an immediate post dominator, but everyone else + // should } -void function_info::find_idominators( ) -{ - // find immediate dominator blocks, using algorithm of - // Muchnick's Adv. Compiler Design & Implemmntation Fig 7.15 - printf("GPGPU-Sim PTX: Finding immediate dominators for \'%s\'...\n", m_name.c_str() ); - fflush(stdout); - assert( m_basic_blocks.size() >= 2 ); // must have a distinquished entry block - for (unsigned i=0; i<m_basic_blocks.size(); i++) { //initialize Tmp(n) to all doms of n except for n - m_basic_blocks[i]->Tmp_ids = m_basic_blocks[i]->dominator_ids; - assert( m_basic_blocks[i]->bb_id == i ); - m_basic_blocks[i]->Tmp_ids.erase(i); - } - for ( int n = 0; n < m_basic_blocks.size(); ++n) { - // point iterator to basic block before the exit - for( std::set<int>::iterator s=m_basic_blocks[n]->Tmp_ids.begin(); s != m_basic_blocks[n]->Tmp_ids.end(); s++ ) { - int bb_s = *s; - for( std::set<int>::iterator t=m_basic_blocks[n]->Tmp_ids.begin(); t != m_basic_blocks[n]->Tmp_ids.end(); ) { - std::set<int>::iterator t_next = t; t_next++; // might erase thing pointed to be t, invalidating iterator t - if( *s == *t ) { - t = t_next; - continue; - } - int bb_t = *t; - if( m_basic_blocks[bb_s]->dominator_ids.find(bb_t) != m_basic_blocks[bb_s]->dominator_ids.end() ) - m_basic_blocks[n]->Tmp_ids.erase(bb_t); - t = t_next; - } - } - } - unsigned num_idoms=0; - unsigned num_nopred = 0; - for ( int n = 0; n < m_basic_blocks.size(); ++n) { - //assert( m_basic_blocks[n]->Tmp_ids.size() <= 1 ); - // if the above assert fails we have an error in either dominator - // computation, the flow graph does not have a unique entry, or some other error - if( !m_basic_blocks[n]->Tmp_ids.empty() ) { - m_basic_blocks[n]->immediatedominator_id = *m_basic_blocks[n]->Tmp_ids.begin(); - num_idoms++; - } else if (m_basic_blocks[n]->predecessor_ids.empty()) { - num_nopred += 1; +void function_info::find_idominators() { + // find immediate dominator blocks, using algorithm of + // Muchnick's Adv. Compiler Design & Implemmntation Fig 7.15 + printf("GPGPU-Sim PTX: Finding immediate dominators for \'%s\'...\n", + m_name.c_str()); + fflush(stdout); + assert(m_basic_blocks.size() >= 2); // must have a distinquished entry block + for (unsigned i = 0; i < m_basic_blocks.size(); + i++) { // initialize Tmp(n) to all doms of n except for n + m_basic_blocks[i]->Tmp_ids = m_basic_blocks[i]->dominator_ids; + assert(m_basic_blocks[i]->bb_id == i); + m_basic_blocks[i]->Tmp_ids.erase(i); + } + for (int n = 0; n < m_basic_blocks.size(); ++n) { + // point iterator to basic block before the exit + for (std::set<int>::iterator s = m_basic_blocks[n]->Tmp_ids.begin(); + s != m_basic_blocks[n]->Tmp_ids.end(); s++) { + int bb_s = *s; + for (std::set<int>::iterator t = m_basic_blocks[n]->Tmp_ids.begin(); + t != m_basic_blocks[n]->Tmp_ids.end();) { + std::set<int>::iterator t_next = t; + t_next++; // might erase thing pointed to be t, invalidating iterator t + if (*s == *t) { + t = t_next; + continue; + } + int bb_t = *t; + if (m_basic_blocks[bb_s]->dominator_ids.find(bb_t) != + m_basic_blocks[bb_s]->dominator_ids.end()) + m_basic_blocks[n]->Tmp_ids.erase(bb_t); + t = t_next; } - } - assert( num_idoms == m_basic_blocks.size()-num_nopred ); - // the entry node does not have an immediate dominator, but everyone else should + } + } + unsigned num_idoms = 0; + unsigned num_nopred = 0; + for (int n = 0; n < m_basic_blocks.size(); ++n) { + // assert( m_basic_blocks[n]->Tmp_ids.size() <= 1 ); + // if the above assert fails we have an error in either dominator + // computation, the flow graph does not have a unique entry, or some other + // error + if (!m_basic_blocks[n]->Tmp_ids.empty()) { + m_basic_blocks[n]->immediatedominator_id = + *m_basic_blocks[n]->Tmp_ids.begin(); + num_idoms++; + } else if (m_basic_blocks[n]->predecessor_ids.empty()) { + num_nopred += 1; + } + } + assert(num_idoms == m_basic_blocks.size() - num_nopred); + // the entry node does not have an immediate dominator, but everyone else + // should } -void function_info::print_dominators() -{ - printf("Printing dominators for function \'%s\':\n", m_name.c_str() ); - std::vector<int>::iterator bb_itr; - for (unsigned i = 0; i < m_basic_blocks.size(); i++) { - printf("ID: %d\t:", i); - for( std::set<int>::iterator j=m_basic_blocks[i]->dominator_ids.begin(); j!=m_basic_blocks[i]->dominator_ids.end(); j++) - printf(" %d", *j ); - printf("\n"); - } +void function_info::print_dominators() { + printf("Printing dominators for function \'%s\':\n", m_name.c_str()); + std::vector<int>::iterator bb_itr; + for (unsigned i = 0; i < m_basic_blocks.size(); i++) { + printf("ID: %d\t:", i); + for (std::set<int>::iterator j = m_basic_blocks[i]->dominator_ids.begin(); + j != m_basic_blocks[i]->dominator_ids.end(); j++) + printf(" %d", *j); + printf("\n"); + } } -void function_info::print_postdominators() -{ - printf("Printing postdominators for function \'%s\':\n", m_name.c_str() ); - std::vector<int>::iterator bb_itr; - for (unsigned i = 0; i < m_basic_blocks.size(); i++) { - printf("ID: %d\t:", i); - for( std::set<int>::iterator j=m_basic_blocks[i]->postdominator_ids.begin(); j!=m_basic_blocks[i]->postdominator_ids.end(); j++) - printf(" %d", *j ); - printf("\n"); - } +void function_info::print_postdominators() { + printf("Printing postdominators for function \'%s\':\n", m_name.c_str()); + std::vector<int>::iterator bb_itr; + for (unsigned i = 0; i < m_basic_blocks.size(); i++) { + printf("ID: %d\t:", i); + for (std::set<int>::iterator j = + m_basic_blocks[i]->postdominator_ids.begin(); + j != m_basic_blocks[i]->postdominator_ids.end(); j++) + printf(" %d", *j); + printf("\n"); + } } -void function_info::print_ipostdominators() -{ - printf("Printing immediate postdominators for function \'%s\':\n", m_name.c_str() ); - std::vector<int>::iterator bb_itr; - for (unsigned i = 0; i < m_basic_blocks.size(); i++) { - printf("ID: %d\t:", i); - printf("%d\n", m_basic_blocks[i]->immediatepostdominator_id); - } +void function_info::print_ipostdominators() { + printf("Printing immediate postdominators for function \'%s\':\n", + m_name.c_str()); + std::vector<int>::iterator bb_itr; + for (unsigned i = 0; i < m_basic_blocks.size(); i++) { + printf("ID: %d\t:", i); + printf("%d\n", m_basic_blocks[i]->immediatepostdominator_id); + } } -void function_info::print_idominators() -{ - printf("Printing immediate dominators for function \'%s\':\n", m_name.c_str() ); - std::vector<int>::iterator bb_itr; - for (unsigned i = 0; i < m_basic_blocks.size(); i++) { - printf("ID: %d\t:", i); - printf("%d\n", m_basic_blocks[i]->immediatedominator_id); - } +void function_info::print_idominators() { + printf("Printing immediate dominators for function \'%s\':\n", + m_name.c_str()); + std::vector<int>::iterator bb_itr; + for (unsigned i = 0; i < m_basic_blocks.size(); i++) { + printf("ID: %d\t:", i); + printf("%d\n", m_basic_blocks[i]->immediatedominator_id); + } } -unsigned function_info::get_num_reconvergence_pairs() -{ - if (!num_reconvergence_pairs) { - if( m_basic_blocks.size() == 0 ) - return 0; - for (unsigned i=0; i< (m_basic_blocks.size()-1); i++) { //last basic block containing exit obviously won't have a pair - if (m_basic_blocks[i]->ptx_end->get_opcode() == BRA_OP) { - num_reconvergence_pairs++; - } +unsigned function_info::get_num_reconvergence_pairs() { + if (!num_reconvergence_pairs) { + if (m_basic_blocks.size() == 0) return 0; + for (unsigned i = 0; i < (m_basic_blocks.size() - 1); + i++) { // last basic block containing exit obviously won't have a pair + if (m_basic_blocks[i]->ptx_end->get_opcode() == BRA_OP) { + num_reconvergence_pairs++; } - } - return num_reconvergence_pairs; + } + } + return num_reconvergence_pairs; } -void function_info::get_reconvergence_pairs(gpgpu_recon_t* recon_points) -{ - unsigned idx=0; //array index - if( m_basic_blocks.size() == 0 ) - return; - for (unsigned i=0; i< (m_basic_blocks.size()-1); i++) { //last basic block containing exit obviously won't have a pair +void function_info::get_reconvergence_pairs(gpgpu_recon_t *recon_points) { + unsigned idx = 0; // array index + if (m_basic_blocks.size() == 0) return; + for (unsigned i = 0; i < (m_basic_blocks.size() - 1); + i++) { // last basic block containing exit obviously won't have a pair #ifdef DEBUG_GET_RECONVERG_PAIRS - printf("i=%d\n", i); fflush(stdout); + printf("i=%d\n", i); + fflush(stdout); #endif - if (m_basic_blocks[i]->ptx_end->get_opcode() == BRA_OP) { + if (m_basic_blocks[i]->ptx_end->get_opcode() == BRA_OP) { #ifdef DEBUG_GET_RECONVERG_PAIRS - printf("\tbranch!\n"); - printf("\tbb_id=%d; ipdom=%d\n", m_basic_blocks[i]->bb_id, m_basic_blocks[i]->immediatepostdominator_id); - printf("\tm_instr_mem index=%d\n", m_basic_blocks[i]->ptx_end->get_m_instr_mem_index()); - fflush(stdout); + printf("\tbranch!\n"); + printf("\tbb_id=%d; ipdom=%d\n", m_basic_blocks[i]->bb_id, + m_basic_blocks[i]->immediatepostdominator_id); + printf("\tm_instr_mem index=%d\n", + m_basic_blocks[i]->ptx_end->get_m_instr_mem_index()); + fflush(stdout); #endif - recon_points[idx].source_pc = m_basic_blocks[i]->ptx_end->get_PC(); - recon_points[idx].source_inst = m_basic_blocks[i]->ptx_end; + recon_points[idx].source_pc = m_basic_blocks[i]->ptx_end->get_PC(); + recon_points[idx].source_inst = m_basic_blocks[i]->ptx_end; #ifdef DEBUG_GET_RECONVERG_PAIRS - printf("\trecon_points[idx].source_pc=%d\n", recon_points[idx].source_pc); + printf("\trecon_points[idx].source_pc=%d\n", recon_points[idx].source_pc); #endif - if( m_basic_blocks[m_basic_blocks[i]->immediatepostdominator_id]->ptx_begin ) { - recon_points[idx].target_pc = m_basic_blocks[m_basic_blocks[i]->immediatepostdominator_id]->ptx_begin->get_PC(); - recon_points[idx].target_inst = m_basic_blocks[m_basic_blocks[i]->immediatepostdominator_id]->ptx_begin; - } else { - // reconverge after function return - recon_points[idx].target_pc = -2; - recon_points[idx].target_inst = NULL; - } + if (m_basic_blocks[m_basic_blocks[i]->immediatepostdominator_id] + ->ptx_begin) { + recon_points[idx].target_pc = + m_basic_blocks[m_basic_blocks[i]->immediatepostdominator_id] + ->ptx_begin->get_PC(); + recon_points[idx].target_inst = + m_basic_blocks[m_basic_blocks[i]->immediatepostdominator_id] + ->ptx_begin; + } else { + // reconverge after function return + recon_points[idx].target_pc = -2; + recon_points[idx].target_inst = NULL; + } #ifdef DEBUG_GET_RECONVERG_PAIRS - m_basic_blocks[m_basic_blocks[i]->immediatepostdominator_id]->ptx_begin->print_insn(); - printf("\trecon_points[idx].target_pc=%d\n", recon_points[idx].target_pc); fflush(stdout); + m_basic_blocks[m_basic_blocks[i]->immediatepostdominator_id] + ->ptx_begin->print_insn(); + printf("\trecon_points[idx].target_pc=%d\n", recon_points[idx].target_pc); + fflush(stdout); #endif - idx++; - } - } + idx++; + } + } } // interface with graphviz (print the graph in DOT language) for plotting -void function_info::print_basic_block_dot() -{ - printf("Basic Block in DOT\n"); - printf("digraph %s {\n", m_name.c_str()); - std::vector<basic_block_t*>::iterator bb_itr; - for (bb_itr = m_basic_blocks.begin();bb_itr != m_basic_blocks.end(); bb_itr++) { - printf("\t"); - std::set<int>::iterator s; - for (s = (*bb_itr)->successor_ids.begin();s != (*bb_itr)->successor_ids.end();s++) { - unsigned succ_bb = *s; - printf("%d -> %d; ", (*bb_itr)->bb_id, succ_bb ); - } - printf("\n"); - } - printf("}\n"); +void function_info::print_basic_block_dot() { + printf("Basic Block in DOT\n"); + printf("digraph %s {\n", m_name.c_str()); + std::vector<basic_block_t *>::iterator bb_itr; + for (bb_itr = m_basic_blocks.begin(); bb_itr != m_basic_blocks.end(); + bb_itr++) { + printf("\t"); + std::set<int>::iterator s; + for (s = (*bb_itr)->successor_ids.begin(); + s != (*bb_itr)->successor_ids.end(); s++) { + unsigned succ_bb = *s; + printf("%d -> %d; ", (*bb_itr)->bb_id, succ_bb); + } + printf("\n"); + } + printf("}\n"); } -unsigned ptx_kernel_shmem_size( void *kernel_impl ) -{ - function_info *f = (function_info*)kernel_impl; - const struct gpgpu_ptx_sim_info *kernel_info = f->get_kernel_info(); - return kernel_info->smem; +unsigned ptx_kernel_shmem_size(void *kernel_impl) { + function_info *f = (function_info *)kernel_impl; + const struct gpgpu_ptx_sim_info *kernel_info = f->get_kernel_info(); + return kernel_info->smem; } -unsigned ptx_kernel_nregs( void *kernel_impl ) -{ - function_info *f = (function_info*)kernel_impl; - const struct gpgpu_ptx_sim_info *kernel_info = f->get_kernel_info(); - return kernel_info->regs; +unsigned ptx_kernel_nregs(void *kernel_impl) { + function_info *f = (function_info *)kernel_impl; + const struct gpgpu_ptx_sim_info *kernel_info = f->get_kernel_info(); + return kernel_info->regs; } -unsigned type_info_key::type_decode( size_t &size, int &basic_type ) const -{ - int type = scalar_type(); - return type_decode(type,size,basic_type); +unsigned type_info_key::type_decode(size_t &size, int &basic_type) const { + int type = scalar_type(); + return type_decode(type, size, basic_type); } -unsigned type_info_key::type_decode( int type, size_t &size, int &basic_type ) -{ - switch ( type ) { - case S8_TYPE: size=8; basic_type=1; return 0; - case S16_TYPE: size=16; basic_type=1; return 1; - case S32_TYPE: size=32; basic_type=1; return 2; - case S64_TYPE: size=64; basic_type=1; return 3; - case U8_TYPE: size=8; basic_type=0; return 4; - case U16_TYPE: size=16; basic_type=0; return 5; - case U32_TYPE: size=32; basic_type=0; return 6; - case U64_TYPE: size=64; basic_type=0; return 7; - case F16_TYPE: size=16; basic_type=-1; return 8; - case F32_TYPE: size=32; basic_type=-1; return 9; - case F64_TYPE: size=64; basic_type=-1; return 10; - case FF64_TYPE: size=64; basic_type=-1; return 10; - case PRED_TYPE: size=1; basic_type=2; return 11; - case B8_TYPE: size=8; basic_type=0; return 12; - case B16_TYPE: size=16; basic_type=0; return 13; - case B32_TYPE: size=32; basic_type=0; return 14; - case B64_TYPE: size=64; basic_type=0; return 15; - case BB64_TYPE: size=64; basic_type=0; return 15; - case BB128_TYPE: size=128; basic_type=0; return 16; - case TEXREF_TYPE: case SAMPLERREF_TYPE: case SURFREF_TYPE: - size=32; basic_type=3; return 16; - default: - printf("ERROR ** type_decode() does not know about \"%s\"\n", decode_token(type) ); - assert(0); +unsigned type_info_key::type_decode(int type, size_t &size, int &basic_type) { + switch (type) { + case S8_TYPE: + size = 8; + basic_type = 1; + return 0; + case S16_TYPE: + size = 16; + basic_type = 1; + return 1; + case S32_TYPE: + size = 32; + basic_type = 1; + return 2; + case S64_TYPE: + size = 64; + basic_type = 1; + return 3; + case U8_TYPE: + size = 8; + basic_type = 0; + return 4; + case U16_TYPE: + size = 16; + basic_type = 0; + return 5; + case U32_TYPE: + size = 32; + basic_type = 0; + return 6; + case U64_TYPE: + size = 64; + basic_type = 0; + return 7; + case F16_TYPE: + size = 16; + basic_type = -1; + return 8; + case F32_TYPE: + size = 32; + basic_type = -1; + return 9; + case F64_TYPE: + size = 64; + basic_type = -1; + return 10; + case FF64_TYPE: + size = 64; + basic_type = -1; + return 10; + case PRED_TYPE: + size = 1; + basic_type = 2; + return 11; + case B8_TYPE: + size = 8; + basic_type = 0; + return 12; + case B16_TYPE: + size = 16; + basic_type = 0; + return 13; + case B32_TYPE: + size = 32; + basic_type = 0; + return 14; + case B64_TYPE: + size = 64; + basic_type = 0; + return 15; + case BB64_TYPE: + size = 64; + basic_type = 0; + return 15; + case BB128_TYPE: + size = 128; + basic_type = 0; + return 16; + case TEXREF_TYPE: + case SAMPLERREF_TYPE: + case SURFREF_TYPE: + size = 32; + basic_type = 3; + return 16; + default: + printf("ERROR ** type_decode() does not know about \"%s\"\n", + decode_token(type)); + assert(0); return 0xDEADBEEF; - } + } } -arg_buffer_t copy_arg_to_buffer(ptx_thread_info * thread, operand_info actual_param_op, const symbol * formal_param) -{ - if( actual_param_op.is_reg() ) { - ptx_reg_t value = thread->get_reg(actual_param_op.get_symbol()); - return arg_buffer_t(formal_param,actual_param_op,value); - } else if ( actual_param_op.is_param_local() ) { - unsigned size=formal_param->get_size_in_bytes(); - addr_t frame_offset = actual_param_op.get_symbol()->get_address(); - addr_t from_addr = thread->get_local_mem_stack_pointer() + frame_offset; - char buffer[1024]; - assert(size<1024); - thread->m_local_mem->read(from_addr,size,buffer); - return arg_buffer_t(formal_param,actual_param_op,buffer,size); - } else { - printf("GPGPU-Sim PTX: ERROR ** need to add support for this operand type in call/return\n"); - abort(); - } +arg_buffer_t copy_arg_to_buffer(ptx_thread_info *thread, + operand_info actual_param_op, + const symbol *formal_param) { + if (actual_param_op.is_reg()) { + ptx_reg_t value = thread->get_reg(actual_param_op.get_symbol()); + return arg_buffer_t(formal_param, actual_param_op, value); + } else if (actual_param_op.is_param_local()) { + unsigned size = formal_param->get_size_in_bytes(); + addr_t frame_offset = actual_param_op.get_symbol()->get_address(); + addr_t from_addr = thread->get_local_mem_stack_pointer() + frame_offset; + char buffer[1024]; + assert(size < 1024); + thread->m_local_mem->read(from_addr, size, buffer); + return arg_buffer_t(formal_param, actual_param_op, buffer, size); + } else { + printf( + "GPGPU-Sim PTX: ERROR ** need to add support for this operand type in " + "call/return\n"); + abort(); + } } -void copy_args_into_buffer_list( const ptx_instruction * pI, - ptx_thread_info * thread, - const function_info * target_func, - arg_buffer_list_t &arg_values ) -{ - unsigned n_return = target_func->has_return(); - unsigned n_args = target_func->num_args(); - for( unsigned arg=0; arg < n_args; arg ++ ) { - const operand_info &actual_param_op = pI->operand_lookup(n_return+1+arg); - const symbol *formal_param = target_func->get_arg(arg); - arg_values.push_back( copy_arg_to_buffer(thread, actual_param_op, formal_param) ); - } +void copy_args_into_buffer_list(const ptx_instruction *pI, + ptx_thread_info *thread, + const function_info *target_func, + arg_buffer_list_t &arg_values) { + unsigned n_return = target_func->has_return(); + unsigned n_args = target_func->num_args(); + for (unsigned arg = 0; arg < n_args; arg++) { + const operand_info &actual_param_op = + pI->operand_lookup(n_return + 1 + arg); + const symbol *formal_param = target_func->get_arg(arg); + arg_values.push_back( + copy_arg_to_buffer(thread, actual_param_op, formal_param)); + } } -void copy_buffer_to_frame(ptx_thread_info * thread, const arg_buffer_t &a) -{ - if( a.is_reg() ) { - ptx_reg_t value = a.get_reg(); - operand_info dst_reg = operand_info(a.get_dst(), thread->get_gpu()->gpgpu_ctx); - thread->set_reg(dst_reg.get_symbol(),value); - } else { - const void *buffer = a.get_param_buffer(); - size_t size = a.get_param_buffer_size(); - const symbol *dst = a.get_dst(); - addr_t frame_offset = dst->get_address(); - addr_t to_addr = thread->get_local_mem_stack_pointer() + frame_offset; - thread->m_local_mem->write(to_addr,size,buffer,NULL,NULL); - } +void copy_buffer_to_frame(ptx_thread_info *thread, const arg_buffer_t &a) { + if (a.is_reg()) { + ptx_reg_t value = a.get_reg(); + operand_info dst_reg = + operand_info(a.get_dst(), thread->get_gpu()->gpgpu_ctx); + thread->set_reg(dst_reg.get_symbol(), value); + } else { + const void *buffer = a.get_param_buffer(); + size_t size = a.get_param_buffer_size(); + const symbol *dst = a.get_dst(); + addr_t frame_offset = dst->get_address(); + addr_t to_addr = thread->get_local_mem_stack_pointer() + frame_offset; + thread->m_local_mem->write(to_addr, size, buffer, NULL, NULL); + } } -void copy_buffer_list_into_frame(ptx_thread_info * thread, arg_buffer_list_t &arg_values) -{ - arg_buffer_list_t::iterator a; - for( a=arg_values.begin(); a != arg_values.end(); a++ ) { - copy_buffer_to_frame(thread, *a); - } +void copy_buffer_list_into_frame(ptx_thread_info *thread, + arg_buffer_list_t &arg_values) { + arg_buffer_list_t::iterator a; + for (a = arg_values.begin(); a != arg_values.end(); a++) { + copy_buffer_to_frame(thread, *a); + } } - - -static std::list<operand_info> check_operands( int opcode, - const std::list<int> &scalar_type, - const std::list<operand_info> &operands, - gpgpu_context* ctx) -{ - static int g_warn_literal_operands_two_type_inst; - if( (opcode == CVT_OP) || (opcode == SET_OP) || (opcode == SLCT_OP) || (opcode == TEX_OP) || (opcode==MMA_OP) || (opcode == DP4A_OP)) { - // just make sure these do not have have const operands... - if( !g_warn_literal_operands_two_type_inst ) { - std::list<operand_info>::const_iterator o; - for( o = operands.begin(); o != operands.end(); o++ ) { - const operand_info &op = *o; - if( op.is_literal() ) { - printf("GPGPU-Sim PTX: PTX uses two scalar type intruction with literal operand.\n"); - g_warn_literal_operands_two_type_inst = 1; - } - } +static std::list<operand_info> check_operands( + int opcode, const std::list<int> &scalar_type, + const std::list<operand_info> &operands, gpgpu_context *ctx) { + static int g_warn_literal_operands_two_type_inst; + if ((opcode == CVT_OP) || (opcode == SET_OP) || (opcode == SLCT_OP) || + (opcode == TEX_OP) || (opcode == MMA_OP) || (opcode == DP4A_OP)) { + // just make sure these do not have have const operands... + if (!g_warn_literal_operands_two_type_inst) { + std::list<operand_info>::const_iterator o; + for (o = operands.begin(); o != operands.end(); o++) { + const operand_info &op = *o; + if (op.is_literal()) { + printf( + "GPGPU-Sim PTX: PTX uses two scalar type intruction with literal " + "operand.\n"); + g_warn_literal_operands_two_type_inst = 1; } - } else { - assert( scalar_type.size() < 2 ); - if( scalar_type.size() == 1 ) { - std::list<operand_info> result; - int inst_type = scalar_type.front(); - std::list<operand_info>::const_iterator o; - for( o = operands.begin(); o != operands.end(); o++ ) { - const operand_info &op = *o; - if( op.is_literal() ) { - if( (op.get_type() == double_op_t) && (inst_type == F32_TYPE) ) { - ptx_reg_t v = op.get_literal_value(); - float u = (float)v.f64; - operand_info n(u, ctx); - result.push_back(n); - } else { - result.push_back(op); - } - } else { - result.push_back(op); - } - } - return result; - } + } + } + } else { + assert(scalar_type.size() < 2); + if (scalar_type.size() == 1) { + std::list<operand_info> result; + int inst_type = scalar_type.front(); + std::list<operand_info>::const_iterator o; + for (o = operands.begin(); o != operands.end(); o++) { + const operand_info &op = *o; + if (op.is_literal()) { + if ((op.get_type() == double_op_t) && (inst_type == F32_TYPE)) { + ptx_reg_t v = op.get_literal_value(); + float u = (float)v.f64; + operand_info n(u, ctx); + result.push_back(n); + } else { + result.push_back(op); + } + } else { + result.push_back(op); + } + } + return result; } - return operands; + } + return operands; } - -ptx_instruction::ptx_instruction( int opcode, - const symbol *pred, - int neg_pred, - int pred_mod, - symbol *label, - const std::list<operand_info> &operands, - const operand_info &return_var, - const std::list<int> &options, - const std::list<int> &wmma_options, - const std::list<int> &scalar_type, - memory_space_t space_spec, - const char *file, - unsigned line, - const char *source, - const core_config *config, - gpgpu_context* ctx ) : warp_inst_t(config), m_return_var(ctx) -{ - gpgpu_ctx = ctx; - m_uid = ++(ctx->g_num_ptx_inst_uid); - m_PC = 0; - m_opcode = opcode; - m_pred = pred; - m_neg_pred = neg_pred; - m_pred_mod = pred_mod; - m_label = label; - const std::list<operand_info> checked_operands = check_operands(opcode,scalar_type,operands, ctx); - m_operands.insert(m_operands.begin(), checked_operands.begin(), checked_operands.end() ); - m_return_var = return_var; - m_options = options; - m_wmma_options = wmma_options; - m_wide = false; - m_hi = false; - m_lo = false; - m_uni = false; - m_exit = false; - m_abs = false; - m_neg = false; - m_to_option = false; - m_cache_option = 0; - m_rounding_mode = RN_OPTION; - m_compare_op = -1; - m_saturation_mode = 0; - m_geom_spec = 0; - m_vector_spec = 0; - m_atomic_spec = 0; - m_membar_level = 0; - m_inst_size = 8; // bytes - int rr=0; - std::list<int>::const_iterator i; - unsigned n=1; - for ( i=wmma_options.begin(); i!= wmma_options.end(); i++, n++ ) { - int last_ptx_inst_option = *i; - switch ( last_ptx_inst_option ) { - case SYNC_OPTION: - case LOAD_A: - case LOAD_B: - case LOAD_C: - case STORE_D: - case MMA: - m_wmma_type=last_ptx_inst_option; - break; - case ROW: - case COL: - m_wmma_layout[rr++]=last_ptx_inst_option; - break; - case M16N16K16: - case M32N8K16: - case M8N32K16: - break; - default: - assert(0); - break; - } - } - rr=0; - n=1; - for ( i=options.begin(); i!= options.end(); i++, n++ ) { - int last_ptx_inst_option = *i; - switch ( last_ptx_inst_option ) { +ptx_instruction::ptx_instruction( + int opcode, const symbol *pred, int neg_pred, int pred_mod, symbol *label, + const std::list<operand_info> &operands, const operand_info &return_var, + const std::list<int> &options, const std::list<int> &wmma_options, + const std::list<int> &scalar_type, memory_space_t space_spec, + const char *file, unsigned line, const char *source, + const core_config *config, gpgpu_context *ctx) + : warp_inst_t(config), m_return_var(ctx) { + gpgpu_ctx = ctx; + m_uid = ++(ctx->g_num_ptx_inst_uid); + m_PC = 0; + m_opcode = opcode; + m_pred = pred; + m_neg_pred = neg_pred; + m_pred_mod = pred_mod; + m_label = label; + const std::list<operand_info> checked_operands = + check_operands(opcode, scalar_type, operands, ctx); + m_operands.insert(m_operands.begin(), checked_operands.begin(), + checked_operands.end()); + m_return_var = return_var; + m_options = options; + m_wmma_options = wmma_options; + m_wide = false; + m_hi = false; + m_lo = false; + m_uni = false; + m_exit = false; + m_abs = false; + m_neg = false; + m_to_option = false; + m_cache_option = 0; + m_rounding_mode = RN_OPTION; + m_compare_op = -1; + m_saturation_mode = 0; + m_geom_spec = 0; + m_vector_spec = 0; + m_atomic_spec = 0; + m_membar_level = 0; + m_inst_size = 8; // bytes + int rr = 0; + std::list<int>::const_iterator i; + unsigned n = 1; + for (i = wmma_options.begin(); i != wmma_options.end(); i++, n++) { + int last_ptx_inst_option = *i; + switch (last_ptx_inst_option) { + case SYNC_OPTION: + case LOAD_A: + case LOAD_B: + case LOAD_C: + case STORE_D: + case MMA: + m_wmma_type = last_ptx_inst_option; + break; + case ROW: + case COL: + m_wmma_layout[rr++] = last_ptx_inst_option; + break; + case M16N16K16: + case M32N8K16: + case M8N32K16: + break; + default: + assert(0); + break; + } + } + rr = 0; + n = 1; + for (i = options.begin(); i != options.end(); i++, n++) { + int last_ptx_inst_option = *i; + switch (last_ptx_inst_option) { case SYNC_OPTION: case ARRIVE_OPTION: case RED_OPTION: - m_barrier_op = last_ptx_inst_option; - break; + m_barrier_op = last_ptx_inst_option; + break; case EQU_OPTION: case NEU_OPTION: case LTU_OPTION: @@ -1186,16 +1279,16 @@ ptx_instruction::ptx_instruction( int opcode, case GE_OPTION: case LS_OPTION: case HS_OPTION: - m_compare_op = last_ptx_inst_option; - break; + m_compare_op = last_ptx_inst_option; + break; case NUM_OPTION: case NAN_OPTION: - m_compare_op = last_ptx_inst_option; + m_compare_op = last_ptx_inst_option; // assert(0); // finish this - break; + break; case SAT_OPTION: - m_saturation_mode = 1; - break; + m_saturation_mode = 1; + break; case RNI_OPTION: case RZI_OPTION: case RMI_OPTION: @@ -1204,38 +1297,39 @@ ptx_instruction::ptx_instruction( int opcode, case RZ_OPTION: case RM_OPTION: case RP_OPTION: - m_rounding_mode = last_ptx_inst_option; - break; + m_rounding_mode = last_ptx_inst_option; + break; case HI_OPTION: - m_compare_op = last_ptx_inst_option; - m_hi = true; - assert( !m_lo ); - assert( !m_wide ); - break; + m_compare_op = last_ptx_inst_option; + m_hi = true; + assert(!m_lo); + assert(!m_wide); + break; case LO_OPTION: - m_compare_op = last_ptx_inst_option; - m_lo = true; - assert( !m_hi ); - assert( !m_wide ); - break; + m_compare_op = last_ptx_inst_option; + m_lo = true; + assert(!m_hi); + assert(!m_wide); + break; case WIDE_OPTION: - m_wide = true; - assert( !m_lo ); - assert( !m_hi ); - break; + m_wide = true; + assert(!m_lo); + assert(!m_hi); + break; case UNI_OPTION: - m_uni = true; // don't care... < now we DO care when constructing flowgraph> - break; + m_uni = true; // don't care... < now we DO care when constructing + // flowgraph> + break; case GEOM_MODIFIER_1D: case GEOM_MODIFIER_2D: case GEOM_MODIFIER_3D: - m_geom_spec = last_ptx_inst_option; - break; + m_geom_spec = last_ptx_inst_option; + break; case V2_TYPE: case V3_TYPE: case V4_TYPE: - m_vector_spec = last_ptx_inst_option; - break; + m_vector_spec = last_ptx_inst_option; + break; case ATOMIC_AND: case ATOMIC_OR: case ATOMIC_XOR: @@ -1246,223 +1340,225 @@ ptx_instruction::ptx_instruction( int opcode, case ATOMIC_DEC: case ATOMIC_MIN: case ATOMIC_MAX: - m_atomic_spec = last_ptx_inst_option; - break; + m_atomic_spec = last_ptx_inst_option; + break; case APPROX_OPTION: - break; + break; case FULL_OPTION: - break; + break; case ANY_OPTION: - m_vote_mode = vote_any; - break; + m_vote_mode = vote_any; + break; case ALL_OPTION: - m_vote_mode = vote_all; - break; + m_vote_mode = vote_all; + break; case BALLOT_OPTION: - m_vote_mode = vote_ballot; - break; + m_vote_mode = vote_ballot; + break; case GLOBAL_OPTION: - m_membar_level = GLOBAL_OPTION; - break; + m_membar_level = GLOBAL_OPTION; + break; case CTA_OPTION: - m_membar_level = CTA_OPTION; - break; + m_membar_level = CTA_OPTION; + break; case SYS_OPTION: - m_membar_level = SYS_OPTION; - break; + m_membar_level = SYS_OPTION; + break; case FTZ_OPTION: - break; + break; case EXIT_OPTION: - m_exit = true; - break; + m_exit = true; + break; case ABS_OPTION: - m_abs = true; - break; + m_abs = true; + break; case NEG_OPTION: - m_neg = true; - break; + m_neg = true; + break; case TO_OPTION: - m_to_option = true; - break; - case CA_OPTION: case CG_OPTION: case CS_OPTION: case LU_OPTION: case CV_OPTION: - m_cache_option = last_ptx_inst_option; - break; + m_to_option = true; + break; + case CA_OPTION: + case CG_OPTION: + case CS_OPTION: + case LU_OPTION: + case CV_OPTION: + m_cache_option = last_ptx_inst_option; + break; case HALF_OPTION: - m_inst_size = 4; // bytes - break; + m_inst_size = 4; // bytes + break; case EXTP_OPTION: - break; + break; case NC_OPTION: - m_cache_option = last_ptx_inst_option; - break; + m_cache_option = last_ptx_inst_option; + break; case UP_OPTION: case DOWN_OPTION: case BFLY_OPTION: case IDX_OPTION: - m_shfl_op = last_ptx_inst_option; - break; + m_shfl_op = last_ptx_inst_option; + break; case PRMT_F4E_MODE: case PRMT_B4E_MODE: case PRMT_RC8_MODE: case PRMT_ECL_MODE: case PRMT_ECR_MODE: case PRMT_RC16_MODE: - m_prmt_op = last_ptx_inst_option; - break; + m_prmt_op = last_ptx_inst_option; + break; default: - assert(0); - break; - } - } - m_scalar_type = scalar_type; - m_space_spec = space_spec; - if( ( opcode == ST_OP || opcode == LD_OP || opcode == LDU_OP ) && (space_spec == undefined_space) ) { - m_space_spec = generic_space; - } - for( std::vector<operand_info>::const_iterator i=m_operands.begin(); i!=m_operands.end(); ++i) { - const operand_info &op = *i; - if( op.get_addr_space() != undefined_space ) - m_space_spec = op.get_addr_space(); // TODO: can have more than one memory space for ptxplus (g8x) inst - } - if( opcode == TEX_OP ) - m_space_spec = tex_space; - - m_source_file = file?file:"<unknown>"; - m_source_line = line; - m_source = source; - // Trim tabs - m_source.erase( std::remove( m_source.begin(), m_source.end(), '\t' ), m_source.end() ); + assert(0); + break; + } + } + m_scalar_type = scalar_type; + m_space_spec = space_spec; + if ((opcode == ST_OP || opcode == LD_OP || opcode == LDU_OP) && + (space_spec == undefined_space)) { + m_space_spec = generic_space; + } + for (std::vector<operand_info>::const_iterator i = m_operands.begin(); + i != m_operands.end(); ++i) { + const operand_info &op = *i; + if (op.get_addr_space() != undefined_space) + m_space_spec = + op.get_addr_space(); // TODO: can have more than one memory space for + // ptxplus (g8x) inst + } + if (opcode == TEX_OP) m_space_spec = tex_space; - if (opcode == CALL_OP) { - const operand_info &target = func_addr(); - assert( target.is_function_address() ); - const symbol *func_addr = target.get_symbol(); - const function_info *target_func = func_addr->get_pc(); - std::string fname = target_func->get_name(); + m_source_file = file ? file : "<unknown>"; + m_source_line = line; + m_source = source; + // Trim tabs + m_source.erase(std::remove(m_source.begin(), m_source.end(), '\t'), + m_source.end()); - if (fname =="vprintf"){ - m_is_printf = true; - } - if(fname == "cudaStreamCreateWithFlags") - m_is_cdp = 1; - if(fname == "cudaGetParameterBufferV2") - m_is_cdp = 2; - if(fname == "cudaLaunchDeviceV2") - m_is_cdp = 4; + if (opcode == CALL_OP) { + const operand_info &target = func_addr(); + assert(target.is_function_address()); + const symbol *func_addr = target.get_symbol(); + const function_info *target_func = func_addr->get_pc(); + std::string fname = target_func->get_name(); - } + if (fname == "vprintf") { + m_is_printf = true; + } + if (fname == "cudaStreamCreateWithFlags") m_is_cdp = 1; + if (fname == "cudaGetParameterBufferV2") m_is_cdp = 2; + if (fname == "cudaLaunchDeviceV2") m_is_cdp = 4; + } } -void ptx_instruction::print_insn() const -{ - print_insn(stdout); - fflush(stdout); +void ptx_instruction::print_insn() const { + print_insn(stdout); + fflush(stdout); } -void ptx_instruction::print_insn( FILE *fp ) const -{ - fprintf( fp, "%s", to_string().c_str() ); +void ptx_instruction::print_insn(FILE *fp) const { + fprintf(fp, "%s", to_string().c_str()); } -std::string ptx_instruction::to_string() const -{ - char buf[ STR_SIZE ]; - unsigned used_bytes = 0; - if( !is_label() ) { - used_bytes += snprintf( buf + used_bytes, STR_SIZE - used_bytes, " PC=0x%03x ", m_PC ); - } else { - used_bytes += snprintf( buf + used_bytes, STR_SIZE - used_bytes, " " ); - } - used_bytes += snprintf( buf + used_bytes, STR_SIZE - used_bytes, - "(%s:%d) %s", - m_source_file.c_str(), m_source_line, - m_source.c_str() ); - return std::string( buf ); +std::string ptx_instruction::to_string() const { + char buf[STR_SIZE]; + unsigned used_bytes = 0; + if (!is_label()) { + used_bytes += + snprintf(buf + used_bytes, STR_SIZE - used_bytes, " PC=0x%03x ", m_PC); + } else { + used_bytes += + snprintf(buf + used_bytes, STR_SIZE - used_bytes, " "); + } + used_bytes += + snprintf(buf + used_bytes, STR_SIZE - used_bytes, "(%s:%d) %s", + m_source_file.c_str(), m_source_line, m_source.c_str()); + return std::string(buf); } -operand_info ptx_instruction::get_pred() const -{ - return operand_info( m_pred, gpgpu_ctx); +operand_info ptx_instruction::get_pred() const { + return operand_info(m_pred, gpgpu_ctx); } - -function_info::function_info(int entry_point, gpgpu_context* ctx ) -{ - gpgpu_ctx = ctx; - m_uid = (gpgpu_ctx->function_info_sm_next_uid)++; - m_entry_point = (entry_point==1)?true:false; - m_extern = (entry_point==2)?true:false; - num_reconvergence_pairs = 0; - m_symtab = NULL; - m_assembled = false; - m_return_var_sym = NULL; - m_kernel_info.cmem = 0; - m_kernel_info.lmem = 0; - m_kernel_info.regs = 0; - m_kernel_info.smem = 0; - m_local_mem_framesize = 0; - m_args_aligned_size = -1; - pdom_done = false; //initialize it to false +function_info::function_info(int entry_point, gpgpu_context *ctx) { + gpgpu_ctx = ctx; + m_uid = (gpgpu_ctx->function_info_sm_next_uid)++; + m_entry_point = (entry_point == 1) ? true : false; + m_extern = (entry_point == 2) ? true : false; + num_reconvergence_pairs = 0; + m_symtab = NULL; + m_assembled = false; + m_return_var_sym = NULL; + m_kernel_info.cmem = 0; + m_kernel_info.lmem = 0; + m_kernel_info.regs = 0; + m_kernel_info.smem = 0; + m_local_mem_framesize = 0; + m_args_aligned_size = -1; + pdom_done = false; // initialize it to false } -unsigned function_info::print_insn( unsigned pc, FILE * fp ) const -{ - unsigned inst_size=1; // return offset to next instruction or 1 if unknown - unsigned index = pc - m_start_PC; - char command[1024]; - char buffer[1024]; - memset(command, 0, 1024); - memset(buffer, 0, 1024); - snprintf(command,1024,"c++filt -p %s",m_name.c_str()); - FILE *p = popen(command,"r"); - buffer[0]=0; - assert(fgets(buffer, 1023, p) != NULL); - // Remove trailing "\n" in buffer - char *c; - if ((c=strchr(buffer, '\n')) != NULL) *c = '\0'; - fprintf(fp,"%s",buffer); - if ( index >= m_instr_mem_size ) { - fprintf(fp, "<past last instruction (max pc=%u)>", m_start_PC + m_instr_mem_size - 1 ); - } else { - if ( m_instr_mem[index] != NULL ) { - m_instr_mem[index]->print_insn(fp); - inst_size = m_instr_mem[index]->isize; - } else - fprintf(fp, "<no instruction at pc = %u>", pc ); - } - pclose(p); - return inst_size; +unsigned function_info::print_insn(unsigned pc, FILE *fp) const { + unsigned inst_size = 1; // return offset to next instruction or 1 if unknown + unsigned index = pc - m_start_PC; + char command[1024]; + char buffer[1024]; + memset(command, 0, 1024); + memset(buffer, 0, 1024); + snprintf(command, 1024, "c++filt -p %s", m_name.c_str()); + FILE *p = popen(command, "r"); + buffer[0] = 0; + assert(fgets(buffer, 1023, p) != NULL); + // Remove trailing "\n" in buffer + char *c; + if ((c = strchr(buffer, '\n')) != NULL) *c = '\0'; + fprintf(fp, "%s", buffer); + if (index >= m_instr_mem_size) { + fprintf(fp, "<past last instruction (max pc=%u)>", + m_start_PC + m_instr_mem_size - 1); + } else { + if (m_instr_mem[index] != NULL) { + m_instr_mem[index]->print_insn(fp); + inst_size = m_instr_mem[index]->isize; + } else + fprintf(fp, "<no instruction at pc = %u>", pc); + } + pclose(p); + return inst_size; } -std::string function_info::get_insn_str( unsigned pc ) const -{ - unsigned index = pc - m_start_PC; - if ( index >= m_instr_mem_size ) { +std::string function_info::get_insn_str(unsigned pc) const { + unsigned index = pc - m_start_PC; + if (index >= m_instr_mem_size) { + char buff[STR_SIZE]; + buff[STR_SIZE - 1] = '\0'; + snprintf(buff, STR_SIZE, "<past last instruction (max pc=%u)>", + m_start_PC + m_instr_mem_size - 1); + return std::string(buff); + } else { + if (m_instr_mem[index] != NULL) { + return m_instr_mem[index]->to_string(); + } else { char buff[STR_SIZE]; - buff[STR_SIZE-1] = '\0'; - snprintf(buff, STR_SIZE, "<past last instruction (max pc=%u)>", m_start_PC + m_instr_mem_size - 1 ); + buff[STR_SIZE - 1] = '\0'; + snprintf(buff, STR_SIZE, "<no instruction at pc = %u>", pc); return std::string(buff); - } else { - if ( m_instr_mem[index] != NULL ) { - return m_instr_mem[index]->to_string(); - } else { - char buff[STR_SIZE]; - buff[STR_SIZE-1] = '\0'; - snprintf(buff, STR_SIZE, "<no instruction at pc = %u>", pc ); - return std::string(buff); - } - } + } + } } -void gpgpu_ptx_assemble( std::string kname, void *kinfo ) -{ - function_info *func_info = (function_info *)kinfo; - if((function_info *)kinfo == NULL) { - printf("GPGPU-Sim PTX: Warning - missing function definition \'%s\'\n", kname.c_str()); - return; - } - if( func_info->is_extern() ) { - printf("GPGPU-Sim PTX: skipping assembly for extern declared function \'%s\'\n", func_info->get_name().c_str() ); - return; - } - func_info->ptx_assemble(); +void gpgpu_ptx_assemble(std::string kname, void *kinfo) { + function_info *func_info = (function_info *)kinfo; + if ((function_info *)kinfo == NULL) { + printf("GPGPU-Sim PTX: Warning - missing function definition \'%s\'\n", + kname.c_str()); + return; + } + if (func_info->is_extern()) { + printf( + "GPGPU-Sim PTX: skipping assembly for extern declared function " + "\'%s\'\n", + func_info->get_name().c_str()); + return; + } + func_info->ptx_assemble(); } |
