Skip to content

Commit

Permalink
[SPIRV] Support 16-bit Type Cast Intrinsics (#4679)
Browse files Browse the repository at this point in the history
* [SPIRV] Support 16-bit Type Cast Intrinsics

This change adds support for 16-bit type cast intrinsics by routing
them into the same logic used by the 32-bit type casts. With this
change in place, asfloat16, asint16, and asuint16 are now translated
into OpBitcast in SPIR-V.

This change also includes new partial disassembly tests for each
function similar to the ones used for 32-bit casts.

* Update Comments in processIntrinsicsAsType

This commit updates the comments at the top of processIntrinsicsAsType
in order to indicate that this function also supports the 16-bit
variants of the type casting intrinsics.
  • Loading branch information
gmitrano-unity committed Sep 27, 2022
1 parent dc5949e commit aaa30e2
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 1 deletion.
16 changes: 15 additions & 1 deletion tools/clang/lib/SPIRV/SpirvEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7969,8 +7969,11 @@ SpirvEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
break;
case hlsl::IntrinsicOp::IOP_asdouble:
case hlsl::IntrinsicOp::IOP_asfloat:
case hlsl::IntrinsicOp::IOP_asfloat16:
case hlsl::IntrinsicOp::IOP_asint:
case hlsl::IntrinsicOp::IOP_asint16:
case hlsl::IntrinsicOp::IOP_asuint:
case hlsl::IntrinsicOp::IOP_asuint16:
retVal = processIntrinsicAsType(callExpr);
break;
case hlsl::IntrinsicOp::IOP_clip:
Expand Down Expand Up @@ -10106,7 +10109,18 @@ SpirvEmitter::processIntrinsicAllOrAny(const CallExpr *callExpr,

SpirvInstruction *
SpirvEmitter::processIntrinsicAsType(const CallExpr *callExpr) {
// This function handles 'asint', 'asuint', 'asfloat', and 'asdouble'.
// This function handles the following intrinsics:
// 'asint'
// 'asint16'
// 'asuint'
// 'asuint16'
// 'asfloat'
// 'asfloat16'
// 'asdouble'

// Note: The logic for the 32-bit and 16-bit variants of these functions is
// identical so we don't bother distinguishing between related types
// like float and float16 in the comments.

// Method 1: ret asint(arg)
// arg component type = {float, uint}
Expand Down
64 changes: 64 additions & 0 deletions tools/clang/test/CodeGenSPIRV/intrinsics.asfloat16.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// RUN: %dxc -T vs_6_2 -E main -enable-16bit-types

// CHECK: OpCapability Float16
// CHECK: OpCapability Int16

void main() {
float16_t result;
float16_t4 result4;

// CHECK: [[a:%\d+]] = OpLoad %short %a
// CHECK-NEXT: [[a_as_half:%\d+]] = OpBitcast %half [[a]]
// CHECK-NEXT: OpStore %result [[a_as_half]]
int16_t a;
result = asfloat16(a);

// CHECK-NEXT: [[b:%\d+]] = OpLoad %ushort %b
// CHECK-NEXT: [[b_as_half:%\d+]] = OpBitcast %half [[b]]
// CHECK-NEXT: OpStore %result [[b_as_half]]
uint16_t b;
result = asfloat16(b);

// CHECK-NEXT: [[c:%\d+]] = OpLoad %half %c
// CHECK-NEXT: OpStore %result [[c]]
float16_t c;
result = asfloat16(c);

// CHECK-NEXT: [[d:%\d+]] = OpLoad %v4short %d
// CHECK-NEXT: [[d_as_half:%\d+]] = OpBitcast %v4half [[d]]
// CHECK-NEXT: OpStore %result4 [[d_as_half]]
int16_t4 d;
result4 = asfloat16(d);

// CHECK-NEXT: [[e:%\d+]] = OpLoad %v4ushort %e
// CHECK-NEXT: [[e_as_half:%\d+]] = OpBitcast %v4half [[e]]
// CHECK-NEXT: OpStore %result4 [[e_as_half]]
uint16_t4 e;
result4 = asfloat16(e);

// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4half %f
// CHECK-NEXT: OpStore %result4 [[f]]
float16_t4 f;
result4 = asfloat16(f);

int16_t2x3 intMat;
uint16_t2x3 uintMat;

// CHECK: [[intMat:%\d+]] = OpLoad %_arr_v3short_uint_2 %intMat
// CHECK-NEXT: [[intMat0:%\d+]] = OpCompositeExtract %v3short [[intMat]] 0
// CHECK-NEXT: [[row0:%\d+]] = OpBitcast %v3half [[intMat0]]
// CHECK-NEXT: [[intMat1:%\d+]] = OpCompositeExtract %v3short [[intMat]] 1
// CHECK-NEXT: [[row1:%\d+]] = OpBitcast %v3half [[intMat1]]
// CHECK-NEXT: [[g:%\d+]] = OpCompositeConstruct %mat2v3half [[row0]] [[row1]]
// CHECK-NEXT: OpStore %g [[g]]
float16_t2x3 g = asfloat16(intMat);

// CHECK: [[uintMat:%\d+]] = OpLoad %_arr_v3ushort_uint_2 %uintMat
// CHECK-NEXT: [[uintMat0:%\d+]] = OpCompositeExtract %v3ushort [[uintMat]] 0
// CHECK-NEXT: [[row0:%\d+]] = OpBitcast %v3half [[uintMat0]]
// CHECK-NEXT: [[uintMat1:%\d+]] = OpCompositeExtract %v3ushort [[uintMat]] 1
// CHECK-NEXT: [[row1:%\d+]] = OpBitcast %v3half [[uintMat1]]
// CHECK-NEXT: [[h:%\d+]] = OpCompositeConstruct %mat2v3half [[row0]] [[row1]]
// CHECK-NEXT: OpStore %h [[h]]
float16_t2x3 h = asfloat16(uintMat);
}
64 changes: 64 additions & 0 deletions tools/clang/test/CodeGenSPIRV/intrinsics.asint16.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// RUN: %dxc -T vs_6_2 -E main -enable-16bit-types

// CHECK: OpCapability Int16
// CHECK: OpCapability Float16

void main() {
int16_t result;
int16_t4 result4;

// CHECK: [[a:%\d+]] = OpLoad %short %a
// CHECK-NEXT: OpStore %result [[a]]
int16_t a;
result = asint16(a);

// CHECK: [[b:%\d+]] = OpLoad %ushort %b
// CHECK-NEXT: [[b_as_short:%\d+]] = OpBitcast %short [[b]]
// CHECK-NEXT: OpStore %result [[b_as_short]]
uint16_t b;
result = asint16(b);

// CHECK: [[c:%\d+]] = OpLoad %half %c
// CHECK-NEXT: [[c_as_short:%\d+]] = OpBitcast %short [[c]]
// CHECK-NEXT: OpStore %result [[c_as_short]]
float16_t c;
result = asint16(c);

// CHECK: [[d:%\d+]] = OpLoad %v4short %d
// CHECK-NEXT: OpStore %result4 [[d]]
int16_t4 d;
result4 = asint16(d);

// CHECK: [[e:%\d+]] = OpLoad %v4ushort %e
// CHECK-NEXT: [[e_as_short:%\d+]] = OpBitcast %v4short [[e]]
// CHECK-NEXT: OpStore %result4 [[e_as_short]]
uint16_t4 e;
result4 = asint16(e);

// CHECK: [[f:%\d+]] = OpLoad %v4half %f
// CHECK-NEXT: [[f_as_short:%\d+]] = OpBitcast %v4short [[f]]
// CHECK-NEXT: OpStore %result4 [[f_as_short]]
float16_t4 f;
result4 = asint16(f);

float16_t2x3 floatMat;
uint16_t2x3 uintMat;

// CHECK: [[floatMat:%\d+]] = OpLoad %mat2v3half %floatMat
// CHECK-NEXT: [[floatMat0:%\d+]] = OpCompositeExtract %v3half [[floatMat]] 0
// CHECK-NEXT: [[row0:%\d+]] = OpBitcast %v3short [[floatMat0]]
// CHECK-NEXT: [[floatMat1:%\d+]] = OpCompositeExtract %v3half [[floatMat]] 1
// CHECK-NEXT: [[row1:%\d+]] = OpBitcast %v3short [[floatMat1]]
// CHECK-NEXT: [[g:%\d+]] = OpCompositeConstruct %_arr_v3short_uint_2 [[row0]] [[row1]]
// CHECK-NEXT: OpStore %g [[g]]
int16_t2x3 g = asint16(floatMat);

// CHECK: [[uintMat:%\d+]] = OpLoad %_arr_v3ushort_uint_2 %uintMat
// CHECK-NEXT: [[uintMat0:%\d+]] = OpCompositeExtract %v3ushort [[uintMat]] 0
// CHECK-NEXT: [[row0:%\d+]] = OpBitcast %v3short [[uintMat0]]
// CHECK-NEXT: [[uintMat1:%\d+]] = OpCompositeExtract %v3ushort [[uintMat]] 1
// CHECK-NEXT: [[row1:%\d+]] = OpBitcast %v3short [[uintMat1]]
// CHECK-NEXT: [[h:%\d+]] = OpCompositeConstruct %_arr_v3short_uint_2 [[row0]] [[row1]]
// CHECK-NEXT: OpStore %h [[h]]
int16_t2x3 h = asint16(uintMat);
}
64 changes: 64 additions & 0 deletions tools/clang/test/CodeGenSPIRV/intrinsics.asuint16.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// RUN: %dxc -T vs_6_2 -E main -enable-16bit-types

// CHECK: OpCapability Int16
// CHECK: OpCapability Float16

void main() {
uint16_t result;
uint16_t4 result4;

// CHECK: [[a:%\d+]] = OpLoad %short %a
// CHECK-NEXT: [[a_as_ushort:%\d+]] = OpBitcast %ushort [[a]]
// CHECK-NEXT: OpStore %result [[a_as_ushort]]
int16_t a;
result = asuint16(a);

// CHECK: [[b:%\d+]] = OpLoad %ushort %b
// CHECK-NEXT: OpStore %result [[b]]
uint16_t b;
result = asuint16(b);

// CHECK: [[c:%\d+]] = OpLoad %half %c
// CHECK-NEXT: [[c_as_ushort:%\d+]] = OpBitcast %ushort [[c]]
// CHECK-NEXT: OpStore %result [[c_as_ushort]]
float16_t c;
result = asuint16(c);

// CHECK: [[d:%\d+]] = OpLoad %v4short %d
// CHECK-NEXT: [[d_as_ushort:%\d+]] = OpBitcast %v4ushort [[d]]
// CHECK-NEXT: OpStore %result4 [[d_as_ushort]]
int16_t4 d;
result4 = asuint16(d);

// CHECK: [[e:%\d+]] = OpLoad %v4ushort %e
// CHECK-NEXT: OpStore %result4 [[e]]
uint16_t4 e;
result4 = asuint16(e);

// CHECK: [[f:%\d+]] = OpLoad %v4half %f
// CHECK-NEXT: [[f_as_ushort:%\d+]] = OpBitcast %v4ushort [[f]]
// CHECK-NEXT: OpStore %result4 [[f_as_ushort]]
float16_t4 f;
result4 = asuint16(f);

float16_t2x3 floatMat;
int16_t2x3 intMat;

// CHECK: [[floatMat:%\d+]] = OpLoad %mat2v3half %floatMat
// CHECK-NEXT: [[floatMat0:%\d+]] = OpCompositeExtract %v3half [[floatMat]] 0
// CHECK-NEXT: [[row0:%\d+]] = OpBitcast %v3ushort [[floatMat0]]
// CHECK-NEXT: [[floatMat1:%\d+]] = OpCompositeExtract %v3half [[floatMat]] 1
// CHECK-NEXT: [[row1:%\d+]] = OpBitcast %v3ushort [[floatMat1]]
// CHECK-NEXT: [[g:%\d+]] = OpCompositeConstruct %_arr_v3ushort_uint_2 [[row0]] [[row1]]
// CHECK-NEXT: OpStore %g [[g]]
uint16_t2x3 g = asuint16(floatMat);

// CHECK: [[intMat:%\d+]] = OpLoad %_arr_v3short_uint_2 %intMat
// CHECK-NEXT: [[intMat0:%\d+]] = OpCompositeExtract %v3short [[intMat]] 0
// CHECK-NEXT: [[row0:%\d+]] = OpBitcast %v3ushort [[intMat0]]
// CHECK-NEXT: [[intMat1:%\d+]] = OpCompositeExtract %v3short [[intMat]] 1
// CHECK-NEXT: [[row1:%\d+]] = OpBitcast %v3ushort [[intMat1]]
// CHECK-NEXT: [[h:%\d+]] = OpCompositeConstruct %_arr_v3ushort_uint_2 [[row0]] [[row1]]
// CHECK-NEXT: OpStore %h [[h]]
uint16_t2x3 h = asuint16(intMat);
}
3 changes: 3 additions & 0 deletions tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1165,8 +1165,11 @@ TEST_F(FileTest, IntrinsicsAsDouble) {
runFileTest("intrinsics.asdouble.hlsl");
}
TEST_F(FileTest, IntrinsicsAsfloat) { runFileTest("intrinsics.asfloat.hlsl"); }
TEST_F(FileTest, IntrinsicsAsfloat16) { runFileTest("intrinsics.asfloat16.hlsl"); }
TEST_F(FileTest, IntrinsicsAsint) { runFileTest("intrinsics.asint.hlsl"); }
TEST_F(FileTest, IntrinsicsAsint16) { runFileTest("intrinsics.asint16.hlsl"); }
TEST_F(FileTest, IntrinsicsAsuint) { runFileTest("intrinsics.asuint.hlsl"); }
TEST_F(FileTest, IntrinsicsAsuint16) { runFileTest("intrinsics.asuint16.hlsl"); }
TEST_F(FileTest, IntrinsicsAsuintArgumentMustBeRValue) {
runFileTest("intrinsics.asuint.rvalue.hlsl");
}
Expand Down

0 comments on commit aaa30e2

Please sign in to comment.