Skip to content

[HLSL] Implementation of the elementwise fmod builtin #108849

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 27, 2024

Conversation

lizhengxing
Copy link
Contributor

@lizhengxing lizhengxing commented Sep 16, 2024

This change add the elementwise fmod builtin to support HLSL function 'fmod' in clang for #99118

Builtins.td - add the fmod builtin
CGBuiltin.cpp - lower the builtin to llvm FRem instruction
hlsl_intrinsics.h - add the fmod api
SemaChecking.cpp - add type checks for builtin
SemaHLSL.cpp - add HLSL type checks for builtin

clang/docs/LanguageExtensions.rst - add the builtin in Elementwise Builtins
clang/docs/ReleaseNotes.rst - announce the builtin

Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added clang Clang issues not falling into any other category backend:X86 clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:headers Headers provided by Clang, e.g. for intrinsics clang:codegen IR generation bugs: mangling, exceptions, etc. backend:DirectX HLSL HLSL Language Support llvm:ir labels Sep 16, 2024
@llvmbot
Copy link
Member

llvmbot commented Sep 16, 2024

@llvm/pr-subscribers-clang-codegen
@llvm/pr-subscribers-clang
@llvm/pr-subscribers-hlsl
@llvm/pr-subscribers-llvm-ir

@llvm/pr-subscribers-backend-x86

Author: Zhengxing li (lizhengxing)

Changes

This change implements the frontend for #99118

Builtins.td - add the fmod builtin
CGBuiltin.cpp - add the builtin to DirectX intrinsic mapping
hlsl_intrinsics.h - add the fmod api
SemaHLSL.cpp - add type checks for builtin
IntrinsicsDirectX.td - add the fmod DirectX intrinsic


Full diff: https://github.com/llvm/llvm-project/pull/108849.diff

7 Files Affected:

  • (modified) clang/include/clang/Basic/Builtins.td (+6)
  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+19)
  • (modified) clang/lib/Headers/hlsl/hlsl_intrinsics.h (+33)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+12)
  • (added) clang/test/CodeGenHLSL/builtins/fmod.hlsl (+122)
  • (added) clang/test/SemaHLSL/BuiltIns/fmod-errors.hlsl (+38)
  • (modified) llvm/include/llvm/IR/IntrinsicsDirectX.td (+1)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 6cf03d27055cd9..56a6813ecd205e 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4782,6 +4782,12 @@ def HLSLStep: LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLFmod : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_fmod"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 // Builtins for XRay.
 def XRayCustomEvent : Builtin {
   let Spellings = ["__xray_customevent"];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index a52e880a764252..840c773020dfab 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18709,6 +18709,25 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
         CGM.getHLSLRuntime().getNormalizeIntrinsic(), ArrayRef<Value *>{X},
         nullptr, "hlsl.normalize");
   }
