Ver Fonte

Fix SROA bug when lowering a memcpy from a cbuffer

There was already code to detect memcpy with cbuffer sources, but they only accounted for one level of GEP indirection. In the presence of complex nested structs and arrays, this might not be the case, so I extended it to support arbitrary GEP nesting.
Tristan Labelle há 6 anos atrás
pai
commit
6639fc88f6

+ 3 - 0
lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp

@@ -4108,6 +4108,9 @@ bool SROA_Helper::LowerMemcpy(Value *V, DxilFieldAnnotation *annotation,
           // For GEP, the ptr could have other GEP read/write.
           // For GEP, the ptr could have other GEP read/write.
           // Only scan one GEP is not enough.
           // Only scan one GEP is not enough.
           Value *Ptr = GEP->getPointerOperand();
           Value *Ptr = GEP->getPointerOperand();
+          while (GEPOperator *NestedGEP = dyn_cast<GEPOperator>(Ptr))
+            Ptr = NestedGEP->getPointerOperand();
+
           if (CallInst *PtrCI = dyn_cast<CallInst>(Ptr)) {
           if (CallInst *PtrCI = dyn_cast<CallInst>(Ptr)) {
             hlsl::HLOpcodeGroup group =
             hlsl::HLOpcodeGroup group =
                 hlsl::GetHLOpcodeGroup(PtrCI->getCalledFunction());
                 hlsl::GetHLOpcodeGroup(PtrCI->getCalledFunction());

+ 14 - 0
tools/clang/test/CodeGenHLSL/quick-test/sroa_memcpy_from_cbuf_nested_field.hlsl

@@ -0,0 +1,14 @@
+// RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
+
+// Regression test for a crash in SROA when replacing a memcpy
+// whose source is a CBuffer value at a deep nesting level (multiple GEPs).
+
+// CHECK: ret void
+
+struct A { float f1[1]; };
+struct B { A a1[1]; };
+struct C { B b; };
+float one(B b) { return 1; }
+B getB(C c) { return c.b; }
+cbuffer CB { C g_c; }
+float main() : SV_Target { return one(getB(g_c)); }