Skip to content

release/22.x: [SystemZ] Remove custom lowering of f16 IS_FPCLASS (#187532)#187943

Merged
dyung merged 1 commit intollvm:release/22.xfrom
llvmbot:issue187532
Mar 23, 2026
Merged

release/22.x: [SystemZ] Remove custom lowering of f16 IS_FPCLASS (#187532)#187943
dyung merged 1 commit intollvm:release/22.xfrom
llvmbot:issue187532

Conversation

@llvmbot
Copy link
Copy Markdown
Member

@llvmbot llvmbot commented Mar 22, 2026

Backport 6eb5ac5

Requested by: @uweigand

@llvmbot
Copy link
Copy Markdown
Member Author

llvmbot commented Mar 22, 2026

@uweigand What do you think about merging this PR to the release branch?

@llvmbot
Copy link
Copy Markdown
Member Author

llvmbot commented Mar 22, 2026

@llvm/pr-subscribers-backend-systemz

Author: None (llvmbot)

Changes

Backport 6eb5ac5

Requested by: @uweigand


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

2 Files Affected:

  • (modified) llvm/lib/Target/SystemZ/SystemZISelLowering.cpp (+1-3)
  • (modified) llvm/test/CodeGen/SystemZ/is_fpclass.ll (+84-10)
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 8f21e00983601..f9a41cbeec004 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -561,7 +561,7 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::FP_ROUND, MVT::f16, LibCall);
     setOperationAction(ISD::STRICT_FP_ROUND, MVT::f16, LibCall);
     setOperationAction(ISD::BITCAST, MVT::i16, Custom);
-    setOperationAction(ISD::IS_FPCLASS, MVT::f16, Custom);
+
     for (auto Op : {ISD::FNEG, ISD::FABS, ISD::FCOPYSIGN})
       setOperationAction(Op, MVT::f16, Legal);
   }
@@ -7129,8 +7129,6 @@ SDValue SystemZTargetLowering::lowerIS_FPCLASS(SDValue Op,
     TDCMask |= SystemZ::TDCMASK_ZERO_MINUS;
   SDValue TDCMaskV = DAG.getConstant(TDCMask, DL, MVT::i64);
 
-  if (Arg.getSimpleValueType() == MVT::f16)
-    Arg = DAG.getFPExtendOrRound(Arg, SDLoc(Arg), MVT::f32);
   SDValue Intr = DAG.getNode(SystemZISD::TDC, DL, ResultVT, Arg, TDCMaskV);
   return getCCResult(DAG, Intr);
 }