+  case Builtin::BI__builtin_hlsl_elementwise_fmod: {
+    Value *Op0 = EmitScalarExpr(E->getArg(0));
+    Value *Op1 = EmitScalarExpr(E->getArg(1));
+    if (!E->getArg(0)->getType()->hasFloatingRepresentation() ||
+        (E->getArg(0)->getType() != E->getArg(1)->getType()))
+      llvm_unreachable("fmod operands must have the same float representation");
+
+    llvm::Triple::ArchType Arch = CGM.getTarget().getTriple().getArch();
+    assert(((Arch == llvm::Triple::dxil) || (Arch == llvm::Triple::spirv)) &&
+           "Unknown target architecture");
+
+    if (CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
+      return Builder.CreateIntrinsic(
+          /*ReturnType=*/Op0->getType(), Intrinsic::dx_fmod,
+          ArrayRef<Value *>{Op0, Op1}, nullptr, "dx.fmod");
+
+    // HLSL's Fmod builtin is equivalent to SPIRV's OpFRem instruction
+    return Builder.CreateFRem(Op0, Op1, "fmod");
+  }
   case Builtin::BI__builtin_hlsl_elementwise_frac: {
     Value *Op0 = EmitScalarExpr(E->getArg(0));
     if (!E->getArg(0)->getType()->hasFloatingRepresentation())
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index d08dcd350d558b..6ff45e191923e8 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -807,6 +807,39 @@ float3 floor(float3);
 _HLSL_BUILTIN_ALIAS(__builtin_elementwise_floor)
 float4 floor(float4);
 
+//===----------------------------------------------------------------------===//
+// fmod builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn T fmod(T x, T y)
+/// \brief Returns the linear interpolation of x to y.
+/// \param x [in] The dividend.
+/// \param y [in] The divisor.
+///
+/// Return the floating-point remainder of the x parameter divided by the y parameter.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_fmod)
+half fmod(half, half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_fmod)
+half2 fmod(half2, half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_fmod)
+half3 fmod(half3, half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_fmod)
+half4 fmod(half4, half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_fmod)
+float fmod(float, float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_fmod)
+float2 fmod(float2, float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_fmod)
+float3 fmod(float3, float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_fmod)
+float4 fmod(float4, float4);
+
 //===----------------------------------------------------------------------===//
 // frac builtins
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 527718c8e7e324..e144d649b6c427 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1649,6 +1649,18 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
       return true;
     break;
   }
+  case Builtin::BI__builtin_hlsl_elementwise_fmod: {
+    if (SemaRef.checkArgCount(TheCall, 2))
+      return true;
+    if (CheckFloatOrHalfRepresentations(&SemaRef, TheCall))
+      return true;
+
+    ExprResult A = TheCall->getArg(0);
+    QualType ArgTyA = A.get()->getType();
+    // return type is the same as the input type
+    TheCall->setType(ArgTyA);
+    break;
+  }
   case Builtin::BI__builtin_hlsl_select: {
     if (SemaRef.checkArgCount(TheCall, 3))
       return true;
diff --git a/clang/test/CodeGenHLSL/builtins/fmod.hlsl b/clang/test/CodeGenHLSL/builtins/fmod.hlsl
new file mode 100644
index 00000000000000..228bbdef76dc39
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/fmod.hlsl
@@ -0,0 +1,122 @@
+// DirectX target:
+//
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
+// RUN:   --check-prefixes=DX-CHECK,DX-NATIVE_HALF
+
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
+// RUN:   -o - | FileCheck %s --check-prefixes=DX-CHECK,DX-NO_HALF 
+
+
+
+// Spirv target:
+//
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   spirv-unknown-vulkan-compute %s -fnative-half-type \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
+// RUN:   --check-prefixes=SPV-CHECK,SPV-NATIVE_HALF
+
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
+// RUN:   -o - | FileCheck %s --check-prefixes=SPV-CHECK,SPV-NO_HALF
+
+
+
+// DX-NATIVE_HALF: define noundef half @
+// DX-NATIVE_HALF: %dx.fmod = call half @llvm.dx.fmod.f16(
+// DX-NATIVE_HALF: ret half %dx.fmod
+// DX-NO_HALF: define noundef float @
+// DX-NO_HALF: %dx.fmod = call float @llvm.dx.fmod.f32(
+// DX-NO_HALF: ret float %dx.fmod
+//
+// SPV-NATIVE_HALF: define spir_func noundef half @
+// SPV-NATIVE_HALF: %fmod = frem half
+// SPV-NATIVE_HALF: ret half %fmod
+// SPV-NO_HALF: define spir_func noundef float @
+// SPV-NO_HALF: %fmod = frem float
+// SPV-NO_HALF: ret float %fmod
+half test_fmod_half(half p0, half p1) { return fmod(p0, p1); }
+
+// DX-NATIVE_HALF: define noundef <2 x half> @
+// DX-NATIVE_HALF: %dx.fmod = call <2 x half> @llvm.dx.fmod.v2f16
+// DX-NATIVE_HALF: ret <2 x half> %dx.fmod
+// DX-NO_HALF: define noundef <2 x float> @
+// DX-NO_HALF: %dx.fmod = call <2 x float> @llvm.dx.fmod.v2f32(
+// DX-NO_HALF: ret <2 x float> %dx.fmod
+//
+// SPV-NATIVE_HALF: define spir_func noundef <2 x half> @
+// SPV-NATIVE_HALF: %fmod = frem <2 x half>
+// SPV-NATIVE_HALF: ret <2 x half> %fmod
+// SPV-NO_HALF: define spir_func noundef <2 x float> @
+// SPV-NO_HALF: %fmod = frem <2 x float>
+// SPV-NO_HALF: ret <2 x float> %fmod
+half2 test_fmod_half2(half2 p0, half2 p1) { return fmod(p0, p1); }
+
+// DX-NATIVE_HALF: define noundef <3 x half> @
+// DX-NATIVE_HALF: %dx.fmod = call <3 x half> @llvm.dx.fmod.v3f16
+// DX-NATIVE_HALF: ret <3 x half> %dx.fmod
+// DX-NO_HALF: define noundef <3 x float> @
+// DX-NO_HALF: %dx.fmod = call <3 x float> @llvm.dx.fmod.v3f32(
+// DX-NO_HALF: ret <3 x float> %dx.fmod
+//
+// SPV-NATIVE_HALF: define spir_func noundef <3 x half> @
+// SPV-NATIVE_HALF: %fmod = frem <3 x half>
+// SPV-NATIVE_HALF: ret <3 x half> %fmod
+// SPV-NO_HALF: define spir_func noundef <3 x float> @
+// SPV-NO_HALF: %fmod = frem <3 x float>
+// SPV-NO_HALF: ret <3 x float> %fmod
+half3 test_fmod_half3(half3 p0, half3 p1) { return fmod(p0, p1); }
+
+// DX-NATIVE_HALF: define noundef <4 x half> @
+// DX-NATIVE_HALF: %dx.fmod = call <4 x half> @llvm.dx.fmod.v4f16
+// DX-NATIVE_HALF: ret <4 x half> %dx.fmod
+// DX-NO_HALF: define noundef <4 x float> @
+// DX-NO_HALF: %dx.fmod = call <4 x float> @llvm.dx.fmod.v4f32(
+// DX-NO_HALF: ret <4 x float> %dx.fmod
+//
+// SPV-NATIVE_HALF: define spir_func noundef <4 x half> @
+// SPV-NATIVE_HALF: %fmod = frem <4 x half>
+// SPV-NATIVE_HALF: ret <4 x half> %fmod
+// SPV-NO_HALF: define spir_func noundef <4 x float> @
+// SPV-NO_HALF: %fmod = frem <4 x float>
+// SPV-NO_HALF: ret <4 x float> %fmod
+half4 test_fmod_half4(half4 p0, half4 p1) { return fmod(p0, p1); }
+
+// DX-CHECK: define noundef float @
+// DX-CHECK: %dx.fmod = call float @llvm.dx.fmod.f32(
+// DX-CHECK: ret float %dx.fmod
+//
+// SPV-CHECK: define spir_func noundef float @
+// SPV-CHECK: %fmod = frem float
+// SPV-CHECK: ret float %fmod
+float test_fmod_float(float p0, float p1) { return fmod(p0, p1); }
+
+// DX-CHECK: define noundef <2 x float> @
+// DX-CHECK: %dx.fmod = call <2 x float> @llvm.dx.fmod.v2f32
+// DX-CHECK: ret <2 x float> %dx.fmod
+//
+// SPV-CHECK: define spir_func noundef <2 x float> @
+// SPV-CHECK: %fmod = frem <2 x float>
+// SPV-CHECK: ret <2 x float> %fmod
+float2 test_fmod_float2(float2 p0, float2 p1) { return fmod(p0, p1); }
+
+// DX-CHECK: define noundef <3 x float> @
+// DX-CHECK: %dx.fmod = call <3 x float> @llvm.dx.fmod.v3f32
+// DX-CHECK: ret <3 x float> %dx.fmod
+//
+// SPV-CHECK: define spir_func noundef <3 x float> @
+// SPV-CHECK: %fmod = frem <3 x float>
+// SPV-CHECK: ret <3 x float> %fmod
+float3 test_fmod_float3(float3 p0, float3 p1) { return fmod(p0, p1); }
+
+// DX-CHECK: define noundef <4 x float> @
+// DX-CHECK: %dx.fmod = call <4 x float> @llvm.dx.fmod.v4f32
+// DX-CHECK: ret <4 x float> %dx.fmod
+//
+// SPV-CHECK: define spir_func noundef <4 x float> @
+// SPV-CHECK: %fmod = frem <4 x float>
+// SPV-CHECK: ret <4 x float> %fmod
+float4 test_fmod_float4(float4 p0, float4 p1) { return fmod(p0, p1); }
+
diff --git a/clang/test/SemaHLSL/BuiltIns/fmod-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/fmod-errors.hlsl
new file mode 100644
index 00000000000000..ce1940403ba53b
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/fmod-errors.hlsl
@@ -0,0 +1,38 @@
+
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected
+
+float test_too_few_arg() {
+  return __builtin_hlsl_elementwise_fmod();
+  // expected-error@-1 {{too few arguments to function call, expected 2, have 0}}
+}
+
+float2 test_too_many_arg(float2 p0, float2 p1, float2 p3) {
+  return __builtin_hlsl_elementwise_fmod(p0, p1, p3);
+  // expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
+}
+
+float builtin_bool_to_float_type_promotion(bool p1, bool p2) {
+  return __builtin_hlsl_elementwise_fmod(p1, p2);
+  // expected-error@-1 {{passing 'bool' to parameter of incompatible type 'float'}}
+}
+
+float builtin_fmod_int_to_float_promotion(int p1, int p2) {
+  return __builtin_hlsl_elementwise_fmod(p1, p2);
+  // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}}
+}
+
+float2 builtin_fmod_int2_to_float2_promotion(int2 p1, int2 p2) {
+  return __builtin_hlsl_elementwise_fmod(p1, p2);
+  // expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
+}
+
+// builtins are variadic functions and so are subject to DefaultVariadicArgumentPromotion
+half builtin_fmod_half_scalar (half p0, half p1) {
+  return __builtin_hlsl_elementwise_fmod(p0, p1);
+  // expected-error@-1 {{passing 'double' to parameter of incompatible type 'float'}}
+}
+
+float builtin_fmod_float_scalar (float p0, float p1) {
+  return __builtin_hlsl_elementwise_fmod (p0, p1);
+  // expected-error@-1 {{passing 'double' to parameter of incompatible type 'float'}}
+}
\ No newline at end of file
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 97c69638fbb0ef..cadc7c1e8ba0fd 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -90,4 +90,5 @@ def int_dx_rsqrt  : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]
 def int_dx_wave_is_first_lane : DefaultAttrsIntrinsic<[llvm_i1_ty], [], [IntrConvergent]>;
 def int_dx_sign : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_any_ty]>;
 def int_dx_step : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>]>;
