Skip to content
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

[HLSL] implement the isinf intrinsic #84927

Merged
merged 3 commits into from
Mar 14, 2024
Merged

Conversation

farzonl
Copy link
Member

@farzonl farzonl commented Mar 12, 2024

This change implements part 1 of 2 for #70095

  • hlsl_intrinsics.h - add the isinf api
  • Builtins.td - add an hlsl builtin for isinf.
  • CGBuiltin.cpp add the ir generation for isinf intrinsic.
  • SemaChecking.cpp - add a non-math elementwise checks because this is a bool return.
  • IntrinsicsDirectX.td - add an isinf intrinsic.

DXIL.td lowering is left, but changes need to be made there before we can support this case.

@farzonl farzonl requested a review from bharadwajy March 12, 2024 15:00
@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 backend:DirectX HLSL HLSL Language Support llvm:ir labels Mar 12, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Mar 12, 2024

@llvm/pr-subscribers-hlsl
@llvm/pr-subscribers-clang
@llvm/pr-subscribers-backend-x86
@llvm/pr-subscribers-llvm-ir

@llvm/pr-subscribers-clang-codegen

Author: Farzon Lotfi (farzonl)

Changes

This change implements part 1 of 2 for #70095

  • hlsl_intrinsics.h - add the isinf api
  • Builtins.td - add an hlsl builtin for isinf.
  • CGBuiltin.cpp add the ir generation for isinf intrinsic.
  • SemaChecking.cpp - add a non-math elementwise checks because this is a bool return.
  • IntrinsicsDirectX.td - add an isinf intrinsic.

DXIL.td lowering is left, but changes need to be made there before we can support this case.


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

7 Files Affected:

  • (modified) clang/include/clang/Basic/Builtins.td (+6)
  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+15)
  • (modified) clang/lib/Headers/hlsl/hlsl_intrinsics.h (+33)
  • (modified) clang/lib/Sema/SemaChecking.cpp (+16)
  • (added) clang/test/CodeGenHLSL/builtins/isinf.hlsl (+45)
  • (added) clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl (+27)
  • (modified) llvm/include/llvm/IR/IntrinsicsDirectX.td (+4)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 9c703377ca8d3e..b3376b316cd222 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4572,6 +4572,12 @@ def HLSLFrac : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLIsinf : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_isinf"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 def HLSLLerp : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_lerp"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 20c35757939152..6f92139bf848b9 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18050,6 +18050,21 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
         /*ReturnType=*/Op0->getType(), Intrinsic::dx_frac,
         ArrayRef<Value *>{Op0}, nullptr, "dx.frac");
   }
+  case Builtin::BI__builtin_hlsl_elementwise_isinf: {
+    Value *Op0 = EmitScalarExpr(E->getArg(0));
+    llvm::Type *Xty = Op0->getType();
+    llvm::Type *retType = llvm::Type::getInt1Ty(this->getLLVMContext());
+    if (Xty->isVectorTy()) {
+      auto *XVecTy = E->getArg(0)->getType()->getAs<VectorType>();
+      retType = llvm::VectorType::get(
+          retType, ElementCount::getFixed(XVecTy->getNumElements()));
+    }
+    if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+      llvm_unreachable("isinf operand must have a float representation");
+    return Builder.CreateIntrinsic(
+        /*ReturnType=*/retType, Intrinsic::dx_isinf, ArrayRef<Value *>{Op0},
+        nullptr, "dx.isinf");
+  }
   case Builtin::BI__builtin_hlsl_mad: {
     Value *M = EmitScalarExpr(E->getArg(0));
     Value *A = EmitScalarExpr(E->getArg(1));
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 45f8544392584e..2c3ab46d959137 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -525,6 +525,39 @@ float3 frac(float3);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
 float4 frac(float4);
 
+//===----------------------------------------------------------------------===//
+// isinf builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn T isinf(T x)
+/// \brief Determines if the specified value \a x  is infinite.
+/// \param x The specified input value.
+///
+/// Returns a value of the same size as the input, with a value set
+/// to True if the x parameter is +INF or -INF. Otherwise, False.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool isinf(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool2 isinf(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool3 isinf(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool4 isinf(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool isinf(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool2 isinf(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool3 isinf(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool4 isinf(float4);
+
 //===----------------------------------------------------------------------===//
 // lerp builtins
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index a5f42b630c3fa2..d7b96ec9779222 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5267,6 +5267,15 @@ bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall) {
   return false;
 }
 
