[llvm-branch-commits] [llvm] 94411c9 - [SystemZ] Remove custom lowering of f16 IS_FPCLASS (#187532)

Douglas Yung via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Mar 22 20:11:43 PDT 2026


Author: Dominik Steenken
Date: 2026-03-23T03:11:30Z
New Revision: 94411c9d56849f00ceb7fac6a4fd7d70490881b7

URL: https://github.com/llvm/llvm-project/commit/94411c9d56849f00ceb7fac6a4fd7d70490881b7
DIFF: https://github.com/llvm/llvm-project/commit/94411c9d56849f00ceb7fac6a4fd7d70490881b7.diff

LOG: [SystemZ] Remove custom lowering of f16 IS_FPCLASS (#187532)

As pointed out in #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 #187518 .

(cherry picked from commit 6eb5ac52ca56fd31c41a619a14093430b27132c3)

Added: 
    

Modified: 
    llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
    llvm/test/CodeGen/SystemZ/is_fpclass.ll

Removed: 
    


################################################################################
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 at 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
+}


        


More information about the llvm-branch-commits mailing list