diff --git a/tools/clang/lib/SPIRV/SpirvEmitter.cpp b/tools/clang/lib/SPIRV/SpirvEmitter.cpp index 79792a80d9..ad19ed7733 100644 --- a/tools/clang/lib/SPIRV/SpirvEmitter.cpp +++ b/tools/clang/lib/SPIRV/SpirvEmitter.cpp @@ -12368,7 +12368,9 @@ SpirvEmitter::processIntrinsicAsType(const CallExpr *callExpr) { // Method 4: double asdouble(uint lowbits, uint highbits) // Method 5: double2 asdouble(uint2 lowbits, uint2 highbits) - // Method 6: + // Method 6: double3 asdouble(uint3 lowbits, uint3 highbits) + // Method 7: double4 asdouble(uint4 lowbits, uint4 highbits) + // Method 8: // void asuint( // in double value, // out uint lowbits, @@ -12417,26 +12419,33 @@ SpirvEmitter::processIntrinsicAsType(const CallExpr *callExpr) { auto *highbits = doExpr(callExpr->getArg(1)); const auto uintType = astContext.UnsignedIntTy; const auto doubleType = astContext.DoubleTy; + uint32_t vecSize; // Handling Method 4 - if (argType->isUnsignedIntegerType()) { + if (!isVectorType(argType, nullptr, &vecSize)) { const auto uintVec2Type = astContext.getExtVectorType(uintType, 2); auto *operand = spvBuilder.createCompositeConstruct( uintVec2Type, {lowbits, highbits}, loc, range); return spvBuilder.createUnaryOp(spv::Op::OpBitcast, doubleType, operand, loc, range); } - // Handling Method 5 + // Handling Method 5, 6, 7 else { - const auto uintVec4Type = astContext.getExtVectorType(uintType, 4); - const auto doubleVec2Type = astContext.getExtVectorType(doubleType, 2); - auto *operand = spvBuilder.createVectorShuffle( - uintVec4Type, lowbits, highbits, {0, 2, 1, 3}, loc, range); - return spvBuilder.createUnaryOp(spv::Op::OpBitcast, doubleVec2Type, - operand, loc, range); + std::vector doubles = {}; + const auto uintVec2Type = astContext.getExtVectorType(uintType, 2); + // For each pair, convert them to double. + for (uint32_t i = 0; i < vecSize; ++i) { + auto *operand = spvBuilder.createVectorShuffle( + uintVec2Type, lowbits, highbits, {i, vecSize + i}, loc, range); + SpirvInstruction *doubleElem = spvBuilder.createUnaryOp( + spv::Op::OpBitcast, doubleType, operand, loc, range); + doubles.push_back(doubleElem); + } + return spvBuilder.createCompositeConstruct(returnType, doubles, loc, + range); } } case 3: { - // Handling Method 6. + // Handling Method 8. const Expr *arg1 = callExpr->getArg(1); const Expr *arg2 = callExpr->getArg(2); diff --git a/tools/clang/test/CodeGenSPIRV/intrinsics.asdouble.hlsl b/tools/clang/test/CodeGenSPIRV/intrinsics.asdouble.hlsl index 1da3c35432..be5df31ef4 100644 --- a/tools/clang/test/CodeGenSPIRV/intrinsics.asdouble.hlsl +++ b/tools/clang/test/CodeGenSPIRV/intrinsics.asdouble.hlsl @@ -19,8 +19,37 @@ void main() { // CHECK: [[low2:%[0-9]+]] = OpLoad %v2uint %low2 // CHECK-NEXT: [[high2:%[0-9]+]] = OpLoad %v2uint %high2 -// CHECK-NEXT: [[arg3:%[0-9]+]] = OpVectorShuffle %v4uint [[low2]] [[high2]] 0 2 1 3 -// CHECK-NEXT: {{%[0-9]+}} = OpBitcast %v2double [[arg3]] +// CHECK-NEXT: [[elem1:%[0-9]+]] = OpVectorShuffle %v2uint [[low2]] [[high2]] 0 2 +// CHECK-NEXT: [[double1:%[0-9]+]] = OpBitcast %double [[elem1]] +// CHECK-NEXT: [[elem2:%[0-9]+]] = OpVectorShuffle %v2uint [[low2]] [[high2]] 1 3 +// CHECK-NEXT: [[double2:%[0-9]+]] = OpBitcast %double [[elem2]] +// CHECK-NEXT: {{%[0-9]+}} = OpCompositeConstruct %v2double [[double1]] [[double2]] uint2 low2, high2; double2 c = asdouble(low2, high2); + +// CHECK: [[low3:%[0-9]+]] = OpLoad %v3uint %low3 +// CHECK-NEXT: [[high3:%[0-9]+]] = OpLoad %v3uint %high3 +// CHECK-NEXT: [[elem1:%[0-9]+]] = OpVectorShuffle %v2uint [[low3]] [[high3]] 0 3 +// CHECK-NEXT: [[double1:%[0-9]+]] = OpBitcast %double [[elem1]] +// CHECK-NEXT: [[elem2:%[0-9]+]] = OpVectorShuffle %v2uint [[low3]] [[high3]] 1 4 +// CHECK-NEXT: [[double2:%[0-9]+]] = OpBitcast %double [[elem2]] +// CHECK-NEXT: [[elem3:%[0-9]+]] = OpVectorShuffle %v2uint [[low3]] [[high3]] 2 5 +// CHECK-NEXT: [[double3:%[0-9]+]] = OpBitcast %double [[elem3]] +// CHECK-NEXT: {{%[0-9]+}} = OpCompositeConstruct %v3double [[double1]] [[double2]] [[double3]] + uint3 low3, high3; + double3 d = asdouble(low3, high3); + +// CHECK: [[low4:%[0-9]+]] = OpLoad %v4uint %low4 +// CHECK-NEXT: [[high4:%[0-9]+]] = OpLoad %v4uint %high4 +// CHECK-NEXT: [[elem1:%[0-9]+]] = OpVectorShuffle %v2uint [[low4]] [[high4]] 0 4 +// CHECK-NEXT: [[double1:%[0-9]+]] = OpBitcast %double [[elem1]] +// CHECK-NEXT: [[elem2:%[0-9]+]] = OpVectorShuffle %v2uint [[low4]] [[high4]] 1 5 +// CHECK-NEXT: [[double2:%[0-9]+]] = OpBitcast %double [[elem2]] +// CHECK-NEXT: [[elem3:%[0-9]+]] = OpVectorShuffle %v2uint [[low4]] [[high4]] 2 6 +// CHECK-NEXT: [[double3:%[0-9]+]] = OpBitcast %double [[elem3]] +// CHECK-NEXT: [[elem4:%[0-9]+]] = OpVectorShuffle %v2uint [[low4]] [[high4]] 3 7 +// CHECK-NEXT: [[double4:%[0-9]+]] = OpBitcast %double [[elem4]] +// CHECK-NEXT: {{%[0-9]+}} = OpCompositeConstruct %v4double [[double1]] [[double2]] [[double3]] [[double4]] + uint4 low4, high4; + double4 e = asdouble(low4, high4); }