Quellcode durchsuchen

[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 vor 5 Jahren
Ursprung
Commit
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``
 ``ddy_coarse``                       ``OpDPdyCoarse``
 ``ddx_fine``                         ``OpDPdxFine``
 ``ddx_fine``                         ``OpDPdxFine``
 ``ddy_fine``                         ``OpDPdyFine``
 ``ddy_fine``                         ``OpDPdyFine``
-``fmod``                             ``OpFMod``
+``fmod``                             ``OpFRem``
 ``fwidth``                           ``OpFwidth``
 ``fwidth``                           ``OpFwidth``
 ``GroupMemoryBarrier``               ``OpMemoryBarrier``
 ``GroupMemoryBarrier``               ``OpMemoryBarrier``
 ``GroupMemoryBarrierWithGroupSync``  ``OpControlBarrier``
 ``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(countbits, BitCount, false);
     INTRINSIC_SPIRV_OP_CASE(isinf, IsInf, true);
     INTRINSIC_SPIRV_OP_CASE(isinf, IsInf, true);
     INTRINSIC_SPIRV_OP_CASE(isnan, IsNan, 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(fwidth, Fwidth, true);
     INTRINSIC_SPIRV_OP_CASE(reversebits, BitReverse, false);
     INTRINSIC_SPIRV_OP_CASE(reversebits, BitReverse, false);
     INTRINSIC_OP_CASE(round, Round, true);
     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:      [[a1:%\d+]] = OpLoad %float %a1
 // CHECK-NEXT: [[a2:%\d+]] = OpLoad %float %a2
 // 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);
   fmod_a = fmod(a1, a2);
 
 
 // CHECK:      [[b1:%\d+]] = OpLoad %v4float %b1
 // CHECK:      [[b1:%\d+]] = OpLoad %v4float %b1
 // CHECK-NEXT: [[b2:%\d+]] = OpLoad %v4float %b2
 // 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);
   fmod_b = fmod(b1, b2);
 
 
 // CHECK:               [[c1:%\d+]] = OpLoad %mat2v3float %c1
 // CHECK:               [[c1:%\d+]] = OpLoad %mat2v3float %c1
 // CHECK-NEXT:          [[c2:%\d+]] = OpLoad %mat2v3float %c2
 // CHECK-NEXT:          [[c2:%\d+]] = OpLoad %mat2v3float %c2
 // CHECK-NEXT:     [[c1_row0:%\d+]] = OpCompositeExtract %v3float [[c1]] 0
 // CHECK-NEXT:     [[c1_row0:%\d+]] = OpCompositeExtract %v3float [[c1]] 0
 // CHECK-NEXT:     [[c2_row0:%\d+]] = OpCompositeExtract %v3float [[c2]] 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:     [[c1_row1:%\d+]] = OpCompositeExtract %v3float [[c1]] 1
 // CHECK-NEXT:     [[c2_row1:%\d+]] = OpCompositeExtract %v3float [[c2]] 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]]
 // CHECK-NEXT:             {{%\d+}} = OpCompositeConstruct %mat2v3float [[fmod_c_row0]] [[fmod_c_row1]]
   fmod_c = fmod(c1, c2);
   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);
   m2x2f = ddx(m2x2f);
 
 
 // CHECK:                       OpLine [[file]] 60 11
 // 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:                       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]]
 // CHECK-NEXT:       {{%\d+}} = OpCompositeConstruct %mat2v2float [[fmod0]] [[fmod1]]
   m2x2f = fmod(m2x2f, float2x2(v4i));
   m2x2f = fmod(m2x2f, float2x2(v4i));