Browse Source

Not hoist when has different operand. (#2569)

Xiang Li 5 years ago
parent
commit
2b296a784e

+ 20 - 0
lib/HLSL/DxilSimpleGVNHoist.cpp

@@ -515,6 +515,26 @@ bool DxilSimpleGVNHoist::tryToHoist(BasicBlock *BB, BasicBlock *Succ0,
 
     Instruction *FirstI = Insts.front();
     if (bHoist) {
+      // When operand is different, need to hoist operand.
+      auto it = Insts.begin();
+      it++;
+      bool bHasDifferentOperand = false;
+      unsigned NumOps = FirstI->getNumOperands();
+      for (; it != Insts.end(); it++) {
+        Instruction *I = *it;
+        assert(NumOps == I->getNumOperands());
+        for (unsigned i = 0; i < NumOps; i++) {
+          if (FirstI->getOperand(i) != I->getOperand(i)) {
+            bHasDifferentOperand = true;
+            break;
+          }
+        }
+        if (bHasDifferentOperand)
+          break;
+      }
+      // TODO: hoist operands.
+      if (bHasDifferentOperand)
+        continue;
       // Move FirstI to BB.
       FirstI->removeFromParent();
       FirstI->insertBefore(TI);

+ 59 - 0
tools/clang/test/HLSLFileCheck/passes/dxil/dxil_simple_gvn_hoist/hoist_fail.hlsl

@@ -0,0 +1,59 @@
+// RUN: %dxc -Emain -T cs_6_0 %s | FileCheck %s
+
+// Make sure not crash.
+// CHECK:main
+
+cbuffer cb
+{
+    float4 p;
+    float a;
+    float b;
+};
+
+RWStructuredBuffer<uint> U0;
+
+struct Data
+{
+    float3 f;
+    uint i;
+};
+
+Data foo()
+{
+    Data d;
+    InterlockedAdd(U0[0], (uint)1);
+
+    d.f = p.z;
+
+    d.i =  p.x;
+    return d;
+}
+
+void bar()
+{
+    float c = (p.x - a) + b;
+
+    if(c > 0)
+        return;
+
+    InterlockedAdd(U0[1], (uint)1);
+}
+
+Data Update(Data d)
+{
+    if (p.z > 0)
+      d = foo();
+    else
+      bar();
+	return d;
+}
+
+RWStructuredBuffer<Data> U1;
+
+[numthreads(64, 1, 1)]
+void main(uint ID : SV_DispatchThreadID)
+{
+    Data d = U1[ID];
+    d = Update(d);
+    U1[ID] = d;
+}