Closed
Description
Description
LLVM Language Reference: llvm.is.fpclass
The lowering of llvm.is.fpclass
depends on the compile-time constant operand i32 <test>
.
Valid bits for <test>
are defined in an enum named FPClassTest.
The following FPClassTest cases are of interest:
fcNegZero
are introduced into the backend from half-to-float castsfcInf
,fcNan
,fcFinite
,fcNormal
map directly to DXIL Ops
There also does not appear to be any lowering for llvm.is.fpclass
to SPIR-V. The lowering of llvm.is.fpclass
to both SPIR-V and DirectX will simplify the codegen for HLSL intrinsics isinf
, isnan
, and isfinite
. These tasks can be addressed in follow-up issues/PRs.
Implementation
- Add a case to
expandIntrinsic()
inDXILIntrinsicExpansion.cpp
to handleIntrinsic::is_fpclass
for cases where the FPClassTest does not have a corresponding DXIL opcode- Implement the intrinsic expansion for the case of
fcNegZero
- (More cases of
FPClassTest
can be added in the future as needed)
- Implement the intrinsic expansion for the case of
- Add a case to
lowerIntrinsics()
inDXILOpLowering.cpp
to handle the lowering ofIntrinsic::is_fpclass
with FPClassTestsfcInf
,fcNan
,fcFinite
,fcNormal
to their respective DXIL ops - Create tests in
llvm/test/CodeGen/DirectX/is_fpclass.ll
DXIL Ops
The following are DXIL ops, their corresponding FPClassTests, and corresponding Clang builtins that match what is described in DXIL.rst.
DXIL Op | FPClassTest | Clang Builtin |
---|---|---|
IsInf |
FPClassTest::fcInf |
Builtin::BI__builtin_isinf |
IsNaN |
FPClassTest::fcNan |
Builtin::BI__builtin_isnan |
IsNormal |
FPClassTest::fcNormal |
Builtin::BI__builtin_isnormal |
IsFinite |
FPClassTest::fcFinite |
Builtin::BI__builtin_isfinite |
Original issue
The half to float casts are introducing @llvm.is.fpclass.f32
into the backend:
Example
%31 = tail call i1 @llvm.is.fpclass.f32(float %29, i32 32)
%32 = tail call i1 @llvm.is.fpclass.f32(float %30, i32 32)
Example with more context
%23 = call %dx.types.Handle @llvm.dx.resource.casthandle.s_dx.types.Handles.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) zeroinitializer)
%24 = call %dx.types.ResRet.f16 @dx.op.rawBufferLoad.f16(i32 139, %dx.types.Handle %23, i32 %21, i32 0, i8 1, i32 2)
%25 = extractvalue %dx.types.ResRet.f16 %24, 0
%26 = call %dx.types.Handle @llvm.dx.resource.casthandle.s_dx.types.Handles.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) zeroinitializer)
%27 = call %dx.types.ResRet.f16 @dx.op.rawBufferLoad.f16(i32 139, %dx.types.Handle %26, i32 %22, i32 0, i8 1, i32 2)
%28 = extractvalue %dx.types.ResRet.f16 %27, 0
%29 = fpext reassoc nnan ninf nsz arcp afn half %25 to float
%30 = fpext reassoc nnan ninf nsz arcp afn half %28 to float
%31 = tail call i1 @llvm.is.fpclass.f32(float %29, i32 32)
%32 = tail call i1 @llvm.is.fpclass.f32(float %30, i32 32)
br i1 %31, label %33, label %37
33: ; preds = %14
%34 = fcmp reassoc nnan ninf nsz arcp afn olt half %28, 0xH0000
%35 = or i1 %34, %32
%36 = select reassoc nnan ninf nsz arcp afn i1 %35, float 0xC00921FB80000000, float %29
br label %90
37: ; preds = %14
%38 = fcmp reassoc nnan ninf nsz arcp afn oeq half %25, 0xH0000
%39 = fcmp reassoc nnan ninf nsz arcp afn oeq half %28, 0xH0000
%40 = select i1 %38, i1 %39, i1 false
br i1 %40, label %41, label %43
Metadata
Metadata
Assignees
Type
Projects
Status
Closed