浏览代码

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.
Greg Roth 5 年之前
父节点
当前提交
9007354c61
共有 1 个文件被更改,包括 19 次插入11 次删除
  1. 19 11
      lib/HLSL/DxilPreparePasses.cpp

+ 19 - 11
lib/HLSL/DxilPreparePasses.cpp

@@ -647,19 +647,27 @@ private:
         Constant *Gep = ConstantExpr::getGetElementPtr(nullptr, GV, Indices);
         Constant *Gep = ConstantExpr::getGetElementPtr(nullptr, GV, Indices);
         SmallDenseMap<llvm::Function*, llvm::ICmpInst*, 16> DxBreakCmpMap;
         SmallDenseMap<llvm::Function*, llvm::ICmpInst*, 16> DxBreakCmpMap;
         // Replace all uses of dx.break with references to the constant global
         // 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);
           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();
           CI->eraseFromParent();
         }
         }
       }
       }