+void SetInputRepresentationReturnType(Sema *S, CallExpr *TheCall,
+                                      QualType ReturnType) {
+  auto *VecTyA = TheCall->getArg(0)->getType()->getAs<VectorType>();
+  if (VecTyA)
+    ReturnType = S->Context.getVectorType(ReturnType, VecTyA->getNumElements(),
+                                          VectorKind::Generic);
+  TheCall->setType(ReturnType);
+}
+
 // Note: returning true in this case results in CheckBuiltinFunctionCall
 // returning an ExprError
 bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
@@ -5285,6 +5294,13 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
       return true;
     break;
   }
+  case Builtin::BI__builtin_hlsl_elementwise_isinf:
+    if (checkArgCount(*this, TheCall, 1))
+      return true;
+    if (CheckAllArgsHaveFloatRepresentation(this, TheCall))
+      return true;
+    SetInputRepresentationReturnType(this, TheCall, this->Context.BoolTy);
+    break;
   case Builtin::BI__builtin_hlsl_elementwise_rcp:
   case Builtin::BI__builtin_hlsl_elementwise_frac: {
     if (PrepareBuiltinElementwiseMathOneArgCall(TheCall))
diff --git a/clang/test/CodeGenHLSL/builtins/isinf.hlsl b/clang/test/CodeGenHLSL/builtins/isinf.hlsl
new file mode 100644
index 00000000000000..df44fc4a91dfd0
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/isinf.hlsl
@@ -0,0 +1,45 @@
+// 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=CHECK,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=CHECK,NO_HALF
+
+// CHECK: define noundef i1 @
+// NATIVE_HALF: %dx.isinf = call i1 @llvm.dx.isinf.f16(
+// NO_HALF: %dx.isinf = call i1 @llvm.dx.isinf.f32(
+// CHECK: ret i1 %dx.isinf
+bool test_isinf_half(half p0) { return isinf(p0); }
+// CHECK: define noundef <2 x i1> @
+// NATIVE_HALF: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f16
+// NO_HALF: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f32(
+// CHECK: ret <2 x i1> %dx.isinf
+bool2 test_isinf_half2(half2 p0) { return isinf(p0); }
+// NATIVE_HALF: define noundef <3 x i1> @
+// NATIVE_HALF: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f16
+// NO_HALF: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f32(
+// CHECK: ret <3 x i1> %dx.isinf
+bool3 test_isinf_half3(half3 p0) { return isinf(p0); }
+// NATIVE_HALF: define noundef <4 x i1> @
+// NATIVE_HALF: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f16
+// NO_HALF: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f32(
+// CHECK: ret <4 x i1> %dx.isinf
+bool4 test_isinf_half4(half4 p0) { return isinf(p0); }
+
+// CHECK: define noundef i1 @
+// CHECK: %dx.isinf = call i1 @llvm.dx.isinf.f32(
+// CHECK: ret i1 %dx.isinf
+bool test_isinf_float(float p0) { return isinf(p0); }
+// CHECK: define noundef <2 x i1> @
+// CHECK: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f32
+// CHECK: ret <2 x i1> %dx.isinf
+bool2 test_isinf_float2(float2 p0) { return isinf(p0); }
+// CHECK: define noundef <3 x i1> @
+// CHECK: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f32
+// CHECK: ret <3 x i1> %dx.isinf
+bool3 test_isinf_float3(float3 p0) { return isinf(p0); }
+// CHECK: define noundef <4 x i1> @
+// CHECK: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f32
+// CHECK: ret <4 x i1> %dx.isinf
+bool4 test_isinf_float4(float4 p0) { return isinf(p0); }
diff --git a/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl
new file mode 100644
index 00000000000000..12c273764c2556
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl
@@ -0,0 +1,27 @@
+
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected
+
+bool test_too_few_arg() {
+  return __builtin_hlsl_elementwise_isinf();
+  // expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+bool2 test_too_many_arg(float2 p0) {
+  return __builtin_hlsl_elementwise_isinf(p0, p0);
+  // expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+bool builtin_bool_to_float_type_promotion(bool p1) {
+  return __builtin_hlsl_elementwise_isinf(p1);
+  // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'bool')}}
+}
+
+bool builtin_isinf_int_to_float_promotion(int p1) {
+  return __builtin_hlsl_elementwise_isinf(p1);
+  // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}}
+}
+
+bool2 builtin_isinf_int2_to_float2_promotion(int2 p1) {
+  return __builtin_hlsl_elementwise_isinf(p1);
+  // 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)}}
+}
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 7229292e377a83..33a663c516256f 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -29,6 +29,10 @@ def int_dx_dot :
 
 def int_dx_frac  : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
 
+def int_dx_isinf :
+    DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>],
+    [llvm_anyfloat_ty]>;
+
 def int_dx_lerp :
     Intrinsic<[LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>],
     [llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>,LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>],

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 12, 2024

