Browse Source

[spirv] Fix type cast array to vector bug

Without this CL, type casting array to vector generates multiple
redundant expressions. For example, type casting array return value
of a function call to vector generates multiple duplicated function
call expressions, which must be actually a single function call. It
is because InitListHandler generates multiple Expr from the same
Expr. This CL updates InitListHandler not to generate redundant Expr.
Jaebaek Seo 6 years ago
parent
commit
6060ab0544

+ 46 - 56
tools/clang/lib/SPIRV/InitListHandler.cpp

@@ -44,7 +44,7 @@ SpirvInstruction *InitListHandler::processCast(QualType toType,
   initializers.clear();
   scalars.clear();
 
-  initializers.push_back(expr);
+  initializers.push_back(theEmitter.loadIfGLValue(expr));
 
   return doProcess(toType, expr->getExprLoc());
 }
@@ -76,22 +76,20 @@ void InitListHandler::flatten(const InitListExpr *expr) {
                    init->IgnoreParenNoopCasts(theEmitter.getASTContext()))) {
       flatten(subInitList);
     } else {
-      initializers.push_back(init);
+      initializers.push_back(theEmitter.loadIfGLValue(init));
     }
   }
 }
 
-void InitListHandler::decompose(const Expr *expr) {
-  const QualType type = expr->getType();
+void InitListHandler::decompose(SpirvInstruction *inst) {
+  const QualType type = inst->getAstResultType();
 
   if (hlsl::IsHLSLVecType(type)) {
-    auto *vec = theEmitter.loadIfGLValue(expr);
     const QualType elemType = hlsl::GetHLSLVecElementType(type);
     const auto size = hlsl::GetHLSLVecSize(type);
 
-    decomposeVector(vec, elemType, size);
+    decomposeVector(inst, elemType, size);
   } else if (hlsl::IsHLSLMatType(type)) {
-    auto *mat = theEmitter.loadIfGLValue(expr);
     const QualType elemType = hlsl::GetHLSLMatElementType(type);
 
     uint32_t rowCount = 0, colCount = 0;
@@ -99,12 +97,12 @@ void InitListHandler::decompose(const Expr *expr) {
 
     if (rowCount == 1 || colCount == 1) {
       // This also handles the scalar case
-      decomposeVector(mat, elemType, rowCount == 1 ? colCount : rowCount);
+      decomposeVector(inst, elemType, rowCount == 1 ? colCount : rowCount);
     } else {
       for (uint32_t i = 0; i < rowCount; ++i)
         for (uint32_t j = 0; j < colCount; ++j) {
           auto *element =
-              spvBuilder.createCompositeExtract(elemType, mat, {i, j});
+              spvBuilder.createCompositeExtract(elemType, inst, {i, j});
           scalars.emplace_back(element, elemType);
         }
     }
@@ -130,8 +128,8 @@ bool InitListHandler::tryToSplitStruct() {
   if (initializers.empty())
     return false;
 
-  auto *init = const_cast<Expr *>(initializers.back());
-  const QualType initType = init->getType();
+  auto *init = initializers.back();
+  const QualType initType = init->getAstResultType();
   if (!initType->isStructureType() ||
       // Sampler types will pass the above check but we cannot split it.
       isSampler(initType))
@@ -140,19 +138,16 @@ bool InitListHandler::tryToSplitStruct() {
   // We are certain the current intializer will be replaced by now.
   initializers.pop_back();
 
-  const auto &context = theEmitter.getASTContext();
   const auto *structDecl = initType->getAsStructureType()->getDecl();
 
   // Create MemberExpr for each field of the struct
-  llvm::SmallVector<const Expr *, 4> fields;
+  llvm::SmallVector<SpirvInstruction *, 4> fields;
+  uint32_t i = 0;
   for (auto *field : structDecl->fields()) {
-    fields.push_back(MemberExpr::Create(
-        context, init, /*isarraw*/ false, /*OperatorLoc*/ {},
-        /*QualifierLoc*/ {}, /*TemplateKWLoc*/ {}, field,
-        DeclAccessPair::make(field, AS_none),
-        DeclarationNameInfo(field->getDeclName(), /*NameLoc*/ {}),
-        /*TemplateArgumentListInfo*/ nullptr, field->getType(),
-        init->getValueKind(), OK_Ordinary));
+    auto *extract =
+        spvBuilder.createCompositeExtract(field->getType(), init, {i});
+    fields.push_back(extract);
+    ++i;
   }
 
   // Push in the reverse order
@@ -165,8 +160,8 @@ bool InitListHandler::tryToSplitConstantArray() {
   if (initializers.empty())
     return false;
 
-  auto *init = const_cast<Expr *>(initializers.back());
-  const QualType initType = init->getType();
+  auto *init = initializers.back();
+  const QualType initType = init->getAstResultType();
   if (!initType->isConstantArrayType())
     return false;
 
@@ -174,7 +169,6 @@ bool InitListHandler::tryToSplitConstantArray() {
   initializers.pop_back();
 
   const auto &context = theEmitter.getASTContext();
-  const auto u32Type = context.getIntTypeForBitwidth(32, /*sigined*/ 0);
 
   const auto *arrayType = context.getAsConstantArrayType(initType);
   const auto elemType = arrayType->getElementType();
@@ -184,14 +178,10 @@ bool InitListHandler::tryToSplitConstantArray() {
   // Create ArraySubscriptExpr for each element of the array
   // TODO: It will generate lots of elements if the array size is very large.
   // But do we have a better solution?
-  llvm::SmallVector<const Expr *, 4> elements;
+  llvm::SmallVector<SpirvInstruction *, 4> elements;
   for (uint32_t i = 0; i < size; ++i) {
-    const auto iVal =
-        llvm::APInt(/*numBits*/ 32, uint64_t(i), /*isSigned*/ false);
-    auto *index = IntegerLiteral::Create(context, iVal, u32Type, {});
-    const auto *element = new (context)
-        ArraySubscriptExpr(init, index, elemType, VK_LValue, OK_Ordinary, {});
-    elements.push_back(element);
+    auto *extract = spvBuilder.createCompositeExtract(elemType, init, {i});
+    elements.push_back(extract);
   }
 
   // Push in the reverse order
@@ -251,16 +241,15 @@ InitListHandler::createInitForBuiltinType(QualType type,
   while (tryToSplitStruct() || tryToSplitConstantArray())
     ;
 
-  const Expr *init = initializers.back();
+  auto *init = initializers.back();
   initializers.pop_back();
 
-  if (!init->getType()->isBuiltinType()) {
+  if (!init->getAstResultType()->isBuiltinType()) {
     decompose(init);
     return createInitForBuiltinType(type, srcLoc);
   }
 
-  auto *value = theEmitter.loadIfGLValue(init);
-  return theEmitter.castToType(value, init->getType(), type, srcLoc);
+  return theEmitter.castToType(init, init->getAstResultType(), type, srcLoc);
 }
 
 SpirvInstruction *
@@ -275,10 +264,10 @@ InitListHandler::createInitForVectorType(QualType elemType, uint32_t count,
     while (tryToSplitStruct() || tryToSplitConstantArray())
       ;
 
-    const Expr *init = initializers.back();
+    auto *init = initializers.back();
 
-    if (hlsl::IsHLSLVecType(init->getType()) &&
-        hlsl::GetHLSLVecSize(init->getType()) == count) {
+    if (hlsl::IsHLSLVecType(init->getAstResultType()) &&
+        hlsl::GetHLSLVecSize(init->getAstResultType()) == count) {
       initializers.pop_back();
       /// HLSL vector types are parameterized templates and we cannot
       /// construct them. So we construct an ExtVectorType here instead.
@@ -286,8 +275,8 @@ InitListHandler::createInitForVectorType(QualType elemType, uint32_t count,
       /// in all type casting methods in SpirvEmitter.
       const auto toVecType =
           theEmitter.getASTContext().getExtVectorType(elemType, count);
-      return theEmitter.castToType(theEmitter.loadIfGLValue(init),
-                                   init->getType(), toVecType, srcLoc);
+      return theEmitter.castToType(init, init->getAstResultType(), toVecType,
+                                   srcLoc);
     }
   }
 
@@ -321,17 +310,18 @@ InitListHandler::createInitForMatrixType(QualType matrixType,
     while (tryToSplitStruct() || tryToSplitConstantArray())
       ;
 
-    const Expr *init = initializers.back();
+    auto *init = initializers.back();
 
-    if (hlsl::IsHLSLMatType(init->getType())) {
+    if (hlsl::IsHLSLMatType(init->getAstResultType())) {
       uint32_t initRowCount = 0, initColCount = 0;
-      hlsl::GetHLSLMatRowColCount(init->getType(), initRowCount, initColCount);
+      hlsl::GetHLSLMatRowColCount(init->getAstResultType(), initRowCount,
+                                  initColCount);
 
       if (rowCount == initRowCount && colCount == initColCount) {
         initializers.pop_back();
         // TODO: We only support FP matrices now. Do type cast here after
         // adding more matrix types.
-        return theEmitter.loadIfGLValue(init);
+        return init;
       }
     }
   }
@@ -362,12 +352,13 @@ SpirvInstruction *InitListHandler::createInitForStructType(QualType type) {
     while (tryToSplitConstantArray())
       ;
 
-    const Expr *init = initializers.back();
+    auto *init = initializers.back();
     // We can only avoid decomposing and reconstructing when the type is
     // exactly the same.
-    if (type.getCanonicalType() == init->getType().getCanonicalType()) {
+    if (type.getCanonicalType() ==
+        init->getAstResultType().getCanonicalType()) {
       initializers.pop_back();
-      return theEmitter.loadIfGLValue(init);
+      return init;
     }
 
     // Otherwise, if the next initializer is a struct, it is not of the same
@@ -401,12 +392,13 @@ InitListHandler::createInitForConstantArrayType(QualType type,
     while (tryToSplitStruct())
       ;
 
-    const Expr *init = initializers.back();
+    auto *init = initializers.back();
     // We can only avoid decomposing and reconstructing when the type is
     // exactly the same.
-    if (type.getCanonicalType() == init->getType().getCanonicalType()) {
+    if (type.getCanonicalType() ==
+        init->getAstResultType().getCanonicalType()) {
       initializers.pop_back();
-      return theEmitter.loadIfGLValue(init);
+      return init;
     }
 
     // Otherwise, if the next initializer is an array, it is not of the same
@@ -453,17 +445,15 @@ InitListHandler::createInitForSamplerImageType(QualType type,
   while (tryToSplitStruct() || tryToSplitConstantArray())
     ;
 
-  const Expr *init = initializers.back();
+  auto *init = initializers.back();
   initializers.pop_back();
 
-  if (init->getType().getCanonicalType() != type.getCanonicalType()) {
-    init->dump();
-    emitError("cannot cast initializer type %0 into variable type %1",
-              init->getLocStart())
-        << init->getType() << type;
+  if (init->getAstResultType().getCanonicalType() != type.getCanonicalType()) {
+    emitError("Cannot cast initializer type %0 into variable type %1", srcLoc)
+        << init->getAstResultType() << type;
     return nullptr;
   }
-  return theEmitter.loadIfGLValue(init);
+  return init;
 }
 
 } // end namespace spirv

+ 2 - 2
tools/clang/lib/SPIRV/InitListHandler.h

@@ -109,7 +109,7 @@ private:
 
   /// Decomposes the given Expr and puts all elements into the end of the
   /// scalars queue.
-  void decompose(const Expr *expr);
+  void decompose(SpirvInstruction *inst);
   void decomposeVector(SpirvInstruction *vec, QualType elemType, uint32_t size);
 
   /// If the next initializer is a struct, replaces it with MemberExprs to all
@@ -146,7 +146,7 @@ private:
   /// initializers to the tail of the queue, we use a vector (containing the
   /// reverse of the original intializer list) here and manipulate its tail.
   /// This is more efficient than using deque.
-  std::vector<const Expr *> initializers;
+  std::vector<SpirvInstruction *> initializers;
   /// A queue keeping track of previously extracted but unused scalars.
   /// Each element is a pair, with the first element as the SPIR-V <result-id>
   /// and the second element as the AST type of the scalar value.

+ 1 - 0
tools/clang/lib/SPIRV/SpirvBuilder.cpp

@@ -1031,6 +1031,7 @@ SpirvConstant *SpirvBuilder::getConstantBool(bool value, bool specConst) {
   // We do not care about making unique constants at this point.
   auto *boolConst = new (context)
       SpirvConstantBoolean(context.getBoolType(), value, specConst);
+  boolConst->setAstResultType(astContext.BoolTy);
   module->addConstant(boolConst);
   return boolConst;
 }

+ 105 - 0
tools/clang/test/CodeGenSPIRV/cast.flat-conversion.array-to-vector.hlsl

@@ -0,0 +1,105 @@
+// Run: %dxc -T ps_6_0 -E main
+
+typedef int A[2];
+
+ConsumeStructuredBuffer<A> intarr_consume;
+
+A getA() {
+  A a = intarr_consume.Consume();
+  return a;
+}
+
+typedef float B[2];
+
+ConsumeStructuredBuffer<B> floatarr_consume;
+
+B getB() {
+  B b = floatarr_consume.Consume();
+  return b;
+}
+
+typedef bool C[2];
+
+ConsumeStructuredBuffer<C> boolarr_consume;
+
+C getC() {
+  C c = boolarr_consume.Consume();
+  return c;
+}
+
+void main() {
+  // CHECK:      [[call_0:%\d+]] = OpFunctionCall %_arr_int_uint_2_0 %getA
+  // CHECK-NEXT:  [[i_0_0:%\d+]] = OpCompositeExtract %int [[call_0]] 0
+  // CHECK-NEXT:  [[i_0_1:%\d+]] = OpCompositeExtract %int [[call_0]] 1
+  // CHECK-NEXT:   [[vi_0:%\d+]] = OpCompositeConstruct %v2int [[i_0_0]] [[i_0_1]]
+  // CHECK-NEXT:                   OpStore %intarray_to_intvec [[vi_0]]
+  int2 intarray_to_intvec = (int2)getA();
+
+  // CHECK:      [[call_1:%\d+]] = OpFunctionCall %_arr_float_uint_2_0 %getB
+  // CHECK-NEXT:  [[f_1_0:%\d+]] = OpCompositeExtract %float [[call_1]] 0
+  // CHECK-NEXT:  [[f_1_1:%\d+]] = OpCompositeExtract %float [[call_1]] 1
+  // CHECK-NEXT:   [[vf_1:%\d+]] = OpCompositeConstruct %v2float [[f_1_0]] [[f_1_1]]
+  // CHECK-NEXT:                   OpStore %floatarray_to_floatvec [[vf_1]]
+  float2 floatarray_to_floatvec = (float2)getB();
+
+  // CHECK:      [[call_2:%\d+]] = OpFunctionCall %_arr_bool_uint_2 %getC
+  // CHECK-NEXT:  [[b_2_0:%\d+]] = OpCompositeExtract %bool [[call_2]] 0
+  // CHECK-NEXT:  [[b_2_1:%\d+]] = OpCompositeExtract %bool [[call_2]] 1
+  // CHECK-NEXT:   [[vb_2:%\d+]] = OpCompositeConstruct %v2bool [[b_2_0]] [[b_2_1]]
+  // CHECK-NEXT:                   OpStore %boolarray_to_boolvec [[vb_2]]
+  bool2 boolarray_to_boolvec = (bool2)getC();
+
+  // CHECK:      [[call_3:%\d+]] = OpFunctionCall %_arr_float_uint_2_0 %getB
+  // CHECK-NEXT:  [[f_3_0:%\d+]] = OpCompositeExtract %float [[call_3]] 0
+  // CHECK-NEXT:  [[f_3_1:%\d+]] = OpCompositeExtract %float [[call_3]] 1
+  // CHECK-NEXT:  [[i_3_0:%\d+]] = OpConvertFToS %int [[f_3_0]]
+  // CHECK-NEXT:  [[i_3_1:%\d+]] = OpConvertFToS %int [[f_3_1]]
+  // CHECK-NEXT:   [[vi_3:%\d+]] = OpCompositeConstruct %v2int [[i_3_0]] [[i_3_1]]
+  // CHECK-NEXT:                   OpStore %floatarray_to_intvec [[vi_3]]
+  int2 floatarray_to_intvec = (int2)getB();
+
+  // CHECK:      [[call_4:%\d+]] = OpFunctionCall %_arr_bool_uint_2 %getC
+  // CHECK-NEXT:  [[b_4_0:%\d+]] = OpCompositeExtract %bool [[call_4]] 0
+  // CHECK-NEXT:  [[b_4_1:%\d+]] = OpCompositeExtract %bool [[call_4]] 1
+  // CHECK-NEXT:  [[i_4_0:%\d+]] = OpSelect %int [[b_4_0]] %int_1 %int_0
+  // CHECK-NEXT:  [[i_4_1:%\d+]] = OpSelect %int [[b_4_1]] %int_1 %int_0
+  // CHECK-NEXT:   [[vi_4:%\d+]] = OpCompositeConstruct %v2int [[i_4_0]] [[i_4_1]]
+  // CHECK-NEXT:                   OpStore %boolarray_to_intvec [[vi_4]]
+  int2 boolarray_to_intvec = (int2)getC();
+
+  // CHECK:      [[call_5:%\d+]] = OpFunctionCall %_arr_int_uint_2_0 %getA
+  // CHECK-NEXT:  [[i_5_0:%\d+]] = OpCompositeExtract %int [[call_5]] 0
+  // CHECK-NEXT:  [[i_5_1:%\d+]] = OpCompositeExtract %int [[call_5]] 1
+  // CHECK-NEXT:  [[f_5_0:%\d+]] = OpConvertSToF %float [[i_5_0]]
+  // CHECK-NEXT:  [[f_5_1:%\d+]] = OpConvertSToF %float [[i_5_1]]
+  // CHECK-NEXT:   [[vf_5:%\d+]] = OpCompositeConstruct %v2float [[f_5_0]] [[f_5_1]]
+  // CHECK-NEXT:                   OpStore %intarray_to_floatvec [[vf_5]]
+  float2 intarray_to_floatvec = (float2)getA();
+
+  // CHECK:      [[call_6:%\d+]] = OpFunctionCall %_arr_bool_uint_2 %getC
+  // CHECK-NEXT:  [[b_6_0:%\d+]] = OpCompositeExtract %bool [[call_6]] 0
+  // CHECK-NEXT:  [[b_6_1:%\d+]] = OpCompositeExtract %bool [[call_6]] 1
+  // CHECK-NEXT:  [[f_6_0:%\d+]] = OpSelect %float [[b_6_0]] %float_1 %float_0
+  // CHECK-NEXT:  [[f_6_1:%\d+]] = OpSelect %float [[b_6_1]] %float_1 %float_0
+  // CHECK-NEXT:   [[vf_6:%\d+]] = OpCompositeConstruct %v2float [[f_6_0]] [[f_6_1]]
+  // CHECK-NEXT:                   OpStore %boolarray_to_floatvec [[vf_6]]
+  float2 boolarray_to_floatvec = (float2)getC();
+
+  // CHECK:      [[call_7:%\d+]] = OpFunctionCall %_arr_int_uint_2_0 %getA
+  // CHECK-NEXT:  [[i_7_0:%\d+]] = OpCompositeExtract %int [[call_7]] 0
+  // CHECK-NEXT:  [[i_7_1:%\d+]] = OpCompositeExtract %int [[call_7]] 1
+  // CHECK-NEXT:  [[b_7_0:%\d+]] = OpINotEqual %bool [[i_7_0]] %int_0
+  // CHECK-NEXT:  [[b_7_1:%\d+]] = OpINotEqual %bool [[i_7_1]] %int_0
+  // CHECK-NEXT:   [[vb_7:%\d+]] = OpCompositeConstruct %v2bool [[b_7_0]] [[b_7_1]]
+  // CHECK-NEXT:                   OpStore %intarray_to_boolvec [[vb_7]]
+  bool2 intarray_to_boolvec = (bool2)getA();
+
+  // CHECK:      [[call_8:%\d+]] = OpFunctionCall %_arr_float_uint_2_0 %getB
+  // CHECK-NEXT:  [[f_8_0:%\d+]] = OpCompositeExtract %float [[call_8]] 0
+  // CHECK-NEXT:  [[f_8_1:%\d+]] = OpCompositeExtract %float [[call_8]] 1
+  // CHECK-NEXT:  [[b_8_0:%\d+]] = OpFOrdNotEqual %bool [[f_8_0]] %float_0
+  // CHECK-NEXT:  [[b_8_1:%\d+]] = OpFOrdNotEqual %bool [[f_8_1]] %float_0
+  // CHECK-NEXT:   [[vb_8:%\d+]] = OpCompositeConstruct %v2bool [[b_8_0]] [[b_8_1]]
+  // CHECK-NEXT:                   OpStore %floatarray_to_boolvec [[vb_8]]
+  bool2 floatarray_to_boolvec = (bool2)getB();
+}

+ 17 - 18
tools/clang/test/CodeGenSPIRV/cast.flat-conversion.struct-to-struct.hlsl

@@ -22,38 +22,37 @@ void main() {
   FirstStruct v;
 
 // Yes, this is a FlatConversion!
-// CHECK:      [[v0ptr:%\d+]] = OpAccessChain %_ptr_Function__arr_v3float_uint_4_0 %values %int_0
-// CHECK-NEXT:    [[v0:%\d+]] = OpLoad %_arr_v3float_uint_4_0 [[v0ptr]]
-// CHECK-NEXT: [[v1ptr:%\d+]] = OpAccessChain %_ptr_Function__arr_mat2v3float_uint_1_0 %values %int_1
-// CHECK-NEXT:    [[v1:%\d+]] = OpLoad %_arr_mat2v3float_uint_1_0 [[v1ptr]]
-// CHECK-NEXT: [[v2ptr:%\d+]] = OpAccessChain %_ptr_Function__arr_v2int_uint_3_0 %values %int_2
-// CHECK-NEXT:    [[v2:%\d+]] = OpLoad %_arr_v2int_uint_3_0 [[v2ptr]]
-// CHECK-NEXT:     [[v:%\d+]] = OpCompositeConstruct %FirstStruct_0 [[v0]] [[v1]] [[v2]]
-// CHECK-NEXT:                  OpStore %v [[v]]
+// CHECK:      [[values:%\d+]] = OpLoad %SecondStruct %values
+// CHECK-NEXT:     [[v0:%\d+]] = OpCompositeExtract %_arr_v3float_uint_4_0 [[values]] 0
+// CHECK-NEXT:     [[v1:%\d+]] = OpCompositeExtract %_arr_mat2v3float_uint_1_0 [[values]] 1
+// CHECK-NEXT:     [[v2:%\d+]] = OpCompositeExtract %_arr_v2int_uint_3_0 [[values]] 2
+// CHECK-NEXT:      [[v:%\d+]] = OpCompositeConstruct %FirstStruct_0 [[v0]] [[v1]] [[v2]]
+// CHECK-NEXT:                   OpStore %v [[v]]
   v = values;
 
-// CHECK:          [[v0ptr:%\d+]] = OpAccessChain %_ptr_Function__arr_v3float_uint_4_0 %values %int_0
-// CHECK-NEXT:        [[v0:%\d+]] = OpLoad %_arr_v3float_uint_4_0 [[v0ptr]]
-// CHECK-NEXT:     [[v1ptr:%\d+]] = OpAccessChain %_ptr_Function__arr_mat2v3float_uint_1_0 %values %int_1
-// CHECK-NEXT:        [[v1:%\d+]] = OpLoad %_arr_mat2v3float_uint_1_0 [[v1ptr]]
-// CHECK-NEXT:     [[v2ptr:%\d+]] = OpAccessChain %_ptr_Function__arr_v2int_uint_3_0 %values %int_2
-// CHECK-NEXT:        [[v2:%\d+]] = OpLoad %_arr_v2int_uint_3_0 [[v2ptr]]
-// CHECK-NEXT:    [[values:%\d+]] = OpCompositeConstruct %FirstStruct_0 [[v0]] [[v1]] [[v2]]
+// CHECK-NEXT: [[values:%\d+]] = OpLoad %SecondStruct %values
+// CHECK-NEXT:     [[v0:%\d+]] = OpCompositeExtract %_arr_v3float_uint_4_0 [[values]] 0
+// CHECK-NEXT:     [[v1:%\d+]] = OpCompositeExtract %_arr_mat2v3float_uint_1_0 [[values]] 1
+// CHECK-NEXT:     [[v2:%\d+]] = OpCompositeExtract %_arr_v2int_uint_3_0 [[values]] 2
+// CHECK-NEXT:    [[v:%\d+]] = OpCompositeConstruct %FirstStruct_0 [[v0]] [[v1]] [[v2]]
 // CHECK-NEXT: [[rwBuf_ptr:%\d+]] = OpAccessChain %_ptr_Uniform_FirstStruct %rwBuf %int_0 %uint_0
-// CHECK-NEXT:   [[anArray:%\d+]] = OpCompositeExtract %_arr_v3float_uint_4_0 [[values]] 0
+// CHECK-NEXT:   [[anArray:%\d+]] = OpCompositeExtract %_arr_v3float_uint_4_0 [[v]] 0
 // CHECK-NEXT:  [[anArray1:%\d+]] = OpCompositeExtract %v3float [[anArray]] 0
 // CHECK-NEXT:  [[anArray2:%\d+]] = OpCompositeExtract %v3float [[anArray]] 1
 // CHECK-NEXT:  [[anArray3:%\d+]] = OpCompositeExtract %v3float [[anArray]] 2
 // CHECK-NEXT:  [[anArray4:%\d+]] = OpCompositeExtract %v3float [[anArray]] 3
 // CHECK-NEXT:      [[res1:%\d+]] = OpCompositeConstruct %_arr_v3float_uint_4 [[anArray1]] [[anArray2]] [[anArray3]] [[anArray4]]
-// CHECK-NEXT:      [[mats:%\d+]] = OpCompositeExtract %_arr_mat2v3float_uint_1_0 [[values]] 1
+
+// CHECK-NEXT:      [[mats:%\d+]] = OpCompositeExtract %_arr_mat2v3float_uint_1_0 [[v]] 1
 // CHECK-NEXT:       [[mat:%\d+]] = OpCompositeExtract %mat2v3float [[mats]] 0
 // CHECK-NEXT:      [[res2:%\d+]] = OpCompositeConstruct %_arr_mat2v3float_uint_1 [[mat]]
-// CHECK-NEXT:      [[ints:%\d+]] = OpCompositeExtract %_arr_v2int_uint_3_0 [[values]] 2
+
+// CHECK-NEXT:      [[ints:%\d+]] = OpCompositeExtract %_arr_v2int_uint_3_0 [[v]] 2
 // CHECK-NEXT:     [[ints1:%\d+]] = OpCompositeExtract %v2int [[ints]] 0
 // CHECK-NEXT:     [[ints2:%\d+]] = OpCompositeExtract %v2int [[ints]] 1
 // CHECK-NEXT:     [[ints3:%\d+]] = OpCompositeExtract %v2int [[ints]] 2
 // CHECK-NEXT:      [[res3:%\d+]] = OpCompositeConstruct %_arr_v2int_uint_3 [[ints1]] [[ints2]] [[ints3]]
+
 // CHECK-NEXT:    [[result:%\d+]] = OpCompositeConstruct %FirstStruct [[res1]] [[res2]] [[res3]]
 // CHECK-NEXT:                      OpStore [[rwBuf_ptr]] [[result]]
   rwBuf[0] = values;

+ 2 - 2
tools/clang/test/CodeGenSPIRV/cast.flat-conversion.struct.hlsl

@@ -16,8 +16,8 @@ float4 main(float4 a: A) : SV_Target {
 // CHECK-NEXT:              OpStore %s [[s]]
     S s = (S)a;
 
-// CHECK:      [[valptr:%\d+]] = OpAccessChain %_ptr_Function_v4float %s %int_0
-// CHECK-NEXT:    [[val:%\d+]] = OpLoad %v4float [[valptr]]
+// CHECK:           [[s:%\d+]] = OpLoad %S %s
+// CHECK-NEXT:    [[val:%\d+]] = OpCompositeExtract %v4float [[s]] 0
 // CHECK-NEXT:      [[s:%\d+]] = OpCompositeConstruct %S [[val]]
 // CHECK-NEXT:      [[t:%\d+]] = OpCompositeConstruct %T [[s]]
 // CHECK-NEXT:                   OpStore %t [[t]]

+ 10 - 10
tools/clang/test/CodeGenSPIRV/cast.flat-conversion.vector.hlsl

@@ -8,16 +8,16 @@ StructuredBuffer<S> MySB;
 
 float4 main() : SV_TARGET
 {
-// CHECK:      [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_v2float %MySB %int_0 %uint_0 %int_0 %uint_0
-// CHECK-NEXT: [[vec:%\d+]] = OpLoad %v2float [[ptr]]
-// CHECK-NEXT:  [[v1:%\d+]] = OpCompositeExtract %float [[vec]] 0
-// CHECK-NEXT:  [[v2:%\d+]] = OpCompositeExtract %float [[vec]] 1
-// CHECK-NEXT: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_v2float %MySB %int_0 %uint_0 %int_0 %uint_1
-// CHECK-NEXT: [[vec:%\d+]] = OpLoad %v2float [[ptr]]
-// CHECK-NEXT:  [[v3:%\d+]] = OpCompositeExtract %float [[vec]] 0
-// CHECK-NEXT:  [[v4:%\d+]] = OpCompositeExtract %float [[vec]] 1
-// CHECK-NEXT: [[val:%\d+]] = OpCompositeConstruct %_arr_float_uint_4 [[v1]] [[v2]] [[v3]] [[v4]]
-// CHECK-NEXT:                OpStore %data [[val]]
+// CHECK:        [[ac:%\d+]] = OpAccessChain %_ptr_Uniform__arr_v2float_uint_2 %MySB %int_0 %uint_0 %int_0
+// CHECK-NEXT: [[mysb:%\d+]] = OpLoad %_arr_v2float_uint_2 [[ac]]
+// CHECK-NEXT: [[vec0:%\d+]] = OpCompositeExtract %v2float [[mysb]] 0
+// CHECK-NEXT: [[vec1:%\d+]] = OpCompositeExtract %v2float [[mysb]] 1
+// CHECK-NEXT:   [[v1:%\d+]] = OpCompositeExtract %float [[vec0]] 0
+// CHECK-NEXT:   [[v2:%\d+]] = OpCompositeExtract %float [[vec0]] 1
+// CHECK-NEXT:   [[v3:%\d+]] = OpCompositeExtract %float [[vec1]] 0
+// CHECK-NEXT:   [[v4:%\d+]] = OpCompositeExtract %float [[vec1]] 1
+// CHECK-NEXT:  [[val:%\d+]] = OpCompositeConstruct %_arr_float_uint_4 [[v1]] [[v2]] [[v3]] [[v4]]
+// CHECK-NEXT:                 OpStore %data [[val]]
     float data[4] = (float[4])MySB[0].data;
     return data[1];
 }

+ 51 - 46
tools/clang/test/CodeGenSPIRV/var.init.array.hlsl

@@ -30,83 +30,88 @@ struct T3 {
 void main() {
     T1 val1[2];
 
+// CHECK:          [[val1:%\d+]] = OpLoad %_arr_T1_uint_2 %val1
+// CHECK-NEXT:   [[val1_0:%\d+]] = OpCompositeExtract %T1 [[val1]] 0
+// CHECK-NEXT:   [[val1_1:%\d+]] = OpCompositeExtract %T1 [[val1]] 1
+// CHECK-NEXT: [[val1_0_0:%\d+]] = OpCompositeExtract %S2 [[val1_0]] 0
+// CHECK-NEXT: [[val1_0_1:%\d+]] = OpCompositeExtract %S2 [[val1_0]] 1
+// CHECK-NEXT:      [[t1c:%\d+]] = OpCompositeExtract %_arr_v2float_uint_2 [[val1_0_0]] 0
+// CHECK-NEXT:    [[t1c_0:%\d+]] = OpCompositeExtract %v2float [[t1c]] 0
+// CHECK-NEXT:    [[t1c_1:%\d+]] = OpCompositeExtract %v2float [[t1c]] 1
+
 // val2[0]: Construct T2.e from T1.c.b[0]
-// CHECK:          [[b_0:%\d+]] = OpAccessChain %_ptr_Function_v2float %val1 %uint_0 %int_0 %int_0 %uint_0
-// CHECK-NEXT: [[b_0_val:%\d+]] = OpLoad %v2float [[b_0]]
-// CHECK-NEXT:   [[e_val:%\d+]] = OpCompositeConstruct %S1 [[b_0_val]]
+// CHECK-NEXT:     [[T2_e:%\d+]] = OpCompositeConstruct %S1 [[t1c_0]]
 
 // val2[0]: Construct T2.f from T1.c.b[1]
-// CHECK-NEXT:     [[b_1:%\d+]] = OpAccessChain %_ptr_Function_v2float %val1 %uint_0 %int_0 %int_0 %uint_1
-// CHECK-NEXT: [[b_1_val:%\d+]] = OpLoad %v2float [[b_1]]
-// CHECK-NEXT:   [[f_val:%\d+]] = OpCompositeConstruct %S1 [[b_1_val]]
+// CHECK-NEXT:     [[T2_f:%\d+]] = OpCompositeConstruct %S1 [[t1c_1]]
 
-// val2[0]: Read T1.d as T2.g
-// CHECK-NEXT:    [[T1_d:%\d+]] = OpAccessChain %_ptr_Function_S2 %val1 %uint_0 %int_1
-// CHECK-NEXT:   [[d_val:%\d+]] = OpLoad %S2 [[T1_d]]
+// val2[0]: Construct val2[0]
+// CHECK-NEXT:     [[T2_0:%\d+]] = OpCompositeConstruct %T2 [[T2_e]] [[T2_f]] [[val1_0_1]]
 
-// CHECK-NEXT:  [[val2_0:%\d+]] = OpCompositeConstruct %T2 [[e_val]] [[f_val]] [[d_val]]
+// CHECK-NEXT: [[val1_1_0:%\d+]] = OpCompositeExtract %S2 [[val1_1]] 0
+// CHECK-NEXT: [[val1_1_1:%\d+]] = OpCompositeExtract %S2 [[val1_1]] 1
+// CHECK-NEXT:      [[t1d:%\d+]] = OpCompositeExtract %_arr_v2float_uint_2 [[val1_1_0]] 0
+// CHECK-NEXT:    [[t1d_0:%\d+]] = OpCompositeExtract %v2float [[t1d]] 0
+// CHECK-NEXT:    [[t1d_1:%\d+]] = OpCompositeExtract %v2float [[t1d]] 1
 
 // val2[1]: Construct T2.e from T1.c.b[0]
-// CHECK-NEXT:     [[b_0:%\d+]] = OpAccessChain %_ptr_Function_v2float %val1 %uint_1 %int_0 %int_0 %uint_0
-// CHECK-NEXT: [[b_0_val:%\d+]] = OpLoad %v2float [[b_0]]
-// CHECK-NEXT:   [[e_val:%\d+]] = OpCompositeConstruct %S1 [[b_0_val]]
+// CHECK-NEXT:     [[T2_e:%\d+]] = OpCompositeConstruct %S1 [[t1d_0]]
 
 // val2[1]: Construct T2.f from T1.c.b[1]
-// CHECK-NEXT:     [[b_1:%\d+]] = OpAccessChain %_ptr_Function_v2float %val1 %uint_1 %int_0 %int_0 %uint_1
-// CHECK-NEXT: [[b_1_val:%\d+]] = OpLoad %v2float [[b_1]]
-// CHECK-NEXT:   [[f_val:%\d+]] = OpCompositeConstruct %S1 [[b_1_val]]
-
-// val2[1]: Read T1.d as T2.g
-// CHECK-NEXT:    [[T1_d:%\d+]] = OpAccessChain %_ptr_Function_S2 %val1 %uint_1 %int_1
-// CHECK-NEXT:   [[d_val:%\d+]] = OpLoad %S2 [[T1_d]]
+// CHECK-NEXT:     [[T2_f:%\d+]] = OpCompositeConstruct %S1 [[t1d_1]]
 
-// CHECK-NEXT:  [[val2_1:%\d+]] = OpCompositeConstruct %T2 [[e_val]] [[f_val]] [[d_val]]
+// val2[1]: Construct val2[1]
+// CHECK-NEXT:     [[T2_1:%\d+]] = OpCompositeConstruct %T2 [[T2_e]] [[T2_f]] [[val1_1_1]]
 
-// CHECK-NEXT:    [[val2:%\d+]] = OpCompositeConstruct %_arr_T2_uint_2 [[val2_0]] [[val2_1]]
-// CHECK-NEXT:                    OpStore %val2 [[val2]]
+// CHECK-NEXT:     [[val2:%\d+]] = OpCompositeConstruct %_arr_T2_uint_2 [[T2_0]] [[T2_1]]
+// CHECK-NEXT:                     OpStore %val2 [[val2]]
     T2 val2[2] = {val1};
 
+// CHECK:          [[val1:%\d+]] = OpAccessChain %_ptr_Function_T1 %val1 %int_0
+// CHECK-NEXT:       [[t1:%\d+]] = OpLoad %T1 [[val1]]
+
+// val3[1]
+// CHECK-NEXT:       [[t3:%\d+]] = OpLoad %T3 %t3
+
+// CHECK-NEXT:     [[s1_0:%\d+]] = OpLoad %S1 %s1
+// CHECK-NEXT:       [[s2:%\d+]] = OpLoad %S2 %s2
+// CHECK-NEXT:     [[s1_1:%\d+]] = OpLoad %S1 %s1
+
 // val3[0]: Construct T3.h from T1.c.b[0]
-// CHECK-NEXT:     [[b_0:%\d+]] = OpAccessChain %_ptr_Function_v2float %val1 %int_0 %int_0 %int_0 %uint_0
-// CHECK-NEXT:   [[h_val:%\d+]] = OpLoad %v2float [[b_0]]
+// CHECK-NEXT:      [[t1c:%\d+]] = OpCompositeExtract %S2 [[t1]] 0
+// CHECK-NEXT:      [[t1d:%\d+]] = OpCompositeExtract %S2 [[t1]] 1
+// CHECK-NEXT:    [[t1c_0:%\d+]] = OpCompositeExtract %_arr_v2float_uint_2 [[t1c]] 0
+// CHECK-NEXT:    [[v2f_0:%\d+]] = OpCompositeExtract %v2float [[t1c_0]] 0
 
 // val3[0]: Construct T3.i from T1.c.b[1]
-// CHECK-NEXT:     [[b_1:%\d+]] = OpAccessChain %_ptr_Function_v2float %val1 %int_0 %int_0 %int_0 %uint_1
-// CHECK-NEXT:   [[i_val:%\d+]] = OpLoad %v2float [[b_1]]
+// CHECK-NEXT:    [[v2f_1:%\d+]] = OpCompositeExtract %v2float [[t1c_0]] 1
 
 // val3[0]: Construct T3.j from T1.d.b[0]
-// CHECK-NEXT:     [[b_0:%\d+]] = OpAccessChain %_ptr_Function_v2float %val1 %int_0 %int_1 %int_0 %uint_0
-// CHECK-NEXT:   [[j_val:%\d+]] = OpLoad %v2float [[b_0]]
+// CHECK-NEXT:    [[t1c_1:%\d+]] = OpCompositeExtract %_arr_v2float_uint_2 [[t1d]] 0
+// CHECK-NEXT:    [[v2f_2:%\d+]] = OpCompositeExtract %v2float [[t1c_1]] 0
 
 // val3[0]: Construct T3.k from T1.d.b[1]
-// CHECK-NEXT:     [[b_1:%\d+]] = OpAccessChain %_ptr_Function_v2float %val1 %int_0 %int_1 %int_0 %uint_1
-// CHECK-NEXT:   [[k_val:%\d+]] = OpLoad %v2float [[b_1]]
+// CHECK-NEXT:    [[v2f_3:%\d+]] = OpCompositeExtract %v2float [[t1c_1]] 1
 
-// CHECK-NEXT:  [[val3_0:%\d+]] = OpCompositeConstruct %T3 [[h_val]] [[i_val]] [[j_val]] [[k_val]]
-
-// val3[1]
-// CHECK-NEXT:  [[t3_val:%\d+]] = OpLoad %T3 %t3
+// CHECK-NEXT:   [[val3_0:%\d+]] = OpCompositeConstruct %T3 [[v2f_0]] [[v2f_1]] [[v2f_2]] [[v2f_3]]
 
 // val3[2]: Construct T3.h from S1.a
-// CHECK-NEXT:    [[s1_a:%\d+]] = OpAccessChain %_ptr_Function_v2float %s1 %int_0
-// CHECK-NEXT:   [[h_val:%\d+]] = OpLoad %v2float [[s1_a]]
+// CHECK-NEXT:     [[t3_h:%\d+]] = OpCompositeExtract %v2float [[s1_0]] 0
 
 // val3[2]: Construct T3.i from S2.b[0]
-// CHECK-NEXT:  [[s2_b_0:%\d+]] = OpAccessChain %_ptr_Function_v2float %s2 %int_0 %uint_0
-// CHECK-NEXT:   [[i_val:%\d+]] = OpLoad %v2float [[s2_b_0]]
+// CHECK-NEXT:     [[s2_0:%\d+]] = OpCompositeExtract %_arr_v2float_uint_2 [[s2]] 0
+// CHECK-NEXT:     [[t3_i:%\d+]] = OpCompositeExtract %v2float [[s2_0]] 0
 
 // val3[2]: Construct T3.j from S2.b[1]
-// CHECK-NEXT:  [[s2_b_1:%\d+]] = OpAccessChain %_ptr_Function_v2float %s2 %int_0 %uint_1
-// CHECK-NEXT:   [[j_val:%\d+]] = OpLoad %v2float [[s2_b_1]]
+// CHECK-NEXT:     [[t3_j:%\d+]] = OpCompositeExtract %v2float [[s2_0]] 1
 
 // val3[2]: Construct T3.k from S1.a
-// CHECK-NEXT:    [[s1_a:%\d+]] = OpAccessChain %_ptr_Function_v2float %s1 %int_0
-// CHECK-NEXT:   [[k_val:%\d+]] = OpLoad %v2float [[s1_a]]
+// CHECK-NEXT:     [[t3_k:%\d+]] = OpCompositeExtract %v2float [[s1_1]] 0
 
-// CHECK-NEXT:  [[val3_2:%\d+]] = OpCompositeConstruct %T3 [[h_val]] [[i_val]] [[j_val]] [[k_val]]
+// CHECK-NEXT:   [[val3_2:%\d+]] = OpCompositeConstruct %T3 [[t3_h]] [[t3_i]] [[t3_j]] [[t3_k]]
 
-// CHECK-NEXT:    [[val3:%\d+]] = OpCompositeConstruct %_arr_T3_uint_3 [[val3_0]] [[t3_val]]
-// CHECK-NEXT:                    OpStore %val3 [[val3]]
+// CHECK-NEXT:     [[val3:%\d+]] = OpCompositeConstruct %_arr_T3_uint_3 [[val3_0]] [[t3]] [[val3_2]]
+// CHECK-NEXT:                     OpStore %val3 [[val3]]
     S1 s1;
     S2 s2;
     T3 t3;

+ 1 - 1
tools/clang/test/CodeGenSPIRV/var.init.hlsl

@@ -47,9 +47,9 @@ float4 main(float component: COLOR) : SV_TARGET {
 
     float2 y;
 // CHECK-NEXT: [[y0:%\d+]] = OpLoad %v2float %y
+// CHECK-NEXT: [[y1:%\d+]] = OpLoad %v2float %y
 // CHECK-NEXT: [[ce0:%\d+]] = OpCompositeExtract %float [[y0]] 0
 // CHECK-NEXT: [[ce1:%\d+]] = OpCompositeExtract %float [[y0]] 1
-// CHECK-NEXT: [[y1:%\d+]] = OpLoad %v2float %y
 // CHECK-NEXT: [[ce2:%\d+]] = OpCompositeExtract %float [[y1]] 0
 // CHECK-NEXT: [[ce3:%\d+]] = OpCompositeExtract %float [[y1]] 1
 // CHECK-NEXT: [[zinit:%\d+]] = OpCompositeConstruct %v4float [[ce0]] [[ce1]] [[ce2]] [[ce3]]

+ 7 - 7
tools/clang/test/CodeGenSPIRV/var.init.matrix.1xn.hlsl

@@ -22,23 +22,23 @@ void main() {
 // CHECK-NEXT: [[scalar:%\d+]] = OpLoad %int %scalar
 // CHECK-NEXT: [[cv0:%\d+]] = OpConvertSToF %float [[scalar]]
 // CHECK-NEXT: [[vec2:%\d+]] = OpLoad %v2uint %vec2
+// CHECK-NEXT: [[vec1:%\d+]] = OpLoad %bool %vec1
 // CHECK-NEXT: [[ce0:%\d+]] = OpCompositeExtract %uint [[vec2]] 0
 // CHECK-NEXT: [[ce1:%\d+]] = OpCompositeExtract %uint [[vec2]] 1
 // CHECK-NEXT: [[cv1:%\d+]] = OpConvertUToF %float [[ce0]]
 // CHECK-NEXT: [[cv2:%\d+]] = OpConvertUToF %float [[ce1]]
-// CHECK-NEXT: [[vec1:%\d+]] = OpLoad %bool %vec1
 // CHECK-NEXT: [[cv3:%\d+]] = OpSelect %float [[vec1]] %float_1 %float_0
 // CHECK-NEXT: [[cc0:%\d+]] = OpCompositeConstruct %v4float [[cv0]] [[cv1]] [[cv2]] [[cv3]]
 // CHECK-NEXT: OpStore %mat5 [[cc0]]
     float1x4 mat5 = {scalar, vec2, vec1};
 
     float1x2 mat6;
-// CHECK-NEXT: [[mat6:%\d+]] = OpLoad %v2float %mat6
-// CHECK-NEXT: [[ce2:%\d+]] = OpCompositeExtract %float [[mat6]] 0
-// CHECK-NEXT: [[ce3:%\d+]] = OpCompositeExtract %float [[mat6]] 1
-// CHECK-NEXT: [[mat6:%\d+]] = OpLoad %v2float %mat6
-// CHECK-NEXT: [[ce4:%\d+]] = OpCompositeExtract %float [[mat6]] 0
-// CHECK-NEXT: [[ce5:%\d+]] = OpCompositeExtract %float [[mat6]] 1
+// CHECK-NEXT: [[mat6_0:%\d+]] = OpLoad %v2float %mat6
+// CHECK-NEXT: [[mat6_1:%\d+]] = OpLoad %v2float %mat6
+// CHECK-NEXT: [[ce2:%\d+]] = OpCompositeExtract %float [[mat6_0]] 0
+// CHECK-NEXT: [[ce3:%\d+]] = OpCompositeExtract %float [[mat6_0]] 1
+// CHECK-NEXT: [[ce4:%\d+]] = OpCompositeExtract %float [[mat6_1]] 0
+// CHECK-NEXT: [[ce5:%\d+]] = OpCompositeExtract %float [[mat6_1]] 1
 // CHECK-NEXT: [[cc1:%\d+]] = OpCompositeConstruct %v4float [[ce2]] [[ce3]] [[ce4]] [[ce5]]
 // CHECK-NEXT: OpStore %mat7 [[cc1]]
     float1x4 mat7 = {mat6, mat6};

+ 7 - 7
tools/clang/test/CodeGenSPIRV/var.init.matrix.mx1.hlsl

@@ -22,23 +22,23 @@ void main() {
 // CHECK-NEXT: [[scalar:%\d+]] = OpLoad %int %scalar
 // CHECK-NEXT: [[cv0:%\d+]] = OpConvertSToF %float [[scalar]]
 // CHECK-NEXT: [[vec2:%\d+]] = OpLoad %v2uint %vec2
+// CHECK-NEXT: [[vec1:%\d+]] = OpLoad %bool %vec1
 // CHECK-NEXT: [[ce0:%\d+]] = OpCompositeExtract %uint [[vec2]] 0
 // CHECK-NEXT: [[ce1:%\d+]] = OpCompositeExtract %uint [[vec2]] 1
 // CHECK-NEXT: [[cv1:%\d+]] = OpConvertUToF %float [[ce0]]
 // CHECK-NEXT: [[cv2:%\d+]] = OpConvertUToF %float [[ce1]]
-// CHECK-NEXT: [[vec1:%\d+]] = OpLoad %bool %vec1
 // CHECK-NEXT: [[cv3:%\d+]] = OpSelect %float [[vec1]] %float_1 %float_0
 // CHECK-NEXT: [[cc0:%\d+]] = OpCompositeConstruct %v4float [[cv0]] [[cv1]] [[cv2]] [[cv3]]
 // CHECK-NEXT: OpStore %mat5 [[cc0]]
     float4x1 mat5 = {scalar, vec2, vec1};
 
     float2x1 mat6;
-// CHECK-NEXT: [[mat6:%\d+]] = OpLoad %v2float %mat6
-// CHECK-NEXT: [[ce2:%\d+]] = OpCompositeExtract %float [[mat6]] 0
-// CHECK-NEXT: [[ce3:%\d+]] = OpCompositeExtract %float [[mat6]] 1
-// CHECK-NEXT: [[mat6:%\d+]] = OpLoad %v2float %mat6
-// CHECK-NEXT: [[ce4:%\d+]] = OpCompositeExtract %float [[mat6]] 0
-// CHECK-NEXT: [[ce5:%\d+]] = OpCompositeExtract %float [[mat6]] 1
+// CHECK-NEXT: [[mat6_0:%\d+]] = OpLoad %v2float %mat6
+// CHECK-NEXT: [[mat6_1:%\d+]] = OpLoad %v2float %mat6
+// CHECK-NEXT: [[ce2:%\d+]] = OpCompositeExtract %float [[mat6_0]] 0
+// CHECK-NEXT: [[ce3:%\d+]] = OpCompositeExtract %float [[mat6_0]] 1
+// CHECK-NEXT: [[ce4:%\d+]] = OpCompositeExtract %float [[mat6_1]] 0
+// CHECK-NEXT: [[ce5:%\d+]] = OpCompositeExtract %float [[mat6_1]] 1
 // CHECK-NEXT: [[cc1:%\d+]] = OpCompositeConstruct %v4float [[ce2]] [[ce3]] [[ce4]] [[ce5]]
 // CHECK-NEXT: OpStore %mat7 [[cc1]]
     float4x1 mat7 = {mat6, mat6};

+ 25 - 29
tools/clang/test/CodeGenSPIRV/var.init.matrix.mxn.hlsl

@@ -46,23 +46,19 @@ void main() {
 // CHECK-NEXT: [[s:%\d+]] = OpLoad %float %scalar
 // CHECK-NEXT: [[vec1:%\d+]] = OpLoad %float %vec1
 // CHECK-NEXT: [[vec2:%\d+]] = OpLoad %v2float %vec2
+// CHECK-NEXT: [[vec3:%\d+]] = OpLoad %v3float %vec3
+// CHECK-NEXT: [[vec2a:%\d+]] = OpLoad %v2float %vec2
+// CHECK-NEXT: [[vec4:%\d+]] = OpLoad %v4float %vec4
 // CHECK-NEXT: [[ce00:%\d+]] = OpCompositeExtract %float [[vec2]] 0
 // CHECK-NEXT: [[ce01:%\d+]] = OpCompositeExtract %float [[vec2]] 1
 // CHECK-NEXT: [[cc14:%\d+]] = OpCompositeConstruct %v4float [[s]] [[vec1]] [[ce00]] [[ce01]]
-
-// CHECK-NEXT: [[vec3:%\d+]] = OpLoad %v3float %vec3
 // CHECK-NEXT: [[ce02:%\d+]] = OpCompositeExtract %float [[vec3]] 0
 // CHECK-NEXT: [[ce03:%\d+]] = OpCompositeExtract %float [[vec3]] 1
 // CHECK-NEXT: [[ce04:%\d+]] = OpCompositeExtract %float [[vec3]] 2
-// CHECK-NEXT: [[vec2a:%\d+]] = OpLoad %v2float %vec2
 // CHECK-NEXT: [[ce05:%\d+]] = OpCompositeExtract %float [[vec2a]] 0
 // CHECK-NEXT: [[ce06:%\d+]] = OpCompositeExtract %float [[vec2a]] 1
 // CHECK-NEXT: [[cc15:%\d+]] = OpCompositeConstruct %v4float [[ce02]] [[ce03]] [[ce04]] [[ce05]]
-
 // CHECK-NEXT: [[cc16:%\d+]] = OpCompositeConstruct %v4float [[ce06]] %float_1 %float_2 %float_3
-
-// CHECK-NEXT: [[vec4:%\d+]] = OpLoad %v4float %vec4
-
 // CHECK-NEXT: [[cc17:%\d+]] = OpCompositeConstruct %mat4v4float [[cc14]] [[cc15]] [[cc16]] [[vec4]]
 // CHECK-NEXT:  OpStore %mat5 [[cc17]]
     float4x4 mat5 = {scalar, vec1, vec2,  // [0]
@@ -85,23 +81,23 @@ void main() {
 
     // Casting
 // CHECK-NEXT: [[intvec1:%\d+]] = OpLoad %int %intVec1
-// CHECK-NEXT: [[convert0:%\d+]] = OpConvertSToF %float [[intvec1]]
 // CHECK-NEXT: [[uintscalar:%\d+]] = OpLoad %uint %uintScalar
 // CHECK-NEXT: [[convert1:%\d+]] = OpConvertUToF %float [[uintscalar]]
 // CHECK-NEXT: [[uintvec2:%\d+]] = OpLoad %v2uint %uintVec2
+// CHECK-NEXT: [[intscalar:%\d+]] = OpLoad %int %intScalar
+// CHECK-NEXT: [[convert4:%\d+]] = OpConvertSToF %float [[intscalar]]
+// CHECK-NEXT: [[boolscalar:%\d+]] = OpLoad %bool %boolScalar
+// CHECK-NEXT: [[convert5:%\d+]] = OpSelect %float [[boolscalar]] %float_1 %float_0
+// CHECK-NEXT: [[boolvec3:%\d+]] = OpLoad %v3bool %boolVec3
+// CHECK-NEXT: [[convert0:%\d+]] = OpConvertSToF %float [[intvec1]]
 // CHECK-NEXT: [[ce07:%\d+]] = OpCompositeExtract %uint [[uintvec2]] 0
 // CHECK-NEXT: [[ce08:%\d+]] = OpCompositeExtract %uint [[uintvec2]] 1
 // CHECK-NEXT: [[convert2:%\d+]] = OpConvertUToF %float [[ce07]]
 // CHECK-NEXT: [[cc18:%\d+]] = OpCompositeConstruct %v3float [[convert0]] [[convert1]] [[convert2]]
 
 // CHECK-NEXT: [[convert3:%\d+]] = OpConvertUToF %float [[ce08]]
-// CHECK-NEXT: [[intscalar:%\d+]] = OpLoad %int %intScalar
-// CHECK-NEXT: [[convert4:%\d+]] = OpConvertSToF %float [[intscalar]]
-// CHECK-NEXT: [[boolscalar:%\d+]] = OpLoad %bool %boolScalar
-// CHECK-NEXT: [[convert5:%\d+]] = OpSelect %float [[boolscalar]] %float_1 %float_0
 // CHECK-NEXT: [[cc19:%\d+]] = OpCompositeConstruct %v3float [[convert3]] [[convert4]] [[convert5]]
 
-// CHECK-NEXT: [[boolvec3:%\d+]] = OpLoad %v3bool %boolVec3
 // CHECK-NEXT: [[convert6:%\d+]] = OpSelect %v3float [[boolvec3]] [[v3fc1]] [[v3fc0]]
 // CHECK-NEXT: [[cc20:%\d+]] = OpCompositeConstruct %mat3v3float [[cc18]] [[cc19]] [[convert6]]
 
@@ -120,13 +116,15 @@ void main() {
     // extract vectors from matrices directly.
 
 // CHECK-NEXT: [[mat8:%\d+]] = OpLoad %mat2v2float %mat8
+// CHECK-NEXT: [[mat9:%\d+]] = OpLoad %mat2v4float %mat9
+// CHECK-NEXT: [[mat10:%\d+]] = OpLoad %v4float %mat10
+
 // CHECK-NEXT: [[mat8_00:%\d+]] = OpCompositeExtract %float [[mat8]] 0 0
 // CHECK-NEXT: [[mat8_01:%\d+]] = OpCompositeExtract %float [[mat8]] 0 1
 // CHECK-NEXT: [[mat8_10:%\d+]] = OpCompositeExtract %float [[mat8]] 1 0
 // CHECK-NEXT: [[mat8_11:%\d+]] = OpCompositeExtract %float [[mat8]] 1 1
 // CHECK-NEXT: [[cc21:%\d+]] = OpCompositeConstruct %v4float [[mat8_00]] [[mat8_01]] [[mat8_10]] [[mat8_11]]
 
-// CHECK-NEXT: [[mat9:%\d+]] = OpLoad %mat2v4float %mat9
 // CHECK-NEXT: [[mat9_00:%\d+]] = OpCompositeExtract %float [[mat9]] 0 0
 // CHECK-NEXT: [[mat9_01:%\d+]] = OpCompositeExtract %float [[mat9]] 0 1
 // CHECK-NEXT: [[mat9_02:%\d+]] = OpCompositeExtract %float [[mat9]] 0 2
@@ -138,7 +136,6 @@ void main() {
 // CHECK-NEXT: [[cc22:%\d+]] = OpCompositeConstruct %v4float [[mat9_00]] [[mat9_01]] [[mat9_02]] [[mat9_03]]
 // CHECK-NEXT: [[cc23:%\d+]] = OpCompositeConstruct %v4float [[mat9_10]] [[mat9_11]] [[mat9_12]] [[mat9_13]]
 
-// CHECK-NEXT: [[mat10:%\d+]] = OpLoad %v4float %mat10
 // CHECK-NEXT: [[mat10_0:%\d+]] = OpCompositeExtract %float [[mat10]] 0
 // CHECK-NEXT: [[mat10_1:%\d+]] = OpCompositeExtract %float [[mat10]] 1
 // CHECK-NEXT: [[mat10_2:%\d+]] = OpCompositeExtract %float [[mat10]] 2
@@ -188,23 +185,21 @@ void main() {
 // CHECK:         [[s:%\d+]] = OpLoad %int %intScalar
 // CHECK-NEXT: [[vec1:%\d+]] = OpLoad %int %intVec1
 // CHECK-NEXT: [[vec2:%\d+]] = OpLoad %v2int %intVec2
+// CHECK-NEXT: [[vec3:%\d+]] = OpLoad %v3int %intVec3
+// CHECK-NEXT:[[vec2a:%\d+]] = OpLoad %v2int %intVec2
+// CHECK-NEXT: [[vec4:%\d+]] = OpLoad %v4int %intVec4
+
 // CHECK-NEXT: [[ce00:%\d+]] = OpCompositeExtract %int [[vec2]] 0
 // CHECK-NEXT: [[ce01:%\d+]] = OpCompositeExtract %int [[vec2]] 1
 // CHECK-NEXT: [[cc14:%\d+]] = OpCompositeConstruct %v4int [[s]] [[vec1]] [[ce00]] [[ce01]]
 
-// CHECK-NEXT: [[vec3:%\d+]] = OpLoad %v3int %intVec3
 // CHECK-NEXT: [[ce02:%\d+]] = OpCompositeExtract %int [[vec3]] 0
 // CHECK-NEXT: [[ce03:%\d+]] = OpCompositeExtract %int [[vec3]] 1
 // CHECK-NEXT: [[ce04:%\d+]] = OpCompositeExtract %int [[vec3]] 2
-// CHECK-NEXT:[[vec2a:%\d+]] = OpLoad %v2int %intVec2
 // CHECK-NEXT: [[ce05:%\d+]] = OpCompositeExtract %int [[vec2a]] 0
 // CHECK-NEXT: [[ce06:%\d+]] = OpCompositeExtract %int [[vec2a]] 1
 // CHECK-NEXT: [[cc15:%\d+]] = OpCompositeConstruct %v4int [[ce02]] [[ce03]] [[ce04]] [[ce05]]
-
 // CHECK-NEXT: [[cc16:%\d+]] = OpCompositeConstruct %v4int [[ce06]] %int_1 %int_2 %int_3
-
-// CHECK-NEXT: [[vec4:%\d+]] = OpLoad %v4int %intVec4
-
 // CHECK-NEXT: [[cc17:%\d+]] = OpCompositeConstruct %_arr_v4int_uint_4 [[cc14]] [[cc15]] [[cc16]] [[vec4]]
 // CHECK-NEXT:  OpStore %imat5 [[cc17]]
     int4x4 imat5 = {intScalar, intVec1, intVec2, // [0]
@@ -224,19 +219,19 @@ void main() {
 // CHECK-NEXT:              [[uintScalar:%\d+]] = OpLoad %uint %uintScalar
 // CHECK-NEXT:               [[intScalar:%\d+]] = OpBitcast %int [[uintScalar]]
 // CHECK-NEXT:                [[uintVec2:%\d+]] = OpLoad %v2uint %uintVec2
+// CHECK-NEXT:             [[floatScalar:%\d+]] = OpLoad %float %floatScalar
+// CHECK-NEXT: [[convert_floatScalar_int:%\d+]] = OpConvertFToS %int [[floatScalar]]
+// CHECK-NEXT:              [[boolScalar:%\d+]] = OpLoad %bool %boolScalar
+// CHECK-NEXT:  [[convert_boolScalar_int:%\d+]] = OpSelect %int [[boolScalar]] %int_1 %int_0
+// CHECK-NEXT:                  [[v3bool:%\d+]] = OpLoad %v3bool %boolVec3
 // CHECK-NEXT:              [[uintVec2e0:%\d+]] = OpCompositeExtract %uint [[uintVec2]] 0
 // CHECK-NEXT:              [[uintVec2e1:%\d+]] = OpCompositeExtract %uint [[uintVec2]] 1
 // CHECK-NEXT:  [[convert_uintVec2e0_int:%\d+]] = OpBitcast %int [[uintVec2e0]]
 // CHECK-NEXT:                [[imat7_r0:%\d+]] = OpCompositeConstruct %v3int [[intVec1]] [[intScalar]] [[convert_uintVec2e0_int]]
 // CHECK-NEXT:  [[convert_uintVec2e1_int:%\d+]] = OpBitcast %int [[uintVec2e1]]
-// CHECK-NEXT:             [[floatScalar:%\d+]] = OpLoad %float %floatScalar
-// CHECK-NEXT: [[convert_floatScalar_int:%\d+]] = OpConvertFToS %int [[floatScalar]]
-// CHECK-NEXT:              [[boolScalar:%\d+]] = OpLoad %bool %boolScalar
-// CHECK-NEXT:  [[convert_boolScalar_int:%\d+]] = OpSelect %int [[boolScalar]] %int_1 %int_0
 // CHECK-NEXT:                [[imat7_r1:%\d+]] = OpCompositeConstruct %v3int [[convert_uintVec2e1_int]] [[convert_floatScalar_int]] [[convert_boolScalar_int]]
-// CHECK-NEXT:                  [[v3bool:%\d+]] = OpLoad %v3bool %boolVec3
 // CHECK-NEXT:                [[imat7_r2:%\d+]] = OpSelect %v3int [[v3bool]] {{%\d+}} {{%\d+}}
-// CHECK-NEXT:                         {{%\d+}} = OpCompositeConstruct %_arr_v3int_uint_3 [[imat7_r0]] [[imat7_r1]] [[imat7_r2]] 
+// CHECK-NEXT:                         {{%\d+}} = OpCompositeConstruct %_arr_v3int_uint_3 [[imat7_r0]] [[imat7_r1]] [[imat7_r2]]
     int3x3 imat7 = {intVec1, uintScalar, uintVec2, // [0] + 1 scalar
                     floatScalar, boolScalar,       // [1] - 1 scalar
                     boolVec3                       // [2]
@@ -251,13 +246,15 @@ void main() {
     // extract vectors from matrices directly.
 
 // CHECK:         [[imat8:%\d+]] = OpLoad %_arr_v2int_uint_2 %imat8
+// CHECK-NEXT:    [[imat9:%\d+]] = OpLoad %_arr_v4int_uint_2 %imat9
+// CHECK-NEXT:   [[imat10:%\d+]] = OpLoad %v4int %imat10
+
 // CHECK-NEXT: [[imat8_00:%\d+]] = OpCompositeExtract %int [[imat8]] 0 0
 // CHECK-NEXT: [[imat8_01:%\d+]] = OpCompositeExtract %int [[imat8]] 0 1
 // CHECK-NEXT: [[imat8_10:%\d+]] = OpCompositeExtract %int [[imat8]] 1 0
 // CHECK-NEXT: [[imat8_11:%\d+]] = OpCompositeExtract %int [[imat8]] 1 1
 // CHECK-NEXT:     [[cc21:%\d+]] = OpCompositeConstruct %v4int [[imat8_00]] [[imat8_01]] [[imat8_10]] [[imat8_11]]
 
-// CHECK-NEXT:    [[imat9:%\d+]] = OpLoad %_arr_v4int_uint_2 %imat9
 // CHECK-NEXT: [[imat9_00:%\d+]] = OpCompositeExtract %int [[imat9]] 0 0
 // CHECK-NEXT: [[imat9_01:%\d+]] = OpCompositeExtract %int [[imat9]] 0 1
 // CHECK-NEXT: [[imat9_02:%\d+]] = OpCompositeExtract %int [[imat9]] 0 2
@@ -269,7 +266,6 @@ void main() {
 // CHECK-NEXT:     [[cc22:%\d+]] = OpCompositeConstruct %v4int [[imat9_00]] [[imat9_01]] [[imat9_02]] [[imat9_03]]
 // CHECK-NEXT:     [[cc23:%\d+]] = OpCompositeConstruct %v4int [[imat9_10]] [[imat9_11]] [[imat9_12]] [[imat9_13]]
 
-// CHECK-NEXT: [[imat10:%\d+]] = OpLoad %v4int %imat10
 // CHECK-NEXT: [[imat10_0:%\d+]] = OpCompositeExtract %int [[imat10]] 0
 // CHECK-NEXT: [[imat10_1:%\d+]] = OpCompositeExtract %int [[imat10]] 1
 // CHECK-NEXT: [[imat10_2:%\d+]] = OpCompositeExtract %int [[imat10]] 2

+ 9 - 10
tools/clang/test/CodeGenSPIRV/var.init.opaque.hlsl

@@ -23,22 +23,21 @@ Texture2D    gTex2D;
 
 float main() : A {
 
-// CHECK:      [[tex3d:%\d+]] = OpLoad %type_3d_image %gTex3D
-// CHECK-NEXT: [[sampl:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT: [[comb2:%\d+]] = OpCompositeConstruct %Combined2 [[tex3d]] [[sampl]]
+// CHECK:       [[tex3d:%\d+]] = OpLoad %type_3d_image %gTex3D
+// CHECK-NEXT:  [[sampl:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:  [[comb2:%\d+]] = OpCompositeConstruct %Combined2 [[tex3d]] [[sampl]]
 // CHECK-NEXT:                  OpStore %comb2 [[comb2]]
     Combined2 comb2 = {gTex3D, gSampler};
 
-// CHECK-NEXT:   [[ptr:%\d+]] = OpAccessChain %_ptr_Function_type_3d_image %comb2 %int_0
-// CHECK-NEXT: [[tex3d:%\d+]] = OpLoad %type_3d_image [[ptr]]
-// CHECK-NEXT: [[inner:%\d+]] = OpCompositeConstruct %Inner [[tex3d]]
-// CHECK-NEXT:   [[ptr:%\d+]] = OpAccessChain %_ptr_Function_type_sampler %comb2 %int_1
-// CHECK-NEXT: [[sampl1:%\d+]] = OpLoad %type_sampler [[ptr]]
+// CHECK-NEXT:  [[tex3d:%\d+]] = OpLoad %Combined2 %comb2
 // CHECK-NEXT: [[tex2d1:%\d+]] = OpLoad %type_2d_image %gTex2D
 // CHECK-NEXT: [[tex2d2:%\d+]] = OpLoad %type_2d_image %gTex2D
 // CHECK-NEXT: [[sampl2:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT: [[comb1:%\d+]] = OpCompositeConstruct %Combined1 [[inner]] [[sampl1]] [[tex2d1]] [[tex2d2]] [[sampl2]]
-// CHECK-NEXT:                  OpStore %comb1 [[comb1]]
+// CHECK-NEXT:  [[tex3d:%\d+]] = OpCompositeExtract %type_3d_image %32 0
+// CHECK-NEXT: [[sampl1:%\d+]] = OpCompositeExtract %type_sampler %32 1
+// CHECK-NEXT:  [[inner:%\d+]] = OpCompositeConstruct %Inner [[tex3d]]
+// CHECK-NEXT:  [[comb1:%\d+]] = OpCompositeConstruct %Combined1 [[inner]] [[sampl1]] [[tex2d1]] [[tex2d2]] [[sampl2]]
+// CHECK-NEXT:                   OpStore %comb1 [[comb1]]
     Combined1 comb1 = {comb2, {gTex2D, gTex2D}, gSampler};
 
     return 1.0;

+ 17 - 22
tools/clang/test/CodeGenSPIRV/var.init.struct.hlsl

@@ -41,7 +41,8 @@ void main() {
 // CHECK-NEXT: [[c0:%\d+]] = OpCompositeConstruct %v2float %float_1 %float_2
 // CHECK-NEXT: [[c1:%\d+]] = OpCompositeConstruct %v2float %float_3 %float_4
 // CHECK-NEXT: [[c:%\d+]] = OpCompositeConstruct %mat2v2float [[c0]] [[c1]]
-// CHECK-NEXT: {{%\d+}} = OpCompositeConstruct %S [[a]] %uint_42 [[c]]
+// CHECK-NEXT: [[s1:%\d+]] = OpCompositeConstruct %S [[a]] %uint_42 [[c]]
+// CHECK-NEXT: OpStore %s1 [[s1]]
     S s1 = {1, 2, 3, 42, 1., 2., 3., 4.};
 
     // Random parentheses
@@ -49,40 +50,34 @@ void main() {
 // CHECK-NEXT: [[c0:%\d+]] = OpCompositeConstruct %v2float %float_1 %float_2
 // CHECK-NEXT: [[c1:%\d+]] = OpCompositeConstruct %v2float %float_3 %float_4
 // CHECK-NEXT: [[c:%\d+]] = OpCompositeConstruct %mat2v2float [[c0]] [[c1]]
-// CHECK-NEXT: {{%\d+}} = OpCompositeConstruct %S [[a]] %uint_42 [[c]]
+// CHECK-NEXT: [[s2:%\d+]] = OpCompositeConstruct %S [[a]] %uint_42 [[c]]
+// CHECK-NEXT: OpStore %s2 [[s2]]
     S s2 = {{1, 2}, 3, {{42}, {{1.}}}, {2., {3., 4.}}};
 
     // Flat initalizer list for nested structs
 // CHECK:      [[y:%\d+]] = OpCompositeConstruct %O %int_1
-// CHECK-NEXT: {{%\d+}} = OpCompositeConstruct %P [[y]] %float_2
+// CHECK-NEXT: [[p:%\d+]] = OpCompositeConstruct %P [[y]] %float_2
+// CHECK-NEXT: OpStore %p [[p]]
     P p = {1, 2.};
 
     // Mixed case: use struct as a whole, decomposing struct, type casting
-// CHECK:      [[s1a:%\d+]] = OpAccessChain %_ptr_Function_v3int %s1 %int_0
-// CHECK-NEXT: [[h:%\d+]] = OpLoad %v3int [[s1a]]
 
-// CHECK-NEXT: [[s1b:%\d+]] = OpAccessChain %_ptr_Function_uint %s1 %int_1
-// CHECK-NEXT: [[i:%\d+]] = OpLoad %uint [[s1b]]
-
-// CHECK-NEXT: [[s1c:%\d+]] = OpAccessChain %_ptr_Function_mat2v2float %s1 %int_2
-// CHECK-NEXT: [[j:%\d+]] = OpLoad %mat2v2float [[s1c]]
+// CHECK-NEXT: [[s1_val:%\d+]] = OpLoad %S %s1
+// CHECK-NEXT: [[l:%\d+]] = OpLoad %S %s2
+// CHECK-NEXT: [[s2_val:%\d+]] = OpLoad %S %s2
+// CHECK-NEXT: [[h:%\d+]] = OpCompositeExtract %v3int [[s1_val]] 0
+// CHECK-NEXT: [[i:%\d+]] = OpCompositeExtract %uint [[s1_val]] 1
+// CHECK-NEXT: [[j:%\d+]] = OpCompositeExtract %mat2v2float [[s1_val]] 2
 
 // CHECK-NEXT: [[k:%\d+]] = OpCompositeConstruct %v2bool %true %false
 
-// CHECK-NEXT: [[l:%\d+]] = OpLoad %S %s2
-
-// CHECK-NEXT: [[s2a:%\d+]] = OpAccessChain %_ptr_Function_v3int %s2 %int_0
-// CHECK-NEXT: [[s2av:%\d+]] = OpLoad %v3int [[s2a]]
+// CHECK-NEXT: [[s2av:%\d+]] = OpCompositeExtract %v3int [[s2_val]] 0
+// CHECK-NEXT: [[s2bv:%\d+]] = OpCompositeExtract %uint [[s2_val]] 1
+// CHECK-NEXT: [[o:%\d+]] = OpCompositeExtract %mat2v2float [[s2_val]] 2
 // CHECK-NEXT: [[m:%\d+]] = OpConvertSToF %v3float [[s2av]]
-
-// CHECK-NEXT: [[s2b:%\d+]] = OpAccessChain %_ptr_Function_uint %s2 %int_1
-// CHECK-NEXT: [[s2bv:%\d+]] = OpLoad %uint [[s2b]]
 // CHECK-NEXT: [[n:%\d+]] = OpBitcast %int [[s2bv]]
-
-// CHECK-NEXT: [[s2c:%\d+]] = OpAccessChain %_ptr_Function_mat2v2float %s2 %int_2
-// CHECK-NEXT: [[o:%\d+]] = OpLoad %mat2v2float [[s2c]]
-
-// CHECK-NEXT: {{%\d+}} = OpCompositeConstruct %T [[h]] [[i]] [[j]] [[k]] [[l]] [[m]] [[n]] [[o]]
+// CHECK-NEXT: [[t:%\d+]] = OpCompositeConstruct %T [[h]] [[i]] [[j]] [[k]] [[l]] [[m]] [[n]] [[o]]
+// CHECK-NEXT: OpStore %t [[t]]
     T t = {s1,          // Decomposing struct
            true, false, // constructing field from scalar
            s2,          // Embedded struct

+ 3 - 0
tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp

@@ -389,6 +389,9 @@ TEST_F(FileTest, CastExplicit2FP) { runFileTest("cast.2fp.explicit.hlsl"); }
 TEST_F(FileTest, CastImplicit2LiteralInt) {
   runFileTest("cast.2literal-int.implicit.hlsl");
 }
+TEST_F(FileTest, CastFlatConversionArrayToVector) {
+  runFileTest("cast.flat-conversion.array-to-vector.hlsl");
+}
 TEST_F(FileTest, CastImplicitFlatConversion) {
   runFileTest("cast.flat-conversion.implicit.hlsl");
 }