Skip to content

Commit fa489af

Browse files
aratajewigcbot
authored andcommitted
Fix printf uncommon use cases
Fix the following printf use cases: 1. `printf("%s", "");` 2. `printf("%s","foo\0foo")`
1 parent 9c27763 commit fa489af

File tree

5 files changed

+100
-13
lines changed

5 files changed

+100
-13
lines changed

IGC/Compiler/CISACodeGen/CISABuilder.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6220,9 +6220,6 @@ namespace IGC
62206220
else {
62216221
if (modMD->stringConstants.count(G))
62226222
{
6223-
ConstantDataSequential* cds = dyn_cast<ConstantDataSequential>(G->getInitializer());
6224-
IGC_ASSERT(cds && (cds->isCString() || cds->isString()));
6225-
(void) cds;
62266223
programSyms.globalStringConst.emplace_back((vISA::GenSymType)symbolEntry.s_type, symbolEntry.s_offset, symbolEntry.s_size, G->getName().str());
62276224
}
62286225
else

IGC/Compiler/Optimizer/OpenCLPasses/OpenCLPrintf/OpenCLPrintfAnalysis.cpp

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,31 @@ bool isPrintfOnlyStringConstantImpl(const llvm::Value *v, std::set<const llvm::U
176176
// path lead to a printf call.
177177
bool OpenCLPrintfAnalysis::isPrintfOnlyStringConstant(const llvm::GlobalVariable *GV)
178178
{
179-
const llvm::Constant *initializer = GV->getInitializer();
180-
if (!initializer)
181-
return false;
182-
const llvm::ConstantDataSequential* cds = llvm::dyn_cast<llvm::ConstantDataSequential>(initializer);
183-
if (!cds || !cds->isCString() || !cds->isString())
179+
const llvm::Constant* Initializer = GV->getInitializer();
180+
if (!Initializer)
181+
{
184182
return false;
183+
}
184+
185+
bool IsNullTerminatedString = false;
186+
if (const auto* cds = llvm::dyn_cast<llvm::ConstantDataSequential>(Initializer))
187+
{
188+
if (cds->isString())
189+
{
190+
StringRef Str = cds->getAsString();
191+
IsNullTerminatedString = Str.contains(0);
192+
}
193+
}
194+
195+
bool IsZeroInitCharArray = Initializer->isZeroValue() &&
196+
isa<ArrayType>(Initializer->getType()) &&
197+
Initializer->getType()->getArrayElementType()->isIntegerTy(8);
198+
199+
if (IsNullTerminatedString || IsZeroInitCharArray)
200+
{
201+
std::set<const llvm::User*> Visited;
202+
return isPrintfOnlyStringConstantImpl(GV, Visited);
203+
}
185204

186-
std::set<const llvm::User *> visited;
187-
return isPrintfOnlyStringConstantImpl(GV, visited);
205+
return false;
188206
}

IGC/Compiler/Optimizer/OpenCLPasses/ProgramScopeConstants/ProgramScopeConstantAnalysis.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,7 @@ bool ProgramScopeConstantAnalysis::runOnModule(Module& M)
129129

130130
// When ZeBin is enabled, constant variables that are string literals
131131
// used only by printf will be stored in the second constant buffer.
132-
ConstantDataSequential* cds = dyn_cast<ConstantDataSequential>(initializer);
133132
bool isZebinPrintfStringConst = Ctx->enableZEBinary() &&
134-
cds && (cds->isCString() || cds->isString()) &&
135133
OpenCLPrintfAnalysis::isPrintfOnlyStringConstant(globalVar);
136134
// Here we follow SPV_EXT_relaxed_printf_string_address_space to relax
137135
// the address space requirement of printf strings and accept
@@ -155,7 +153,7 @@ bool ProgramScopeConstantAnalysis::runOnModule(Module& M)
155153
}
156154
}
157155

