Skip to content

Commit af7dd19

Browse files
ustachowigcbot
authored andcommitted
Add debug option to inject printf with pointer and type on every detected cast
This commit introduces a new debug feature that inserts a printf statement before load and store operations. The printf outputs the pointer value and the type that is being loaded or stored. This feature is controlled by a new debug flag.
1 parent d60a48c commit af7dd19

File tree

9 files changed

+245
-5
lines changed

9 files changed

+245
-5
lines changed

IGC/AdaptorOCL/UnifyIROCL.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*========================== begin_copyright_notice ============================
22
3-
Copyright (C) 2017-2022 Intel Corporation
3+
Copyright (C) 2017-2024 Intel Corporation
44
55
SPDX-License-Identifier: MIT
66
@@ -75,6 +75,7 @@ SPDX-License-Identifier: MIT
7575
#include "Compiler/Optimizer/OpenCLPasses/WGFuncs/WGFuncResolution.hpp"
7676
#include "Compiler/Optimizer/OpenCLPasses/AlignmentAnalysis/AlignmentAnalysis.hpp"
7777
#include "Compiler/Optimizer/PreCompiledFuncImport.hpp"
78+
#include "Compiler/Optimizer/OpenCLPasses/OpenCLPrintf/InjectPrintf.hpp"
7879
#include "Compiler/Optimizer/OpenCLPasses/OpenCLPrintf/OpenCLPrintfAnalysis.hpp"
7980
#include "Compiler/Optimizer/OpenCLPasses/OpenCLPrintf/OpenCLPrintfResolution.hpp"
8081
#include "Compiler/Optimizer/OpenCLPasses/AggregateArguments/AggregateArguments.hpp"
@@ -545,6 +546,7 @@ static void CommonOCLBasedPasses(OpenCLProgramContext* pContext)
545546
// Analysis passes
546547
mpm.add(new WIFuncsAnalysis());
547548
mpm.add(new ImageFuncsAnalysis());
549+
mpm.add(new InjectPrintf());
548550
mpm.add(new OpenCLPrintfAnalysis());
549551
mpm.add(createDeadCodeEliminationPass());
550552
mpm.add(new ProgramScopeConstantAnalysis());

IGC/Compiler/InitializePasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,4 @@ void initializeLoopCountAnalysisPass(llvm::PassRegistry&);
272272
void initializeCollectLoopCountPass(llvm::PassRegistry&);
273273
void initializeRemoveLoopDependencyPass(llvm::PassRegistry&);
274274
void initializeResourceLoopUnrollPass(llvm::PassRegistry&);
275+
void initializeInjectPrintfPass(llvm::PassRegistry&);

IGC/Compiler/Optimizer/OpenCLPasses/OpenCLPrintf/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#=========================== begin_copyright_notice ============================
22
#
3-
# Copyright (C) 2017-2021 Intel Corporation
3+
# Copyright (C) 2017-2024 Intel Corporation
44
#
55
# SPDX-License-Identifier: MIT
66
#
@@ -12,12 +12,14 @@ include_directories("${CMAKE_CURRENT_SOURCE_DIR}")
1212
set(IGC_BUILD__SRC__OpenCLPrintf
1313
"${CMAKE_CURRENT_SOURCE_DIR}/OpenCLPrintfAnalysis.cpp"
1414
"${CMAKE_CURRENT_SOURCE_DIR}/OpenCLPrintfResolution.cpp"
15+
"${CMAKE_CURRENT_SOURCE_DIR}/InjectPrintf.cpp"
1516
)
1617
set(IGC_BUILD__SRC__OpenCLPasses_OpenCLPrintf ${IGC_BUILD__SRC__OpenCLPrintf} PARENT_SCOPE)
1718

