瀏覽代碼

Fix crash when assigning to global matrix in compat mode (#1709)

* An earlier bitcast instruction would create an unused GEP instruction referencing the matrix, which the matrix lowering code couldn't handle. Removed that GEP.
* A special case for single-index matrix access was probably meant to catch `m._11` and assumed a value type of float, but it also applied to the first subscript of `m[0][0]`, which returns `floatn`, hence a crash due to mismatched types. The condition was updated to test for non-vector values.
Tristan Labelle 6 年之前
父節點
當前提交
a69864789d

+ 3 - 3
lib/HLSL/HLMatrixLowerPass.cpp

@@ -1793,9 +1793,10 @@ void HLMatrixLowerPass::TranslateMatSubscriptOnGlobalPtr(
 
   // Cannot generate vector pointer
   // Replace all uses with scalar pointers.
-  if (idxList.size() == 1) {
+  if (!matSubInst->getType()->getPointerElementType()->isVectorTy()) {
+    DXASSERT(idxList.size() == 1, "Expected a single matrix element index if the result is not a vector");
     Value *Ptr =
-        subBuilder.CreateInBoundsGEP(vecPtr, {zeroIdx, idxList[0]});
+      subBuilder.CreateInBoundsGEP(vecPtr, { zeroIdx, idxList[0] });
     matSubInst->replaceAllUsesWith(Ptr);
   } else {
     // Split the use of CI with Ptrs.
@@ -2347,7 +2348,6 @@ void HLMatrixLowerPass::runOnGlobalMatrixArray(GlobalVariable *GV) {
     HLModule::UpdateGlobalVariableDebugInfo(GV, Finder, VecGV);
   }
 
-  DenseMap<Instruction *, Value *> matToVecMap;
   for (User *U : GV->users()) {
     Value *VecGEP = nullptr;
     // Must be GEP or GEPOperator.

+ 11 - 0
tools/clang/lib/CodeGen/CGHLSLMS.cpp

@@ -4018,7 +4018,9 @@ static void SimplifyBitCast(BitCastOperator *BC, SmallInstSet &deadInsts) {
 
   FromTy = FromTy->getPointerElementType();
   ToTy = ToTy->getPointerElementType();
+
   // Take care case like %2 = bitcast %struct.T* %1 to <1 x float>*.
+  bool GEPCreated = false;
   if (FromTy->isStructTy()) {
     IRBuilder<> Builder(FromTy->getContext());
     if (Instruction *I = dyn_cast<Instruction>(BC))
@@ -4032,6 +4034,7 @@ static void SimplifyBitCast(BitCastOperator *BC, SmallInstSet &deadInsts) {
     }
     std::vector<Value *> idxList(nestLevel, zeroIdx);
     Ptr = Builder.CreateGEP(Ptr, idxList);
+    GEPCreated = true;
   }
 
   for (User *U : BC->users()) {
@@ -4059,6 +4062,14 @@ static void SimplifyBitCast(BitCastOperator *BC, SmallInstSet &deadInsts) {
       DXASSERT(0, "not support yet");
     }
   }
+
+  // We created a GEP instruction but didn't end up consuming it, so delete it.
+  if (GEPCreated && Ptr->use_empty()) {
+    if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr))
+      GEP->eraseFromParent();
+    else
+      cast<Constant>(Ptr)->destroyConstant();
+  }
 }
 
 typedef float(__cdecl *FloatUnaryEvalFuncType)(float);

+ 33 - 14
tools/clang/test/CodeGenHLSL/quick-test/global-var-write-test01.hlsl

@@ -6,41 +6,60 @@
 
 float g_s;
 float4 g_v = float4(1.0, -1.0, 0.0, 1.0);
-// TODO: writing to a global matrix currently causes the compiler to crash. fix it.
-// int2x2 g_m;
+int2x2 g_m;
+row_major int2x2 g_m_rm;
+int2x2 g_m2;
 bool g_b = false;
 int g_a[5];
 int g_a2d[3][2];
-float4 main(uint a
-            : A) : SV_Target {
+int2x2 g_ma[4];
+
+float4 main(uint a : A) : SV_Target {
   // update global scalar
   g_s = a;
 
   // update global vector
   g_v = float4(a + 1, a + 2, a + 3, a + 4);
 
-  /*
   // update global matrix
   for (uint i = 0; i < 2; i++)
     for (uint j = 0; j < 2; j++)
       g_m[i][j] = a + i + j;
-  */
-  
-  // update global 2d array
-  for (uint i = 0; i < 3; i++)
+      
+  // update global row_major matrix
+  for (uint i = 0; i < 2; i++)
     for (uint j = 0; j < 2; j++)
-      g_a2d[i][j] = a + i + j;
+      g_m_rm[i][j] = a + i + j;
+
+  // update global matrix through element access
+  g_m2._11 = a;
+  g_m2._12_21 = float2(a, a + 1);
+  g_m2._21_22 = a + 3;
+
+  // update global boolean
+  g_b = true;
 
   // update global array
   for (uint i = 0; i < 5; i++)
     g_a[i] = a + i;
+  
+  // update global 2d array
+  for (uint i = 0; i < 3; i++)
+    for (uint j = 0; j < 2; j++)
+      g_a2d[i][j] = a + i + j;
 
-  // update global boolean
-  g_b = true;
+  // update global matrix array
+  for (uint i = 0; i < 4; i++)
+    for (uint j = 0; j < 2; j++)
+      for (uint k = 0; k < 2; k++)
+        g_ma[i][j][k] = a + i + j;
 
   return float4(g_s, g_s, g_s, g_s) +
          g_v +
-         // float4(g_m[0][0], g_m[0][1], g_m[1][0], g_m[1][1]) +
+         float4(g_m[0][0], g_m[0][1], g_m[1][0], g_m[1][1]) +
+         float4(g_m_rm[0][0], g_m_rm[0][1], g_m_rm[1][0], g_m_rm[1][1]) +
+         float4(g_m2._11, g_m2._12, g_m2._21_22) +
+         float4(g_a[0], g_a[1], g_a[2], g_a[3]) +
          float4(g_a2d[0][0], g_a2d[0][1], g_a2d[1][0], g_a2d[1][1]) +
-         float4(g_a[0], g_a[1], g_a[2], g_a[3]);
+         float4(g_ma[0][0][0], g_ma[1][0][1], g_ma[2][1][0], g_ma[3][1][1]);
 }