158-
if (initializer->isZeroValue())
156+
if (initializer->isZeroValue() && !isZebinPrintfStringConst)
159157
{
160158
zeroInitializedGlobals.push_back(globalVar);
161159
continue;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
;=========================== begin_copyright_notice ============================
2+
;
3+
; Copyright (C) 2025 Intel Corporation
4+
;
5+
; SPDX-License-Identifier: MIT
6+
;
7+
;============================ end_copyright_notice =============================
8+
9+
; RUN: igc_opt -igc-programscope-constant-analysis -igc-serialize-metadata \
10+
; RUN: -S < %s | FileCheck %s
11+
; ------------------------------------------------
12+
; ProgramScopeConstantAnalysis
13+
; ------------------------------------------------
14+
15+
; Below LLVM IR was produced from the following OpenCL C code:
16+
;
17+
; kernel void test()
18+
; {
19+
; printf("%s", "");
20+
; }
21+
22+
; CHECK: !{!"stringConstants", ![[FORMAT_STR_MD:.*]], ![[STR_MD:.*]]}
23+
; CHECK: ![[FORMAT_STR_MD]] = !{!"stringConstantsSet[0]", [3 x i8] addrspace(2)* @.str}
24+
; CHECK: ![[STR_MD]] = !{!"stringConstantsSet[1]", [1 x i8] addrspace(2)* @.str.1}
25+
26+
@.str = internal unnamed_addr addrspace(2) constant [3 x i8] c"%s\00", align 1
27+
@.str.1 = internal unnamed_addr addrspace(2) constant [1 x i8] zeroinitializer, align 1
28+
29+
define spir_kernel void @test() {
30+
entry:
31+
%0 = getelementptr inbounds [3 x i8], [3 x i8] addrspace(2)* @.str, i64 0, i64 0
32+
%1 = getelementptr inbounds [1 x i8], [1 x i8] addrspace(2)* @.str.1, i64 0, i64 0
33+
%call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* %0, i8 addrspace(2)* %1)
34+
ret void
35+
}
36+
37+
declare i32 @printf(i8 addrspace(2)*, ...)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
;=========================== begin_copyright_notice ============================
2+
;
3+
; Copyright (C) 2025 Intel Corporation
4+
;
5+
; SPDX-License-Identifier: MIT
6+
;
7+
;============================ end_copyright_notice =============================
8+
9+
; RUN: igc_opt -igc-programscope-constant-analysis -igc-serialize-metadata \
10+
; RUN: -S < %s | FileCheck %s
11+
; ------------------------------------------------
12+
; ProgramScopeConstantAnalysis
13+
; ------------------------------------------------
14+
15+
; Below LLVM IR was produced from the following OpenCL C code:
16+
;
17+
; kernel void test()
18+
; {
19+
; printf("%s","foo\0foo");
20+
; }
21+
22+
; CHECK: !{!"stringConstants", ![[FORMAT_STR_MD:.*]], ![[FOO_STR_MD:.*]]}
23+
; CHECK: ![[FORMAT_STR_MD]] = !{!"stringConstantsSet[0]", [3 x i8] addrspace(2)* @.str}
24+
; CHECK: ![[FOO_STR_MD]] = !{!"stringConstantsSet[1]", [8 x i8] addrspace(2)* @.str.1}
25+
26+
@.str = internal unnamed_addr addrspace(2) constant [3 x i8] c"%s\00", align 1
27+
@.str.1 = internal unnamed_addr addrspace(2) constant [8 x i8] c"foo\00foo\00", align 1
28+
29+
define spir_kernel void @test() {
30+
entry:
31+
%0 = getelementptr inbounds [3 x i8], [3 x i8] addrspace(2)* @.str, i64 0, i64 0
32+
%1 = getelementptr inbounds [8 x i8], [8 x i8] addrspace(2)* @.str.1, i64 0, i64 0
33+
%call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* %0, i8 addrspace(2)* %1)
34+
ret void
35+
}
36+
37+
declare i32 @printf(i8 addrspace(2)*, ...)

0 commit comments

Comments
 (0)