1819
set(IGC_BUILD__HDR__OpenCLPrintf
1920
"${CMAKE_CURRENT_SOURCE_DIR}/OpenCLPrintfAnalysis.hpp"
2021
"${CMAKE_CURRENT_SOURCE_DIR}/OpenCLPrintfResolution.hpp"
22+
"${CMAKE_CURRENT_SOURCE_DIR}/InjectPrintf.hpp"
2123
)
2224
set(IGC_BUILD__HDR__OpenCLPasses_OpenCLPrintf ${IGC_BUILD__HDR__OpenCLPrintf} PARENT_SCOPE)
2325

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*========================== begin_copyright_notice ============================
2+
3+
Copyright (C) 2024 Intel Corporation
4+
5+
SPDX-License-Identifier: MIT
6+
7+
============================= end_copyright_notice ===========================*/
8+
9+
#include "InjectPrintf.hpp"
10+
#include "llvm/IR/IRBuilder.h"
11+
#include <common/igc_regkeys.hpp>
12+
13+
#include "common/LLVMWarningsPush.hpp"
14+
#include "common/LLVMWarningsPop.hpp"
15+
#include "Compiler/IGCPassSupport.h"
16+
17+
18+
using namespace IGC;
19+
using namespace llvm;
20+
21+
char InjectPrintf::ID = 0;
22+
23+
#define PASS_FLAG "inject-printf"
24+
#define PASS_DESCRIPTION "Inject printf before load and store operations for ptr Pass."
25+
#define PASS_CFG_ONLY false
26+
#define PASS_ANALYSIS false
27+
IGC_INITIALIZE_PASS_BEGIN(InjectPrintf, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
28+
IGC_INITIALIZE_PASS_END(InjectPrintf, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
29+
30+
enum class InjectPrintfFlagType {
31+
#define INJECT_PRINTF_OPTION(Name, Val) Name = Val,
32+
#include "igc_regkeys_enums_defs.h"
33+
INJECT_PRINTF_OPTIONS
34+
#undef INJECT_PRINTF_OPTION
35+
#undef INJECT_PRINTF_OPTIONS
36+
};
37+
38+
InjectPrintf::InjectPrintf() : FunctionPass(ID) {
39+
initializeInjectPrintfPass(*PassRegistry::getPassRegistry());
40+
}
41+
42+
GlobalVariable* InjectPrintf::createGlobalFormatStr(Module* Module, LLVMContext& Context) {
43+
IGC_ASSERT(Module != nullptr);
44+
45+
const char* FormatStrLiteral = "Pointer: %p, Type: %s\n";
46+
size_t MaxLength = 256;
47+
size_t FormatStrSize = strnlen(FormatStrLiteral, MaxLength) + 1;
48+
49+
GlobalVariable* FormatStrGlobal = new GlobalVariable(
50+
*Module,
51+
ArrayType::get(Type::getInt8Ty(Context), FormatStrSize),
52+
true,
53+
GlobalValue::InternalLinkage,
54+
ConstantDataArray::getString(Context, FormatStrLiteral, true),
55+
"",
56+
nullptr,
57+
GlobalValue::ThreadLocalMode::NotThreadLocal,
58+
2
59+
);
60+
FormatStrGlobal->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
61+
62+
return FormatStrGlobal;
63+
}
64+
65+
Value* InjectPrintf::createGEP(GlobalVariable* GlobalVariable, Instruction* InsertBefore) {
66+
IGC_ASSERT(GlobalVariable != nullptr);
67+
IGC_ASSERT(InsertBefore != nullptr);
68+
69+
LLVMContext& Context = GlobalVariable->getParent()->getContext();
70+
const auto Zero = ConstantInt::getSigned(Type::getInt32Ty(Context), 0);
71+
auto Result = GetElementPtrInst::Create(
72+
GlobalVariable->getValueType(),
73+
GlobalVariable,
74+
{ Zero, Zero },
75+
"",
76+
InsertBefore
77+
);
78+
Result->setIsInBounds(true);
79+
return Result;
80+
}
81+
82+
void InjectPrintf::insertPrintf(IRBuilder<>& Builder, FunctionCallee PrintfFunc, GlobalVariable* FormatStrGlobal, Instruction* Inst, Value* PointerOperand, Type* ValueType) {
83+
IGC_ASSERT(FormatStrGlobal != nullptr);
84+
IGC_ASSERT(Inst != nullptr);
85+
IGC_ASSERT(PointerOperand != nullptr);
86+
IGC_ASSERT(ValueType != nullptr);
87+
88+
Builder.SetInsertPoint(Inst);
89+
Value* FormatStr = createGEP(FormatStrGlobal, Inst);
90+
std::string TypeStr;
91+
raw_string_ostream RSO(TypeStr);
92+
ValueType->print(RSO);
93+
Value* TypeStrGlobal = Builder.CreateGlobalStringPtr(RSO.str());
94+
Builder.CreateCall(PrintfFunc, { FormatStr, PointerOperand, TypeStrGlobal });
95+
}
96+
97+
bool InjectPrintf::runOnFunction(Function& F) {
98+
LLVMContext& Context = F.getContext();
99+
Module* Module = F.getParent();
100+
if (!Module) {
101+
errs() << "Error: Module is null\n";
102+
return false;
103+
}
104+
105+
IRBuilder<> Builder(Context);
106+
GlobalVariable* FormatStrGlobal = createGlobalFormatStr(Module, Context);
107+
108+
FunctionCallee PrintfFunc = Module->getOrInsertFunction(
109+
"printf",
110+
FunctionType::get(
111+
IntegerType::getInt32Ty(Context),
112+
PointerType::get(Type::getInt8Ty(Context), 2),
113+
true
114+
)
115+
);
116+
117+
auto InjectPrintfFlag = static_cast<InjectPrintfFlagType>(IGC_GET_FLAG_VALUE(InjectPrintfFlag));
118+
for (auto& BB : F) {
119+
for (auto& I : BB) {
120+
if (auto* Load = dyn_cast<LoadInst>(&I)) {
121+
if (InjectPrintfFlag == InjectPrintfFlagType::InjectPrintfLoads || InjectPrintfFlag == InjectPrintfFlagType::InjectPrintfLoadsAndStores) {
122+
insertPrintf(Builder, PrintfFunc, FormatStrGlobal, Load, Load->getPointerOperand(), Load->getType());
123+
}
124+
}
125+
if (auto* Store = dyn_cast<StoreInst>(&I)) {
126+
if (InjectPrintfFlag == InjectPrintfFlagType::InjectPrintfStores || InjectPrintfFlag == InjectPrintfFlagType::InjectPrintfLoadsAndStores) {
127+
insertPrintf(Builder, PrintfFunc, FormatStrGlobal, Store, Store->getPointerOperand(), Store->getValueOperand()->getType());
128+
}
129+
}
130+
}
131+
}
132+
133+
return true;
134+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*========================== begin_copyright_notice ============================
2+
3+
Copyright (C) 2024 Intel Corporation
4+
5+
SPDX-License-Identifier: MIT
6+
7+
============================= end_copyright_notice ===========================*/
8+
9+
#ifndef INJECT_PRINTF_HPP
10+
#define INJECT_PRINTF_HPP
11+
12+
#include "llvm/IR/Function.h"
13+
#include "llvm/Pass.h"
14+
#include "llvm/IR/IRBuilder.h"
15+
16+
namespace IGC
17+
{
18+
class InjectPrintf : public llvm::FunctionPass
19+
{
20+
public:
21+
static char ID;
22+
23+
InjectPrintf();
24+
~InjectPrintf() {}
25+
26+
virtual llvm::StringRef getPassName() const override
27+
{
28+
return "InjectPrintf";
29+
}
30+
31+
bool runOnFunction(llvm::Function& F) override;
32+
33+
private:
34+
llvm::GlobalVariable* createGlobalFormatStr(llvm::Module* module, llvm::LLVMContext& context);
35+
llvm::Value* createGEP(llvm::GlobalVariable* globalVariable, llvm::Instruction* insertBefore);
36+
void insertPrintf(llvm::IRBuilder<>& builder, llvm::FunctionCallee printfFunc, llvm::GlobalVariable* formatStrGlobal, llvm::Instruction* inst, llvm::Value* pointerOperand, llvm::Type* valueType);
37+
};
38+
}
39+
40+
#endif // INJECT_PRINTF_HPP
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
;=========================== begin_copyright_notice ============================
2+
;
3+
; Copyright (C) 2024 Intel Corporation
4+
;
5+
; SPDX-License-Identifier: MIT
6+
;
7+
;============================ end_copyright_notice =============================
8+
; REQUIRES: regkeys
9+
;
10+
; RUN: igc_opt -regkey InjectPrintfFlag=1 --inject-printf -S < %s | FileCheck %s --check-prefix=LOADS
11+
; RUN: igc_opt -regkey InjectPrintfFlag=2 --inject-printf -S < %s | FileCheck %s --check-prefix=STORES
12+
; RUN: igc_opt -regkey InjectPrintfFlag=3 --inject-printf -S < %s | FileCheck %s --check-prefix=LOADS_AND_STORES
13+
;
14+
; ------------------------------------------------
15+
; InjectPrintf
16+
; ------------------------------------------------
17+
18+
@global_var = global i32 0
19+
20+
define spir_kernel void @test_function() {
21+
entry:
22+
%ptr = alloca i32, align 4
23+
%val = load i32, i32* %ptr, align 4
24+
store i32 %val, i32* @global_var, align 4
25+
ret void
26+
}
27+
28+
; LOADS-LABEL: @test_function(
29+
; LOADS: call i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* %0, i32* %ptr, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @1, i32 0, i32 0))
30+
; LOADS: load i32, i32* %ptr, align 4
31+
; LOADS-NOT: call i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* %0, i32* @global_var, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @1, i32 0, i32 0))
32+
; LOADS: store i32 %val, i32* @global_var, align 4
33+
; LOADS: ret void
34+
35+
; STORES-LABEL: @test_function(
36+
; STORES-NOT: call i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* %0, i32* %ptr, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @1, i32 0, i32 0))
37+
; STORES: load i32, i32* %ptr, align 4
38+
; STORES: call i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* %0, i32* @global_var, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @1, i32 0, i32 0))
39+
; STORES: store i32 %val, i32* @global_var, align 4
40+
; STORES: ret void
41+
42+
; LOADS_AND_STORES-LABEL: @test_function(
43+
; LOADS_AND_STORES: call i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* %0, i32* %ptr, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @1, i32 0, i32 0))
44+
; LOADS_AND_STORES: load i32, i32* %ptr, align 4
45+
; LOADS_AND_STORES: call i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* %2, i32* @global_var, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @2, i32 0, i32 0))
46+
; LOADS_AND_STORES: store i32 %val, i32* @global_var, align 4
47+
; LOADS_AND_STORES: ret void

