From be2030e841e6ce99b347b6d5c94ecb01fcddfc97 Mon Sep 17 00:00:00 2001 From: luciechoi Date: Wed, 3 Dec 2025 04:54:25 +0000 Subject: [PATCH 1/2] fix asdouble --- tools/clang/lib/SPIRV/SpirvEmitter.cpp | 32 +++++++++++++------ .../CodeGenSPIRV/intrinsics.asdouble.hlsl | 29 +++++++++++++++-- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/tools/clang/lib/SPIRV/SpirvEmitter.cpp b/tools/clang/lib/SPIRV/SpirvEmitter.cpp index 79792a80d9..7e0931f960 100644 --- a/tools/clang/lib/SPIRV/SpirvEmitter.cpp +++ b/tools/clang/lib/SPIRV/SpirvEmitter.cpp @@ -12368,7 +12368,8 @@ 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: // void asuint( // in double value, // out uint lowbits, @@ -12417,26 +12418,37 @@ 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 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 = {}; + // For each pair, convert them to double. + for (uint32_t i = 0; i < vecSize; ++i) { + SpirvInstruction *lowElem = spvBuilder.createCompositeExtract( + uintType, lowbits, {i}, loc, range); + SpirvInstruction *highElem = spvBuilder.createCompositeExtract( + uintType, highbits, {i}, loc, range); + const auto uintVec2Type = astContext.getExtVectorType(uintType, 2); + auto *operand = spvBuilder.createCompositeConstruct( + uintVec2Type, {lowElem, highElem}, 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 7. 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..aec0b0ae9d 100644 --- a/tools/clang/test/CodeGenSPIRV/intrinsics.asdouble.hlsl +++ b/tools/clang/test/CodeGenSPIRV/intrinsics.asdouble.hlsl @@ -19,8 +19,33 @@ 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: [[lowbit1:%[0-9]+]] = OpCompositeExtract %uint [[low2]] 0 +// CHECK-NEXT: [[highbit1:%[0-9]+]] = OpCompositeExtract %uint [[high2]] 0 +// CHECK-NEXT: [[comp1:%[0-9]+]] = OpCompositeConstruct %v2uint [[lowbit1]] [[highbit1]] +// CHECK-NEXT: [[double1:%[0-9]+]] = OpBitcast %double [[comp1]] +// CHECK-NEXT: [[lowbit2:%[0-9]+]] = OpCompositeExtract %uint [[low2]] 1 +// CHECK-NEXT: [[highbit2:%[0-9]+]] = OpCompositeExtract %uint [[high2]] 1 +// CHECK-NEXT: [[comp2:%[0-9]+]] = OpCompositeConstruct %v2uint [[lowbit2]] [[highbit2]] +// CHECK-NEXT: [[double2:%[0-9]+]] = OpBitcast %double [[comp2]] +// 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: [[lowbit1:%[0-9]+]] = OpCompositeExtract %uint [[low3]] 0 +// CHECK-NEXT: [[highbit1:%[0-9]+]] = OpCompositeExtract %uint [[high3]] 0 +// CHECK-NEXT: [[comp1:%[0-9]+]] = OpCompositeConstruct %v2uint [[lowbit1]] [[highbit1]] +// CHECK-NEXT: [[double1:%[0-9]+]] = OpBitcast %double [[comp1]] +// CHECK-NEXT: [[lowbit2:%[0-9]+]] = OpCompositeExtract %uint [[low3]] 1 +// CHECK-NEXT: [[highbit2:%[0-9]+]] = OpCompositeExtract %uint [[high3]] 1 +// CHECK-NEXT: [[comp2:%[0-9]+]] = OpCompositeConstruct %v2uint [[lowbit2]] [[highbit2]] +// CHECK-NEXT: [[double2:%[0-9]+]] = OpBitcast %double [[comp2]] +// CHECK-NEXT: [[lowbit3:%[0-9]+]] = OpCompositeExtract %uint [[low3]] 2 +// CHECK-NEXT: [[highbit3:%[0-9]+]] = OpCompositeExtract %uint [[high3]] 2 +// CHECK-NEXT: [[comp3:%[0-9]+]] = OpCompositeConstruct %v2uint [[lowbit3]] [[highbit3]] +// CHECK-NEXT: [[double3:%[0-9]+]] = OpBitcast %double [[comp3]] +// CHECK-NEXT: {{%[0-9]+}} = OpCompositeConstruct %v3double [[double1]] [[double2]] [[double3]] + uint3 low3, high3; + double3 d = asdouble(low3, high3); } From 04842e65cf007e0b72070d2e775126e0a3e8265c Mon Sep 17 00:00:00 2001 From: luciechoi Date: Mon, 15 Dec 2025 06:39:54 +0000 Subject: [PATCH 2/2] use OpVectorShuffle --- tools/clang/lib/SPIRV/SpirvEmitter.cpp | 17 +++---- .../CodeGenSPIRV/intrinsics.asdouble.hlsl | 44 ++++++++++--------- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/tools/clang/lib/SPIRV/SpirvEmitter.cpp b/tools/clang/lib/SPIRV/SpirvEmitter.cpp index 7e0931f960..ad19ed7733 100644 --- a/tools/clang/lib/SPIRV/SpirvEmitter.cpp +++ b/tools/clang/lib/SPIRV/SpirvEmitter.cpp @@ -12369,7 +12369,8 @@ SpirvEmitter::processIntrinsicAsType(const CallExpr *callExpr) { // Method 4: double asdouble(uint lowbits, uint highbits) // Method 5: double2 asdouble(uint2 lowbits, uint2 highbits) // Method 6: double3 asdouble(uint3 lowbits, uint3 highbits) - // Method 7: + // Method 7: double4 asdouble(uint4 lowbits, uint4 highbits) + // Method 8: // void asuint( // in double value, // out uint lowbits, @@ -12427,18 +12428,14 @@ SpirvEmitter::processIntrinsicAsType(const CallExpr *callExpr) { return spvBuilder.createUnaryOp(spv::Op::OpBitcast, doubleType, operand, loc, range); } - // Handling Method 5, 6 + // Handling Method 5, 6, 7 else { 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) { - SpirvInstruction *lowElem = spvBuilder.createCompositeExtract( - uintType, lowbits, {i}, loc, range); - SpirvInstruction *highElem = spvBuilder.createCompositeExtract( - uintType, highbits, {i}, loc, range); - const auto uintVec2Type = astContext.getExtVectorType(uintType, 2); - auto *operand = spvBuilder.createCompositeConstruct( - uintVec2Type, {lowElem, highElem}, loc, range); + 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); @@ -12448,7 +12445,7 @@ SpirvEmitter::processIntrinsicAsType(const CallExpr *callExpr) { } } case 3: { - // Handling Method 7. + // 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 aec0b0ae9d..be5df31ef4 100644 --- a/tools/clang/test/CodeGenSPIRV/intrinsics.asdouble.hlsl +++ b/tools/clang/test/CodeGenSPIRV/intrinsics.asdouble.hlsl @@ -19,33 +19,37 @@ void main() { // CHECK: [[low2:%[0-9]+]] = OpLoad %v2uint %low2 // CHECK-NEXT: [[high2:%[0-9]+]] = OpLoad %v2uint %high2 -// CHECK-NEXT: [[lowbit1:%[0-9]+]] = OpCompositeExtract %uint [[low2]] 0 -// CHECK-NEXT: [[highbit1:%[0-9]+]] = OpCompositeExtract %uint [[high2]] 0 -// CHECK-NEXT: [[comp1:%[0-9]+]] = OpCompositeConstruct %v2uint [[lowbit1]] [[highbit1]] -// CHECK-NEXT: [[double1:%[0-9]+]] = OpBitcast %double [[comp1]] -// CHECK-NEXT: [[lowbit2:%[0-9]+]] = OpCompositeExtract %uint [[low2]] 1 -// CHECK-NEXT: [[highbit2:%[0-9]+]] = OpCompositeExtract %uint [[high2]] 1 -// CHECK-NEXT: [[comp2:%[0-9]+]] = OpCompositeConstruct %v2uint [[lowbit2]] [[highbit2]] -// CHECK-NEXT: [[double2:%[0-9]+]] = OpBitcast %double [[comp2]] +// 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: [[lowbit1:%[0-9]+]] = OpCompositeExtract %uint [[low3]] 0 -// CHECK-NEXT: [[highbit1:%[0-9]+]] = OpCompositeExtract %uint [[high3]] 0 -// CHECK-NEXT: [[comp1:%[0-9]+]] = OpCompositeConstruct %v2uint [[lowbit1]] [[highbit1]] -// CHECK-NEXT: [[double1:%[0-9]+]] = OpBitcast %double [[comp1]] -// CHECK-NEXT: [[lowbit2:%[0-9]+]] = OpCompositeExtract %uint [[low3]] 1 -// CHECK-NEXT: [[highbit2:%[0-9]+]] = OpCompositeExtract %uint [[high3]] 1 -// CHECK-NEXT: [[comp2:%[0-9]+]] = OpCompositeConstruct %v2uint [[lowbit2]] [[highbit2]] -// CHECK-NEXT: [[double2:%[0-9]+]] = OpBitcast %double [[comp2]] -// CHECK-NEXT: [[lowbit3:%[0-9]+]] = OpCompositeExtract %uint [[low3]] 2 -// CHECK-NEXT: [[highbit3:%[0-9]+]] = OpCompositeExtract %uint [[high3]] 2 -// CHECK-NEXT: [[comp3:%[0-9]+]] = OpCompositeConstruct %v2uint [[lowbit3]] [[highbit3]] -// CHECK-NEXT: [[double3:%[0-9]+]] = OpBitcast %double [[comp3]] +// 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); }