Skip to content

[DirectX] Legalize the llvm.is.fpclass intrinsic #137209

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

Closed
farzonl opened this issue Apr 24, 2025 · 0 comments · Fixed by #138048
Closed

[DirectX] Legalize the llvm.is.fpclass intrinsic #137209

farzonl opened this issue Apr 24, 2025 · 0 comments · Fixed by #138048
Assignees

Comments

@farzonl
Copy link
Member

farzonl commented Apr 24, 2025

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 casts
  • fcInf, 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() in DXILIntrinsicExpansion.cpp to handle Intrinsic::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)
  • Add a case to lowerIntrinsics() in DXILOpLowering.cpp to handle the lowering of Intrinsic::is_fpclass with FPClassTests fcInf, 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
@Icohedron Icohedron self-assigned this Apr 24, 2025
@Icohedron Icohedron moved this to Active in HLSL Support Apr 25, 2025
@Icohedron Icohedron moved this from Active to Planning in HLSL Support Apr 25, 2025
@Icohedron Icohedron changed the title [DirectX] Legalize the llvm.is.fpclass intrinsic [DirectX] [SPIR-V] Legalize the llvm.is.fpclass intrinsic Apr 29, 2025
@Icohedron Icohedron added clang:HLSL:SPIRV Clang HLSL SPIRV support backend:SPIR-V and removed clang:HLSL:SPIRV Clang HLSL SPIRV support labels Apr 29, 2025
@Icohedron Icohedron changed the title [DirectX] [SPIR-V] Legalize the llvm.is.fpclass intrinsic [DirectX] Legalize the llvm.is.fpclass intrinsic Apr 29, 2025
@damyanp damyanp moved this from Planning to Active in HLSL Support Apr 30, 2025
@github-project-automation github-project-automation bot moved this from Active to Closed in HLSL Support May 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Closed
2 participants