Skip to content

Commit 2a0833a

Browse files
authored
[spirv] Translate HLSL min/max to NMin/NMax (#4517)
The specification for the HLSL min and max intrinsic functions states that if one of the values is NaN, the other will be given as the result, which is correctly represented by the GLSL.std.450 instructions NMin and NMax, respectively. By the semantics of the previously used FMin and FMax instructions, this would be undefined behavior. Fixes #3221
1 parent b75a988 commit 2a0833a

6 files changed

Lines changed: 30 additions & 22 deletions

File tree

docs/SPIR-V.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2357,8 +2357,8 @@ HLSL Intrinsic Function GLSL Extended Instruction
23572357
``log10`` ``Log2`` (scaled by ``1/log2(10)``)
23582358
``log2`` ``Log2``
23592359
``mad`` ``Fma``
2360-
``max`` ``SMax``/``UMax``/``FMax``
2361-
``min`` ``SMin``/``UMin``/``FMin``
2360+
``max`` ``SMax``/``UMax``/``NMax``
2361+
``min`` ``SMin``/``UMin``/``NMin``
23622362
``modf`` ``ModfStruct``
23632363
``normalize`` ``Normalize``
23642364
``pow`` ``Pow``

tools/clang/lib/SPIRV/SpirvEmitter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8136,9 +8136,9 @@ SpirvEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
81368136
INTRINSIC_OP_CASE(lerp, FMix, true);
81378137
INTRINSIC_OP_CASE(log, Log, true);
81388138
INTRINSIC_OP_CASE(log2, Log2, true);
8139-
INTRINSIC_OP_CASE_SINT_UINT_FLOAT(max, SMax, UMax, FMax, true);
8139+
INTRINSIC_OP_CASE_SINT_UINT_FLOAT(max, SMax, UMax, NMax, true);
81408140
INTRINSIC_OP_CASE(umax, UMax, true);
8141-
INTRINSIC_OP_CASE_SINT_UINT_FLOAT(min, SMin, UMin, FMin, true);
8141+
INTRINSIC_OP_CASE_SINT_UINT_FLOAT(min, SMin, UMin, NMin, true);
81428142
INTRINSIC_OP_CASE(umin, UMin, true);
81438143
INTRINSIC_OP_CASE(normalize, Normalize, false);
81448144
INTRINSIC_OP_CASE(pow, Pow, true);

tools/clang/test/CodeGenSPIRV/intrinsics.max.hlsl

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
// RUN: %dxc -T vs_6_0 -E main
22

3+
// According to HLSL reference on denormals for 'max', if one of the
4+
// values is NaN, the other will be given as the result. If both values
5+
// are NaN, the result will be NaN.
6+
37
// CHECK: [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
48

59
void main() {
@@ -19,38 +23,38 @@ void main() {
1923
uint3 j1,j2;
2024
uresult3 = max(j1,j2);
2125

22-
// CHECK: {{%\d+}} = OpExtInst %float [[glsl]] FMax {{%\d+}} {{%\d+}}
26+
// CHECK: {{%\d+}} = OpExtInst %float [[glsl]] NMax {{%\d+}} {{%\d+}}
2327
float a1,a2;
2428
result = max(a1,a2);
2529

26-
// CHECK: {{%\d+}} = OpExtInst %float [[glsl]] FMax {{%\d+}} {{%\d+}}
30+
// CHECK: {{%\d+}} = OpExtInst %float [[glsl]] NMax {{%\d+}} {{%\d+}}
2731
float1 b1,b2;
2832
result = max(b1,b2);
2933

30-
// CHECK: {{%\d+}} = OpExtInst %v3float [[glsl]] FMax {{%\d+}} {{%\d+}}
34+
// CHECK: {{%\d+}} = OpExtInst %v3float [[glsl]] NMax {{%\d+}} {{%\d+}}
3135
float3 c1,c2;
3236
result3 = max(c1,c2);
3337

34-
// CHECK: {{%\d+}} = OpExtInst %float [[glsl]] FMax {{%\d+}} {{%\d+}}
38+
// CHECK: {{%\d+}} = OpExtInst %float [[glsl]] NMax {{%\d+}} {{%\d+}}
3539
float1x1 d1,d2;
3640
result = max(d1,d2);
3741

38-
// CHECK: {{%\d+}} = OpExtInst %v2float [[glsl]] FMax {{%\d+}} {{%\d+}}
42+
// CHECK: {{%\d+}} = OpExtInst %v2float [[glsl]] NMax {{%\d+}} {{%\d+}}
3943
float1x2 e1,e2;
4044
result2 = max(e1,e2);
4145

42-
// CHECK: {{%\d+}} = OpExtInst %v4float [[glsl]] FMax {{%\d+}} {{%\d+}}
46+
// CHECK: {{%\d+}} = OpExtInst %v4float [[glsl]] NMax {{%\d+}} {{%\d+}}
4347
float4x1 f1,f2;
4448
result4 = max(f1,f2);
4549

4650
// CHECK: [[g1:%\d+]] = OpLoad %mat2v3float %g1
4751
// CHECK-NEXT: [[g2:%\d+]] = OpLoad %mat2v3float %g2
4852
// CHECK-NEXT: [[g1_row0:%\d+]] = OpCompositeExtract %v3float [[g1]] 0
4953
// CHECK-NEXT: [[g2_row0:%\d+]] = OpCompositeExtract %v3float [[g2]] 0
50-
// CHECK-NEXT: [[result_row0:%\d+]] = OpExtInst %v3float [[glsl]] FMax [[g1_row0]] [[g2_row0]]
54+
// CHECK-NEXT: [[result_row0:%\d+]] = OpExtInst %v3float [[glsl]] NMax [[g1_row0]] [[g2_row0]]
5155
// CHECK-NEXT: [[g1_row1:%\d+]] = OpCompositeExtract %v3float [[g1]] 1
5256
// CHECK-NEXT: [[g2_row1:%\d+]] = OpCompositeExtract %v3float [[g2]] 1
53-
// CHECK-NEXT: [[result_row1:%\d+]] = OpExtInst %v3float [[glsl]] FMax [[g1_row1]] [[g2_row1]]
57+
// CHECK-NEXT: [[result_row1:%\d+]] = OpExtInst %v3float [[glsl]] NMax [[g1_row1]] [[g2_row1]]
5458
// CHECK-NEXT: {{%\d+}} = OpCompositeConstruct %mat2v3float [[result_row0]] [[result_row1]]
5559
float2x3 g1,g2;
5660
result2x3 = max(g1,g2);

tools/clang/test/CodeGenSPIRV/intrinsics.min.hlsl

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
// RUN: %dxc -T vs_6_0 -E main
22

3+
// According to HLSL reference on denormals for 'min', if one of the
4+
// values is NaN, the other will be given as the result. If both values
5+
// are NaN, the result will be NaN.
6+
37
// CHECK: [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
48

59
void main() {
@@ -19,38 +23,38 @@ void main() {
1923
uint3 j1,j2;
2024
uresult3 = min(j1,j2);
2125

22-
// CHECK: {{%\d+}} = OpExtInst %float [[glsl]] FMin {{%\d+}} {{%\d+}}
26+
// CHECK: {{%\d+}} = OpExtInst %float [[glsl]] NMin {{%\d+}} {{%\d+}}
2327
float a1,a2;
2428
result = min(a1,a2);
2529

26-
// CHECK: {{%\d+}} = OpExtInst %float [[glsl]] FMin {{%\d+}} {{%\d+}}
30+
// CHECK: {{%\d+}} = OpExtInst %float [[glsl]] NMin {{%\d+}} {{%\d+}}
2731
float1 b1,b2;
2832
result = min(b1,b2);
2933

30-
// CHECK: {{%\d+}} = OpExtInst %v3float [[glsl]] FMin {{%\d+}} {{%\d+}}
34+
// CHECK: {{%\d+}} = OpExtInst %v3float [[glsl]] NMin {{%\d+}} {{%\d+}}
3135
float3 c1,c2;
3236
result3 = min(c1,c2);
3337

34-
// CHECK: {{%\d+}} = OpExtInst %float [[glsl]] FMin {{%\d+}} {{%\d+}}
38+
// CHECK: {{%\d+}} = OpExtInst %float [[glsl]] NMin {{%\d+}} {{%\d+}}
3539
float1x1 d1,d2;
3640
result = min(d1,d2);
3741

38-
// CHECK: {{%\d+}} = OpExtInst %v2float [[glsl]] FMin {{%\d+}} {{%\d+}}
42+
// CHECK: {{%\d+}} = OpExtInst %v2float [[glsl]] NMin {{%\d+}} {{%\d+}}
3943
float1x2 e1,e2;
4044
result2 = min(e1,e2);
4145

42-
// CHECK: {{%\d+}} = OpExtInst %v4float [[glsl]] FMin {{%\d+}} {{%\d+}}
46+
// CHECK: {{%\d+}} = OpExtInst %v4float [[glsl]] NMin {{%\d+}} {{%\d+}}
4347
float4x1 f1,f2;
4448
result4 = min(f1,f2);
4549

4650
// CHECK: [[g1:%\d+]] = OpLoad %mat2v3float %g1
4751
// CHECK-NEXT: [[g2:%\d+]] = OpLoad %mat2v3float %g2
4852
// CHECK-NEXT: [[g1_row0:%\d+]] = OpCompositeExtract %v3float [[g1]] 0
4953
// CHECK-NEXT: [[g2_row0:%\d+]] = OpCompositeExtract %v3float [[g2]] 0
50-
// CHECK-NEXT: [[result_row0:%\d+]] = OpExtInst %v3float [[glsl]] FMin [[g1_row0]] [[g2_row0]]
54+
// CHECK-NEXT: [[result_row0:%\d+]] = OpExtInst %v3float [[glsl]] NMin [[g1_row0]] [[g2_row0]]
5155
// CHECK-NEXT: [[g1_row1:%\d+]] = OpCompositeExtract %v3float [[g1]] 1
5256
// CHECK-NEXT: [[g2_row1:%\d+]] = OpCompositeExtract %v3float [[g2]] 1
53-
// CHECK-NEXT: [[result_row1:%\d+]] = OpExtInst %v3float [[glsl]] FMin [[g1_row1]] [[g2_row1]]
57+
// CHECK-NEXT: [[result_row1:%\d+]] = OpExtInst %v3float [[glsl]] NMin [[g1_row1]] [[g2_row1]]
5458
// CHECK-NEXT: {{%\d+}} = OpCompositeConstruct %mat2v3float [[result_row0]] [[result_row1]]
5559
float2x3 g1,g2;
5660
result2x3 = min(g1,g2);

tools/clang/test/CodeGenSPIRV/shader.debug.line.intrinsic.hlsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,5 +182,5 @@ void main() {
182182
// CHECK-NEXT: OpExtInst %float {{%\d+}} Cos
183183
cos(v4f.x));
184184
// CHECK: DebugLine [[src]] %uint_180 %uint_183 %uint_3 %uint_17
185-
// CHECK-NEXT: OpExtInst %float {{%\d+}} FMax
185+
// CHECK-NEXT: OpExtInst %float {{%\d+}} NMax
186186
}

tools/clang/test/CodeGenSPIRV/spirv.debug.opline.intrinsic.hlsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,5 +182,5 @@ void main() {
182182
// CHECK-NEXT: OpExtInst %float {{%\d+}} Cos
183183
cos(v4f.x));
184184
// CHECK: OpLine [[file]] 180 3
185-
// CHECK-NEXT: OpExtInst %float {{%\d+}} FMax
185+
// CHECK-NEXT: OpExtInst %float {{%\d+}} NMax
186186
}

0 commit comments

Comments
 (0)