Account for non-one user of dx.break call (#2802)

* Account for non-one user of dx.break call

The original code expected that optimizations wouldn't remove any of the
users of a call to dx.break(). In loop unrolling cases, simplifyCFG may
do just that, which caused the original assert and assume we're right
method to break.

Now we assert we're in the confines of what is now known to be possible,
but we don't assume anything. There's a loop over the users of the call
instruction that I only ever expect to be executed once or never, but
it's there just in case.
This commit is contained in:
Greg Roth 2020-03-31 18:15:52 -07:00 коммит произвёл GitHub
Родитель d3af7f1237
Коммит 9007354c61
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
1 изменённых файлов: 19 добавлений и 11 удалений

Просмотреть файл

@ -647,19 +647,27 @@ private:
Constant *Gep = ConstantExpr::getGetElementPtr(nullptr, GV, Indices);
SmallDenseMap<llvm::Function*, llvm::ICmpInst*, 16> DxBreakCmpMap;
// Replace all uses of dx.break with references to the constant global
for (User *U : BreakFunc->users()) {
DXASSERT(U->hasOneUse() && isa<CallInst>(U), "User of dx.break function isn't call or has multiple users");
BranchInst *BI = cast<BranchInst>(*U->user_begin());
for (auto I = BreakFunc->user_begin(), E = BreakFunc->user_end(); I != E;) {
User *U = *I++;
CallInst *CI = cast<CallInst>(U);
Function *F = BI->getParent()->getParent();
ICmpInst *Cmp = DxBreakCmpMap.lookup(F);
if (!Cmp) {
BasicBlock &EntryBB = F->getEntryBlock();
LoadInst *LI = new LoadInst(Gep, nullptr, false, EntryBB.getTerminator());
Cmp = new ICmpInst(EntryBB.getTerminator(), ICmpInst::ICMP_EQ, LI, llvm::ConstantInt::get(i32Ty,0));
DxBreakCmpMap.insert(std::make_pair(F, Cmp));
// SimplifyCFG might have removed our user
DXASSERT(U->getNumUses() <= 1,
"User of dx.break function has multiple users");
// In spite of the <=1 assert above, loop here in case the assumption is wrong
for (auto II = U->user_begin(), EE = U->user_end(); II != EE;) {
User *UU = *II++;
BranchInst *BI = cast<BranchInst>(UU);
Function *F = BI->getParent()->getParent();
ICmpInst *Cmp = DxBreakCmpMap.lookup(F);
if (!Cmp) {
BasicBlock &EntryBB = F->getEntryBlock();
LoadInst *LI = new LoadInst(Gep, nullptr, false, EntryBB.getTerminator());
Cmp = new ICmpInst(EntryBB.getTerminator(), ICmpInst::ICMP_EQ, LI, llvm::ConstantInt::get(i32Ty,0));
DxBreakCmpMap.insert(std::make_pair(F, Cmp));
}
BI->setCondition(Cmp);
}
BI->setCondition(Cmp);
CI->eraseFromParent();
}
}