Jelajahi Sumber

Avoid constant expr from GEP create (#3046)

In SROA, we create a GEP and later expect it to be an Instruction.
However, if the indices are all constant, it will return a constant
expression, which crashes hard. By setting the flag added for just this
purpose, this is avoided.

This situation results when a second bitcast of a non POD type follows a
pair of memcpy replacements that propagate the global variable to the
bitcast operation. This test contrives a memcpy by assigning the global
to a local and then the bitcasts by passing the local into a function
call.
Greg Roth 5 tahun lalu
induk
melakukan
7fcb79be5c

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

@@ -2474,6 +2474,7 @@ void SROA_Helper::RewriteBitCast(BitCastInst *BCI) {
     idxList[i] = zeroIdx;
 
   IRBuilder<> Builder(BCI);
+  Builder.AllowFolding = false; // We need an Instruction, so make sure we don't get a constant
   Instruction *GEP = cast<Instruction>(Builder.CreateInBoundsGEP(Val, idxList));
   BCI->replaceAllUsesWith(GEP);
   BCI->eraseFromParent();

+ 36 - 0
tools/clang/test/HLSLFileCheck/passes/hl/sroa_hlsl/memcpy_gv_and_bitcast.hlsl

@@ -0,0 +1,36 @@
+// RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
+
+// Regression test for a crash that occured when a memcpy replacement
+// resulted in a global operand to a bitcast converting between inherited types
+// The texture member prevents more trivial casting
+// The three-level inheritance results in two bitcasts, one of which is the problem one
+
+// CHECK: @main
+struct A
+{
+  float4 stuff;
+};
+
+struct B : A
+{
+  Texture2D m_texture;
+  float4 gimme() {return stuff;}
+};
+
+struct C : B
+{
+  void dostuff() {stuff = 0;}
+  static C New(float4 f) { C c; c.stuff = f; return c; }
+};
+
+static const C globby = C::New(float4(1,2,3,4));
+
+float4 f(C classy) {
+  return classy.gimme();
+}
+float4 main() : SV_Target
+{
+  C loki = globby;
+  return f(loki);
+}
+