Преглед изворни кода

[spirv] Fix incorrect opcode generation for fmod() function (#2990)

* [spirv] Fix incorrect opcode generation for fmod() function

In HLSL fmod() function, first argument is used to deduce return value sign,
which is equivalent to spirv OpFRem, not OpFMod.

Please see the following documentation links for further reference.
https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-fmod
https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#OpFRem

* [spirv] Fix test failures.

Co-authored-by: Ehsan Nasiri <[email protected]>
Maciej Latocha пре 5 година
родитељ
комит
607d2e4eea

+ 1 - 1
docs/SPIR-V.rst

@@ -2055,7 +2055,7 @@ The following intrinsic HLSL functions have direct SPIR-V opcodes for them:
 ``ddy_coarse``                       ``OpDPdyCoarse``
 ``ddx_fine``                         ``OpDPdxFine``
 ``ddy_fine``                         ``OpDPdyFine``
-``fmod``                             ``OpFMod``
+``fmod``                             ``OpFRem``
 ``fwidth``                           ``OpFwidth``
 ``GroupMemoryBarrier``               ``OpMemoryBarrier``
 ``GroupMemoryBarrierWithGroupSync``  ``OpControlBarrier``

+ 1 - 1
tools/clang/lib/SPIRV/SpirvEmitter.cpp

@@ -7268,7 +7268,7 @@ SpirvEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
     INTRINSIC_SPIRV_OP_CASE(countbits, BitCount, false);
     INTRINSIC_SPIRV_OP_CASE(isinf, IsInf, true);
     INTRINSIC_SPIRV_OP_CASE(isnan, IsNan, true);
-    INTRINSIC_SPIRV_OP_CASE(fmod, FMod, true);
+    INTRINSIC_SPIRV_OP_CASE(fmod, FRem, true);
     INTRINSIC_SPIRV_OP_CASE(fwidth, Fwidth, true);
     INTRINSIC_SPIRV_OP_CASE(reversebits, BitReverse, false);
     INTRINSIC_OP_CASE(round, Round, true);

+ 4 - 4
tools/clang/test/CodeGenSPIRV/intrinsics.fmod.hlsl

@@ -7,22 +7,22 @@ void main() {
 
 // CHECK:      [[a1:%\d+]] = OpLoad %float %a1
 // CHECK-NEXT: [[a2:%\d+]] = OpLoad %float %a2
-// CHECK-NEXT:    {{%\d+}} = OpFMod %float [[a1]] [[a2]]
+// CHECK-NEXT:    {{%\d+}} = OpFRem %float [[a1]] [[a2]]
   fmod_a = fmod(a1, a2);
 
 // CHECK:      [[b1:%\d+]] = OpLoad %v4float %b1
 // CHECK-NEXT: [[b2:%\d+]] = OpLoad %v4float %b2
-// CHECK-NEXT:    {{%\d+}} = OpFMod %v4float [[b1]] [[b2]]
+// CHECK-NEXT:    {{%\d+}} = OpFRem %v4float [[b1]] [[b2]]
   fmod_b = fmod(b1, b2);
 
 // CHECK:               [[c1:%\d+]] = OpLoad %mat2v3float %c1
 // CHECK-NEXT:          [[c2:%\d+]] = OpLoad %mat2v3float %c2
 // CHECK-NEXT:     [[c1_row0:%\d+]] = OpCompositeExtract %v3float [[c1]] 0
 // CHECK-NEXT:     [[c2_row0:%\d+]] = OpCompositeExtract %v3float [[c2]] 0
-// CHECK-NEXT: [[fmod_c_row0:%\d+]] = OpFMod %v3float [[c1_row0]] [[c2_row0]]
+// CHECK-NEXT: [[fmod_c_row0:%\d+]] = OpFRem %v3float [[c1_row0]] [[c2_row0]]
 // CHECK-NEXT:     [[c1_row1:%\d+]] = OpCompositeExtract %v3float [[c1]] 1
 // CHECK-NEXT:     [[c2_row1:%\d+]] = OpCompositeExtract %v3float [[c2]] 1
-// CHECK-NEXT: [[fmod_c_row1:%\d+]] = OpFMod %v3float [[c1_row1]] [[c2_row1]]
+// CHECK-NEXT: [[fmod_c_row1:%\d+]] = OpFRem %v3float [[c1_row1]] [[c2_row1]]
 // CHECK-NEXT:             {{%\d+}} = OpCompositeConstruct %mat2v3float [[fmod_c_row0]] [[fmod_c_row1]]
   fmod_c = fmod(c1, c2);
 }

+ 2 - 2
tools/clang/test/CodeGenSPIRV/spirv.debug.opline.intrinsic.hlsl

@@ -53,9 +53,9 @@ void main() {
   m2x2f = ddx(m2x2f);
 
 // CHECK:                       OpLine [[file]] 60 11
-// CHECK-NEXT: [[fmod0:%\d+]] = OpFMod %v2float {{%\d+}} {{%\d+}}
+// CHECK-NEXT: [[fmod0:%\d+]] = OpFRem %v2float {{%\d+}} {{%\d+}}
 // CHECK:                       OpLine [[file]] 60 11
-// CHECK-NEXT: [[fmod1:%\d+]] = OpFMod %v2float {{%\d+}} {{%\d+}}
+// CHECK-NEXT: [[fmod1:%\d+]] = OpFRem %v2float {{%\d+}} {{%\d+}}
 // CHECK-NEXT:       {{%\d+}} = OpCompositeConstruct %mat2v2float [[fmod0]] [[fmod1]]
   m2x2f = fmod(m2x2f, float2x2(v4i));