+def int_dx_fmod : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>]>;
 }

@farzonl
Copy link
Member

farzonl commented Sep 24, 2024

The SPIRV frem testing doesn't appear to be complete in
llvm/test/CodeGen/SPIRV/instructions/scalar-floating-point-arithmetic.ll
llvm/test/CodeGen/SPIRV/instructions/vector-floating-point-arithmetic.ll

for all our cases we defined in hlsl_intrinsics.h. Should we add more test cases?

Personally I'd like to see at least one test case in:
llvm/test/CodeGen/SPIRV/hlsl-intrinsics/fmod.ll
Makes it easy to track which intrinsics we have completed for the SPIRV backend.

@farzonl
Copy link
Member

farzonl commented Sep 24, 2024

We should announce __builtin_elementwise_fmod here: clang/docs/ReleaseNotes.rst
See @spall PR where we just did this: https://github.com/llvm/llvm-project/pull/108121/files

@lizhengxing
Copy link
Contributor Author

The SPIRV frem testing doesn't appear to be complete in llvm/test/CodeGen/SPIRV/instructions/scalar-floating-point-arithmetic.ll llvm/test/CodeGen/SPIRV/instructions/vector-floating-point-arithmetic.ll

for all our cases we defined in hlsl_intrinsics.h. Should we add more test cases?

