int* inform_black_box(int const *series, size_t l, size_t n, size_t m, int const *b, size_t const *r, size_t const *s, int *box, inform_error *err) { if (check_arguments(series, l, n, m, b, r, s, err)) { return NULL; } size_t max_r, max_s; compute_lengths(r, s, l, &max_r, &max_s); bool allocate = (box == NULL); if (allocate) { box = calloc(n * (m - max_r - max_s + 1), sizeof(int)); if (box == NULL) { INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); } } size_t *data = calloc(2 * l, sizeof(size_t)); if (data == NULL) { if (allocate) free(box); INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); } size_t *history = data; if (r == NULL) { for (size_t i = 0; i < l; ++i) history[i] = 1; } else { memcpy(history, r, l * sizeof(size_t)); } size_t *future = data + l; if (s != NULL) { memcpy(future, s, l * sizeof(size_t)); } accumulate(series, l, n, m, b, history, future, max_r, max_s, box, err); if (inform_failed(err)) { if (allocate) free(box); box = NULL; } free(data); return box; }
void gooda::convert_to_afdo(const gooda::gooda_report& report, gooda::afdo_data& data, boost::program_options::variables_map& vm){ bool lbr; if(vm.count("auto")){ auto total_count_lbr = total_count(report, BB_EXEC); lbr = total_count_lbr > 0; } else { lbr = vm.count("lbr"); } //Choose the correct counter std::string counter_name = lbr ? BB_EXEC : UNHALTED_CORE_CYCLES; //Verify that the file has the correct column if(!vm.count("auto") && total_count(report, counter_name) == 0){ throw gooda::gooda_exception("The file is not valid for the current mode"); } //Empty each cache inlining_cache.clear(); discriminator_cache.clear(); auto filter = get_process_filter(report, vm, counter_name); log::emit<log::Debug>() << "Filter by \"" << filter << "\"" << log::endl; for(std::size_t i = 0; i < report.functions(); ++i){ auto& line = report.hotspot_function(i); //Only if the function passes the filters if(filter.empty() || line.get_string(report.get_hotspot_file().column(PROCESS)) == filter){ auto string_cycles = line.get_string(report.get_hotspot_file().column(counter_name)); //Some functions are filled empty by Gooda for some reason //In some case, it means 0, in that case, it is not a problem to ignore it either, cause not really hotspot if(string_cycles.empty()){ continue; } gooda::afdo_function function; function.i = i; function.executable_file = get_application_file(report, i); function.name = line.get_string(report.get_hotspot_file().column(FUNCTION_NAME)); if(lbr){ function.total_count = line.get_counter(report.get_hotspot_file().column(SW_INST_RETIRED)); } else { auto count = report.get_hotspot_file().multiplex_line().get_double(report.get_hotspot_file().column(UNHALTED_CORE_CYCLES)) * line.get_counter(report.get_hotspot_file().column(UNHALTED_CORE_CYCLES)); function.total_count = static_cast<gcov_type>(count); } //We need the asm file to continue if(!report.has_asm_file(function.i)){ continue; } //Check that the function file is correctly set auto& file = report.asm_file(function.i); bool invalid = false; for(std::size_t j = 0; j < file.lines(); ++j){ auto& line = file.line(j); //Basic Block have no file if(boost::starts_with(line.get_string(file.column(DISASSEMBLY)), "Basic Block")){ continue; } //Line without addresses have special meaning if(line.get_string(file.column(ADDRESS)).empty()){ continue; } //Gooda does not always found the source file of a function //In that case, declare the function as invalid and return quickly auto princ_file = line.get_string(file.column(PRINC_FILE)); if(princ_file == "null"){ log::emit<log::Warning>() << function.name << " is invalid (null file)" << log::endl; invalid = true; break; } if(princ_file.empty()){ log::emit<log::Warning>() << function.name << " is invalid (empty file)" << log::endl; invalid = true; break; } } if(invalid){ continue; } //Add the function data.functions.push_back(std::move(function)); } } //Update function names (replace unmangled with mangled names) update_function_names(report, data, vm); //Fill the inlining cache (gets inlined function names) fill_inlining_cache(report, data, vm); //Fill the discriminator cache (gets the discriminators of each lines) fill_discriminator_cache(report, data, vm); //Generate the inline stacks for(auto& function : data.functions){ //Collect function.file and function.entry_count auto bbs = collect_basic_blocks(report, function, lbr); if(lbr){ lbr_annotate(report, function, bbs); } else { ca_annotate(report, function, bbs); } } //Prune uncounted functions prune_uncounted_functions(data); //Strip current directory from paths strip_paths(data); //Fill the file name table with the strings from the AFDO profile fill_file_name_table(data); //Compute the working set compute_working_set(report, data, vm, lbr); //Set the sizes of the different sections compute_lengths(data); //Note: No need to fill the modules because it is not used by GCC //It will be automatically written empty by the AFDO generator }