فهرست منبع

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);
         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();
         }
       }