Skip to content

Commit 125b272

Browse files
PiotrFusikigcbot
authored andcommitted
Fix infinite recursion in InlineLocalsResolution.
InlineLocalsResolution::traverseCGN performs depth-first traversal and caused a stack overflow on a call graph cycle.
1 parent 74aa563 commit 125b272

File tree

5 files changed

+39
-48
lines changed

5 files changed

+39
-48
lines changed

IGC/AdaptorCommon/AddImplicitArgs.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ bool BuiltinCallGraphAnalysis::runOnModule(Module &M)
528528
for (auto I = scc_begin(&CG), IE = scc_end(&CG); I != IE; ++I)
529529
{
530530
const std::vector<CallGraphNode*>& SCCNodes = *I;
531-
traveseCallGraphSCC(SCCNodes);
531+
traverseCallGraphSCC(SCCNodes);
532532
}
533533

534534
// Detect stack calls that use implicit args, and force inline them, since they are not supported
@@ -580,7 +580,7 @@ bool BuiltinCallGraphAnalysis::pruneCallGraphForStackCalls(CallGraph& CG)
580580
return changed;
581581
}
582582

583-
void BuiltinCallGraphAnalysis::traveseCallGraphSCC(const std::vector<CallGraphNode *> &SCCNodes)
583+
void BuiltinCallGraphAnalysis::traverseCallGraphSCC(const std::vector<CallGraphNode *> &SCCNodes)
584584
{
585585
// all functions in one scc should end up with the same result
586586
ImplicitArgmentDetail *argData = nullptr;

IGC/AdaptorCommon/AddImplicitArgs.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ namespace IGC
164164

165165
virtual bool runOnModule(llvm::Module &M) override;
166166

167-
void traveseCallGraphSCC(const std::vector<llvm::CallGraphNode *> &SCCNodes);
167+
void traverseCallGraphSCC(const std::vector<llvm::CallGraphNode *> &SCCNodes);
168168
void combineTwoArgDetail(ImplicitArgmentDetail&, ImplicitArgmentDetail&, llvm::Value*);
169169
void writeBackAllIntoMetaData(ImplicitArgmentDetail&, llvm::Function*);
170170

IGC/Compiler/CISACodeGen/ResolveGAS.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -951,13 +951,10 @@ namespace IGC
951951
{
952952
Function* oldFunc;
953953
GenericPointerArgs newArgs;
954-
Function* newFunc;
954+
Function* newFunc = nullptr;
955955

956-
FuncToUpdate(Function* f, GenericPointerArgs& args)
956+
FuncToUpdate(Function* f, const GenericPointerArgs& args) : oldFunc(f), newArgs(args)
957957
{
958-
oldFunc = f;
959-
newArgs = args;
960-
newFunc = nullptr;
961958
}
962959
};
963960

IGC/Compiler/Optimizer/OpenCLPasses/LocalBuffers/InlineLocalsResolution.cpp

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -124,19 +124,17 @@ bool InlineLocalsResolution::runOnModule(Module& M)
124124

125125
LLVMContext& C = M.getContext();
126126

127-
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
127+
for (Function& F : M)
128128
{
129-
Function* pFunc = &(*I);
130-
131-
if (pFunc->isDeclaration() || !isEntryFunc(pMdUtils, pFunc))
129+
if (F.isDeclaration() || !isEntryFunc(pMdUtils, &F))
132130
{
133131
continue;
134132
}
135133

136134
unsigned int totalSize = 0;
137135

138136
// Get the offset at which local arguments start
139-
auto sizeIter = sizeMap.find(pFunc);
137+
auto sizeIter = sizeMap.find(&F);
140138
if (sizeIter != sizeMap.end())
141139
{
142140
totalSize += sizeIter->second;
@@ -146,7 +144,7 @@ bool InlineLocalsResolution::runOnModule(Module& M)
146144
totalSize = (totalSize & 0xFFFF);
147145

148146
bool IsFirstSLMArgument = true;
149-
for (Function::arg_iterator A = pFunc->arg_begin(), AE = pFunc->arg_end(); A != AE; ++A)
147+
for (Function::arg_iterator A = F.arg_begin(), AE = F.arg_end(); A != AE; ++A)
150148
{
151149
Argument* arg = &(*A);
152150
PointerType* ptrType = dyn_cast<PointerType>(arg->getType());
@@ -176,15 +174,15 @@ bool InlineLocalsResolution::runOnModule(Module& M)
176174
if (IsFirstSLMArgument) {
177175
auto BufType = ArrayType::get(Type::getInt8Ty(M.getContext()), 0);
178176
auto ExtSLM = new GlobalVariable(M, BufType, false, GlobalVariable::ExternalLinkage, nullptr,
179-
pFunc->getName() + "-ExtSLM", nullptr, GlobalVariable::ThreadLocalMode::NotThreadLocal,
177+
F.getName() + "-ExtSLM", nullptr, GlobalVariable::ThreadLocalMode::NotThreadLocal,
180178
ADDRESS_SPACE_LOCAL);
181179
auto NewPtr = ConstantExpr::getBitCast(ExtSLM, arg->getType());
182180
arg->replaceAllUsesWith(NewPtr);
183181
// Update MD.
184182
LocalOffsetMD localOffset;
185183
localOffset.m_Var = ExtSLM;
186184
localOffset.m_Offset = Offset;
187-
modMD->FuncMD[pFunc].localOffsets.push_back(localOffset);
185+
modMD->FuncMD[&F].localOffsets.push_back(localOffset);
188186

189187
IGC::appendToUsed(M, ExtSLM);
190188
IsFirstSLMArgument = false;
@@ -197,7 +195,7 @@ bool InlineLocalsResolution::runOnModule(Module& M)
197195
// Bitcast to i8*, GEP, bitcast back to original type.
198196
Value* sizeConstant = ConstantInt::get(Type::getInt32Ty(C), Offset);
199197
SmallVector<Value*, 1> idx(1, sizeConstant);
200-
Instruction* pInsertBefore = &(*pFunc->begin()->getFirstInsertionPt());
198+
Instruction* pInsertBefore = &(*F.begin()->getFirstInsertionPt());
201199
Type* pLocalCharPtrType = Type::getInt8Ty(C)->getPointerTo(ADDRESS_SPACE_LOCAL);
202200
Instruction* pCharPtr = BitCastInst::CreatePointerCast(arg, pLocalCharPtrType, "localToChar", pInsertBefore);
203201
Value* pMovedCharPtr = GetElementPtrInst::Create(nullptr, pCharPtr, idx, "movedLocal", pInsertBefore);
@@ -346,15 +344,15 @@ void InlineLocalsResolution::collectInfoOnSharedLocalMem(Module& M)
346344

347345
// scan inst to collect all call instructions
348346

349-
for (Module::iterator F = M.begin(), FE = M.end(); F != FE; ++F)
347+
for (Function& F : M)
350348
{
351-
if (F->isDeclaration())
349+
if (F.isDeclaration())
352350
{
353351
continue;
354352
}
355353

356354
unsigned maxBytesOnFunc = 0;
357-
for (auto I = inst_begin(&(*F)), IE = inst_end(&(*F)); I != IE; ++I)
355+
for (auto I = inst_begin(&F), IE = inst_end(&F); I != IE; ++I)
358356
{
359357
Instruction* inst = &(*I);
360358
if (CallInst * CI = dyn_cast<CallInst>(inst))
@@ -389,7 +387,7 @@ void InlineLocalsResolution::collectInfoOnSharedLocalMem(Module& M)
389387
}
390388
if (maxBytesOnFunc != 0)
391389
{
392-
m_FuncToMemPoolSizeMap[&(*F)] = maxBytesOnFunc;
390+
m_FuncToMemPoolSizeMap[&F] = maxBytesOnFunc;
393391
}
394392
}
395393

@@ -467,7 +465,7 @@ void InlineLocalsResolution::collectInfoOnSharedLocalMem(Module& M)
467465
}
468466

469467
// set debugging info, and insert mov inst.
470-
IF_DEBUG_INFO(for (auto I : m_FuncToVarsMap))
468+
IF_DEBUG_INFO(for (const auto& I : m_FuncToVarsMap))
471469
{
472470
IF_DEBUG_INFO(Function * userFunc = I.first;)
473471
IF_DEBUG_INFO(for (auto G : I.second))
@@ -492,18 +490,18 @@ void InlineLocalsResolution::computeOffsetList(Module& M, std::map<Function*, un
492490
return;
493491
}
494492

495-
// let's travese the CallGraph to calculate the local
493+
// let's traverse the CallGraph to calculate the local
496494
// variables of kernel from all user functions.
497495
m_chkSet.clear();
498496
for (auto& N : CG)
499497
{
500498
Function* f = N.second->getFunction();
501499
if (!f || f->isDeclaration() || m_chkSet.find(f) != m_chkSet.end()) continue;
502-
traveseCGN(*N.second);
500+
traverseCGN(*N.second);
503501
}
504502

505503
// set up the offsetMap;
506-
for (auto I : m_FuncToVarsMap)
504+
for (const auto& I : m_FuncToVarsMap)
507505
{
508506
Function* F = I.first;
509507

@@ -538,16 +536,16 @@ void InlineLocalsResolution::computeOffsetList(Module& M, std::map<Function*, un
538536
}
539537

540538
// Ok, we've collected the information, now write it into the MD.
541-
for (auto iter = sizeMap.begin(), end = sizeMap.end(); iter != end; ++iter)
539+
for (auto& iter : sizeMap)
542540
{
543541
// ignore non-entry functions.
544-
if (!isEntryFunc(pMdUtils, iter->first))
542+
if (!isEntryFunc(pMdUtils, iter.first))
545543
{
546544
continue;
547545
}
548546

549547
// If this function doesn't have any locals, no need for MD.
550-
if (iter->second == 0)
548+
if (iter.second == 0)
551549
{
552550
continue;
553551
}
@@ -557,32 +555,35 @@ void InlineLocalsResolution::computeOffsetList(Module& M, std::map<Function*, un
557555
// we are going to have inline parameters. So, we need to make sure the
558556
// first local parameter is appropriately aligned, which, at worst,
559557
// can be 256 bits.
560-
iter->second = iSTD::Align(iter->second, 32);
558+
iter.second = iSTD::Align(iter.second, 32);
561559

562560
// Add the size information of this function
563-
modMD->FuncMD[iter->first].localSize = iter->second;
561+
modMD->FuncMD[iter.first].localSize = iter.second;
564562

565563
// And now the offsets.
566-
for (auto offsetIter = offsetMap[iter->first].begin(), offsetEnd = offsetMap[iter->first].end(); offsetIter != offsetEnd; ++offsetIter)
564+
for (const auto& offsetIter : offsetMap[iter.first])
567565
{
568-
unsigned Offset = offsetIter->second;
569-
if (!useAsPointerOnly(offsetIter->first))
566+
unsigned Offset = offsetIter.second;
567+
if (!useAsPointerOnly(offsetIter.first))
570568
Offset |= VALID_LOCAL_HIGH_BITS;
571569

572570
LocalOffsetMD localOffset;
573-
localOffset.m_Var = offsetIter->first;
571+
localOffset.m_Var = offsetIter.first;
574572
localOffset.m_Offset = Offset;
575-
modMD->FuncMD[iter->first].localOffsets.push_back(localOffset);
573+
modMD->FuncMD[iter.first].localOffsets.push_back(localOffset);
576574
}
577575
}
578576
pMdUtils->save(M.getContext());
579577
}
580578

581-
void InlineLocalsResolution::traveseCGN(llvm::CallGraphNode& CGN)
579+
void InlineLocalsResolution::traverseCGN(const llvm::CallGraphNode& CGN)
582580
{
583581
Function* f = CGN.getFunction();
584582

585-
for (auto N : CGN)
583+
// mark this function
584+
m_chkSet.insert(f);
585+
586+
for (const auto& N : CGN)
586587
{
587588
Function* sub = N.second->getFunction();
588589
if (!sub || sub->isDeclaration()) continue;
@@ -592,18 +593,15 @@ void InlineLocalsResolution::traveseCGN(llvm::CallGraphNode& CGN)
592593
{
593594
// this sub-routine is not visited before.
594595
// visit it first
595-
traveseCGN(*N.second);
596+
traverseCGN(*N.second);
596597
}
597598

598599
// the sub-routine was visited before, collect information
599600

600601
// count each global on this sub-routine
601602
GlobalVariableSet& GS_f = m_FuncToVarsMap[f];
602-
GlobalVariableSet& GS_sub = m_FuncToVarsMap[sub];
603-
for (auto I = GS_sub.begin(); I != GS_sub.end(); ++I)
604-
{
605-
GS_f.insert(*I);
606-
}
603+
const GlobalVariableSet& GS_sub = m_FuncToVarsMap[sub];
604+
GS_f.insert(GS_sub.begin(), GS_sub.end());
607605

608606
// automatic storages
609607
if (m_FuncToMemPoolSizeMap.find(sub) != m_FuncToMemPoolSizeMap.end())
@@ -620,8 +618,4 @@ void InlineLocalsResolution::traveseCGN(llvm::CallGraphNode& CGN)
620618
}
621619
}
622620
}
623-
624-
// mark this function
625-
626-
m_chkSet.insert(f);
627621
}

IGC/Compiler/Optimizer/OpenCLPasses/LocalBuffers/InlineLocalsResolution.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ namespace IGC
8888
bool unusedGlobal(llvm::Value* V, std::unordered_set<llvm::Value*>& unusedNodes);
8989
void collectInfoOnSharedLocalMem(llvm::Module&);
9090
void computeOffsetList(llvm::Module&, std::map<llvm::Function*, unsigned int>&);
91-
void traveseCGN(llvm::CallGraphNode&);
91+
void traverseCGN(const llvm::CallGraphNode&);
9292

9393
private:
9494

0 commit comments

Comments
 (0)