Personally I'd like to see at least one test case in: llvm/test/CodeGen/SPIRV/hlsl-intrinsics/fmod.ll Makes it easy to track which intrinsics we have completed for the SPIRV backend.

I'll add those codegen tests in the second PR for #99118 . That PR is backend specific.

@lizhengxing
Copy link
Contributor Author

We should announce __builtin_elementwise_fmod here: clang/docs/ReleaseNotes.rst See @spall PR where we just did this: https://github.com/llvm/llvm-project/pull/108121/files

Done.

@farzonl
Copy link
Member

farzonl commented Sep 25, 2024

This LGTM. There is one last thing we might want to do. But I'm not requiring it for sign off.
We ussually add elementwise math builtins here:

  • clang/test/CodeGen/builtins-elementwise-math.c
  • clang/test/CodeGen/strictfp-elementwise-bulitins.cpp
  • clang/test/Sema/builtins-elementwise-math.c
  • clang/test/SemaCXX/builtins-elementwise-math.cpp

Also I'd take a look at the existing fmod test cases and make sure there is nothing we need to update there:

clang/test/CodeGen/X86/math-builtins.c:11:  f = __builtin_fmod(f,f);    f = __builtin_fmodf(f,f);   f =  __builtin_fmodl(f,f);  f = __builtin_fmodf128(f,f);
clang/test/CodeGen/builtins.c:318:  resd = __builtin_fmod(D,D);
clang/test/CodeGen/constrained-math-builtins.c:11:  f = __builtin_fmod(f,f);    f = __builtin_fmodf(f,f);   f =  __builtin_fmodl(f,f); f = __builtin_fmodf128(f,f);
clang/test/CodeGenOpenCL/builtins-f16.cl:55:  res = __builtin_fmodf16(h0, h1);