@llvm/pr-subscribers-backend-directx

Author: Farzon Lotfi (farzonl)

Changes

This change implements part 1 of 2 for #70095

  • hlsl_intrinsics.h - add the isinf api
  • Builtins.td - add an hlsl builtin for isinf.
  • CGBuiltin.cpp add the ir generation for isinf intrinsic.
  • SemaChecking.cpp - add a non-math elementwise checks because this is a bool return.
  • IntrinsicsDirectX.td - add an isinf intrinsic.

DXIL.td lowering is left, but changes need to be made there before we can support this case.


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

7 Files Affected:

  • (modified) clang/include/clang/Basic/Builtins.td (+6)
  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+15)
  • (modified) clang/lib/Headers/hlsl/hlsl_intrinsics.h (+33)
  • (modified) clang/lib/Sema/SemaChecking.cpp (+16)
  • (added) clang/test/CodeGenHLSL/builtins/isinf.hlsl (+45)
  • (added) clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl (+27)
  • (modified) llvm/include/llvm/IR/IntrinsicsDirectX.td (+4)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 9c703377ca8d3e..b3376b316cd222 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4572,6 +4572,12 @@ def HLSLFrac : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLIsinf : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_isinf"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 def HLSLLerp : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_lerp"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 20c35757939152..6f92139bf848b9 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18050,6 +18050,21 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
         /*ReturnType=*/Op0->getType(), Intrinsic::dx_frac,
         ArrayRef<Value *>{Op0}, nullptr, "dx.frac");
   }
+  case Builtin::BI__builtin_hlsl_elementwise_isinf: {
+    Value *Op0 = EmitScalarExpr(E->getArg(0));
+    llvm::Type *Xty = Op0->getType();
+    llvm::Type *retType = llvm::Type::getInt1Ty(this->getLLVMContext());
+    if (Xty->isVectorTy()) {
+      auto *XVecTy = E->getArg(0)->getType()->getAs<VectorType>();
+      retType = llvm::VectorType::get(
+          retType, ElementCount::getFixed(XVecTy->getNumElements()));
+    }
+    if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+      llvm_unreachable("isinf operand must have a float representation");
+    return Builder.CreateIntrinsic(
+        /*ReturnType=*/retType, Intrinsic::dx_isinf, ArrayRef<Value *>{Op0},
+        nullptr, "dx.isinf");
+  }
   case Builtin::BI__builtin_hlsl_mad: {
     Value *M = EmitScalarExpr(E->getArg(0));
     Value *A = EmitScalarExpr(E->getArg(1));
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 45f8544392584e..2c3ab46d959137 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -525,6 +525,39 @@ float3 frac(float3);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
 float4 frac(float4);
 
+//===----------------------------------------------------------------------===//
+// isinf builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn T isinf(T x)
+/// \brief Determines if the specified value \a x  is infinite.
+/// \param x The specified input value.
+///
+/// Returns a value of the same size as the input, with a value set
+/// to True if the x parameter is +INF or -INF. Otherwise, False.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool isinf(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool2 isinf(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool3 isinf(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool4 isinf(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool isinf(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool2 isinf(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool3 isinf(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
+bool4 isinf(float4);
+
 //===----------------------------------------------------------------------===//
 // lerp builtins
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index a5f42b630c3fa2..d7b96ec9779222 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5267,6 +5267,15 @@ bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall) {
   return false;
 }
 
+void SetInputRepresentationReturnType(Sema *S, CallExpr *TheCall,
+                                      QualType ReturnType) {
+  auto *VecTyA = TheCall->getArg(0)->getType()->getAs<VectorType>();
+  if (VecTyA)
+    ReturnType = S->Context.getVectorType(ReturnType, VecTyA->getNumElements(),
+                                          VectorKind::Generic);
+  TheCall->setType(ReturnType);
+}
+
 // Note: returning true in this case results in CheckBuiltinFunctionCall
 // returning an ExprError
 bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
@@ -5285,6 +5294,13 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
       return true;
     break;
   }
