// Insert code for incrementing our byte, flop, etc. counters. bool BytesFlops::runOnFunction(Function& function) { // Do nothing if we're supposed to ignore this function. StringRef function_name = function.getName(); string function_name_orig = demangle_func_name(function_name.str()); remove_all_instances(function_name_orig, ' '); // Normalize the name by removing spaces. if ( instrument_only != NULL ) { if ( (instrument_only->find(function_name) == instrument_only->end()) && (instrument_only->find(function_name_orig) == instrument_only->end()) ) return false; } if ( dont_instrument != NULL ) { if ( (dont_instrument->find(function_name) != dont_instrument->end()) || (dont_instrument->find(function_name_orig) != dont_instrument->end()) ) return false; } if (function_name == "bf_categorize_counters") // Avoid the endless recursion that would be caused if we were // to instrument bf_categorize_counters() using // bf_categorize_counters(). return false; if ( "bf_initialize_func_map" == function_name ) { return false; } if ( function.empty() ) { return false; } // Reset all of our static counters. static_loads = 0; static_stores = 0; static_flops = 0; static_ops = 0; static_cond_brs = 0; static_bblocks = 0; // Instrument "interesting" instructions in every basic block. Module* module = function.getParent(); instrument_entire_function(module, function, function_name); // Return, indicating that we modified this function. return true; }
// Generate a description of a data structure. string DataStructCounters::generate_symbol_desc (void) const { stringstream locstr; bool is_global = strcmp(syminfo.function, "*GLOBAL*") == 0; if (syminfo.symbol[0] == '[') locstr << (allocation ? "Unnamed" : "Unknown") << " data structure"; else locstr << "Variable " << demangle_func_name(syminfo.symbol); if (is_global) { if (strcmp(syminfo.file, "??") != 0) locstr << " declared"; } else locstr << (allocation ? " allocated in" : " accessed in") << ' ' << demangle_func_name(syminfo.function); if (strcmp(syminfo.file, "??") != 0) { locstr << " at " << syminfo.file; if (syminfo.line > 0) locstr << ':' << syminfo.line; } return locstr.str(); }
// Output load and store counters by data structure. void bf_report_data_struct_counts (void) { // Sort all data structures in the interval tree by decreasing order // of total bytes accessed. Ignore any unaccessed data structures. vector<DataStructCounters*> interesting_data; for (auto iter = id_to_counters->begin(); iter != id_to_counters->end(); iter++) { DataStructCounters* counters = iter->second; if (counters->bytes_loaded + counters->bytes_stored > 0) interesting_data.push_back(counters); } sort(interesting_data.begin(), interesting_data.end(), compare_counter_interest); // Output a textual header line. *bfout << "BYFL_DATA_STRUCT_HEADER: " << setw(20) << "Size" << ' ' << setw(20) << "LD_bytes" << ' ' << setw(20) << "ST_bytes" << ' ' << setw(20) << "LD_ops" << ' ' << setw(20) << "ST_ops" << ' ' << setw(29) << left << "Origin" << internal << ' ' << "Description" << '\n'; // Output a binary table header. *bfbin << uint8_t(BINOUT_TABLE_BASIC) << "Data-structure accesses"; *bfbin << uint8_t(BINOUT_COL_UINT64) << "Number of allocations" << uint8_t(BINOUT_COL_UINT64) << "Total bytes allocated" << uint8_t(BINOUT_COL_UINT64) << "Maximum memory footprint" << uint8_t(BINOUT_COL_UINT64) << "Bytes loaded" << uint8_t(BINOUT_COL_UINT64) << "Bytes stored" << uint8_t(BINOUT_COL_UINT64) << "Load operations" << uint8_t(BINOUT_COL_UINT64) << "Store operations" << uint8_t(BINOUT_COL_BOOL) << "Known allocation point" << uint8_t(BINOUT_COL_STRING) << "Mangled origin" << uint8_t(BINOUT_COL_STRING) << "Demangled origin" << uint8_t(BINOUT_COL_STRING) << "Mangled variable name" << uint8_t(BINOUT_COL_STRING) << "Demangled variable name" << uint8_t(BINOUT_COL_STRING) << "Mangled function name" << uint8_t(BINOUT_COL_STRING) << "Demangled function name" << uint8_t(BINOUT_COL_STRING) << "File name" << uint8_t(BINOUT_COL_UINT64) << "Line number" << uint8_t(BINOUT_COL_STRING) << "Description" << uint8_t(BINOUT_COL_NONE); // Output both textual and binary data. for (auto iter = interesting_data.cbegin(); iter != interesting_data.cend(); iter++) { // Demangle the origin name. const DataStructCounters* counters = *iter; const bf_symbol_info_t* syminfo = &counters->syminfo; string demangled_origin(demangle_func_name(syminfo->origin)); string short_demangled_origin(demangled_origin); size_t refpos = short_demangled_origin.find(" referencing "); if (refpos != string::npos) short_demangled_origin.erase(refpos); const string description = counters->generate_symbol_desc(); // Output textual data-structure information. *bfout << "BYFL_DATA_STRUCT: " << setw(20) << counters->max_size << ' ' << setw(20) << counters->bytes_loaded << ' ' << setw(20) << counters->bytes_stored << ' ' << setw(20) << counters->load_ops << ' ' << setw(20) << counters->store_ops << ' ' << setw(29) << left << short_demangled_origin << internal << ' ' << description << '\n'; // Output binary data-structure information. *bfbin << uint8_t(BINOUT_ROW_DATA) << counters->num_allocs << counters->bytes_alloced << counters->max_size << counters->bytes_loaded << counters->bytes_stored << counters->load_ops << counters->store_ops << counters->allocation << string(syminfo->origin) << demangled_origin << (string(syminfo->symbol[0] == '[' ? "" : syminfo->symbol)) << (string(syminfo->symbol[0] == '[' ? "" : demangle_func_name(syminfo->symbol))) << (strcmp(syminfo->function, "*GLOBAL*") == 0 ? "" : syminfo->function) << (strcmp(syminfo->function, "*GLOBAL*") == 0 ? "" : demangle_func_name(syminfo->function)) << (strcmp(syminfo->file, "??") == 0 ? "" : syminfo->file) << uint64_t(syminfo->line) << description; } *bfbin << uint8_t(BINOUT_ROW_NONE); }