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,9 +30,10 @@ 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 )
 | 
			
		||||
{   
 | 
			
		||||
{
 | 
			
		||||
    if( pFile == NULL )
 | 
			
		||||
    {
 | 
			
		||||
        return EINVAL;
 | 
			
		||||
 | 
			
		||||
@ -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