Skip to content

Commit 9ee056e

Browse files
authored
[SPIR-V] Remove bitcast from float->int conversion (microsoft#6533)
OpConvertFToU and FToS convert numerically from floating point to integer, with rounding toward 0.0, matching the defined behavior of HLSL without any need for an initial bitwidth conversion from floating point to floating point, which can result in incorrect rounding behavior (see microsoft#6501). Note that behavior is undefined if the target type is not wide enough to hold the converted value, however this was also true with an initial bitcast (because an N-bit FP can hold values outside the range of an N-bit int), and I can't come up with any case where an intial truncation would result in correct defined behavior where this straight conversion would be undefined since the precision will inevitably be lost anyways. Fixes microsoft#6501
1 parent dda80a9 commit 9ee056e

File tree

4 files changed

+15
-29
lines changed

4 files changed

+15
-29
lines changed

tools/clang/lib/SPIRV/SpirvEmitter.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8233,17 +8233,14 @@ SpirvInstruction *SpirvEmitter::castToInt(SpirvInstruction *fromVal,
82338233
}
82348234

82358235
if (isFloatOrVecOfFloatType(fromType)) {
8236-
// First convert the source to the bitwidth of the destination if necessary.
8237-
fromVal = convertBitwidth(fromVal, srcLoc, fromType, toIntType, nullptr,
8238-
srcRange);
82398236
if (isSintOrVecOfSintType(toIntType)) {
82408237
return spvBuilder.createUnaryOp(spv::Op::OpConvertFToS, toIntType,
82418238
fromVal, srcLoc, srcRange);
8242-
} else if (isUintOrVecOfUintType(toIntType)) {
8239+
}
8240+
8241+
if (isUintOrVecOfUintType(toIntType)) {
82438242
return spvBuilder.createUnaryOp(spv::Op::OpConvertFToU, toIntType,
82448243
fromVal, srcLoc, srcRange);
8245-
} else {
8246-
emitError("casting from floating point to integer unimplemented", srcLoc);
82478244
}
82488245
}
82498246

@@ -8310,6 +8307,7 @@ SpirvInstruction *SpirvEmitter::castToInt(SpirvInstruction *fromVal,
83108307
return result;
83118308
}
83128309

8310+
emitError("casting from given type to integer unimplemented", srcLoc);
83138311
return nullptr;
83148312
}
83158313

tools/clang/test/CodeGenSPIRV/cast.bitwidth.hlsl

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,15 @@ void main() {
4141
// 32-bit float to various 64-bit types.
4242
float aaa;
4343
// CHECK: [[aaa:%[0-9]+]] = OpLoad %float %aaa
44-
// CHECK-NEXT: [[aaa_double:%[0-9]+]] = OpFConvert %double [[aaa]]
45-
// CHECK-NEXT: [[aaa_ulong:%[0-9]+]] = OpConvertFToU %ulong [[aaa_double]]
44+
// CHECK-NEXT: [[aaa_ulong:%[0-9]+]] = OpConvertFToU %ulong [[aaa]]
4645
// CHECK-NEXT: OpStore %bbb [[aaa_ulong]]
4746
uint64_t bbb = aaa;
4847
// CHECK: [[aaa_0:%[0-9]+]] = OpLoad %float %aaa
4948
// CHECK-NEXT: [[aaa_double_0:%[0-9]+]] = OpFConvert %double [[aaa_0]]
5049
// CHECK-NEXT: OpStore %ccc [[aaa_double_0]]
5150
double ccc = aaa;
5251
// CHECK: [[aaa_1:%[0-9]+]] = OpLoad %float %aaa
53-
// CHECK-NEXT: [[aaa_double_1:%[0-9]+]] = OpFConvert %double [[aaa_1]]
54-
// CHECK-NEXT: [[aaa_long:%[0-9]+]] = OpConvertFToS %long [[aaa_double_1]]
52+
// CHECK-NEXT: [[aaa_long:%[0-9]+]] = OpConvertFToS %long [[aaa_1]]
5553
// CHECK-NEXT: OpStore %ddd [[aaa_long]]
5654
int64_t ddd = aaa;
5755

@@ -95,31 +93,27 @@ void main() {
9593
// 64-bit float to various 32-bit types.
9694
double eee;
9795
// CHECK: [[e64_2:%[0-9]+]] = OpLoad %double %eee
98-
// CHECK-NEXT: [[e32_2:%[0-9]+]] = OpFConvert %float [[e64_2]]
99-
// CHECK-NEXT: [[e_uint_0:%[0-9]+]] = OpConvertFToU %uint [[e32_2]]
96+
// CHECK-NEXT: [[e_uint_0:%[0-9]+]] = OpConvertFToU %uint [[e64_2]]
10097
// CHECK-NEXT: OpStore %fff [[e_uint_0]]
10198
uint fff = eee;
10299
// CHECK: [[e_2:%[0-9]+]] = OpLoad %double %eee
103100
// CHECK-NEXT: [[e_float_1:%[0-9]+]] = OpFConvert %float [[e_2]]
104101
// CHECK-NEXT: OpStore %ggg [[e_float_1]]
105102
float ggg = eee;
106103
// CHECK: [[e_3:%[0-9]+]] = OpLoad %double %eee
107-
// CHECK-NEXT: [[e_float_2:%[0-9]+]] = OpFConvert %float [[e_3]]
108-
// CHECK-NEXT: [[e_int_3:%[0-9]+]] = OpConvertFToS %int [[e_float_2]]
104+
// CHECK-NEXT: [[e_int_3:%[0-9]+]] = OpConvertFToS %int [[e_3]]
109105
// CHECK-NEXT: OpStore %hhh [[e_int_3]]
110106
int hhh = eee;
111107

112108

113109
// Vector case: 64-bit float to various 32-bit types.
114110
double2 i;
115111
// CHECK: [[i_double:%[0-9]+]] = OpLoad %v2double %i
116-
// CHECK-NEXT: [[i_float:%[0-9]+]] = OpFConvert %v2float [[i_double]]
117-
// CHECK-NEXT: [[i_uint:%[0-9]+]] = OpConvertFToU %v2uint [[i_float]]
112+
// CHECK-NEXT: [[i_uint:%[0-9]+]] = OpConvertFToU %v2uint [[i_double]]
118113
// CHECK-NEXT: OpStore %j [[i_uint]]
119114
uint2 j = i;
120115
// CHECK: [[i_double_0:%[0-9]+]] = OpLoad %v2double %i
121-
// CHECK-NEXT: [[i_float_0:%[0-9]+]] = OpFConvert %v2float [[i_double_0]]
122-
// CHECK-NEXT: [[i_int:%[0-9]+]] = OpConvertFToS %v2int [[i_float_0]]
116+
// CHECK-NEXT: [[i_int:%[0-9]+]] = OpConvertFToS %v2int [[i_double_0]]
123117
// CHECK-NEXT: OpStore %k [[i_int]]
124118
int2 k = i;
125119
// CHECK: [[i_double_1:%[0-9]+]] = OpLoad %v2double %i

tools/clang/test/CodeGenSPIRV/cast.flat-conversion.literal-initializer.hlsl

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,8 @@ void main() {
2626
// CHECK-NEXT: [[inf_double:%[0-9]+]] = OpFConvert %double [[inf]]
2727
// CHECK-NEXT: [[inf2_double:%[0-9]+]] = OpCompositeConstruct %v2double [[inf_double]] [[inf_double]]
2828
// CHECK-NEXT: [[inf_double_0:%[0-9]+]] = OpFConvert %double [[inf]]
29-
// CHECK-NEXT: [[inf_double_:%[0-9]+]] = OpFConvert %double [[inf]]
30-
// CHECK-NEXT: [[inf_int64:%[0-9]+]] = OpConvertFToS %long [[inf_double_]]
31-
// CHECK-NEXT: [[inf_double__0:%[0-9]+]] = OpFConvert %double [[inf]]
32-
// CHECK-NEXT: [[inf_uint64:%[0-9]+]] = OpConvertFToU %ulong [[inf_double__0]]
29+
// CHECK-NEXT: [[inf_int64:%[0-9]+]] = OpConvertFToS %long [[inf]]
30+
// CHECK-NEXT: [[inf_uint64:%[0-9]+]] = OpConvertFToU %ulong [[inf]]
3331
// CHECK-NEXT: {{%[0-9]+}} = OpCompositeConstruct %S [[inf2]] [[inf]] [[inf2_double]] [[inf_double_0]] [[inf_int64]] [[inf_uint64]]
3432
S s3 = (S)(1.0 / 0.0);
3533

@@ -38,10 +36,8 @@ void main() {
3836
// CHECK-NEXT: [[b_double:%[0-9]+]] = OpFConvert %double [[b]]
3937
// CHECK-NEXT: [[b2_double:%[0-9]+]] = OpCompositeConstruct %v2double [[b_double]] [[b_double]]
4038
// CHECK-NEXT: [[b_double_0:%[0-9]+]] = OpFConvert %double [[b]]
41-
// CHECK-NEXT: [[b_double_:%[0-9]+]] = OpFConvert %double [[b]]
42-
// CHECK-NEXT: [[b_int64:%[0-9]+]] = OpConvertFToS %long [[b_double_]]
43-
// CHECK-NEXT: [[b_double__0:%[0-9]+]] = OpFConvert %double [[b]]
44-
// CHECK-NEXT: [[b_uint64:%[0-9]+]] = OpConvertFToU %ulong [[b_double__0]]
39+
// CHECK-NEXT: [[b_int64:%[0-9]+]] = OpConvertFToS %long [[b]]
40+
// CHECK-NEXT: [[b_uint64:%[0-9]+]] = OpConvertFToU %ulong [[b]]
4541
// CHECK-NEXT: {{%[0-9]+}} = OpCompositeConstruct %S [[b2_float]] [[b]] [[b2_double]] [[b_double_0]] [[b_int64]] [[b_uint64]]
4642
float b;
4743
S s2 = (S)(b);

tools/clang/test/CodeGenSPIRV/cast.struct-to-int.hlsl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ void main()
7878
// CHECK-DAG: [[U255:%[^ ]*]] = OpConstant [[UINT]] 255
7979
// CHECK-DAG: [[U3:%[^ ]*]] = OpConstant [[UINT]] 3
8080
// CHECK-DAG: [[ULONG:%[^ ]*]] = OpTypeInt 64 0
81-
// CHECK-DAG: [[DOUBLE:%[^ ]*]] = OpTypeFloat 64
8281

8382
buf[0] = (uint) colors;
8483
// CHECK: [[COLORS:%[^ ]*]] = OpLoad [[TWOCOLORS]]
@@ -106,8 +105,7 @@ void main()
106105
lbuf[0] += (uint64_t) m;
107106
// CHECK: [[MIX:%[^ ]*]] = OpLoad [[MIXED]]
108107
// CHECK: [[MIX0:%[^ ]*]] = OpCompositeExtract [[FLOAT]] [[MIX]] 0
109-
// CHECK: [[V1_1:%[^ ]*]] = OpFConvert [[DOUBLE]] [[MIX0]]
110-
// CHECK: [[V2_0:%[^ ]*]] = OpConvertFToU [[ULONG]] [[V1_1]]
108+
// CHECK: [[V2_0:%[^ ]*]] = OpConvertFToU [[ULONG]] [[MIX0]]
111109
// CHECK: [[LBUF00_0:%[^ ]*]] = OpAccessChain %{{[^ ]*}} [[LBUF]] [[I0]] [[U0]]
112110
// CHECK: [[V3:%[^ ]*]] = OpLoad [[ULONG]] [[LBUF00_0]]
113111
// CHECK: [[V4:%[^ ]*]] = OpIAdd [[ULONG]] [[V3]] [[V2_0]]

0 commit comments

Comments
 (0)