Skip to content

Commit 7ab102d

Browse files
petechoupszymich
authored andcommitted
ZEBIN: Put a const string literal into .data.const.string section only if used by printf only.
Compiler can not distinguish a char array between a string literal. So, to be safe we can only place a const string literal into the read-only str section that is accessed by CPU when the string literal is used only by printf. For all other cases, we need to place it into the read-only data section.
1 parent 09a695a commit 7ab102d

File tree

6 files changed

+76
-6
lines changed

6 files changed

+76
-6
lines changed

IGC/Compiler/CISACodeGen/CISABuilder.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5697,6 +5697,7 @@ namespace IGC
56975697
{
56985698
ValueToSymbolList symbolTableList;
56995699
CreateSymbolTable(symbolTableList);
5700+
ModuleMetaData* modMD = m_program->GetContext()->getModuleMetaData();
57005701

57015702
// Get the data for zebin
57025703
for (auto I : symbolTableList)
@@ -5720,10 +5721,13 @@ namespace IGC
57205721
}
57215722
// global constants and string literals
57225723
else {
5723-
Constant* initializer = G->getInitializer();
5724-
ConstantDataSequential* cds = dyn_cast<ConstantDataSequential>(initializer);
5725-
if (cds && (cds->isCString() || cds->isString()))
5724+
if (modMD->stringConstants.count(G))
5725+
{
5726+
ConstantDataSequential* cds = dyn_cast<ConstantDataSequential>(G->getInitializer());
5727+
IGC_ASSERT(cds && (cds->isCString() || cds->isString()));
5728+
(void) cds;
57265729
programSyms.globalStringConst.emplace_back((vISA::GenSymType)symbolEntry.s_type, symbolEntry.s_offset, symbolEntry.s_size, G->getName().str());
5730+
}
57275731
else
57285732
programSyms.globalConst.emplace_back((vISA::GenSymType)symbolEntry.s_type, symbolEntry.s_offset, symbolEntry.s_size, G->getName().str());
57295733
}

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,30 @@ void OpenCLPrintfAnalysis::addPrintfBufferArgs(Function& F)
8787
implicitArgs.push_back(ImplicitArg::PRINTF_BUFFER);
8888
ImplicitArgs::addImplicitArgs(F, implicitArgs, m_pMDUtils);
8989
}
90+
91+
bool OpenCLPrintfAnalysis::isTopLevelUserPrintf(llvm::Value* V)
92+
{
93+
// Recursively check the users of the value until reaching the top level
94+
// user. Note that printf has no users.
95+
96+
// Base case: return true when the current value has no user and is a call
97+
// to printf. Otherwise return false.
98+
if (V->user_empty())
99+
{
100+
if (llvm::CallInst *call = llvm::dyn_cast<llvm::CallInst>(V))
101+
{
102+
return call->getCalledFunction()->getName() ==
103+
OpenCLPrintfAnalysis::OPENCL_PRINTF_FUNCTION_NAME;
104+
}
105+
return false;
106+
}
107+
108+
// Check users recursively.
109+
for (auto user : V->users()) {
110+
if (!isTopLevelUserPrintf(user))
111+
return false;
112+
}
113+
114+
// Return true as every top level user is a printf call.
115+
return true;
116+
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ namespace IGC
5151

5252
static const llvm::StringRef OPENCL_PRINTF_FUNCTION_NAME;
5353

54+
// Return true if every top level user is a printf call. Note that the
55+
// function is expected to work only before printf is expanded.
56+
static bool isTopLevelUserPrintf(llvm::Value* V);
57+
5458
private:
5559

5660
/// @brief Adds an implicit argument for address of printf output buffer

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ SPDX-License-Identifier: MIT
99
#include "AdaptorCommon/ImplicitArgs.hpp"
1010
#include "AdaptorCommon/AddImplicitArgs.hpp"
1111
#include "Compiler/Optimizer/OpenCLPasses/ProgramScopeConstants/ProgramScopeConstantAnalysis.hpp"
12+
#include "Compiler/Optimizer/OpenCLPasses/OpenCLPrintf/OpenCLPrintfAnalysis.hpp"
1213
#include "Compiler/IGCPassSupport.h"
1314
#include "common/LLVMWarningsPush.hpp"
1415
#include <llvm/IR/Module.h>
@@ -160,11 +161,13 @@ bool ProgramScopeConstantAnalysis::runOnModule(Module& M)
160161
}
161162