IGC/common/igc_flags.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*========================== begin_copyright_notice ============================
22
3-
Copyright (C) 2017-2023 Intel Corporation
3+
Copyright (C) 2017-2024 Intel Corporation
44
55
SPDX-License-Identifier: MIT
66
@@ -470,6 +470,7 @@ DECLARE_IGC_REGKEY(bool, StackOverflowDetection, false, "Inserts checks f
470470
DECLARE_IGC_REGKEY(bool, BufferBoundsChecking, false, "Setting this to 1 (true) enables buffer bounds checking", false)
471471
DECLARE_IGC_REGKEY(DWORD, MinimumValidAddress, 0, "If it's greater than 0, it enables minimal valid address checking where the threshold is the given value (in hex).", false)
472472
DECLARE_IGC_REGKEY(bool, AssignZeroToUndefPhiNodes, false, "Assigns a null value to such a phi node which has an undefined value during emitting vISA", false)
473+
DECLARE_IGC_REGKEY_ENUM(InjectPrintfFlag, 0, "Inject printf debugging flag", INJECT_PRINTF_OPTIONS, true)
473474

474475
DECLARE_IGC_GROUP("IGC Features")
475476
DECLARE_IGC_REGKEY(bool, EnableOCLSIMD16, true, "Enable OCL SIMD16 mode", true)

IGC/common/igc_regkeys.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*========================== begin_copyright_notice ============================
22
3-
Copyright (C) 2017-2023 Intel Corporation
3+
Copyright (C) 2017-2024 Intel Corporation
44
55
SPDX-License-Identifier: MIT
66
@@ -32,6 +32,8 @@ SPDX-License-Identifier: MIT
3232
#define TRIBOOL_OPTION(Name, Val) #Name "=" #Val ","
3333
#define RTMEMORY_STYLE_OPTION(Name, Val) #Name "=" #Val ","
3434

35+
#define INJECT_PRINTF_OPTION(Name, Val) #Name "=" #Val ","
36+
3537
#include "igc_regkeys_enums_defs.h"
3638

3739

@@ -54,6 +56,9 @@ SPDX-License-Identifier: MIT
5456
#undef RTMEMORY_STYLE_OPTION
5557
#undef RTMEMORY_STYLE_OPTIONS
5658

59+
#undef INJECT_PRINTF_OPTION
60+
#undef INJECT_PRINTF_OPTIONS
61+
5762
#undef DECLARE_IGC_GROUP
5863
#undef DECLARE_IGC_REGKEY_ENUM
5964
#undef DECLARE_IGC_REGKEY_BITMASK

IGC/common/igc_regkeys_enums_defs.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*========================== begin_copyright_notice ============================
22
3-
Copyright (C) 2022-2023 Intel Corporation
3+
Copyright (C) 2022-2024 Intel Corporation
44
55
SPDX-License-Identifier: MIT
66
@@ -101,3 +101,11 @@ SPDX-License-Identifier: MIT
101101
TRIBOOL_OPTION(Enabled, 1)
102102
#endif // TRIBOOL_OPTION
103103

104+
105+
#ifdef INJECT_PRINTF_OPTION
106+
#define INJECT_PRINTF_OPTIONS \
107+
INJECT_PRINTF_OPTION(InjectPrintfNone, 0)\
108+
INJECT_PRINTF_OPTION(InjectPrintfLoads, 1)\
109+
INJECT_PRINTF_OPTION(InjectPrintfStores, 2)\
110+
INJECT_PRINTF_OPTION(InjectPrintfLoadsAndStores, 3)
111+
#endif // INJECT_PRINTF_OPTION

0 commit comments

Comments
 (0)