Skip to content

Commit 9fc58f1

Browse files
committed
[PowerPC] Support of ppc_fp128 in lowering of llvm.is_fpclass
PowerPC supports `ppc_fp128`, which is not an IEEE floating point type. The generic lowering of llvm.is_fpclass could not handle it properly. This change extends the generic lowering code to support `ppc_fp128`. The change was tested on emulator using runtime tests from https://reviews.llvm.org/D112933 and the patch for clang https://reviews.llvm.org/D112932. Differential Revision: https://reviews.llvm.org/D113908
1 parent 7858219 commit 9fc58f1

File tree

2 files changed

+322
-0
lines changed

2 files changed

+322
-0
lines changed

llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7439,6 +7439,14 @@ SDValue TargetLowering::expandIS_FPCLASS(EVT ResultVT, SDValue Op,
74397439
if (Test == 0 || (Test & fcAllFlags) == fcAllFlags)
74407440
return DAG.getBoolConstant(true, DL, ResultVT, OperandVT);
74417441

7442+
// PPC double double is a pair of doubles, of which the higher part determines
7443+
// the value class.
7444+
if (OperandVT == MVT::ppcf128) {
7445+
Op = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::f64, Op,
7446+
DAG.getConstant(1, DL, MVT::i32));
7447+
OperandVT = MVT::f64;
7448+
}
7449+
74427450
// Some checks may be represented as inversion of simpler check, for example
74437451
// "inf|normal|subnormal|zero" => !"nan".
74447452
bool IsInverted = false;
Lines changed: 314 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 -verify-machineinstrs -o - %s | FileCheck %s
3+
4+
5+
define i1 @isnan_float(float %x) nounwind {
6+
; CHECK-LABEL: isnan_float:
7+
; CHECK: # %bb.0:
8+
; CHECK-NEXT: fcmpu 0, 1, 1
9+
; CHECK-NEXT: li 3, 0
10+
; CHECK-NEXT: li 4, 1
11+
; CHECK-NEXT: isel 3, 4, 3, 3
12+
; CHECK-NEXT: blr
13+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 3) ; nan
14+
ret i1 %1
15+
}
16+
17+
define i1 @isnan_double(double %x) nounwind {
18+
; CHECK-LABEL: isnan_double:
19+
; CHECK: # %bb.0:
20+
; CHECK-NEXT: fcmpu 0, 1, 1
21+
; CHECK-NEXT: li 3, 0
22+
; CHECK-NEXT: li 4, 1
23+
; CHECK-NEXT: isel 3, 4, 3, 3
24+
; CHECK-NEXT: blr
25+
%1 = call i1 @llvm.is.fpclass.f64(double %x, i32 3) ; nan
26+
ret i1 %1
27+
}
28+
29+
define i1 @isnan_ppc_fp128(ppc_fp128 %x) nounwind {
30+
; CHECK-LABEL: isnan_ppc_fp128:
31+
; CHECK: # %bb.0:
32+
; CHECK-NEXT: fcmpu 0, 1, 1
33+
; CHECK-NEXT: li 3, 0
34+
; CHECK-NEXT: li 4, 1
35+
; CHECK-NEXT: isel 3, 4, 3, 3
36+
; CHECK-NEXT: blr
37+
%1 = call i1 @llvm.is.fpclass.ppcf128(ppc_fp128 %x, i32 3) ; nan
38+
ret i1 %1
39+
}
40+
41+
define i1 @isnan_f128(fp128 %x) nounwind {
42+
; CHECK-LABEL: isnan_f128:
43+
; CHECK: # %bb.0:
44+
; CHECK-NEXT: xscmpuqp 0, 2, 2
45+
; CHECK-NEXT: li 3, 0
46+
; CHECK-NEXT: li 4, 1
47+
; CHECK-NEXT: isel 3, 4, 3, 3
48+
; CHECK-NEXT: blr
49+
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 3) ; nan
50+
ret i1 %1
51+
}
52+
53+
define i1 @isnan_float_strictfp(float %x) strictfp nounwind {
54+
; CHECK-LABEL: isnan_float_strictfp:
55+
; CHECK: # %bb.0:
56+
; CHECK-NEXT: xscvdpspn 0, 1
57+
; CHECK-NEXT: lis 4, 32640
58+
; CHECK-NEXT: mffprwz 3, 0
59+
; CHECK-NEXT: clrlwi 3, 3, 1
60+
; CHECK-NEXT: cmpw 3, 4
61+
; CHECK-NEXT: li 3, 0
62+
; CHECK-NEXT: li 4, 1
63+
; CHECK-NEXT: iselgt 3, 4, 3
64+
; CHECK-NEXT: blr
65+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 3) ; nan
66+
ret i1 %1
67+
}
68+
69+
define i1 @isnan_double_strictfp(double %x) strictfp nounwind {
70+
; CHECK-LABEL: isnan_double_strictfp:
71+
; CHECK: # %bb.0:
72+
; CHECK-NEXT: mffprd 3, 1
73+
; CHECK-NEXT: li 4, 2047
74+
; CHECK-NEXT: clrldi 3, 3, 1
75+
; CHECK-NEXT: rldic 4, 4, 52, 1
76+
; CHECK-NEXT: cmpd 3, 4
77+
; CHECK-NEXT: li 3, 0
78+
; CHECK-NEXT: li 4, 1
79+
; CHECK-NEXT: iselgt 3, 4, 3
80+
; CHECK-NEXT: blr
81+
%1 = call i1 @llvm.is.fpclass.f64(double %x, i32 3) ; nan
82+
ret i1 %1
83+
}
84+
85+
define i1 @isnan_ppc_fp128_strictfp(ppc_fp128 %x) strictfp nounwind {
86+
; CHECK-LABEL: isnan_ppc_fp128_strictfp:
87+
; CHECK: # %bb.0:
88+
; CHECK-NEXT: mffprd 3, 1
89+
; CHECK-NEXT: li 4, 2047
90+
; CHECK-NEXT: clrldi 3, 3, 1
91+
; CHECK-NEXT: rldic 4, 4, 52, 1
92+
; CHECK-NEXT: cmpd 3, 4
93+
; CHECK-NEXT: li 3, 0
94+
; CHECK-NEXT: li 4, 1
95+
; CHECK-NEXT: iselgt 3, 4, 3
96+
; CHECK-NEXT: blr
97+
%1 = call i1 @llvm.is.fpclass.ppcf128(ppc_fp128 %x, i32 3) ; nan
98+
ret i1 %1
99+
}
100+
101+
define i1 @isnan_f128_strictfp(fp128 %x) strictfp nounwind {
102+
; CHECK-LABEL: isnan_f128_strictfp:
103+
; CHECK: # %bb.0:
104+
; CHECK-NEXT: stxv 34, -16(1)
105+
; CHECK-NEXT: li 5, 32767
106+
; CHECK-NEXT: ld 4, -8(1)
107+
; CHECK-NEXT: ld 3, -16(1)
108+
; CHECK-NEXT: rldic 5, 5, 48, 1
109+
; CHECK-NEXT: clrldi 4, 4, 1
110+
; CHECK-NEXT: cmpld 4, 5
111+
; CHECK-NEXT: cmpd 1, 4, 5
112+
; CHECK-NEXT: crandc 20, 5, 2
113+
; CHECK-NEXT: cmpdi 1, 3, 0
114+
; CHECK-NEXT: li 3, 1
115+
; CHECK-NEXT: crandc 21, 2, 6
116+
; CHECK-NEXT: crnor 20, 21, 20
117+
; CHECK-NEXT: isel 3, 0, 3, 20
118+
; CHECK-NEXT: blr
119+
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 3) ; nan
120+
ret i1 %1
121+
}
122+
123+
define i1 @isinf_float(float %x) nounwind {
124+
; CHECK-LABEL: isinf_float:
125+
; CHECK: # %bb.0:
126+
; CHECK-NEXT: xscvdpspn 0, 1
127+
; CHECK-NEXT: li 4, 1
128+
; CHECK-NEXT: mffprwz 3, 0
129+
; CHECK-NEXT: clrlwi 3, 3, 1
130+
; CHECK-NEXT: xoris 3, 3, 32640
131+
; CHECK-NEXT: cmplwi 3, 0
132+
; CHECK-NEXT: li 3, 0
133+
; CHECK-NEXT: iseleq 3, 4, 3
134+
; CHECK-NEXT: blr
135+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 516) ; 0x204 = "inf"
136+
ret i1 %1
137+
}
138+
139+
define i1 @isinf_ppc_fp128(ppc_fp128 %x) nounwind {
140+
; CHECK-LABEL: isinf_ppc_fp128:
141+
; CHECK: # %bb.0:
142+
; CHECK-NEXT: mffprd 3, 1
143+
; CHECK-NEXT: li 4, 2047
144+
; CHECK-NEXT: clrldi 3, 3, 1
145+
; CHECK-NEXT: rldic 4, 4, 52, 1
146+
; CHECK-NEXT: cmpd 3, 4
147+
; CHECK-NEXT: li 3, 0
148+
; CHECK-NEXT: li 4, 1
149+
; CHECK-NEXT: iseleq 3, 4, 3
150+
; CHECK-NEXT: blr
151+
%1 = call i1 @llvm.is.fpclass.ppcf128(ppc_fp128 %x, i32 516) ; 0x204 = "inf"
152+
ret i1 %1
153+
}
154+
155+
define i1 @isinf_f128(fp128 %x) nounwind {
156+
; CHECK-LABEL: isinf_f128:
157+
; CHECK: # %bb.0:
158+
; CHECK-NEXT: stxv 34, -16(1)
159+
; CHECK-NEXT: li 5, 32767
160+
; CHECK-NEXT: ld 4, -8(1)
161+
; CHECK-NEXT: ld 3, -16(1)
162+
; CHECK-NEXT: rldic 5, 5, 48, 1
163+
; CHECK-NEXT: clrldi 4, 4, 1
164+
; CHECK-NEXT: xor 4, 4, 5
165+
; CHECK-NEXT: or 3, 3, 4
166+
; CHECK-NEXT: cntlzd 3, 3
167+
; CHECK-NEXT: rldicl 3, 3, 58, 63
168+
; CHECK-NEXT: blr
169+
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 516) ; 0x204 = "inf"
170+
ret i1 %1
171+
}
172+
173+
define i1 @isfinite_float(float %x) nounwind {
174+
; CHECK-LABEL: isfinite_float:
175+
; CHECK: # %bb.0:
176+
; CHECK-NEXT: xscvdpspn 0, 1
177+
; CHECK-NEXT: lis 4, 32640
178+
; CHECK-NEXT: mffprwz 3, 0
179+
; CHECK-NEXT: clrlwi 3, 3, 1
180+
; CHECK-NEXT: cmpw 3, 4
181+
; CHECK-NEXT: li 3, 0
182+
; CHECK-NEXT: li 4, 1
183+
; CHECK-NEXT: isellt 3, 4, 3
184+
; CHECK-NEXT: blr
185+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 504) ; 0x1f8 = "finite"
186+
ret i1 %1
187+
}
188+
189+
define i1 @isfinite_f128(fp128 %x) nounwind {
190+
; CHECK-LABEL: isfinite_f128:
191+
; CHECK: # %bb.0:
192+
; CHECK-NEXT: stxv 34, -16(1)
193+
; CHECK-NEXT: li 4, 32767
194+
; CHECK-NEXT: ld 3, -8(1)
195+
; CHECK-NEXT: rldic 4, 4, 48, 1
196+
; CHECK-NEXT: clrldi 3, 3, 1
197+
; CHECK-NEXT: cmpd 3, 4
198+
; CHECK-NEXT: li 3, 0
199+
; CHECK-NEXT: li 4, 1
200+
; CHECK-NEXT: isellt 3, 4, 3
201+
; CHECK-NEXT: blr
202+
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 504) ; 0x1f8 = "finite"
203+
ret i1 %1
204+
}
205+
206+
define i1 @isnormal_float(float %x) nounwind {
207+
; CHECK-LABEL: isnormal_float:
208+
; CHECK: # %bb.0:
209+
; CHECK-NEXT: xscvdpspn 0, 1
210+
; CHECK-NEXT: li 4, 1
211+
; CHECK-NEXT: mffprwz 3, 0
212+
; CHECK-NEXT: clrlwi 3, 3, 1
213+
; CHECK-NEXT: addis 3, 3, -128
214+
; CHECK-NEXT: srwi 3, 3, 24
215+
; CHECK-NEXT: cmplwi 3, 127
216+
; CHECK-NEXT: li 3, 0
217+
; CHECK-NEXT: isellt 3, 4, 3
218+
; CHECK-NEXT: blr
219+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 264) ; 0x108 = "normal"
220+
ret i1 %1
221+
}
222+
223+
define i1 @isnormal_f128(fp128 %x) nounwind {
224+
; CHECK-LABEL: isnormal_f128:
225+
; CHECK: # %bb.0:
226+
; CHECK-NEXT: stxv 34, -16(1)
227+
; CHECK-NEXT: li 4, -1
228+
; CHECK-NEXT: ld 3, -8(1)
229+
; CHECK-NEXT: rldic 4, 4, 48, 0
230+
; CHECK-NEXT: clrldi 3, 3, 1
231+
; CHECK-NEXT: add 3, 3, 4
232+
; CHECK-NEXT: li 4, 1
233+
; CHECK-NEXT: rldicl 3, 3, 15, 49
234+
; CHECK-NEXT: cmpldi 3, 16383
235+
; CHECK-NEXT: li 3, 0
236+
; CHECK-NEXT: isellt 3, 4, 3
237+
; CHECK-NEXT: blr
238+
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 264) ; 0x108 = "normal"
239+
ret i1 %1
240+
}
241+
242+
define i1 @issubnormal_float(float %x) nounwind {
243+
; CHECK-LABEL: issubnormal_float:
244+
; CHECK: # %bb.0:
245+
; CHECK-NEXT: xscvdpspn 0, 1
246+
; CHECK-NEXT: lis 4, 127
247+
; CHECK-NEXT: ori 4, 4, 65535
248+
; CHECK-NEXT: mffprwz 3, 0
249+
; CHECK-NEXT: clrlwi 3, 3, 1
250+
; CHECK-NEXT: addi 3, 3, -1
251+
; CHECK-NEXT: cmplw 3, 4
252+
; CHECK-NEXT: li 3, 0
253+
; CHECK-NEXT: li 4, 1
254+
; CHECK-NEXT: isellt 3, 4, 3
255+
; CHECK-NEXT: blr
256+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 144) ; 0x90 = "subnormal"
257+
ret i1 %1
258+
}
259+
260+
define i1 @issubnormal_f128(fp128 %x) nounwind {
261+
; CHECK-LABEL: issubnormal_f128:
262+
; CHECK: # %bb.0:
263+
; CHECK-NEXT: stxv 34, -16(1)
264+
; CHECK-NEXT: li 5, -1
265+
; CHECK-NEXT: ld 4, -8(1)
266+
; CHECK-NEXT: ld 3, -16(1)
267+
; CHECK-NEXT: rldic 5, 5, 0, 16
268+
; CHECK-NEXT: clrldi 4, 4, 1
269+
; CHECK-NEXT: addic 3, 3, -1
270+
; CHECK-NEXT: addme 4, 4
271+
; CHECK-NEXT: cmpdi 1, 3, -1
272+
; CHECK-NEXT: li 3, 1
273+
; CHECK-NEXT: cmpld 4, 5
274+
; CHECK-NEXT: crandc 20, 0, 2
275+
; CHECK-NEXT: crandc 21, 2, 6
276+
; CHECK-NEXT: crnor 20, 21, 20
277+
; CHECK-NEXT: isel 3, 0, 3, 20
278+
; CHECK-NEXT: blr
279+
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 144) ; 0x90 = "subnormal"
280+
ret i1 %1
281+
}
282+
283+
define i1 @iszero_float(float %x) nounwind {
284+
; CHECK-LABEL: iszero_float:
285+
; CHECK: # %bb.0:
286+
; CHECK-NEXT: xxlxor 0, 0, 0
287+
; CHECK-NEXT: li 3, 0
288+
; CHECK-NEXT: li 4, 1
289+
; CHECK-NEXT: fcmpu 0, 1, 0
290+
; CHECK-NEXT: iseleq 3, 4, 3
291+
; CHECK-NEXT: blr
292+
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 96) ; 0x60 = "zero"
293+
ret i1 %1
294+
}
295+
296+
define i1 @iszero_f128(fp128 %x) nounwind {
297+
; CHECK-LABEL: iszero_f128:
298+
; CHECK: # %bb.0:
299+
; CHECK-NEXT: addis 3, 2, .LCPI18_0@toc@ha
300+
; CHECK-NEXT: li 4, 1
301+
; CHECK-NEXT: addi 3, 3, .LCPI18_0@toc@l
302+
; CHECK-NEXT: lxv 35, 0(3)
303+
; CHECK-NEXT: li 3, 0
304+
; CHECK-NEXT: xscmpuqp 0, 2, 3
305+
; CHECK-NEXT: iseleq 3, 4, 3
306+
; CHECK-NEXT: blr
307+
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 96) ; 0x60 = "zero"
308+
ret i1 %1
309+
}
310+
311+
declare i1 @llvm.is.fpclass.f32(float, i32)
312+
declare i1 @llvm.is.fpclass.f64(double, i32)
313+
declare i1 @llvm.is.fpclass.ppcf128(ppc_fp128, i32)
314+
declare i1 @llvm.is.fpclass.f128(fp128, i32)

0 commit comments

Comments
 (0)