162163
// When ZeBin is enabled, constant variables that are string literals
163-
// will be stored in the second const buffer
164+
// used only by printf will be stored in the second const buffer.
164165
ConstantDataSequential* cds = dyn_cast<ConstantDataSequential>(initializer);
165-
bool isStringConst = cds && (cds->isCString() || cds->isString());
166-
if (Ctx->enableZEBinary() && isStringConst)
166+
bool isPrintfOnlyStringConst = cds && (cds->isCString() || cds->isString()) &&
167+
OpenCLPrintfAnalysis::isTopLevelUserPrintf(globalVar);
168+
if (Ctx->enableZEBinary() && isPrintfOnlyStringConst)
167169
{
170+
m_pModuleMd->stringConstants.insert(globalVar);
168171
inlineProgramScopeBuffer = &m_pModuleMd->inlineConstantBuffers[1].Buffer;
169172
}
170173
else

IGC/common/MDFrameWork.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ template<typename Key, typename Value>
4343
MDNode* CreateNode(const std::map<Key, Value> &FuncMD, Module* module, StringRef name);
4444
template<typename Key, typename Value>
4545
MDNode* CreateNode(const MapVector<Key, Value> &FuncMD, Module* module, StringRef name);
46+
template<typename Key>
47+
MDNode* CreateNode(const std::set<Key> &FuncMD, Module* module, StringRef name);
4648
MDNode* CreateNode(const std::string &s, Module* module, StringRef name);
4749
MDNode* CreateNode(char* i, Module* module, StringRef name);
4850

@@ -69,6 +71,8 @@ template<typename Key, typename Value>
6971
void readNode(std::map<Key, Value> &funcMD, MDNode* node);
7072
template<typename Key, typename Value>
7173
void readNode(MapVector<Key, Value> &funcMD, MDNode* node);
74+
template<typename Key>
75+
void readNode(std::set<Key> &funcMD, MDNode* node);
7276

7377
template<typename T>
7478
void readNode(T &t, MDNode* node, StringRef name);
@@ -283,6 +287,20 @@ MDNode* CreateNode(const MapVector<Key, Value> &FuncMD, Module* module, StringRe
283287
return node;
284288
}
285289

290+
template<typename Key>
291+
MDNode* CreateNode(const std::set<Key> &FuncMD, Module* module, StringRef name)
292+
{
293+
std::vector<Metadata*> nodes;
294+
nodes.push_back(MDString::get(module->getContext(), name));
295+
int i = 0;
296+
for ( auto it = FuncMD.begin(); it != FuncMD.end(); ++it)
297+
{
298+
nodes.push_back(CreateNode(*it, module, name.str() + "Set[" + std::to_string(i) + "]"));
299+
}
300+
MDNode* node = MDNode::get(module->getContext(), nodes);
301+
return node;
302+
}
303+
286304
void readNode(unsigned char &b, MDNode* node)
287305
{
288306
ValueAsMetadata* pVal = cast<ValueAsMetadata>(node->getOperand(1));
@@ -432,6 +450,18 @@ void readNode(MapVector<Key, Value> &keyMD, MDNode* node)
432450
return;
433451
}
434452

453+
template<typename Key>
454+
void readNode(std::set<Key> &keyMD, MDNode* node)
455+
{
456+
for (unsigned k = 1; k < node->getNumOperands(); k++)
457+
{
458+
Key key;
459+
readNode(key, cast<MDNode>(node->getOperand(k)));
460+
keyMD.insert(key);
461+
}
462+
return;
463+
}
464+
435465
template<typename T>
436466
void readNode(T &t, MDNode* node, StringRef name)
437467
{

IGC/common/MDFrameWork.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ SPDX-License-Identifier: MIT
1212

1313
#include <string>
1414
#include <map>
15+
#include <set>
1516
#include <vector>
1617
#include <array>
1718
#include <optional>
@@ -640,6 +641,7 @@ namespace IGC
640641
std::map<uint32_t, std::array<uint32_t, 4>> inlineDynTextures;
641642
std::vector<InlineResInfo> inlineResInfoData;
642643
ImmConstantInfo immConstant;
644+
std::set<llvm::GlobalVariable*> stringConstants;
643645
std::vector<InlineProgramScopeBuffer> inlineConstantBuffers;
644646
std::vector<InlineProgramScopeBuffer> inlineGlobalBuffers;
645647
std::vector<PointerProgramBinaryInfo> GlobalPointerProgramBinaryInfos;

0 commit comments

Comments
 (0)