+  case Builtin::BI__builtin_hlsl_elementwise_isinf:
+    if (checkArgCount(*this, TheCall, 1))
+      return true;
+    if (CheckAllArgsHaveFloatRepresentation(this, TheCall))
+      return true;
+    SetInputRepresentationReturnType(this, TheCall, this->Context.BoolTy);
+    break;
   case Builtin::BI__builtin_hlsl_elementwise_rcp:
   case Builtin::BI__builtin_hlsl_elementwise_frac: {
     if (PrepareBuiltinElementwiseMathOneArgCall(TheCall))
diff --git a/clang/test/CodeGenHLSL/builtins/isinf.hlsl b/clang/test/CodeGenHLSL/builtins/isinf.hlsl
new file mode 100644
index 00000000000000..df44fc4a91dfd0
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/isinf.hlsl
@@ -0,0 +1,45 @@
+// 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=CHECK,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=CHECK,NO_HALF
+
+// CHECK: define noundef i1 @
+// NATIVE_HALF: %dx.isinf = call i1 @llvm.dx.isinf.f16(
+// NO_HALF: %dx.isinf = call i1 @llvm.dx.isinf.f32(
+// CHECK: ret i1 %dx.isinf
+bool test_isinf_half(half p0) { return isinf(p0); }
+// CHECK: define noundef <2 x i1> @
+// NATIVE_HALF: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f16
+// NO_HALF: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f32(
+// CHECK: ret <2 x i1> %dx.isinf
+bool2 test_isinf_half2(half2 p0) { return isinf(p0); }
+// NATIVE_HALF: define noundef <3 x i1> @
+// NATIVE_HALF: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f16
+// NO_HALF: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f32(
+// CHECK: ret <3 x i1> %dx.isinf
+bool3 test_isinf_half3(half3 p0) { return isinf(p0); }
+// NATIVE_HALF: define noundef <4 x i1> @
+// NATIVE_HALF: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f16
+// NO_HALF: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f32(
+// CHECK: ret <4 x i1> %dx.isinf
+bool4 test_isinf_half4(half4 p0) { return isinf(p0); }
+
+// CHECK: define noundef i1 @
+// CHECK: %dx.isinf = call i1 @llvm.dx.isinf.f32(
+// CHECK: ret i1 %dx.isinf
+bool test_isinf_float(float p0) { return isinf(p0); }
+// CHECK: define noundef <2 x i1> @
+// CHECK: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f32
+// CHECK: ret <2 x i1> %dx.isinf
+bool2 test_isinf_float2(float2 p0) { return isinf(p0); }
+// CHECK: define noundef <3 x i1> @
+// CHECK: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f32
+// CHECK: ret <3 x i1> %dx.isinf
+bool3 test_isinf_float3(float3 p0) { return isinf(p0); }
+// CHECK: define noundef <4 x i1> @
+// CHECK: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f32
+// CHECK: ret <4 x i1> %dx.isinf
+bool4 test_isinf_float4(float4 p0) { return isinf(p0); }
diff --git a/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl
new file mode 100644
index 00000000000000..12c273764c2556
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl
@@ -0,0 +1,27 @@
+
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected
+
+bool test_too_few_arg() {
+  return __builtin_hlsl_elementwise_isinf();
+  // expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+bool2 test_too_many_arg(float2 p0) {
+  return __builtin_hlsl_elementwise_isinf(p0, p0);
+  // expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+bool builtin_bool_to_float_type_promotion(bool p1) {
+  return __builtin_hlsl_elementwise_isinf(p1);
+  // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'bool')}}
+}
+
+bool builtin_isinf_int_to_float_promotion(int p1) {
+  return __builtin_hlsl_elementwise_isinf(p1);
+  // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}}
+}
+
+bool2 builtin_isinf_int2_to_float2_promotion(int2 p1) {
+  return __builtin_hlsl_elementwise_isinf(p1);
+  // 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)}}
+}
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 7229292e377a83..33a663c516256f 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -29,6 +29,10 @@ def int_dx_dot :
 
 def int_dx_frac  : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
 
+def int_dx_isinf :
+    DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>],
+    [llvm_anyfloat_ty]>;
+
 def int_dx_lerp :
     Intrinsic<[LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>],
     [llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>,LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>],

@farzonl farzonl self-assigned this Mar 12, 2024
@farzonl farzonl linked an issue Mar 12, 2024 that may be closed by this pull request
clang/lib/Sema/SemaChecking.cpp Outdated Show resolved Hide resolved
clang/lib/CodeGen/CGBuiltin.cpp Outdated Show resolved Hide resolved
Copy link

github-actions bot commented Mar 14, 2024

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

@farzonl farzonl merged commit d192b64 into llvm:main Mar 14, 2024
3 of 4 checks passed
@farzonl farzonl deleted the hlsl-isinf-intrinsic branch March 14, 2024 22:07
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 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
Status: Done
Development

Successfully merging this pull request may close these issues.

[HLSL] implement isinf intrinsic
4 participants