Skip to content

Commit c96cc50

Browse files
committed
[SystemZ] Custom lowering of llvm.is_fpclass
Differential Revision: https://reviews.llvm.org/D114695
1 parent 4007756 commit c96cc50

File tree

3 files changed

+185
-0
lines changed

3 files changed

+185
-0
lines changed

llvm/lib/Target/SystemZ/SystemZISelLowering.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,9 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
471471
setOperationAction(ISD::FREM, VT, Expand);
472472
setOperationAction(ISD::FPOW, VT, Expand);
473473

474+
// Special treatment.
475+
setOperationAction(ISD::IS_FPCLASS, VT, Custom);
476+
474477
// Handle constrained floating-point operations.
475478
setOperationAction(ISD::STRICT_FADD, VT, Legal);
476479
setOperationAction(ISD::STRICT_FSUB, VT, Legal);
@@ -5615,6 +5618,41 @@ SDValue SystemZTargetLowering::lowerShift(SDValue Op, SelectionDAG &DAG,
56155618
return Op;
56165619
}
56175620

5621+
SDValue SystemZTargetLowering::lowerIS_FPCLASS(SDValue Op,
5622+
SelectionDAG &DAG) const {
5623+
SDLoc DL(Op);
5624+
MVT ResultVT = Op.getSimpleValueType();
5625+
SDValue Arg = Op.getOperand(0);
5626+
auto CNode = cast<ConstantSDNode>(Op.getOperand(1));
5627+
unsigned Check = CNode->getZExtValue();
5628+
5629+
unsigned TDCMask = 0;
5630+
if (Check & fcSNan)
5631+
TDCMask |= SystemZ::TDCMASK_SNAN_PLUS | SystemZ::TDCMASK_SNAN_MINUS;
5632+
if (Check & fcQNan)
5633+
TDCMask |= SystemZ::TDCMASK_QNAN_PLUS | SystemZ::TDCMASK_QNAN_MINUS;
5634+
if (Check & fcPosInf)
5635+
TDCMask |= SystemZ::TDCMASK_INFINITY_PLUS;
5636+
if (Check & fcNegInf)
5637+
TDCMask |= SystemZ::TDCMASK_INFINITY_MINUS;
5638+
if (Check & fcPosNormal)
5639+
TDCMask |= SystemZ::TDCMASK_NORMAL_PLUS;
5640+
if (Check & fcNegNormal)
5641+
TDCMask |= SystemZ::TDCMASK_NORMAL_MINUS;
5642+
if (Check & fcPosSubnormal)
5643+
TDCMask |= SystemZ::TDCMASK_SUBNORMAL_PLUS;
5644+
if (Check & fcNegSubnormal)
5645+
TDCMask |= SystemZ::TDCMASK_SUBNORMAL_MINUS;
5646+
if (Check & fcPosZero)
5647+
TDCMask |= SystemZ::TDCMASK_ZERO_PLUS;
5648+
if (Check & fcNegZero)
5649+
TDCMask |= SystemZ::TDCMASK_ZERO_MINUS;
5650+
SDValue TDCMaskV = DAG.getConstant(TDCMask, DL, MVT::i32);
5651+
5652+
SDValue Intr = DAG.getNode(SystemZISD::TDC, DL, ResultVT, Arg, TDCMaskV);
5653+
return getCCResult(DAG, Intr);
5654+
}
5655+
56185656
SDValue SystemZTargetLowering::LowerOperation(SDValue Op,
56195657
SelectionDAG &DAG) const {
56205658
switch (Op.getOpcode()) {
@@ -5732,6 +5770,8 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op,
57325770
return lowerShift(Op, DAG, SystemZISD::VSRL_BY_SCALAR);
57335771
case ISD::SRA:
57345772
return lowerShift(Op, DAG, SystemZISD::VSRA_BY_SCALAR);
5773+
case ISD::IS_FPCLASS:
5774+
return lowerIS_FPCLASS(Op, DAG);
57355775
default:
57365776
llvm_unreachable("Unexpected node to lower");
57375777
}

llvm/lib/Target/SystemZ/SystemZISelLowering.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,7 @@ class SystemZTargetLowering : public TargetLowering {
680680
SDValue lowerSIGN_EXTEND_VECTOR_INREG(SDValue Op, SelectionDAG &DAG) const;
681681
SDValue lowerZERO_EXTEND_VECTOR_INREG(SDValue Op, SelectionDAG &DAG) const;
682682
SDValue lowerShift(SDValue Op, SelectionDAG &DAG, unsigned ByScalar) const;
683+
SDValue lowerIS_FPCLASS(SDValue Op, SelectionDAG &DAG) const;
683684

684685
bool canTreatAsByteVector(EVT VT) const;
685686
SDValue combineExtract(const SDLoc &DL, EVT ElemVT, EVT VecVT, SDValue OrigOp,
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; Test intrinsic 'is_fpclass'.
3+
;
4+
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
5+
6+
declare i1 @llvm.is.fpclass.f32(float, i32)
7+
declare i1 @llvm.is.fpclass.f64(double, i32)
8+
declare i1 @llvm.is.fpclass.f128(fp128, i32)
9+
10+
11+
define i1 @isnan_f(float %x) {
12+
; CHECK-LABEL: isnan_f:
13+
; CHECK: # %bb.0:
14+
; CHECK-NEXT: tceb %f0, 15
15+
; CHECK-NEXT: ipm %r2
16+
; CHECK-NEXT: srl %r2, 28
17+
; CHECK-NEXT: br %r14
18+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 3) ; nan
19+
ret i1 %1
20+
}
21+
22+
define i1 @isnan_d(double %x) {
23+
; CHECK-LABEL: isnan_d:
24+
; CHECK: # %bb.0:
25+
; CHECK-NEXT: tcdb %f0, 15
26+
; CHECK-NEXT: ipm %r2
27+
; CHECK-NEXT: srl %r2, 28
28+
; CHECK-NEXT: br %r14
29+
%1 = call i1 @llvm.is.fpclass.f64(double %x, i32 3) ; nan
30+
ret i1 %1
31+
}
32+
33+
define i1 @isnan_x(fp128 %x) {
34+
; CHECK-LABEL: isnan_x:
35+
; CHECK: # %bb.0:
36+
; CHECK-NEXT: ld %f0, 0(%r2)
37+
; CHECK-NEXT: ld %f2, 8(%r2)
38+
; CHECK-NEXT: tcxb %f0, 15
39+
; CHECK-NEXT: ipm %r2
40+
; CHECK-NEXT: srl %r2, 28
41+
; CHECK-NEXT: br %r14
42+
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 3) ; nan
43+
ret i1 %1
44+
}
45+
46+
define i1 @isqnan_f(float %x) {
47+
; CHECK-LABEL: isqnan_f:
48+
; CHECK: # %bb.0:
49+
; CHECK-NEXT: tceb %f0, 12
50+
; CHECK-NEXT: ipm %r2
51+
; CHECK-NEXT: srl %r2, 28
52+
; CHECK-NEXT: br %r14
53+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 2) ; qnan
54+
ret i1 %1
55+
}
56+
57+
define i1 @issnan_f(float %x) {
58+
; CHECK-LABEL: issnan_f:
59+
; CHECK: # %bb.0:
60+
; CHECK-NEXT: tceb %f0, 3
61+
; CHECK-NEXT: ipm %r2
62+
; CHECK-NEXT: srl %r2, 28
63+
; CHECK-NEXT: br %r14
64+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 1) ; snan
65+
ret i1 %1
66+
}
67+
68+
define i1 @isinf_f(float %x) {
69+
; CHECK-LABEL: isinf_f:
70+
; CHECK: # %bb.0:
71+
; CHECK-NEXT: tceb %f0, 48
72+
; CHECK-NEXT: ipm %r2
73+
; CHECK-NEXT: srl %r2, 28
74+
; CHECK-NEXT: br %r14
75+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 516) ; 0x204 = "inf"
76+
ret i1 %1
77+
}
78+
79+
define i1 @isposinf_f(float %x) {
80+
; CHECK-LABEL: isposinf_f:
81+
; CHECK: # %bb.0:
82+
; CHECK-NEXT: tceb %f0, 32
83+
; CHECK-NEXT: ipm %r2
84+
; CHECK-NEXT: srl %r2, 28
85+
; CHECK-NEXT: br %r14
86+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 512) ; 0x200 = "+inf"
87+
ret i1 %1
88+
}
89+
90+
define i1 @isneginf_f(float %x) {
91+
; CHECK-LABEL: isneginf_f:
92+
; CHECK: # %bb.0:
93+
; CHECK-NEXT: tceb %f0, 16
94+
; CHECK-NEXT: ipm %r2
95+
; CHECK-NEXT: srl %r2, 28
96+
; CHECK-NEXT: br %r14
97+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 4) ; "-inf"
98+
ret i1 %1
99+
}
100+
101+
define i1 @isfinite_f(float %x) {
102+
; CHECK-LABEL: isfinite_f:
103+
; CHECK: # %bb.0:
104+
; CHECK-NEXT: tceb %f0, 4032
105+
; CHECK-NEXT: ipm %r2
106+
; CHECK-NEXT: srl %r2, 28
107+
; CHECK-NEXT: br %r14
108+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 504) ; 0x1f8 = "finite"
109+
ret i1 %1
110+
}
111+
112+
define i1 @isposfinite_f(float %x) {
113+
; CHECK-LABEL: isposfinite_f:
114+
; CHECK: # %bb.0:
115+
; CHECK-NEXT: tceb %f0, 2688
116+
; CHECK-NEXT: ipm %r2
117+
; CHECK-NEXT: srl %r2, 28
118+
; CHECK-NEXT: br %r14
119+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 448) ; 0x1c0 = "+finite"
120+
ret i1 %1
121+
}
122+
123+
define i1 @isnegfinite_f(float %x) {
124+
; CHECK-LABEL: isnegfinite_f:
125+
; CHECK: # %bb.0:
126+
; CHECK-NEXT: tceb %f0, 1344
127+
; CHECK-NEXT: ipm %r2
128+
; CHECK-NEXT: srl %r2, 28
129+
; CHECK-NEXT: br %r14
130+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 56) ; 0x38 = "-finite"
131+
ret i1 %1
132+
}
133+
134+
define i1 @isnotfinite_f(float %x) {
135+
; CHECK-LABEL: isnotfinite_f:
136+
; CHECK: # %bb.0:
137+
; CHECK-NEXT: tceb %f0, 63
138+
; CHECK-NEXT: ipm %r2
139+
; CHECK-NEXT: srl %r2, 28
140+
; CHECK-NEXT: br %r14
141+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 519) ; ox207 = "inf|nan"
142+
ret i1 %1
143+
}
144+

0 commit comments

Comments
 (0)