mirror of
https://github.com/intel/intel-graphics-compiler.git
synced 2025-11-04 08:21:06 +08:00
Update for IGC-Metrics
1. Updated the way how the metrics are collected from the debug info. 2. Added cost-model for the SIMD16
This commit is contained in:
@ -1086,6 +1086,11 @@ else()
|
||||
"/ignore:4197"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(IGC_BUILD__EXPORT_SYMBOLS_LINK_FLAGS_DEBUG
|
||||
"${IGC_BUILD__EXPORT_SYMBOLS_LINK_FLAGS_DEBUG}"
|
||||
"/ignore:4099")
|
||||
|
||||
# Disable LTCG due to release build time increase
|
||||
#igc_config_flag_apply_settings(
|
||||
# LinkerOptions
|
||||
@ -1122,6 +1127,7 @@ if(_igc_compiler_is_clang)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
# ================================== Compiler preprocessor definitions =================================
|
||||
|
||||
# ? CL_NUMBER < env:CL_NUMBER if env:CL_NUMBER != ''
|
||||
@ -1352,10 +1358,9 @@ add_subdirectory(common)
|
||||
igc_sg_define(IGC__common)
|
||||
igc_sg_define(IGC__Common_CLElfLib)
|
||||
|
||||
#Metrcis
|
||||
include(igc_find_protobuf)
|
||||
include(Metrics/protobuf_metrics.cmake)
|
||||
|
||||
# Add protobuf
|
||||
include(igc_find_protobuf)
|
||||
|
||||
set(IGC_BUILD__SPIRV_TOOLS_ENABLED ON)
|
||||
|
||||
@ -1428,6 +1433,9 @@ if(MSVC)
|
||||
)
|
||||
endif()
|
||||
|
||||
#Metrcis
|
||||
include(Metrics/protobuf_metrics.cmake)
|
||||
|
||||
# Sources/headers for main libraries.
|
||||
set(IGC_BUILD__SRC__IGC__igc_common
|
||||
${IGC_BUILD__SRC__IGC_AdaptorOCL}
|
||||
@ -1883,6 +1891,7 @@ if(UNIX)
|
||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/AdaptorOCL/cif DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/igc COMPONENT igc-opencl-devel)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/common/StateSaveAreaHeader.h DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/igc/common COMPONENT igc-opencl-devel)
|
||||
|
||||
|
||||
if(IGC_BUILD__LLVM_SOURCES AND IGC_OPTION__LLVM_LLD)
|
||||
# For now lld could be included only via building from LLVM sources
|
||||
if(NOT ${CMAKE_BUILD_TYPE} EQUAL "Release")
|
||||
|
||||
@ -232,6 +232,9 @@ bool DebugInfoPass::runOnModule(llvm::Module& M)
|
||||
|
||||
if (finalize)
|
||||
{
|
||||
m_currShader->GetContext()->metrics.CollectDataFromDebugInfo(
|
||||
&m_currShader->GetDebugInfoData(), &decodedDbg);
|
||||
|
||||
IDebugEmitter::Release(m_pDebugEmitter);
|
||||
}
|
||||
}
|
||||
|
||||
@ -928,7 +928,6 @@ static bool hasMultipleExits(Loop* L, WIAnalysis* WI) {
|
||||
/// L6
|
||||
/// L7
|
||||
/// then it returns {L2, L5}
|
||||
///
|
||||
static void getNestedLoopsWithMultpleExists(Loop* L, WIAnalysis* WI,
|
||||
SmallVectorImpl<Loop*>& Result) {
|
||||
if (getNumOfNonUniformExits(L, WI) > 1) {
|
||||
@ -947,9 +946,10 @@ static void getNestedLoopsWithMultpleExists(Loop* L, WIAnalysis* WI,
|
||||
getNestedLoopsWithMultpleExists(InnerL, WI, Result);
|
||||
}
|
||||
|
||||
static const float NestedLoopsWithMultipleExits_THRESHOLD = 0.7f;
|
||||
|
||||
/// Check if loops with multiple exists dominate the entire function.
|
||||
static bool hasNestedLoopsWithMultipleExits(Function* F, LoopInfo* LI,
|
||||
/// Return the ratio between loops with multiple exists to other instructions in function.
|
||||
static float NestedLoopsWithMultipleExitsRatio(Function* F, LoopInfo* LI,
|
||||
WIAnalysis* WI) {
|
||||
// Find top level nested loops with multiple non-uniform exists.
|
||||
SmallVector<Loop*, 8> Loops;
|
||||
@ -971,16 +971,26 @@ static bool hasNestedLoopsWithMultipleExits(Function* F, LoopInfo* LI,
|
||||
for (auto& BB : F->getBasicBlockList())
|
||||
FuncSize += (unsigned)BB.size();
|
||||
|
||||
bool retVal = false;
|
||||
if (FuncSize > 0)
|
||||
{
|
||||
retVal = float(LoopSize) / FuncSize >= 0.7f;
|
||||
return float(LoopSize) / FuncSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static bool hasLongStridedLdStInLoop(Function* F, LoopInfo* LI, WIAnalysis* WI) {
|
||||
static const unsigned LongStridedLdStInLoop_THRESHOLD = 3;
|
||||
|
||||
typedef struct {
|
||||
unsigned LDs = 0;
|
||||
unsigned STs = 0;
|
||||
llvm::Loop* pProblematicLoop = nullptr;
|
||||
} LdStInLoop;
|
||||
|
||||
static const LdStInLoop LongStridedLdStInLoop(Function* F, LoopInfo* LI, WIAnalysis* WI) {
|
||||
LdStInLoop retVal;
|
||||
SmallVector<Loop*, 32> Loops;
|
||||
// Collect innermost simple loop.
|
||||
for (auto I = LI->begin(), E = LI->end(); I != E; ++I) {
|
||||
@ -1018,27 +1028,65 @@ static bool hasLongStridedLdStInLoop(Function* F, LoopInfo* LI, WIAnalysis* WI)
|
||||
++STs;
|
||||
}
|
||||
}
|
||||
if (LDs > 3 || STs > 3)
|
||||
return true;
|
||||
if (LDs > LongStridedLdStInLoop_THRESHOLD ||
|
||||
STs > LongStridedLdStInLoop_THRESHOLD)
|
||||
{
|
||||
retVal.LDs = LDs;
|
||||
retVal.STs = STs;
|
||||
retVal.pProblematicLoop = L;
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool Simd32ProfitabilityAnalysis::checkSimd16Profitable(CodeGenContext* ctx) {
|
||||
if ((IGC_GET_FLAG_VALUE(OCLSIMD16SelectionMask) & 0x1) &&
|
||||
getLoopCyclomaticComplexity() >= CYCLOMATIC_COMPLEXITY_THRESHOLD) {
|
||||
return false;
|
||||
if ((IGC_GET_FLAG_VALUE(OCLSIMD16SelectionMask) & 0x1))
|
||||
{
|
||||
int loopCyclomaticComplexity = getLoopCyclomaticComplexity();
|
||||
|
||||
ctx->metrics.CollectLoopCyclomaticComplexity(
|
||||
F,
|
||||
loopCyclomaticComplexity,
|
||||
CYCLOMATIC_COMPLEXITY_THRESHOLD);
|
||||
|
||||
if (loopCyclomaticComplexity >= CYCLOMATIC_COMPLEXITY_THRESHOLD)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((IGC_GET_FLAG_VALUE(OCLSIMD16SelectionMask) & 0x2) &&
|
||||
hasNestedLoopsWithMultipleExits(F, LI, WI)) {
|
||||
return false;
|
||||
if (IGC_GET_FLAG_VALUE(OCLSIMD16SelectionMask) & 0x2)
|
||||
{
|
||||
float nestedLoopsWithMultipleExits = NestedLoopsWithMultipleExitsRatio(F, LI, WI);
|
||||
|
||||
ctx->metrics.CollectNestedLoopsWithMultipleExits(
|
||||
F,
|
||||
nestedLoopsWithMultipleExits,
|
||||
NestedLoopsWithMultipleExits_THRESHOLD);
|
||||
|
||||
if (nestedLoopsWithMultipleExits >= NestedLoopsWithMultipleExits_THRESHOLD)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If there's wider vector load/store in a loop, skip SIMD16.
|
||||
if ((IGC_GET_FLAG_VALUE(OCLSIMD16SelectionMask) & 0x4) &&
|
||||
hasLongStridedLdStInLoop(F, LI, WI)) {
|
||||
return false;
|
||||
if (IGC_GET_FLAG_VALUE(OCLSIMD16SelectionMask) & 0x4)
|
||||
{
|
||||
LdStInLoop ldStInLoop = LongStridedLdStInLoop(F, LI, WI);
|
||||
|
||||
ctx->metrics.CollectLongStridedLdStInLoop(
|
||||
F,
|
||||
ldStInLoop.pProblematicLoop,
|
||||
ldStInLoop.LDs,
|
||||
ldStInLoop.STs,
|
||||
LongStridedLdStInLoop_THRESHOLD);
|
||||
|
||||
if (ldStInLoop.pProblematicLoop != nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto hasDouble = [](Function& F) {
|
||||
@ -1056,9 +1104,15 @@ bool Simd32ProfitabilityAnalysis::checkSimd16Profitable(CodeGenContext* ctx) {
|
||||
const CPlatform* platform = &ctx->platform;
|
||||
if (platform->GetPlatformFamily() == IGFX_GEN9_CORE &&
|
||||
platform->getPlatformInfo().eProductFamily == IGFX_GEMINILAKE &&
|
||||
hasDouble(*F)) {
|
||||
hasDouble(*F))
|
||||
{
|
||||
ctx->metrics.CollectIsGeminiLakeWithDoubles(F, false);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->metrics.CollectIsGeminiLakeWithDoubles(F, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -9,6 +9,8 @@ SPDX-License-Identifier: MIT
|
||||
#include "IGCMetric.h"
|
||||
#include "IGCMetricImpl.h"
|
||||
|
||||
class VISAModule;
|
||||
|
||||
namespace IGCMetrics
|
||||
{
|
||||
inline IGCMetricImpl* get(void* pIGCMetric)
|
||||
@ -74,8 +76,57 @@ namespace IGCMetrics
|
||||
get(igcMetric)->CollectLoops(loopInfo);
|
||||
}
|
||||
|
||||
void IGCMetric::CollectLoopCyclomaticComplexity(
|
||||
llvm::Function* pFunc,
|
||||
int LoopCyclomaticComplexity,
|
||||
int LoopCyclomaticComplexity_Max)
|
||||
{
|
||||
get(igcMetric)->CollectLoopCyclomaticComplexity(
|
||||
pFunc,
|
||||
LoopCyclomaticComplexity,
|
||||
LoopCyclomaticComplexity_Max);
|
||||
}
|
||||
|
||||
void IGCMetric::CollectNestedLoopsWithMultipleExits(
|
||||
llvm::Function* pFunc,
|
||||
float NestedLoopsWithMultipleExitsRatio,
|
||||
float NestedLoopsWithMultipleExitsRatio_Max)
|
||||
{
|
||||
get(igcMetric)->CollectNestedLoopsWithMultipleExits(
|
||||
pFunc,
|
||||
NestedLoopsWithMultipleExitsRatio,
|
||||
NestedLoopsWithMultipleExitsRatio_Max);
|
||||
}
|
||||
|
||||
void IGCMetric::CollectLongStridedLdStInLoop(
|
||||
llvm::Function* pFunc,
|
||||
llvm::Loop* pProblematicLoop,
|
||||
int LongStridedLdStInLoop_LdCnt,
|
||||
int LongStridedLdStInLoop_StCnt,
|
||||
int LongStridedLdStInLoop_MaxCntLdOrSt)
|
||||
{
|
||||
get(igcMetric)->CollectLongStridedLdStInLoop(
|
||||
pFunc,
|
||||
pProblematicLoop,
|
||||
LongStridedLdStInLoop_LdCnt,
|
||||
LongStridedLdStInLoop_StCnt,
|
||||
LongStridedLdStInLoop_MaxCntLdOrSt);
|
||||
}
|
||||
|
||||
void IGCMetric::CollectIsGeminiLakeWithDoubles(
|
||||
llvm::Function* pFunc,
|
||||
bool IsGeminiLakeWithDoubles)
|
||||
{
|
||||
get(igcMetric)->CollectIsGeminiLakeWithDoubles(pFunc, IsGeminiLakeWithDoubles);
|
||||
}
|
||||
|
||||
void IGCMetric::FinalizeStats()
|
||||
{
|
||||
get(igcMetric)->FinalizeStats();
|
||||
}
|
||||
|
||||
void IGCMetric::CollectDataFromDebugInfo(IGC::DebugInfoData* pDebugInfo, IGC::DbgDecoder* pDebugDecoder)
|
||||
{
|
||||
get(igcMetric)->CollectDataFromDebugInfo(pDebugInfo, pDebugDecoder);
|
||||
}
|
||||
}
|
||||
@ -19,6 +19,12 @@ SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace IGC
|
||||
{
|
||||
class DebugInfoData;
|
||||
class DbgDecoder;
|
||||
}
|
||||
|
||||
namespace IGCMetrics
|
||||
{
|
||||
class IGCMetric
|
||||
@ -44,6 +50,29 @@ namespace IGCMetrics
|
||||
|
||||
void CollectRegStats(KERNEL_INFO* vISAstats);
|
||||
|
||||
void CollectLoopCyclomaticComplexity(
|
||||
llvm::Function* pFunc,
|
||||
int LoopCyclomaticComplexity,
|
||||
int LoopCyclomaticComplexity_Max);
|
||||
|
||||
void CollectNestedLoopsWithMultipleExits(
|
||||
llvm::Function* pFunc,
|
||||
float NestedLoopsWithMultipleExitsRatio,
|
||||
float NestedLoopsWithMultipleExitsRatio_Max);
|
||||
|
||||
void CollectLongStridedLdStInLoop(
|
||||
llvm::Function* pFunc,
|
||||
llvm::Loop* pProblematicLoop,
|
||||
int LongStridedLdStInLoop_LdCnt,
|
||||
int LongStridedLdStInLoop_StCnt,
|
||||
int LongStridedLdStInLoop_MaxCntLdOrSt);
|
||||
|
||||
void CollectIsGeminiLakeWithDoubles(
|
||||
llvm::Function* pFunc,
|
||||
bool IsGeminiLakeWithDoubles);
|
||||
|
||||
void CollectDataFromDebugInfo(IGC::DebugInfoData* pDebugInfo, IGC::DbgDecoder* pDebugDecoder);
|
||||
|
||||
void FinalizeStats();
|
||||
|
||||
void OutputMetrics();
|
||||
|
||||
@ -6,25 +6,30 @@ SPDX-License-Identifier: MIT
|
||||
|
||||
============================= end_copyright_notice ===========================*/
|
||||
|
||||
#include "common/LLVMWarningsPush.hpp"
|
||||
#include <llvm/IR/Instructions.h>
|
||||
#include <llvm/Support/Path.h>
|
||||
#include "common/LLVMWarningsPop.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <Metrics/IGCMetricImpl.h>
|
||||
#include <Probe/Assertion.h>
|
||||
|
||||
#include <iomanip>
|
||||
#include <common/igc_regkeys.hpp>
|
||||
#include <visa/G4_IR.hpp>
|
||||
#include <visa/SpillManagerGMRF.h>
|
||||
#include <visa/LinearScanRA.h>
|
||||
#include <visa/LocalRA.h>
|
||||
#include <visa/LocalScheduler/Dependencies_G4IR.h>
|
||||
#include <Metrics/IGCMetricImpl.h>
|
||||
|
||||
#include <Probe/Assertion.h>
|
||||
#include <Compiler/CISACodeGen/ShaderCodeGen.hpp>
|
||||
#include <DebugInfo/VISAModule.hpp>
|
||||
#include <Compiler/DebugInfo/ScalarVISAModule.h>
|
||||
#include <visaBuilder_interface.h>
|
||||
#include <visa/Common_ISA.h>
|
||||
|
||||
#include "common/LLVMWarningsPush.hpp"
|
||||
#include <llvm/IR/Instructions.h>
|
||||
#include <llvm/Support/Path.h>
|
||||
#include <llvm/IR/DebugInfo.h>
|
||||
#include "common/LLVMWarningsPop.hpp"
|
||||
|
||||
#define DEBUG_METRIC 0
|
||||
|
||||
namespace IGCMetrics
|
||||
{
|
||||
@ -40,11 +45,6 @@ namespace IGCMetrics
|
||||
#ifdef IGC_METRICS__PROTOBUF_ATTACHED
|
||||
this->map_EmuCalls.clear();
|
||||
this->map_Func.clear();
|
||||
for (auto func : map_InstrLoc2Func)
|
||||
{
|
||||
delete func.second;
|
||||
}
|
||||
this->map_InstrLoc2Func.clear();
|
||||
this->map_Loops.clear();
|
||||
#endif
|
||||
}
|
||||
@ -65,9 +65,9 @@ namespace IGCMetrics
|
||||
std::stringstream ss;
|
||||
|
||||
ss << std::hex
|
||||
<< std::setfill('0')
|
||||
<< std::setw(sizeof(Hash->asmHash) * CHAR_BIT / 4)
|
||||
<< Hash->asmHash;
|
||||
<< std::setfill('0')
|
||||
<< std::setw(sizeof(Hash->asmHash) * CHAR_BIT / 4)
|
||||
<< Hash->asmHash;
|
||||
|
||||
oclProgram.set_hash(ss.str());
|
||||
#endif
|
||||
@ -81,7 +81,7 @@ namespace IGCMetrics
|
||||
if (IGC_GET_FLAG_VALUE(MetricsDumpEnable) > 0)
|
||||
{
|
||||
// Out file with ext OPTRPT - OPTimization RePoT
|
||||
std::string fileName = "OCL_" + oclProgram.hash() + ".optrpt";
|
||||
std::string fileName = oclProgram.hash() + ".optrpt";
|
||||
|
||||
std::ofstream metric_data;
|
||||
metric_data.open(fileName);
|
||||
@ -147,49 +147,47 @@ namespace IGCMetrics
|
||||
#ifdef IGC_METRICS__PROTOBUF_ATTACHED
|
||||
llvm::DILocation* debLoc = (llvm::DILocation*)emulatedInstruction->getDebugLoc();
|
||||
|
||||
auto func_m_list = GetFuncMetric(emulatedInstruction);
|
||||
if (func_m_list == nullptr)
|
||||
auto func_m = GetFuncMetric(emulatedInstruction);
|
||||
if (func_m == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (auto func_m : *func_m_list)
|
||||
|
||||
IGC_METRICS::InstrStats* stats = func_m->mutable_instruction_stats();
|
||||
IGC_METRICS::FuncEmuCalls* emuCall_m = nullptr;
|
||||
|
||||
// Count how many instructions we added
|
||||
int extraInstrAdded = CountInstInFunc(emulatedInstruction->getParent()->getParent()) -
|
||||
countInstInFunc;
|
||||
// reset counter
|
||||
countInstInFunc = 0;
|
||||
|
||||
if (map_EmuCalls.find(debLoc) != map_EmuCalls.end())
|
||||
{
|
||||
IGC_METRICS::InstrStats* stats = func_m->mutable_instruction_stats();
|
||||
IGC_METRICS::FuncEmuCalls* emuCall_m = nullptr;
|
||||
// For case when receive extra instruction to already recoreded emu-function
|
||||
emuCall_m = map_EmuCalls[debLoc];
|
||||
}
|
||||
else
|
||||
{
|
||||
// For case if we discover new emulated function
|
||||
emuCall_m = func_m->add_emufunctioncalls();
|
||||
map_EmuCalls.insert({ debLoc, emuCall_m });
|
||||
|
||||
// Count how many instructions we added
|
||||
int extraInstrAdded = CountInstInFunc(emulatedInstruction->getParent()->getParent()) -
|
||||
countInstInFunc;
|
||||
// reset counter
|
||||
countInstInFunc = 0;
|
||||
auto emuCall_m_loc = emuCall_m->add_funccallloc();
|
||||
FillCodeRef(emuCall_m_loc, debLoc);
|
||||
stats->set_countemulatedinst(stats->countemulatedinst() + 1);
|
||||
|
||||
if (map_EmuCalls.find(debLoc) != map_EmuCalls.end())
|
||||
if (IGC_IS_FLAG_ENABLED(ForceDPEmulation) && isDPType(emulatedInstruction))
|
||||
{
|
||||
// For case when receive extra instruction to already recoreded emu-function
|
||||
emuCall_m = map_EmuCalls[debLoc];
|
||||
emuCall_m->set_type(IGC_METRICS::FuncEmuCalls_Reason4FuncEmu_FP_MODEL_MODE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// For case if we discover new emulated function
|
||||
emuCall_m = func_m->add_emufunctioncalls();
|
||||
map_EmuCalls.insert({ debLoc, emuCall_m });
|
||||
|
||||
auto emuCall_m_loc = emuCall_m->add_funccallloc();
|
||||
FillCodeRef(emuCall_m_loc, debLoc);
|
||||
stats->set_countemulatedinst(stats->countemulatedinst() + 1);
|
||||
|
||||
if (IGC_IS_FLAG_ENABLED(ForceDPEmulation) && isDPType(emulatedInstruction))
|
||||
{
|
||||
emuCall_m->set_type(IGC_METRICS::FuncEmuCalls_Reason4FuncEmu_FP_MODEL_MODE);
|
||||
}
|
||||
else
|
||||
{
|
||||
emuCall_m->set_type(IGC_METRICS::FuncEmuCalls_Reason4FuncEmu_NO_HW_SUPPORT);
|
||||
}
|
||||
emuCall_m->set_type(IGC_METRICS::FuncEmuCalls_Reason4FuncEmu_NO_HW_SUPPORT);
|
||||
}
|
||||
// Count amount of instructions created to emulate not supported instruction
|
||||
emuCall_m->set_count(emuCall_m->count() + extraInstrAdded);
|
||||
}
|
||||
// Count amount of instructions created to emulate not supported instruction
|
||||
emuCall_m->set_count(emuCall_m->count() + extraInstrAdded);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -197,16 +195,14 @@ namespace IGCMetrics
|
||||
{
|
||||
if (!Enable()) return;
|
||||
#ifdef IGC_METRICS__PROTOBUF_ATTACHED
|
||||
auto func_m_list = GetFuncMetric(coalescedAccess);
|
||||
if (func_m_list == nullptr)
|
||||
auto func_m = GetFuncMetric(coalescedAccess);
|
||||
if (func_m == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (auto func_m : *func_m_list)
|
||||
{
|
||||
IGC_METRICS::InstrStats* stats = func_m->mutable_instruction_stats();
|
||||
stats->set_countcoalescedaccess(stats->countcoalescedaccess() + 1);
|
||||
}
|
||||
|
||||
IGC_METRICS::InstrStats* stats = func_m->mutable_instruction_stats();
|
||||
stats->set_countcoalescedaccess(stats->countcoalescedaccess() + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -218,63 +214,6 @@ namespace IGCMetrics
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto record = kernelInfo->variables.begin();
|
||||
record != kernelInfo->variables.end(); ++record)
|
||||
{
|
||||
auto varInfo = record->second;
|
||||
// Find to which function this var info belongs
|
||||
auto keyMap = GetHash(varInfo->srcFilename, varInfo->lineNb);
|
||||
auto func_m_list = GetFuncMetric(keyMap);
|
||||
|
||||
if (func_m_list == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto func_m : *func_m_list)
|
||||
{
|
||||
bool alreadyRecord = false;
|
||||
for (int i = 0; i < func_m->variables_size(); ++i)
|
||||
{
|
||||
if (func_m->variables(i).name() == record->first)
|
||||
{
|
||||
alreadyRecord = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (alreadyRecord)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
auto varInfo_m = func_m->add_variables();
|
||||
varInfo_m->set_name(record->first);
|
||||
varInfo_m->set_type((IGC_METRICS::VarInfo_VarType)varInfo->type);
|
||||
varInfo_m->set_memoryaccess((IGC_METRICS::VarInfo_MemAccess)varInfo->memoryAccess);
|
||||
varInfo_m->set_addrmodel((IGC_METRICS::VarInfo_AddressModel)varInfo->addrModel);
|
||||
varInfo_m->set_size(varInfo->size);
|
||||
varInfo_m->set_promoted2grf(varInfo->promoted2GRF);
|
||||
varInfo_m->set_isspill(varInfo->isSpill);
|
||||
varInfo_m->set_isuniform(varInfo->isUniform);
|
||||
varInfo_m->set_isconst(varInfo->isConst);
|
||||
|
||||
auto bcInfo = varInfo_m->mutable_bc_stats();
|
||||
bcInfo->set_count(varInfo->bc_count);
|
||||
bcInfo->set_samebank(varInfo->bc_sameBank);
|
||||
bcInfo->set_twosrc(varInfo->bc_twoSrc);
|
||||
|
||||
if (varInfo->srcFilename == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto codeRef = varInfo_m->mutable_varloc();
|
||||
|
||||
FillCodeRef(codeRef, varInfo->srcFilename, varInfo->lineNb);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -343,71 +282,337 @@ namespace IGCMetrics
|
||||
#endif
|
||||
}
|
||||
|
||||
void IGCMetricImpl::CollectLoopCyclomaticComplexity(
|
||||
llvm::Function* pFunc,
|
||||
int LoopCyclomaticComplexity,
|
||||
int LoopCyclomaticComplexity_Max)
|
||||
{
|
||||
if (!Enable()) return;
|
||||
#ifdef IGC_METRICS__PROTOBUF_ATTACHED
|
||||
IGC_METRICS::Function* func_metric = GetFuncMetric(pFunc);
|
||||
|
||||
if (func_metric)
|
||||
{
|
||||
auto costmodel = func_metric->mutable_costmodel_stats();
|
||||
auto simd16cost = costmodel->mutable_simd16();
|
||||
simd16cost->set_loopcyclomaticcomplexity(LoopCyclomaticComplexity);
|
||||
simd16cost->set_loopcyclomaticcomplexity_max(LoopCyclomaticComplexity_Max);
|
||||
simd16cost->set_loopcyclomaticcomplexity_status(
|
||||
LoopCyclomaticComplexity < LoopCyclomaticComplexity_Max ?
|
||||
IGC_METRICS::CostModelStats_CostStatus::CostModelStats_CostStatus_OK :
|
||||
IGC_METRICS::CostModelStats_CostStatus::CostModelStats_CostStatus_BAD);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void IGCMetricImpl::CollectNestedLoopsWithMultipleExits(
|
||||
llvm::Function* pFunc,
|
||||
float NestedLoopsWithMultipleExitsRatio,
|
||||
float NestedLoopsWithMultipleExitsRatio_Max)
|
||||
{
|
||||
if (!Enable()) return;
|
||||
#ifdef IGC_METRICS__PROTOBUF_ATTACHED
|
||||
IGC_METRICS::Function* func_metric = GetFuncMetric(pFunc);
|
||||
|
||||
if (func_metric)
|
||||
{
|
||||
auto costmodel = func_metric->mutable_costmodel_stats();
|
||||
auto simd16cost = costmodel->mutable_simd16();
|
||||
simd16cost->set_nestedloopswithmultipleexitsratio(NestedLoopsWithMultipleExitsRatio);
|
||||
simd16cost->set_nestedloopswithmultipleexitsratio_max(NestedLoopsWithMultipleExitsRatio_Max);
|
||||
simd16cost->set_nestedloopswithmultipleexitsratio_status(
|
||||
NestedLoopsWithMultipleExitsRatio < NestedLoopsWithMultipleExitsRatio_Max ?
|
||||
IGC_METRICS::CostModelStats_CostStatus::CostModelStats_CostStatus_OK :
|
||||
IGC_METRICS::CostModelStats_CostStatus::CostModelStats_CostStatus_BAD);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void IGCMetricImpl::CollectLongStridedLdStInLoop(
|
||||
llvm::Function* pFunc,
|
||||
llvm::Loop* pProblematicLoop,
|
||||
int LongStridedLdStInLoop_LdCnt,
|
||||
int LongStridedLdStInLoop_StCnt,
|
||||
int LongStridedLdStInLoop_MaxCntLdOrSt)
|
||||
{
|
||||
if (!Enable()) return;
|
||||
#ifdef IGC_METRICS__PROTOBUF_ATTACHED
|
||||
IGC_METRICS::Function* func_metric = GetFuncMetric(pFunc);
|
||||
|
||||
if (func_metric)
|
||||
{
|
||||
auto costmodel = func_metric->mutable_costmodel_stats();
|
||||
auto simd16cost = costmodel->mutable_simd16();
|
||||
|
||||
if (pProblematicLoop == nullptr)
|
||||
{
|
||||
simd16cost->set_longstridedldstinloop_status(
|
||||
IGC_METRICS::CostModelStats_CostStatus::CostModelStats_CostStatus_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
simd16cost->set_longstridedldstinloop_status(
|
||||
IGC_METRICS::CostModelStats_CostStatus::CostModelStats_CostStatus_BAD);
|
||||
simd16cost->set_longstridedldstinloop_ldcnt(LongStridedLdStInLoop_LdCnt);
|
||||
simd16cost->set_longstridedldstinloop_stcnt(LongStridedLdStInLoop_StCnt);
|
||||
simd16cost->set_longstridedldstinloop_maxcntldorst(LongStridedLdStInLoop_MaxCntLdOrSt);
|
||||
|
||||
FillCodeRef(simd16cost->mutable_longstridedldstinloop_problematicloop(),
|
||||
pProblematicLoop->getStartLoc());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void IGCMetricImpl::CollectIsGeminiLakeWithDoubles(
|
||||
llvm::Function* pFunc,
|
||||
bool IsGeminiLakeWithDoubles)
|
||||
{
|
||||
if (!Enable()) return;
|
||||
#ifdef IGC_METRICS__PROTOBUF_ATTACHED
|
||||
IGC_METRICS::Function* func_metric = GetFuncMetric(pFunc);
|
||||
|
||||
if (func_metric)
|
||||
{
|
||||
auto costmodel = func_metric->mutable_costmodel_stats();
|
||||
auto simd16cost = costmodel->mutable_simd16();
|
||||
|
||||
simd16cost->set_isgeminilakewithdoubles_status(IsGeminiLakeWithDoubles ?
|
||||
IGC_METRICS::CostModelStats_CostStatus::CostModelStats_CostStatus_OK :
|
||||
IGC_METRICS::CostModelStats_CostStatus::CostModelStats_CostStatus_BAD);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void IGCMetricImpl::FinalizeStats()
|
||||
{
|
||||
if (!Enable()) return;
|
||||
#ifdef IGC_METRICS__PROTOBUF_ATTACHED
|
||||
UpdateLoopsInfo();
|
||||
UpdateModelCost();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void IGCMetricImpl::CollectDataFromDebugInfo(IGC::DebugInfoData* pDebugInfo, IGC::DbgDecoder* pDebugDecoder)
|
||||
{
|
||||
if (!Enable()) return;
|
||||
#ifdef IGC_METRICS__PROTOBUF_ATTACHED
|
||||
|
||||
oclProgram.set_device((IGC_METRICS::DeviceType)
|
||||
pDebugInfo->m_pShader->m_Platform->getPlatformInfo().eProductFamily);
|
||||
|
||||
llvm::DenseMap<llvm::Function*, IGC::VISAModule*>* pListFuncData =
|
||||
&pDebugInfo->m_VISAModules;
|
||||
llvm::DenseMap< llvm::DIVariable*, IGC_METRICS::VarInfo*> var_db2metric;
|
||||
|
||||
for (auto pListFuncData_it = pListFuncData->begin();
|
||||
pListFuncData_it != pListFuncData->end(); ++pListFuncData_it)
|
||||
{
|
||||
llvm::Function* pFunc = pListFuncData_it->first;
|
||||
IGC::VISAModule* vISAData = pListFuncData_it->second;
|
||||
|
||||
//IGC::ScalarVisaModule* scalarVM = llvm::dyn_cast<IGC::ScalarVisaModule>(vISAData);
|
||||
|
||||
#ifdef DEBUG_METRIC
|
||||
std::printf("\nList of symbols:\n");
|
||||
|
||||
for (auto it_dbgInfo = pDebugInfo->m_FunctionSymbols[pFunc].begin();
|
||||
it_dbgInfo != pDebugInfo->m_FunctionSymbols[pFunc].end(); ++it_dbgInfo)
|
||||
{
|
||||
std::printf("pointer{%p} key{%s} val{%s}\n",
|
||||
it_dbgInfo->first,
|
||||
it_dbgInfo->first->getName().str().c_str(), it_dbgInfo->second->getName().getCString());
|
||||
it_dbgInfo->first->dump();
|
||||
}
|
||||
#endif
|
||||
|
||||
const llvm::Value* pVal = nullptr;
|
||||
llvm::MDNode* pNode = nullptr;
|
||||
|
||||
// Iterate over all instruction ported to vISA
|
||||
for (auto instr = vISAData->begin(); instr != vISAData->end(); ++instr)
|
||||
{
|
||||
llvm::DebugLoc* dbLoc = nullptr;
|
||||
if (const llvm::DbgDeclareInst* pDbgAddrInst =
|
||||
llvm::dyn_cast<llvm::DbgDeclareInst>(*instr))
|
||||
{
|
||||
// Get : call void @llvm.dbg.value
|
||||
dbLoc = (llvm::DebugLoc*) & pDbgAddrInst->getDebugLoc();
|
||||
pVal = pDbgAddrInst->getAddress();
|
||||
pNode = pDbgAddrInst->getVariable();
|
||||
}
|
||||
else if (const llvm::DbgValueInst* pDbgValInst =
|
||||
llvm::dyn_cast<llvm::DbgValueInst>(*instr))
|
||||
{
|
||||
// Get : call void @llvm.dbg.value
|
||||
|
||||
// Avoid undef values in metadata
|
||||
{
|
||||
llvm::MetadataAsValue* mdAv = llvm::dyn_cast<llvm::MetadataAsValue>(pDbgValInst->getArgOperand(0));
|
||||
if (mdAv != nullptr)
|
||||
{
|
||||
llvm::ValueAsMetadata* vAsMD = llvm::dyn_cast<llvm::ValueAsMetadata>(mdAv->getMetadata());
|
||||
if (vAsMD != nullptr &&
|
||||
llvm::isa<llvm::UndefValue>(vAsMD->getValue()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dbLoc = (llvm::DebugLoc*) & pDbgValInst->getDebugLoc();
|
||||
pVal = pDbgValInst->getValue();
|
||||
pNode = pDbgValInst->getVariable();
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extract debuginfo variable data
|
||||
llvm::DIVariable* diVar = llvm::cast<llvm::DIVariable>(pNode);
|
||||
|
||||
std::string varName = diVar->getName().str();
|
||||
// Get CVariable data for this user variable
|
||||
auto cvar = pDebugInfo->getMapping(*pFunc, pVal);
|
||||
|
||||
if (cvar == nullptr)
|
||||
{
|
||||
// If not found check in whole shader data
|
||||
cvar = pDebugInfo->m_pShader->GetSymbol((llvm::Value*)pVal);
|
||||
}
|
||||
|
||||
IGC_METRICS::Function* func_m = GetFuncMetric(*instr);
|
||||
|
||||
#ifdef DEBUG_METRIC
|
||||
std::printf("\ninstr (varname:%s, pointer:%p) :\n", varName.c_str(), pVal);
|
||||
(*instr)->dump();
|
||||
#endif
|
||||
IGC_METRICS::VarInfo* varInfo_m = nullptr;
|
||||
if (var_db2metric.find(diVar) != var_db2metric.end())
|
||||
{
|
||||
// Already added user variable
|
||||
|
||||
// It is for case when one of the user variables
|
||||
// is referenced in many places and requires new registers
|
||||
varInfo_m = var_db2metric[diVar];
|
||||
}
|
||||
else
|
||||
{
|
||||
// New user variable
|
||||
varInfo_m = func_m->add_variables();
|
||||
|
||||
varInfo_m->set_name(varName);
|
||||
varInfo_m->set_size(cvar->GetSize());
|
||||
varInfo_m->set_type((IGC_METRICS::VarInfo_VarType)cvar->GetType());
|
||||
FillCodeRef(varInfo_m->mutable_varloc(),
|
||||
diVar);
|
||||
|
||||
var_db2metric.insert(std::pair{ diVar, varInfo_m });
|
||||
}
|
||||
|
||||
// Loop in case when we have simd32 splitted into two simd16
|
||||
auto varLocList = vISAData->GetVariableLocation(*instr);
|
||||
for (auto varLoc = varLocList.begin(); varLoc != varLocList.end(); ++varLoc)
|
||||
{
|
||||
const auto* varInfo = vISAData->getVarInfo(*pDebugDecoder, varLoc->GetRegister());
|
||||
auto varInfo_reg_m = varInfo_m->add_reg();
|
||||
|
||||
varInfo_reg_m->set_addrmodel(varLoc->IsInGlobalAddrSpace() ?
|
||||
IGC_METRICS::VarInfo_AddressModel::VarInfo_AddressModel_GLOBAL :
|
||||
IGC_METRICS::VarInfo_AddressModel::VarInfo_AddressModel_LOCAL);
|
||||
varInfo_reg_m->set_promoted2grf(varLoc->IsRegister());
|
||||
|
||||
//varInfo_m->set_memoryaccess((IGC_METRICS::VarInfo_MemAccess)varInfo->memoryAccess);
|
||||
|
||||
if (varInfo != nullptr)
|
||||
{
|
||||
// check if any?
|
||||
varInfo_reg_m->set_isspill(varInfo->lrs[0].isSpill());
|
||||
varInfo_reg_m->set_liverangestart(varInfo->lrs[0].start);
|
||||
varInfo_reg_m->set_liverangeend(varInfo->lrs[0].end);
|
||||
}
|
||||
varInfo_reg_m->set_isuniform(cvar->IsUniform());
|
||||
varInfo_reg_m->set_isconst(cvar->IsImmediate());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef IGC_METRICS__PROTOBUF_ATTACHED
|
||||
void IGCMetricImpl::UpdateCollectInstructions(llvm::Function* func)
|
||||
|
||||
void IGCMetricImpl::UpdateModelCost()
|
||||
{
|
||||
for (auto bb = func->begin(); bb != func->end(); ++bb)
|
||||
// Function which checks the overall model cost of kernel status for SIMD16 and SIMD32
|
||||
|
||||
auto isOkStatus = [](IGC_METRICS::CostModelStats_CostStatus Status)
|
||||
{
|
||||
for (auto inst_i = bb->begin(); inst_i != bb->end(); ++inst_i)
|
||||
return Status !=
|
||||
IGC_METRICS::CostModelStats_CostStatus::CostModelStats_CostStatus_BAD;
|
||||
};
|
||||
|
||||
for (auto func_m_i = map_Func.begin(); func_m_i != map_Func.end(); ++func_m_i)
|
||||
{
|
||||
auto func_m = func_m_i->second;
|
||||
|
||||
if (func_m->has_costmodel_stats())
|
||||
{
|
||||
llvm::DILocation* dbLoc = inst_i->getDebugLoc();
|
||||
auto costmodel = func_m->mutable_costmodel_stats();
|
||||
|
||||
if (dbLoc)
|
||||
if (costmodel->has_simd16())
|
||||
{
|
||||
MFuncList* func_m_list = nullptr;
|
||||
HashKey key = GetHash(dbLoc);
|
||||
llvm::DISubprogram* subProg = func->getSubprogram();
|
||||
auto simd16 = costmodel->mutable_simd16();
|
||||
|
||||
if (map_InstrLoc2Func.find(key) == map_InstrLoc2Func.end())
|
||||
{
|
||||
func_m_list = new MFuncList();
|
||||
func_m_list->push_back(map_Func[subProg]);
|
||||
map_InstrLoc2Func.insert({ key, func_m_list });
|
||||
}
|
||||
else
|
||||
{
|
||||
func_m_list = map_InstrLoc2Func[key];
|
||||
if (std::find(func_m_list->begin(),
|
||||
func_m_list->end(), map_Func[subProg]) == func_m_list->end())
|
||||
{
|
||||
func_m_list->push_back(map_Func[subProg]);
|
||||
}
|
||||
}
|
||||
simd16->set_overallstatus(
|
||||
isOkStatus(simd16->loopcyclomaticcomplexity_status()) &&
|
||||
isOkStatus(simd16->nestedloopswithmultipleexitsratio_status()) &&
|
||||
isOkStatus(simd16->longstridedldstinloop_status()) &&
|
||||
isOkStatus(simd16->isgeminilakewithdoubles_status()));
|
||||
}
|
||||
|
||||
if (costmodel->has_simd32())
|
||||
{
|
||||
auto simd32 = costmodel->mutable_simd32();
|
||||
|
||||
simd32->set_overallstatus(
|
||||
isOkStatus(simd32->instructioncount_status()) &&
|
||||
isOkStatus(simd32->threadgroupsize_status()) &&
|
||||
isOkStatus(simd32->threadgroupsizehint_status()) &&
|
||||
isOkStatus(simd32->subgroupfunctionarepresent_status()) &&
|
||||
isOkStatus(simd32->gen9orgen10withieeesqrtordivfunc_status()) &&
|
||||
isOkStatus(simd32->nonuniformloop_status()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IGCMetricImpl::UpdateCollectInstructions(llvm::Function* func)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IGCMetricImpl::CollectLoop(llvm::Loop* loop)
|
||||
{
|
||||
if (loop->getStartLoc() && loop->getStartLoc()->getScope())
|
||||
{
|
||||
if (map_Loops.find(loop->getStartLoc()->getScope()) == map_Loops.end())
|
||||
{
|
||||
auto func_m_list = GetFuncMetric(loop);
|
||||
if (func_m_list == nullptr)
|
||||
auto func_m = GetFuncMetric(loop);
|
||||
if (func_m == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (auto func_m : *func_m_list)
|
||||
{
|
||||
auto cfg_stats = func_m->mutable_cfg_stats();
|
||||
auto loop_m = cfg_stats->add_loops_stats();
|
||||
auto loopLoc = loop_m->mutable_looploc();
|
||||
|
||||
FillCodeRef(loopLoc, loop->getStartLoc());
|
||||
loop_m->set_nestinglevel(loop->getLoopDepth());
|
||||
auto cfg_stats = func_m->mutable_cfg_stats();
|
||||
auto loop_m = cfg_stats->add_loops_stats();
|
||||
auto loopLoc = loop_m->mutable_looploc();
|
||||
|
||||
map_Loops.insert({ loop->getStartLoc()->getScope(), loop_m });
|
||||
}
|
||||
FillCodeRef(loopLoc, loop->getStartLoc());
|
||||
loop_m->set_nestinglevel(loop->getLoopDepth());
|
||||
|
||||
map_Loops.insert({ loop->getStartLoc()->getScope(), loop_m });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -467,7 +672,7 @@ namespace IGCMetrics
|
||||
func_m->functioncalls(i).name()))
|
||||
{
|
||||
// For case if we have already record created
|
||||
callFunc_m = (IGC_METRICS::FuncCalls*)&func_m->functioncalls(i);
|
||||
callFunc_m = (IGC_METRICS::FuncCalls*) & func_m->functioncalls(i);
|
||||
callFunc_m->set_count(callFunc_m->count() + 1);
|
||||
break;
|
||||
}
|
||||
@ -515,71 +720,32 @@ namespace IGCMetrics
|
||||
return instCount;
|
||||
}
|
||||
|
||||
MFuncList* IGCMetricImpl::GetFuncMetric(HashKey Key)
|
||||
IGC_METRICS::Function* IGCMetricImpl::GetFuncMetric(const llvm::Instruction* const pInstr)
|
||||
{
|
||||
if (Key == HashKey_NULL)
|
||||
return map_Func[
|
||||
pInstr->getDebugLoc()->getScope()->getSubprogram()];
|
||||
}
|
||||
|
||||
IGC_METRICS::Function* IGCMetricImpl::GetFuncMetric(llvm::Instruction* pInstr)
|
||||
{
|
||||
return GetFuncMetric(pInstr->getParent()->getParent());
|
||||
}
|
||||
|
||||
IGC_METRICS::Function* IGCMetricImpl::GetFuncMetric(llvm::Loop* pLoop)
|
||||
{
|
||||
return GetFuncMetric(pLoop->getBlocks()[0]->getParent());
|
||||
}
|
||||
|
||||
IGC_METRICS::Function* IGCMetricImpl::GetFuncMetric(llvm::Function* pFunc)
|
||||
{
|
||||
if (map_Func.find(pFunc->getSubprogram()) == map_Func.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
if (map_InstrLoc2Func.find(Key) == map_InstrLoc2Func.end())
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
return map_Func[pFunc->getSubprogram()];
|
||||
}
|
||||
return map_InstrLoc2Func[Key];
|
||||
}
|
||||
|
||||
MFuncList* IGCMetricImpl::GetFuncMetric(llvm::Instruction* pInstr)
|
||||
{
|
||||
return GetFuncMetric(GetHash(pInstr->getDebugLoc()));
|
||||
}
|
||||
|
||||
MFuncList* IGCMetricImpl::GetFuncMetric(llvm::Loop* pLoop)
|
||||
{
|
||||
return GetFuncMetric(GetHash(pLoop->getStartLoc()));
|
||||
}
|
||||
|
||||
HashKey IGCMetricImpl::GetHash(llvm::DILocation* Loc)
|
||||
{
|
||||
if (Loc == nullptr || Loc->getDirectory().empty() || Loc->getFilename().empty())
|
||||
{
|
||||
return HashKey_NULL;
|
||||
}
|
||||
return GetHash(
|
||||
GetFullPath(Loc->getDirectory().str(), Loc->getFilename().str()),
|
||||
Loc->getLine());
|
||||
}
|
||||
|
||||
HashKey IGCMetricImpl::GetHash(const std::string& dir, const std::string& fileName, int line)
|
||||
{
|
||||
return GetHash(GetFullPath(dir, fileName), line);
|
||||
}
|
||||
|
||||
HashKey IGCMetricImpl::GetHash(const char* dir, const char* fileName, int line)
|
||||
{
|
||||
if (dir == nullptr || fileName == nullptr)
|
||||
{
|
||||
return HashKey_NULL;
|
||||
}
|
||||
return GetHash(std::string(dir), std::string(fileName), line);
|
||||
}
|
||||
|
||||
HashKey IGCMetricImpl::GetHash(const char* filePathName, int line)
|
||||
{
|
||||
if (filePathName == nullptr)
|
||||
{
|
||||
return HashKey_NULL;
|
||||
}
|
||||
return GetHash(std::string(filePathName), line);
|
||||
}
|
||||
|
||||
HashKey IGCMetricImpl::GetHash(const std::string& filePathName, int line)
|
||||
{
|
||||
if (filePathName.length() == 0 && line == 0)
|
||||
{
|
||||
return HashKey_NULL;
|
||||
}
|
||||
std::hash<std::string> hasher;
|
||||
return hasher(filePathName + std::to_string(line));
|
||||
}
|
||||
|
||||
void IGCMetricImpl::FillCodeRef(IGC_METRICS::CodeRef* codeRef, llvm::DISubprogram* Loc)
|
||||
@ -602,6 +768,16 @@ namespace IGCMetrics
|
||||
Loc->getLine());
|
||||
}
|
||||
|
||||
void IGCMetricImpl::FillCodeRef(IGC_METRICS::CodeRef* codeRef, llvm::DIVariable* Var)
|
||||
{
|
||||
if (Var == nullptr || Var->getDirectory().empty() || Var->getFilename().empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
FillCodeRef(codeRef, GetFullPath(Var->getDirectory().str(), Var->getFilename().str()),
|
||||
Var->getLine());
|
||||
}
|
||||
|
||||
void IGCMetricImpl::FillCodeRef(IGC_METRICS::CodeRef* codeRef, const std::string& filePathName, int line)
|
||||
{
|
||||
if (filePathName.empty())
|
||||
|
||||
@ -8,6 +8,7 @@ SPDX-License-Identifier: MIT
|
||||
|
||||
#include "common/LLVMWarningsPush.hpp"
|
||||
#include <llvm/IR/Module.h>
|
||||
#include <llvm/IR/Instructions.h>
|
||||
#include "llvm/IR/DebugInfoMetadata.h"
|
||||
#include "llvm/IR/DebugLoc.h"
|
||||
#include <llvm/Analysis/LoopInfo.h>
|
||||
@ -16,24 +17,23 @@ SPDX-License-Identifier: MIT
|
||||
#include <3d/common/iStdLib/types.h>
|
||||
#include <common/shaderHash.hpp>
|
||||
#include "KernelInfo.h"
|
||||
#include "IGCMetric.h"
|
||||
|
||||
#ifdef IGC_METRICS__PROTOBUF_ATTACHED
|
||||
#include <google/protobuf/util/json_util.h>
|
||||
#include <Metrics/proto_schema/igc_metrics.pb.h>
|
||||
#include <Metrics/proto_schema/instruction_stats.pb.h>
|
||||
|
||||
#define HashKey size_t
|
||||
#define HashKey_NULL 0
|
||||
#endif // IGC_METRICS
|
||||
|
||||
#include "Compiler/CISACodeGen/CVariable.hpp"
|
||||
#include <Compiler/CISACodeGen/DebugInfoData.hpp>
|
||||
#include <DebugInfo/VISADebugDecoder.hpp>
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace IGCMetrics
|
||||
{
|
||||
#ifdef IGC_METRICS__PROTOBUF_ATTACHED
|
||||
typedef std::vector<IGC_METRICS::Function*> MFuncList;
|
||||
#endif
|
||||
|
||||
class IGCMetricImpl
|
||||
{
|
||||
private:
|
||||
@ -42,9 +42,6 @@ namespace IGCMetrics
|
||||
IGC_METRICS::Program oclProgram;
|
||||
|
||||
// Helpers
|
||||
// Map all instruction line number, filepath to Function
|
||||
// { Key: Hash(fullPathFile+LineNb), Value:Function list containing this instruction }
|
||||
std::map<HashKey, MFuncList*> map_InstrLoc2Func;
|
||||
// Map Function debuginfo to Function metrics
|
||||
std::map<llvm::DISubprogram*, IGC_METRICS::Function*> map_Func;
|
||||
// helpers for emulated calls
|
||||
@ -58,23 +55,21 @@ namespace IGCMetrics
|
||||
|
||||
void GetFunctionCalls(IGC_METRICS::Function* func_m, llvm::Function& func);
|
||||
|
||||
inline MFuncList* GetFuncMetric(llvm::Instruction* pInstr);
|
||||
inline MFuncList* GetFuncMetric(llvm::Loop* pLoop);
|
||||
inline MFuncList* GetFuncMetric(HashKey Key);
|
||||
inline IGC_METRICS::Function* GetFuncMetric(const llvm::Instruction* const pInstr);
|
||||
inline IGC_METRICS::Function* GetFuncMetric(llvm::Instruction* pInstr);
|
||||
inline IGC_METRICS::Function* GetFuncMetric(llvm::Loop* pLoop);
|
||||
|
||||
inline IGC_METRICS::Function* GetFuncMetric(llvm::Function* pFunc);
|
||||
|
||||
void CollectInstructions(llvm::Module* pModule);
|
||||
|
||||
void UpdateLoopsInfo();
|
||||
void UpdateModelCost();
|
||||
void CollectLoop(llvm::Loop* loop);
|
||||
|
||||
static HashKey GetHash(const char* dir, const char* fileName, int line);
|
||||
static HashKey GetHash(const char* filePathName, int line);
|
||||
static HashKey GetHash(const std::string& dir, const std::string& fileName, int line);
|
||||
static HashKey GetHash(const std::string& filePathName, int line);
|
||||
static HashKey GetHash(llvm::DILocation* Loc);
|
||||
|
||||
static inline void FillCodeRef(IGC_METRICS::CodeRef* codeRef, llvm::DISubprogram* Loc);
|
||||
static inline void FillCodeRef(IGC_METRICS::CodeRef* codeRef, llvm::DILocation* Loc);
|
||||
static inline void FillCodeRef(IGC_METRICS::CodeRef* codeRef, llvm::DIVariable* Var);
|
||||
static inline void FillCodeRef(IGC_METRICS::CodeRef* codeRef, const std::string& filePathName, int line);
|
||||
|
||||
static inline const std::string GetFullPath(const char* dir, const char* fileName);
|
||||
@ -101,6 +96,29 @@ namespace IGCMetrics
|
||||
|
||||
void CollectRegStats(KERNEL_INFO* vISAstats);
|
||||
|
||||
void CollectLoopCyclomaticComplexity(
|
||||
llvm::Function* pFunc,
|
||||
int LoopCyclomaticComplexity,
|
||||
int LoopCyclomaticComplexity_Max);
|
||||
|
||||
void CollectNestedLoopsWithMultipleExits(
|
||||
llvm::Function* pFunc,
|
||||
float NestedLoopsWithMultipleExitsRatio,
|
||||
float NestedLoopsWithMultipleExitsRatio_Max);
|
||||
|
||||
void CollectLongStridedLdStInLoop(
|
||||
llvm::Function* pFunc,
|
||||
llvm::Loop* pProblematicLoop,
|
||||
int LongStridedLdStInLoop_LdCnt,
|
||||
int LongStridedLdStInLoop_StCnt,
|
||||
int LongStridedLdStInLoop_MaxCntLdOrSt);
|
||||
|
||||
void CollectIsGeminiLakeWithDoubles(
|
||||
llvm::Function* pFunc,
|
||||
bool IsGeminiLakeWithDoubles);
|
||||
|
||||
void CollectDataFromDebugInfo(IGC::DebugInfoData* pDebugInfo, IGC::DbgDecoder* pDebugDecoder);
|
||||
|
||||
void FinalizeStats();
|
||||
|
||||
void OutputMetrics();
|
||||
|
||||
88
IGC/Metrics/proto_schema/cost_model_stats.proto
Normal file
88
IGC/Metrics/proto_schema/cost_model_stats.proto
Normal file
@ -0,0 +1,88 @@
|
||||
/*========================== begin_copyright_notice ============================
|
||||
|
||||
Copyright (C) 2021 Intel Corporation
|
||||
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
============================= end_copyright_notice ===========================*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
import "Metrics/proto_schema/code_reference.proto";
|
||||
|
||||
package IGC_METRICS;
|
||||
|
||||
message CostModelStats
|
||||
{
|
||||
enum CostStatus
|
||||
{
|
||||
NOT_CHECK = 0;
|
||||
OK = 1;
|
||||
BAD = 2;
|
||||
}
|
||||
|
||||
message CostSIMD16
|
||||
{
|
||||
CostStatus LoopCyclomaticComplexity_Status = 1;
|
||||
int32 LoopCyclomaticComplexity = 2;
|
||||
int32 LoopCyclomaticComplexity_Max = 3;
|
||||
|
||||
CostStatus NestedLoopsWithMultipleExitsRatio_Status = 4;
|
||||
float NestedLoopsWithMultipleExitsRatio = 5;
|
||||
float NestedLoopsWithMultipleExitsRatio_Max = 6;
|
||||
|
||||
// If LdCnt OR StCnt is bigger than MaxCntLdOrSt
|
||||
// then LongStridedLdStInLoop_Status is BAD
|
||||
CostStatus LongStridedLdStInLoop_Status = 7;
|
||||
// If LongStridedLdStInLoop_Status is BAD
|
||||
// then data below will have the information
|
||||
// for problematic loop
|
||||
int32 LongStridedLdStInLoop_LdCnt = 8;
|
||||
int32 LongStridedLdStInLoop_StCnt = 9;
|
||||
int32 LongStridedLdStInLoop_MaxCntLdOrSt = 10;
|
||||
CodeRef LongStridedLdStInLoop_ProblematicLoop = 11;
|
||||
|
||||
// If this flag is true - then we don't have GeminiLake
|
||||
// or existing doubles in shader
|
||||
CostStatus IsGeminiLakeWithDoubles_Status = 12;
|
||||
|
||||
// If we met all requirements for SIMD 16 then set true
|
||||
bool OverallStatus = 13;
|
||||
}
|
||||
|
||||
message CostSIMD32
|
||||
{
|
||||
enum LoopCount
|
||||
{
|
||||
LIKELY_SMALL = 0;
|
||||
LOOPCOUNT_LIKELY_LARGE = 1;
|
||||
LOOPCOUNT_UNKNOWN = 2;
|
||||
}
|
||||
|
||||
CostStatus InstructionCount_Status = 1;
|
||||
int32 InstructionCount = 2;
|
||||
int32 InstructionCount_Max = 3;
|
||||
|
||||
CostStatus ThreadGroupSize_Status = 4;
|
||||
int32 ThreadGroupSize = 5;
|
||||
int32 ThreadGroupSize_Max = 6;
|
||||
|
||||
CostStatus ThreadGroupSizeHint_Status = 7;
|
||||
int32 ThreadGroupSizeHint = 8;
|
||||
int32 ThreadGroupSizeHint_Max = 9;
|
||||
|
||||
CostStatus SubgroupFunctionArePresent_Status = 10;
|
||||
|
||||
CostStatus Gen9OrGen10WithIEEESqrtOrDivFunc_Status = 11;
|
||||
|
||||
CostStatus NonUniformLoop_Status = 12;
|
||||
LoopCount NonUniformLoop_Count = 13;
|
||||
CodeRef NonUniformLoop_ProblematicLoop = 14;
|
||||
|
||||
// If we met all requirements for SIMD 32 then set true
|
||||
bool OverallStatus = 15;
|
||||
}
|
||||
|
||||
CostSIMD16 simd16 = 1;
|
||||
CostSIMD32 simd32 = 2;
|
||||
}
|
||||
@ -18,6 +18,7 @@ import "Metrics/proto_schema/mem_alloc_stats.proto";
|
||||
import "Metrics/proto_schema/code_reference.proto";
|
||||
import "Metrics/proto_schema/local_reg_stats.proto";
|
||||
import "Metrics/proto_schema/cfg_stats.proto";
|
||||
import "Metrics/proto_schema/cost_model_stats.proto";
|
||||
|
||||
package IGC_METRICS;
|
||||
|
||||
@ -51,4 +52,6 @@ message Function
|
||||
LocalRegStats local_reg_stats = 11;
|
||||
|
||||
CFGStats cfg_stats = 12;
|
||||
|
||||
CostModelStats costModel_stats = 13;
|
||||
}
|
||||
@ -21,18 +21,17 @@ message VarInfo {
|
||||
Type_W = 3; // signed word integer
|
||||
Type_UB = 4; // unsigned byte integer
|
||||
Type_B = 5; // signed byte integer
|
||||
Type_F = 6; // signed single precision
|
||||
Type_VF = 7; // 32-bit restricted Vector Float
|
||||
Type_DF = 6;
|
||||
Type_F = 7; // signed single precision
|
||||
Type_V = 8; // 32-bit halfbyte integer Vector
|
||||
Type_DF = 9;
|
||||
Type_VF = 9; // 32-bit restricted Vector Float
|
||||
Type_BOOL = 10;
|
||||
Type_UV = 11;
|
||||
Type_Q = 12; // 64-bit signed integer
|
||||
Type_UQ = 13; // 64-bit unsigned integer
|
||||
Type_UQ = 11; // 64-bit unsigned integer
|
||||
Type_UV = 12;
|
||||
Type_Q = 13; // 64-bit signed integer
|
||||
Type_HF = 14; // half float
|
||||
Type_NF = 15; // native float (only used by plane macro)
|
||||
Type_BF = 16; // bfloat16 (used in mov only)
|
||||
Type_UNDEF = 17;
|
||||
Type_BF = 15; // bfloat16 (used in mov only)
|
||||
Type_UNDEF = 16;
|
||||
}
|
||||
|
||||
enum AddressModel {
|
||||
@ -48,6 +47,18 @@ message VarInfo {
|
||||
ATOMIC = 4;
|
||||
}
|
||||
|
||||
message RegUsage {
|
||||
bool promoted2GRF = 1;
|
||||
AddressModel addrModel = 2;
|
||||
MemAccess memoryAccess = 3;
|
||||
bool isSpill = 4;
|
||||
bool isUniform = 5;
|
||||
bool isConst = 6;
|
||||
|
||||
int32 liveRangeStart = 7;
|
||||
int32 liveRangeEnd = 8;
|
||||
}
|
||||
|
||||
message BankConflictInfo {
|
||||
int32 count = 1;
|
||||
int32 sameBank = 2;
|
||||
@ -57,13 +68,9 @@ message VarInfo {
|
||||
optional string name = 1;
|
||||
int32 size = 2;
|
||||
VarType type = 3;
|
||||
bool promoted2GRF = 4;
|
||||
AddressModel addrModel = 5;
|
||||
MemAccess memoryAccess = 6;
|
||||
bool isSpill = 7;
|
||||
bool isUniform = 8;
|
||||
bool isConst = 9;
|
||||
BankConflictInfo bc_stats = 10;
|
||||
repeated RegUsage reg = 4;
|
||||
|
||||
optional CodeRef varLoc = 11;
|
||||
BankConflictInfo bc_stats = 5;
|
||||
|
||||
optional CodeRef varLoc = 6;
|
||||
}
|
||||
@ -50,6 +50,7 @@ list(APPEND IGC_METRICS_HDRS "Metrics/IGCMetricImpl.h")
|
||||
add_library(igc_metric STATIC ${IGC_METRICS_SRCS} ${IGC_METRICS_HDRS})
|
||||
|
||||
add_dependencies(igc_metric intrinsics_gen)
|
||||
add_dependencies(igc_metric ${IGC_BUILD__PROJ__GenISAIntrinsics})
|
||||
|
||||
if(IGC_METRICS)
|
||||
target_link_libraries(igc_metric protobuf::libprotobuf)
|
||||
|
||||
@ -14,6 +14,8 @@ SPDX-License-Identifier: MIT
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef MEMCPY_S
|
||||
#define MEMCPY_S
|
||||
typedef int errno_t;
|
||||
inline errno_t memcpy_s( void *dst, size_t numberOfElements, const void *src, size_t count )
|
||||
{
|
||||
@ -28,6 +30,7 @@ inline errno_t memcpy_s( void *dst, size_t numberOfElements, const void *src, si
|
||||
memcpy( dst, src, count );
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline errno_t fopen_s( FILE** pFile, const char* filename, const char *mode )
|
||||
{
|
||||
|
||||
@ -498,50 +498,9 @@ void* VISAKernelImpl::encodeAndEmit(unsigned int& binarySize)
|
||||
|
||||
if (getOptions()->getOption(vISA_GenerateKernelInfo))
|
||||
{
|
||||
auto kernel = getKernel();
|
||||
m_kernelInfo = new KERNEL_INFO();
|
||||
|
||||
m_kernelInfo->name = kernel->getName();
|
||||
|
||||
BB_LIST_ITER bbItEnd = kernel->fg.end();
|
||||
for (auto bbIt = kernel->fg.begin();
|
||||
bbIt != bbItEnd;
|
||||
bbIt++)
|
||||
{
|
||||
G4_BB* bb = (*bbIt);
|
||||
for (auto inst : bb->getInstList())
|
||||
{
|
||||
auto loc = inst->getLocation();
|
||||
if (loc == nullptr) continue;
|
||||
auto dstRg = inst->getDst();
|
||||
if (dstRg == nullptr) continue;
|
||||
auto decl = dstRg->getTopDcl();
|
||||
if (decl == nullptr) continue;
|
||||
//auto reg = decl->getRegVar();
|
||||
|
||||
VarInfo* varInfo = nullptr;
|
||||
|
||||
if ((varInfo = m_kernelInfo->AddVarInfo(decl->getName())) != nullptr)
|
||||
{
|
||||
varInfo->lineNb = loc->getLineNo();
|
||||
varInfo->srcFilename = loc->getSrcFilename();
|
||||
varInfo->isSpill = decl->isSpilled();
|
||||
// fixed values == const variable?
|
||||
varInfo->isConst = dstRg->isImm();
|
||||
varInfo->promoted2GRF = dstRg->isGreg();
|
||||
varInfo->size = decl->getByteSize();
|
||||
|
||||
varInfo->type = (short)decl->getElemType();
|
||||
|
||||
//varInfo->isUniform = N\A
|
||||
//varInfo->addrModel = N\A
|
||||
//varInfo->memoryAccess = N\A
|
||||
//varInfo->bc_count = N\A
|
||||
//varInfo->bc_sameBank = N\A
|
||||
//varInfo->bc_twoSrc = N\A
|
||||
}
|
||||
}
|
||||
}
|
||||
//auto kernel = getKernel();
|
||||
//m_kernelInfo = new KERNEL_INFO();
|
||||
// TODO check if this will be needed anymore
|
||||
}
|
||||
|
||||
if (m_options->getOption(vISA_outputToFile))
|
||||
|
||||
@ -19,6 +19,8 @@ SPDX-License-Identifier: MIT
|
||||
#include <errno.h>
|
||||
#include "common/secure_string.h"
|
||||
|
||||
#ifndef MEMCPY_S
|
||||
#define MEMCPY_S
|
||||
typedef int errno_t;
|
||||
static errno_t memcpy_s(void* dst, size_t numberOfElements, const void* src, size_t count)
|
||||
{
|
||||
@ -37,6 +39,7 @@ static errno_t memcpy_s(void* dst, size_t numberOfElements, const void* src, siz
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* stdio.h portability code end */
|
||||
|
||||
|
||||
@ -49,8 +49,7 @@ public:
|
||||
class KERNEL_INFO
|
||||
{
|
||||
public:
|
||||
std::map<std::string, VarInfo*> variables;
|
||||
std::string name;
|
||||
std::map<int, VarInfo*> variables;
|
||||
|
||||
KERNEL_INFO() { }
|
||||
~KERNEL_INFO()
|
||||
@ -61,19 +60,6 @@ public:
|
||||
}
|
||||
variables.clear();
|
||||
}
|
||||
|
||||
VarInfo* AddVarInfo(const char* name)
|
||||
{
|
||||
// Add only not existing item
|
||||
if (variables.find(name) == variables.end())
|
||||
{
|
||||
VarInfo* varInfo = new VarInfo();
|
||||
variables.insert({name, varInfo });
|
||||
return varInfo;
|
||||
}
|
||||
// If exists, return nullptr
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user