ソースを参照

Erase dx.break call instruction when replaced (#2867)

After replacing an unneeded call to dx.break with a constant, the call
instruction remained. This removes it when it is replaced entirely.
Greg Roth 5 年 前
コミット
a9f1342d28

+ 2 - 1
lib/HLSL/DxilPreparePasses.cpp

@@ -633,7 +633,7 @@ private:
   // Convert all uses of dx.break() into per-function load/cmp of dx.break.cond global constant
   void LowerDxBreak(Module &M) {
     if (Function *BreakFunc = M.getFunction(DXIL::kDxBreakFuncName)) {
-      if (BreakFunc->getNumUses()) {
+      if (!BreakFunc->use_empty()) {
         llvm::Type *i32Ty = llvm::Type::getInt32Ty(M.getContext());
         Type *i32ArrayTy = ArrayType::get(i32Ty, 1);
         unsigned int Values[1] = { 0 };
@@ -1186,6 +1186,7 @@ public:
     for (auto &BB : BreakBBs) {
       // Replace the call instruction with a constant boolen
       BB.second->replaceAllUsesWith(C);
+      BB.second->eraseFromParent();
       Changed = true;
     }
     return Changed;

+ 24 - 0
tools/clang/test/HLSLFileCheck/hlsl/intrinsics/wave/reduction/WaveAndEmptyBreak.hlsl

@@ -0,0 +1,24 @@
+// RUN: %dxc -T cs_6_0 %s | FileCheck %s
+
+// Test a case that might appear to require dx.break, but ultimately does not.
+// CHECK-NOT: dx.break
+
+RWStructuredBuffer<uint> u0;
+Texture1D<uint> t0;
+SamplerComparisonState  s0;
+[RootSignature("DescriptorTable(SRV(t0), UAV(u0)), DescriptorTable(Sampler(s0))")]
+[numthreads(64, 1, 1)]
+void main(uint GI : SV_GroupIndex)
+{
+    uint RetMask;
+    uint GIKey = t0[GI];
+    uint Mask = t0[GI+1];
+    for ( ;; )
+    {
+        const uint FirstKey = WaveReadLaneFirst(GIKey);
+
+        RetMask = WaveReadLaneAt(Mask, FirstKey);
+        if (FirstKey == GIKey) break;
+    }
+    u0[GI] = RetMask.x;
+}