Browse Source

[spirv] Handle parentheses in vector swizzling. (#2066)

Ehsan 6 years ago
parent
commit
327e37077e

+ 8 - 4
tools/clang/lib/SPIRV/SpirvEmitter.cpp

@@ -5349,14 +5349,18 @@ void SpirvEmitter::condenseVectorElementExpr(
     const HLSLVectorElementExpr *expr, const Expr **basePtr,
     hlsl::VectorMemberAccessPositions *flattenedAccessor) {
   llvm::SmallVector<hlsl::VectorMemberAccessPositions, 2> accessors;
-  accessors.push_back(expr->getEncodedElementAccess());
+  *basePtr = expr;
 
-  // Recursively descending until we find the true base vector. In the
-  // meanwhile, collecting accessors in the reverse order.
-  *basePtr = expr->getBase();
+  // Recursively descending until we find the true base vector (the base vector
+  // that does not have a base vector). In the meanwhile, collecting accessors
+  // in the reverse order.
+  // Example: for myVector.yxwz.yxz.xx.yx, the true base is 'myVector'.
   while (const auto *vecElemBase = dyn_cast<HLSLVectorElementExpr>(*basePtr)) {
     accessors.push_back(vecElemBase->getEncodedElementAccess());
     *basePtr = vecElemBase->getBase();
+    // We need to skip any number of parentheses around swizzling at any level.
+    while (const auto *parenExpr = dyn_cast<ParenExpr>(*basePtr))
+      *basePtr = parenExpr->getSubExpr();
   }
 
   *flattenedAccessor = accessors.back();

+ 22 - 0
tools/clang/test/CodeGenSPIRV/op.vector.swizzle.hlsl

@@ -136,4 +136,26 @@ void main() {
 // CHECK-NEXT: [[ac3:%\d+]] = OpAccessChain %_ptr_Function_float %v4f2 %int_3
 // CHECK-NEXT: OpStore [[ac3]] [[e0]]
     v4f2.w.x.x.x = v4f1.y.x.x.x; // continuously selecting one element
+
+    // Continuous selection with parentheses
+
+// CHECK-NEXT: [[ptr:%\d+]] = OpAccessChain %_ptr_Function_float %v4f1 %int_3
+// CHECK-NEXT:                OpStore [[ptr]] %float_5
+    (v4f1.xwzy.yxz).x = 5.0f;
+
+// CHECK-NEXT: [[ptr:%\d+]] = OpAccessChain %_ptr_Function_float %v4f1 %int_3
+// CHECK-NEXT:                OpStore [[ptr]] %float_5
+    (v4f1.xwzy).yxz.x = 5.0f;
+
+// CHECK-NEXT: [[ptr:%\d+]] = OpAccessChain %_ptr_Function_float %v4f1 %int_3
+// CHECK-NEXT:                OpStore [[ptr]] %float_5
+    ((v4f1.xwzy).yxz).x = 5.0f;
+
+// CHECK-NEXT: [[ptr:%\d+]] = OpAccessChain %_ptr_Function_float %v4f1 %int_3
+// CHECK-NEXT:                OpStore [[ptr]] %float_5
+    (((v4f1.xwzy).yxz).x) = 5.0f;
+
+// CHECK-NEXT: [[ptr:%\d+]] = OpAccessChain %_ptr_Function_float %v4f1 %int_3
+// CHECK-NEXT:                OpStore [[ptr]] %float_5
+    ((((v4f1.xwzy).yxz)).x) = 5.0f;
 }