Browse Source

Fixed a bug where nested LCSSA creation uses wrong body for outer loops. (#2105)

Adam Yang 6 years ago
parent
commit
345b8b5743

+ 2 - 1
lib/Transforms/Scalar/DxilLoopUnroll.cpp

@@ -372,7 +372,8 @@ static bool processInstruction(SetVector<BasicBlock *> &Body, Loop &L, Instructi
     // Recurse and re-process each PHI instruction. FIXME: we should really
     // Recurse and re-process each PHI instruction. FIXME: we should really
     // convert this entire thing to a worklist approach where we process a
     // convert this entire thing to a worklist approach where we process a
     // vector of instructions...
     // vector of instructions...
-    processInstruction(Body, *OtherLoop, *I, DT, EBs, PredCache, LI);
+    SetVector<BasicBlock *> OtherLoopBody(OtherLoop->block_begin(), OtherLoop->block_end()); // HLSL Change
+    processInstruction(OtherLoopBody, *OtherLoop, *I, DT, EBs, PredCache, LI);
   }
   }
 
 
   // Remove PHI nodes that did not have any uses rewritten.
   // Remove PHI nodes that did not have any uses rewritten.

+ 57 - 0
tools/clang/test/CodeGenHLSL/batch/unroll/nested_lcssa_1.hlsl

@@ -0,0 +1,57 @@
+// RUN: %dxc -E main -T cs_6_0 %s | FileCheck %s
+
+// CHECK: @main
+
+// Regression test for a validation error caused by nested LCSSA formation uses
+// the wrong set of blocks when constructing LCSSA PHI's for a parent loop. This
+// causes wrong assumptions to be made about which users are actually in the
+// loop.
+
+// [unroll] on both loops causes validator failure with uninitialized value
+// when reading problemValue after the early conditional return.
+// error: validation errors
+// Instructions should not read uninitialized value
+
+float g_float;
+RWTexture2D<float4> g_Output;
+
+float doStuff()
+{
+  float res = 0;
+  float problemValue = 0;
+  float sum = 0.0f;
+
+  [unroll]
+  for (uint i = 0; i < 3; ++i)
+  {
+    sum += g_float;
+  }
+
+  if (0.0 == sum)
+  {
+    return 0; // early conditional return that causes issue
+  }
+
+  problemValue = 1.0f * sum;
+
+  [unroll]
+  for (uint j = 0; j < 3; ++j)
+  {
+    res += g_float;
+  }
+
+  res *= problemValue;
+  return res;
+}
+
+[numthreads(8, 8, 1)]
+void main(uint2 tid : SV_DispatchThreadID)
+{
+  float res = 0;
+  for (uint i = 0; i < 1; ++i)
+  {
+    res = doStuff();
+  }
+  g_Output[tid] = res;
+}
+

+ 29 - 0
tools/clang/test/CodeGenHLSL/batch/unroll/nested_lcssa_2.hlsl

@@ -0,0 +1,29 @@
+// RUN: %dxc -E main -T vs_6_0 %s | FileCheck %s
+
+// CHECK: @main
+
+// Regression test for a validation error caused by nested LCSSA formation uses
+// the wrong set of blocks when constructing LCSSA PHI's for a parent loop. This
+// causes wrong assumptions to be made about which users are actually in the
+// loop.
+
+float bilinearWeights;
+float2 main() : OUT {
+    float2 output = float2(0.0f,0);
+    for(uint sampleIdx = 0; sampleIdx < 1; ++sampleIdx) {
+        float totalWeight = 0.0f;
+
+        [unroll]
+        for(uint i = 0; i < 1; ++i) {
+            totalWeight += bilinearWeights;
+        }
+
+        float2 occlusion = float2(1.0f, 0);
+        if(totalWeight > 0.0f)
+            occlusion = 1 / totalWeight;
+
+        output += occlusion;
+    }
+
+    return output;
+}