diff --git a/llvm/test/CodeGen/SystemZ/is_fpclass.ll b/llvm/test/CodeGen/SystemZ/is_fpclass.ll
index 98b856c5737ed..8734a1464d2e0 100644
--- a/llvm/test/CodeGen/SystemZ/is_fpclass.ll
+++ b/llvm/test/CodeGen/SystemZ/is_fpclass.ll
@@ -12,16 +12,13 @@ declare i1 @llvm.is.fpclass.f128(fp128, i32)
 define i1 @isnan_h(half %x) {
 ; CHECK-LABEL: isnan_h:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    stmg %r14, %r15, 112(%r15)
-; CHECK-NEXT:    .cfi_offset %r14, -48
-; CHECK-NEXT:    .cfi_offset %r15, -40
-; CHECK-NEXT:    aghi %r15, -160
-; CHECK-NEXT:    .cfi_def_cfa_offset 320
-; CHECK-NEXT:    brasl %r14, __extendhfsf2@PLT
-; CHECK-NEXT:    tceb %f0, 15
-; CHECK-NEXT:    ipm %r2
-; CHECK-NEXT:    srl %r2, 28
-; CHECK-NEXT:    lmg %r14, %r15, 272(%r15)
+; CHECK-NEXT:    # kill: def $f0h killed $f0h def $f0d
+; CHECK-NEXT:    lgdr %r0, %f0
+; CHECK-NEXT:    risbg %r0, %r0, 49, 191, 16
+; CHECK-NEXT:    chi %r0, 31744
+; CHECK-NEXT:    ipm %r0
+; CHECK-NEXT:    risbg %r2, %r0, 63, 191, 35
+; CHECK-NEXT:    # kill: def $r2l killed $r2l killed $r2d
 ; CHECK-NEXT:    br %r14
   %1 = call i1 @llvm.is.fpclass.f16(half %x, i32 3)  ; nan
   ret i1 %1
@@ -161,3 +158,80 @@ define i1 @isnotfinite_f(float %x) {
   ret i1 %1
 }
 
+
+define i1 @isnormal_h(half %x) {
+; CHECK-LABEL: isnormal_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    # kill: def $f0h killed $f0h def $f0d
+; CHECK-NEXT:    lgdr %r0, %f0
+; CHECK-NEXT:    risbg %r0, %r0, 49, 191, 16
+; CHECK-NEXT:    ahi %r0, -1024
+; CHECK-NEXT:    llhr %r0, %r0
+; CHECK-NEXT:    chi %r0, 30720
+; CHECK-NEXT:    ipm %r0
+; CHECK-NEXT:    risbg %r2, %r0, 63, 191, 36
+; CHECK-NEXT:    # kill: def $r2l killed $r2l killed $r2d
+; CHECK-NEXT:    br %r14
+  %1 = call i1 @llvm.is.fpclass.f16(half %x, i32 264)  ; 0x108 = normal
+  ret i1 %1
+}
+
+define i1 @isnormal_f(float %x) {
+; CHECK-LABEL: isnormal_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tceb %f0, 768
+; CHECK-NEXT:    ipm %r2
+; CHECK-NEXT:    srl %r2, 28
+; CHECK-NEXT:    br %r14
+  %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 264)  ; 0x108 = normal
+  ret i1 %1
+}
+
+define i1 @isnormal_d(double %x) {
+; CHECK-LABEL: isnormal_d:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tcdb %f0, 768
+; CHECK-NEXT:    ipm %r2
+; CHECK-NEXT:    srl %r2, 28
+; CHECK-NEXT:    br %r14
+  %1 = call i1 @llvm.is.fpclass.f64(double %x, i32 264)  ; 0x108 = normal
+  ret i1 %1
+}
+
+define i1 @issubnormal_h(half %x) {
+; CHECK-LABEL: issubnormal_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    # kill: def $f0h killed $f0h def $f0d
+; CHECK-NEXT:    lgdr %r0, %f0
+; CHECK-NEXT:    risbg %r0, %r0, 49, 191, 16
+; CHECK-NEXT:    ahi %r0, -1
+; CHECK-NEXT:    clfi %r0, 1023
+; CHECK-NEXT:    ipm %r0
+; CHECK-NEXT:    risbg %r2, %r0, 63, 191, 36
+; CHECK-NEXT:    # kill: def $r2l killed $r2l killed $r2d
+; CHECK-NEXT:    br %r14
+  %1 = call i1 @llvm.is.fpclass.f16(half %x, i32 144)  ; 0x90 = subnormal
+  ret i1 %1
+}
+
+define i1 @issubnormal_f(float %x) {
+; CHECK-LABEL: issubnormal_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tceb %f0, 192
+; CHECK-NEXT:    ipm %r2
+; CHECK-NEXT:    srl %r2, 28
+; CHECK-NEXT:    br %r14
+  %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 144)  ; 0x90 = subnormal
+  ret i1 %1
+}
+
+define i1 @issubnormal_d(double %x) {
+; CHECK-LABEL: issubnormal_d:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tcdb %f0, 192
+; CHECK-NEXT:    ipm %r2
+; CHECK-NEXT:    srl %r2, 28
+; CHECK-NEXT:    br %r14
+  %1 = call i1 @llvm.is.fpclass.f64(double %x, i32 144)  ; 0x90 = subnormal
+  ret i1 %1
+}

Copy link
Copy Markdown
Member

@uweigand uweigand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Bugfix to a feature new in 22.x, so would be good to get the fix there too. (This will also help Rust, where the bug showed up initially.)

@github-project-automation github-project-automation Bot moved this from Needs Triage to Needs Merge in LLVM Release Status Mar 22, 2026
As pointed out in llvm#187518 , currently, `__builtin_isnormal` returns
`true` for subnormal half precision floating point numbers on `s390x.

This is because there is a custom lowering defined which lowers an `f16`
`IS_FPCLASS` ISD node by extending the `f16` value to `f32`, and then
using SystemZ's "test data class" instruction to determine whether the
number is subnormal. However, a number that is subnormal in 16 bits of
precision will no longer be subnormal in 32 bits of precision, and so
the test always returns true, i.e. all subnormal numbers are classified
as normal.

This PR addresses this by removing the custom lowering and instead
relying on the generic expansion of `IS_FPCLASS`, which does not have
this error.

Fixes llvm#187518 .

(cherry picked from commit 6eb5ac5)
@dyung dyung merged commit 94411c9 into llvm:release/22.x Mar 23, 2026
2 of 3 checks passed
@github-project-automation github-project-automation Bot moved this from Needs Merge to Done in LLVM Release Status Mar 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

4 participants