Skip to content

Commit dfbef57

Browse files
committed
[SPIRV] Add OpInf support for isinf hlsl intrinsic
fixes #148051 - update EmitHLSLBuiltinExpr in CGHLSLBuiltins.cpp to toggle intrinsics by target - Add a GENERATE_HLSL_INTRINSIC_FUNCTION for isinf in CGHLSLRuntime.h - Update the SPIRVInstructionSelector.cpp to emit the OpSinf instruction - Updates the isinf.hlsl test to check spirv intrinsic generation - add OpIsinf.ll tests
1 parent 2fc0e2c commit dfbef57

File tree

6 files changed

+116
-34
lines changed

6 files changed

+116
-34
lines changed

clang/lib/CodeGen/CGHLSLBuiltins.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,8 +536,9 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
536536
}
537537
if (!E->getArg(0)->getType()->hasFloatingRepresentation())
538538
llvm_unreachable("isinf operand must have a float representation");
539-
return Builder.CreateIntrinsic(retType, Intrinsic::dx_isinf,
540-
ArrayRef<Value *>{Op0}, nullptr, "dx.isinf");
539+
return Builder.CreateIntrinsic(
540+
retType, CGM.getHLSLRuntime().getIsInfIntrinsic(),
541+
ArrayRef<Value *>{Op0}, nullptr, "hlsl.isinf");
541542
}
542543
case Builtin::BI__builtin_hlsl_mad: {
543544
Value *M = EmitScalarExpr(E->getArg(0));

clang/lib/CodeGen/CGHLSLRuntime.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ class CGHLSLRuntime {
9191
GENERATE_HLSL_INTRINSIC_FUNCTION(Frac, frac)
9292
GENERATE_HLSL_INTRINSIC_FUNCTION(FlattenedThreadIdInGroup,
9393
flattened_thread_id_in_group)
94+
GENERATE_HLSL_INTRINSIC_FUNCTION(IsInf, isinf)
9495
GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp)
9596
GENERATE_HLSL_INTRINSIC_FUNCTION(Normalize, normalize)
9697
GENERATE_HLSL_INTRINSIC_FUNCTION(Rsqrt, rsqrt)
Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,62 @@
11
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
22
// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
3-
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
4-
// RUN: --check-prefixes=CHECK,NATIVE_HALF
3+
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
4+
// RUN: --check-prefixes=CHECK,DXCHECK,NATIVE_HALF
55
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
66
// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
7-
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
7+
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,DXCHECK,NO_HALF
88

9-
// CHECK: define hidden noundef i1 @
10-
// NATIVE_HALF: %dx.isinf = call i1 @llvm.dx.isinf.f16(
11-
// NO_HALF: %dx.isinf = call i1 @llvm.dx.isinf.f32(
12-
// CHECK: ret i1 %dx.isinf
9+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
10+
// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \
11+
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
12+
// RUN: --check-prefixes=CHECK,SPVCHECK,NATIVE_HALF
13+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
14+
// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
15+
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,SPVCHECK,NO_HALF
16+
17+
// DXCHECK: define hidden [[FN_TYPE:]]noundef i1 @
18+
// SPVCHECK: define hidden [[FN_TYPE:spir_func ]]noundef i1 @
19+
// DXCHECK: %hlsl.isinf = call i1 @llvm.[[ICF:dx]].isinf.f32(
20+
// SPVCHECK: %hlsl.isinf = call i1 @llvm.[[ICF:spv]].isinf.f32(
21+
// CHECK: ret i1 %hlsl.isinf
22+
bool test_isinf_float(float p0) { return isinf(p0); }
23+
24+
// CHECK: define hidden [[FN_TYPE]]noundef i1 @
25+
// NATIVE_HALF: %hlsl.isinf = call i1 @llvm.[[ICF]].isinf.f16(
26+
// NO_HALF: %hlsl.isinf = call i1 @llvm.[[ICF]].isinf.f32(
27+
// CHECK: ret i1 %hlsl.isinf
1328
bool test_isinf_half(half p0) { return isinf(p0); }
14-
// CHECK: define hidden noundef <2 x i1> @
15-
// NATIVE_HALF: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f16
16-
// NO_HALF: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f32(
17-
// CHECK: ret <2 x i1> %dx.isinf
29+
30+
// CHECK: define hidden [[FN_TYPE]]noundef <2 x i1> @
31+
// NATIVE_HALF: %hlsl.isinf = call <2 x i1> @llvm.[[ICF]].isinf.v2f16
32+
// NO_HALF: %hlsl.isinf = call <2 x i1> @llvm.[[ICF]].isinf.v2f32(
33+
// CHECK: ret <2 x i1> %hlsl.isinf
1834
bool2 test_isinf_half2(half2 p0) { return isinf(p0); }
19-
// NATIVE_HALF: define hidden noundef <3 x i1> @
20-
// NATIVE_HALF: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f16
21-
// NO_HALF: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f32(
22-
// CHECK: ret <3 x i1> %dx.isinf
35+
36+
// NATIVE_HALF: define hidden [[FN_TYPE]]noundef <3 x i1> @
37+
// NATIVE_HALF: %hlsl.isinf = call <3 x i1> @llvm.[[ICF]].isinf.v3f16
38+
// NO_HALF: %hlsl.isinf = call <3 x i1> @llvm.[[ICF]].isinf.v3f32(
39+
// CHECK: ret <3 x i1> %hlsl.isinf
2340
bool3 test_isinf_half3(half3 p0) { return isinf(p0); }
24-
// NATIVE_HALF: define hidden noundef <4 x i1> @
25-
// NATIVE_HALF: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f16
26-
// NO_HALF: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f32(
27-
// CHECK: ret <4 x i1> %dx.isinf
41+
42+
// NATIVE_HALF: define hidden [[FN_TYPE]]noundef <4 x i1> @
43+
// NATIVE_HALF: %hlsl.isinf = call <4 x i1> @llvm.[[ICF]].isinf.v4f16
44+
// NO_HALF: %hlsl.isinf = call <4 x i1> @llvm.[[ICF]].isinf.v4f32(
45+
// CHECK: ret <4 x i1> %hlsl.isinf
2846
bool4 test_isinf_half4(half4 p0) { return isinf(p0); }
2947

30-
// CHECK: define hidden noundef i1 @
31-
// CHECK: %dx.isinf = call i1 @llvm.dx.isinf.f32(
32-
// CHECK: ret i1 %dx.isinf
33-
bool test_isinf_float(float p0) { return isinf(p0); }
34-
// CHECK: define hidden noundef <2 x i1> @
35-
// CHECK: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f32
36-
// CHECK: ret <2 x i1> %dx.isinf
48+
49+
// CHECK: define hidden [[FN_TYPE]]noundef <2 x i1> @
50+
// CHECK: %hlsl.isinf = call <2 x i1> @llvm.[[ICF]].isinf.v2f32
51+
// CHECK: ret <2 x i1> %hlsl.isinf
3752
bool2 test_isinf_float2(float2 p0) { return isinf(p0); }
38-
// CHECK: define hidden noundef <3 x i1> @
39-
// CHECK: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f32
40-
// CHECK: ret <3 x i1> %dx.isinf
53+
54+
// CHECK: define hidden [[FN_TYPE]]noundef <3 x i1> @
55+
// CHECK: %hlsl.isinf = call <3 x i1> @llvm.[[ICF]].isinf.v3f32
56+
// CHECK: ret <3 x i1> %hlsl.isinf
4157
bool3 test_isinf_float3(float3 p0) { return isinf(p0); }
42-
// CHECK: define hidden noundef <4 x i1> @
43-
// CHECK: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f32
44-
// CHECK: ret <4 x i1> %dx.isinf
58+
59+
// CHECK: define hidden [[FN_TYPE]]noundef <4 x i1> @
60+
// CHECK: %hlsl.isinf = call <4 x i1> @llvm.[[ICF]].isinf.v4f32
61+
// CHECK: ret <4 x i1> %hlsl.isinf
4562
bool4 test_isinf_float4(float4 p0) { return isinf(p0); }

llvm/include/llvm/IR/IntrinsicsSPIRV.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ let TargetPrefix = "spv" in {
8585
def int_spv_distance : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>;
8686
def int_spv_faceforward : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
8787
def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>;
88+
def int_spv_isinf : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>],
89+
[llvm_anyfloat_ty], [IntrNoMem]>;
8890
def int_spv_lerp : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
8991
[IntrNoMem] >;
9092
def int_spv_length : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_anyfloat_ty], [IntrNoMem]>;

llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
204204
bool selectIntegerDotExpansion(Register ResVReg, const SPIRVType *ResType,
205205
MachineInstr &I) const;
206206

207+
bool selectOpIsInf(Register ResVReg, const SPIRVType *ResType,
208+
MachineInstr &I) const;
209+
207210
template <bool Signed>
208211
bool selectDot4AddPacked(Register ResVReg, const SPIRVType *ResType,
209212
MachineInstr &I) const;
@@ -2042,6 +2045,17 @@ bool SPIRVInstructionSelector::selectIntegerDotExpansion(
20422045
return Result;
20432046
}
20442047

2048+
bool SPIRVInstructionSelector::selectOpIsInf(Register ResVReg,
2049+
const SPIRVType *ResType,
2050+
MachineInstr &I) const {
2051+
MachineBasicBlock &BB = *I.getParent();
2052+
return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIsInf))
2053+
.addDef(ResVReg)
2054+
.addUse(GR.getSPIRVTypeID(ResType))
2055+
.addUse(I.getOperand(2).getReg())
2056+
.constrainAllUses(TII, TRI, RBI);
2057+
}
2058+
20452059
template <bool Signed>
20462060
bool SPIRVInstructionSelector::selectDot4AddPacked(Register ResVReg,
20472061
const SPIRVType *ResType,
@@ -3183,6 +3197,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
31833197
return selectExtInst(ResVReg, ResType, I, GL::FaceForward);
31843198
case Intrinsic::spv_frac:
31853199
return selectExtInst(ResVReg, ResType, I, CL::fract, GL::Fract);
3200+
case Intrinsic::spv_isinf:
3201+
return selectOpIsInf(ResVReg, ResType, I);
31863202
case Intrinsic::spv_normalize:
31873203
return selectExtInst(ResVReg, ResType, I, CL::normalize, GL::Normalize);
31883204
case Intrinsic::spv_refract:
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val --target-env spv1.4 %}
3+
4+
; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16
5+
; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
6+
; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4
7+
; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4
8+
; CHECK-DAG: %[[#bool:]] = OpTypeBool
9+
; CHECK-DAG: %[[#vec4_bool:]] = OpTypeVector %[[#bool]] 4
10+
11+
define noundef i1 @isinf_half(half noundef %a) {
12+
entry:
13+
; CHECK: %[[#]] = OpFunction %[[#bool]] None %[[#]]
14+
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_16]]
15+
; CHECK: %[[#]] = OpIsInf %[[#bool]] %[[#arg0]]
16+
%hlsl.isinf = call i1 @llvm.spv.isinf.f16(half %a)
17+
ret i1 %hlsl.isinf
18+
}
19+
20+
define noundef i1 @isinf_float(float noundef %a) {
21+
entry:
22+
; CHECK: %[[#]] = OpFunction %[[#bool]] None %[[#]]
23+
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_32]]
24+
; CHECK: %[[#]] = OpIsInf %[[#bool]] %[[#arg0]]
25+
%hlsl.isinf = call i1 @llvm.spv.isinf.f32(float %a)
26+
ret i1 %hlsl.isinf
27+
}
28+
29+
define noundef <4 x i1> @isinf_half4(<4 x half> noundef %a) {
30+
entry:
31+
; CHECK: %[[#]] = OpFunction %[[#vec4_bool]] None %[[#]]
32+
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]]
33+
; CHECK: %[[#]] = OpIsInf %[[#vec4_bool]] %[[#arg0]]
34+
%hlsl.isinf = call <4 x i1> @llvm.spv.isinf.v4f16(<4 x half> %a)
35+
ret <4 x i1> %hlsl.isinf
36+
}
37+
38+
define noundef <4 x i1> @isinf_float4(<4 x float> noundef %a) {
39+
entry:
40+
; CHECK: %[[#]] = OpFunction %[[#vec4_bool]] None %[[#]]
41+
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]]
42+
; CHECK: %[[#]] = OpIsInf %[[#vec4_bool]] %[[#arg0]]
43+
%hlsl.isinf = call <4 x i1> @llvm.spv.isinf.v4f32(<4 x float> %a)
44+
ret <4 x i1> %hlsl.isinf
45+
}

0 commit comments

Comments
 (0)