@farzonl
Copy link
Member

farzonl commented Sep 25, 2024

change the title of this PR to remove the word intrinsic. That word has a specific meaning in LLVM and folks might get confused. Something like: [HLSL] Implementation of the fmod API.

If you really want to use the word intrinsic then just reuse the HLSL keyword so HLSL is a modifier to specify the kind of intrinsic: [HLSL] Implementation of the fmod HLSL intrinsic.

@lizhengxing lizhengxing changed the title [HLSL] Implementation of the fmod intrinsic [HLSL] Implementation of the elementwise fmod builtin Sep 25, 2024
@lizhengxing
Copy link
Contributor Author

This LGTM. There is one last thing we might want to do. But I'm not requiring it for sign off. We ussually add elementwise math builtins here:

  • clang/test/CodeGen/builtins-elementwise-math.c
  • clang/test/CodeGen/strictfp-elementwise-bulitins.cpp
  • clang/test/Sema/builtins-elementwise-math.c
  • clang/test/SemaCXX/builtins-elementwise-math.cpp

Also I'd take a look at the existing fmod test cases and make sure there is nothing we need to update there:

clang/test/CodeGen/X86/math-builtins.c:11:  f = __builtin_fmod(f,f);    f = __builtin_fmodf(f,f);   f =  __builtin_fmodl(f,f);  f = __builtin_fmodf128(f,f);
clang/test/CodeGen/builtins.c:318:  resd = __builtin_fmod(D,D);
clang/test/CodeGen/constrained-math-builtins.c:11:  f = __builtin_fmod(f,f);    f = __builtin_fmodf(f,f);   f =  __builtin_fmodl(f,f); f = __builtin_fmodf128(f,f);
clang/test/CodeGenOpenCL/builtins-f16.cl:55:  res = __builtin_fmodf16(h0, h1);

Done.

@lizhengxing
Copy link
Contributor Author

change the title of this PR to remove the word intrinsic. That word has a specific meaning in LLVM and folks might get confused. Something like: [HLSL] Implementation of the fmod API.

If you really want to use the word intrinsic then just reuse the HLSL keyword so HLSL is a modifier to specify the kind of intrinsic: [HLSL] Implementation of the fmod HLSL intrinsic.

Done. Renamed it to [HLSL] Implementation of the elementwise fmod builtin .

Copy link

github-actions bot commented Sep 26, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@farzonl
Copy link
Member

farzonl commented Sep 26, 2024

@lizhengxing please run clang-format.

This change add the elementwise fmod builtin to support HLSL function 'fmod' in clang for llvm#99118
Builtins.td           - add the fmod builtin
CGBuiltin.cpp         - lower the builtin to llvm FRem instruction
hlsl_intrinsics.h     - add the fmod api
SemaChecking.cpp      - add type checks for builtin
SemaHLSL.cpp          - add HLSL type checks for builtin

clang/docs/LanguageExtensions.rst  - add the builtin in *Elementwise Builtins*
clang/docs/ReleaseNotes.rst        - announce the builtin
@lizhengxing
Copy link
Contributor Author

@farzonl Could you help to merge this PR? The 2 failing checks are in libc++ since yesterday. It might be caused by #107638.

@hekota pinged the authors of #107638 to see if they think it might be related.

@farzonl farzonl merged commit 5d08f32 into llvm:main Sep 27, 2024
7 of 9 checks passed
Copy link

@lizhengxing Congratulations on having your first Pull Request (PR) merged into the LLVM Project!

Your changes will be combined with recent changes from other authors, then tested by our build bots. If there is a problem with a build, you may receive a report in an email or a comment on this PR.

Please check whether problems have been caused by your change specifically, as the builds can include changes from many authors. It is not uncommon for your change to be included in a build that fails due to someone else's changes, or infrastructure issues.

How to do this, and the rest of the post-merge process, is covered in detail here.

If your change does cause a problem, it may be reverted, or you can revert it yourself. This is a normal part of LLVM development. You can fix your changes and open a new PR to merge them again.

If you don't get any reports, no action is required from you. Your changes are working as expected, well done!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:DirectX backend:X86 clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:headers Headers provided by Clang, e.g. for intrinsics clang Clang issues not falling into any other category HLSL HLSL Language Support llvm:ir
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

4 participants