Skip to content

Commit 4558a9d

Browse files
committed
[SDAG] Reverse the canonicalization of isInf/isNanOrInf
1 parent 644a3f3 commit 4558a9d

File tree

9 files changed

+562
-596
lines changed

9 files changed

+562
-596
lines changed

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3467,12 +3467,50 @@ void SelectionDAGBuilder::visitICmp(const User &I) {
34673467
setValue(&I, DAG.getSetCC(getCurSDLoc(), DestVT, Op1, Op2, Opcode));
34683468
}
34693469

3470+
SDValue SelectionDAGBuilder::lowerIsFpClass(Value *ClassVal,
3471+
FPClassTest ClassTest) {
3472+
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
3473+
const DataLayout &DL = DAG.getDataLayout();
3474+
SDLoc sdl = getCurSDLoc();
3475+
3476+
EVT DestVT =
3477+
TLI.getValueType(DL, CmpInst::makeCmpResultType(ClassVal->getType()));
3478+
EVT ArgVT = TLI.getValueType(DL, ClassVal->getType());
3479+
MachineFunction &MF = DAG.getMachineFunction();
3480+
const Function &F = MF.getFunction();
3481+
SDValue Op = getValue(ClassVal);
3482+
SDNodeFlags Flags;
3483+
Flags.setNoFPExcept(!F.getAttributes().hasFnAttr(llvm::Attribute::StrictFP));
3484+
// If ISD::IS_FPCLASS should be expanded, do it right now, because the
3485+
// expansion can use illegal types. Making expansion early allows
3486+
// legalizing these types prior to selection.
3487+
if (!TLI.isOperationLegalOrCustom(ISD::IS_FPCLASS, ArgVT))
3488+
return TLI.expandIS_FPCLASS(DestVT, Op, ClassTest, Flags, sdl, DAG);
3489+
3490+
SDValue Check = DAG.getTargetConstant(ClassTest, sdl, MVT::i32);
3491+
return DAG.getNode(ISD::IS_FPCLASS, sdl, DestVT, {Op, Check}, Flags);
3492+
}
3493+
34703494
void SelectionDAGBuilder::visitFCmp(const User &I) {
34713495
FCmpInst::Predicate predicate = FCmpInst::BAD_FCMP_PREDICATE;
3472-
if (const FCmpInst *FC = dyn_cast<FCmpInst>(&I))
3496+
if (const FCmpInst *FC = dyn_cast<FCmpInst>(&I)) {
34733497
predicate = FC->getPredicate();
3474-
else if (const ConstantExpr *FC = dyn_cast<ConstantExpr>(&I))
3498+
3499+
// Reverse the canonicalization if it is a FP class test
3500+
auto ShouldReverseTransform = [](FPClassTest ClassTest) {
3501+
return ClassTest == fcInf || ClassTest == (fcInf | fcNan);
3502+
};
3503+
auto [ClassVal, ClassTest] =
3504+
fcmpToClassTest(predicate, *FC->getParent()->getParent(),
3505+
FC->getOperand(0), FC->getOperand(1));
3506+
if (ClassVal && (ShouldReverseTransform(ClassTest) ||
3507+
ShouldReverseTransform(~ClassTest))) {
3508+
setValue(&I, lowerIsFpClass(ClassVal, ClassTest));
3509+
return;
3510+
}
3511+
} else if (const ConstantExpr *FC = dyn_cast<ConstantExpr>(&I))
34753512
predicate = FCmpInst::Predicate(FC->getPredicate());
3513+
34763514
SDValue Op1 = getValue(I.getOperand(0));
34773515
SDValue Op2 = getValue(I.getOperand(1));
34783516

@@ -6666,29 +6704,11 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
66666704
DAG.setRoot(Res.getValue(0));
66676705
return;
66686706
case Intrinsic::is_fpclass: {
6669-
const DataLayout DLayout = DAG.getDataLayout();
6670-
EVT DestVT = TLI.getValueType(DLayout, I.getType());
6671-
EVT ArgVT = TLI.getValueType(DLayout, I.getArgOperand(0)->getType());
6672-
FPClassTest Test = static_cast<FPClassTest>(
6673-
cast<ConstantInt>(I.getArgOperand(1))->getZExtValue());
6674-
MachineFunction &MF = DAG.getMachineFunction();
6675-
const Function &F = MF.getFunction();
6676-
SDValue Op = getValue(I.getArgOperand(0));
6677-
SDNodeFlags Flags;
6678-
Flags.setNoFPExcept(
6679-
!F.getAttributes().hasFnAttr(llvm::Attribute::StrictFP));
6680-
// If ISD::IS_FPCLASS should be expanded, do it right now, because the
6681-
// expansion can use illegal types. Making expansion early allows
6682-
// legalizing these types prior to selection.
6683-
if (!TLI.isOperationLegalOrCustom(ISD::IS_FPCLASS, ArgVT)) {
6684-
SDValue Result = TLI.expandIS_FPCLASS(DestVT, Op, Test, Flags, sdl, DAG);
6685-
setValue(&I, Result);
6686-
return;
6687-
}
6688-
6689-
SDValue Check = DAG.getTargetConstant(Test, sdl, MVT::i32);
6690-
SDValue V = DAG.getNode(ISD::IS_FPCLASS, sdl, DestVT, {Op, Check}, Flags);
6691-
setValue(&I, V);
6707+
setValue(&I,
6708+
lowerIsFpClass(
6709+
I.getArgOperand(0),
6710+
static_cast<FPClassTest>(
6711+
cast<ConstantInt>(I.getArgOperand(1))->getZExtValue())));
66926712
return;
66936713
}
66946714
case Intrinsic::get_fpenv: {

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,7 @@ class SelectionDAGBuilder {
700700
MCSymbol *&BeginLabel);
701701
SDValue lowerEndEH(SDValue Chain, const InvokeInst *II,
702702
const BasicBlock *EHPadBB, MCSymbol *BeginLabel);
703+
SDValue lowerIsFpClass(Value *ClassVal, FPClassTest ClassTest);
703704
};
704705

705706
/// This struct represents the registers (physical or virtual)

llvm/test/CodeGen/AArch64/fpclass-test.ll

Lines changed: 45 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44
define i1 @test_is_inf_or_nan(double %arg) {
55
; CHECK-LABEL: test_is_inf_or_nan:
66
; CHECK: // %bb.0:
7-
; CHECK-NEXT: fabs d0, d0
8-
; CHECK-NEXT: mov x8, #9218868437227405312 // =0x7ff0000000000000
9-
; CHECK-NEXT: fmov d1, x8
10-
; CHECK-NEXT: fcmp d0, d1
11-
; CHECK-NEXT: cset w8, eq
12-
; CHECK-NEXT: csinc w0, w8, wzr, vc
7+
; CHECK-NEXT: fmov x9, d0
8+
; CHECK-NEXT: mov x8, #9218868437227405311 // =0x7fefffffffffffff
9+
; CHECK-NEXT: and x9, x9, #0x7fffffffffffffff
10+
; CHECK-NEXT: cmp x9, x8
11+
; CHECK-NEXT: cset w0, gt
1312
; CHECK-NEXT: ret
1413
%abs = tail call double @llvm.fabs.f64(double %arg)
1514
%ret = fcmp ueq double %abs, 0x7FF0000000000000
@@ -19,12 +18,11 @@ define i1 @test_is_inf_or_nan(double %arg) {
1918
define i1 @test_is_not_inf_or_nan(double %arg) {
2019
; CHECK-LABEL: test_is_not_inf_or_nan:
2120
; CHECK: // %bb.0:
22-
; CHECK-NEXT: fabs d0, d0
21+
; CHECK-NEXT: fmov x9, d0
2322
; CHECK-NEXT: mov x8, #9218868437227405312 // =0x7ff0000000000000
24-
; CHECK-NEXT: fmov d1, x8
25-
; CHECK-NEXT: fcmp d0, d1
26-
; CHECK-NEXT: cset w8, mi
27-
; CHECK-NEXT: csinc w0, w8, wzr, le
23+
; CHECK-NEXT: and x9, x9, #0x7fffffffffffffff
24+
; CHECK-NEXT: cmp x9, x8
25+
; CHECK-NEXT: cset w0, lt
2826
; CHECK-NEXT: ret
2927
%abs = tail call double @llvm.fabs.f64(double %arg)
3028
%ret = fcmp one double %abs, 0x7FF0000000000000
@@ -63,12 +61,9 @@ define <vscale x 2 x i1> @test_vec_is_inf_or_nan(<vscale x 2 x double> %arg) {
6361
; CHECK-LABEL: test_vec_is_inf_or_nan:
6462
; CHECK: // %bb.0:
6563
; CHECK-NEXT: ptrue p0.d
66-
; CHECK-NEXT: mov x8, #9218868437227405312 // =0x7ff0000000000000
67-
; CHECK-NEXT: mov z1.d, x8
68-
; CHECK-NEXT: fabs z0.d, p0/m, z0.d
69-
; CHECK-NEXT: fcmuo p1.d, p0/z, z0.d, z1.d
70-
; CHECK-NEXT: fcmeq p0.d, p0/z, z0.d, z1.d
71-
; CHECK-NEXT: sel p0.b, p0, p0.b, p1.b
64+
; CHECK-NEXT: mov z1.d, #0x7ff0000000000000
65+
; CHECK-NEXT: and z0.d, z0.d, #0x7fffffffffffffff
66+
; CHECK-NEXT: cmpge p0.d, p0/z, z0.d, z1.d
7267
; CHECK-NEXT: ret
7368
%abs = tail call <vscale x 2 x double> @llvm.fabs.nxv2f64(<vscale x 2 x double> %arg)
7469
%ret = fcmp ueq <vscale x 2 x double> %abs, splat (double 0x7FF0000000000000)
@@ -79,12 +74,9 @@ define <vscale x 2 x i1> @test_vec_is_not_inf_or_nan(<vscale x 2 x double> %arg)
7974
; CHECK-LABEL: test_vec_is_not_inf_or_nan:
8075
; CHECK: // %bb.0:
8176
; CHECK-NEXT: ptrue p0.d
82-
; CHECK-NEXT: mov x8, #9218868437227405312 // =0x7ff0000000000000
83-
; CHECK-NEXT: mov z1.d, x8
84-
; CHECK-NEXT: fabs z0.d, p0/m, z0.d
85-
; CHECK-NEXT: fcmgt p1.d, p0/z, z1.d, z0.d
86-
; CHECK-NEXT: fcmgt p0.d, p0/z, z0.d, z1.d
87-
; CHECK-NEXT: sel p0.b, p0, p0.b, p1.b
77+
; CHECK-NEXT: mov z1.d, #0x7ff0000000000000
78+
; CHECK-NEXT: and z0.d, z0.d, #0x7fffffffffffffff
79+
; CHECK-NEXT: cmpgt p0.d, p0/z, z1.d, z0.d
8880
; CHECK-NEXT: ret
8981
%abs = tail call <vscale x 2 x double> @llvm.fabs.nxv2f64(<vscale x 2 x double> %arg)
9082
%ret = fcmp one <vscale x 2 x double> %abs, splat (double 0x7FF0000000000000)
@@ -122,29 +114,14 @@ define <vscale x 2 x i1> @test_vec_is_not_inf(<vscale x 2 x double> %arg) {
122114
define i1 @test_fp128_is_inf_or_nan(fp128 %arg) {
123115
; CHECK-LABEL: test_fp128_is_inf_or_nan:
124116
; CHECK: // %bb.0:
125-
; CHECK-NEXT: sub sp, sp, #64
126-
; CHECK-NEXT: stp x30, x19, [sp, #48] // 16-byte Folded Spill
127-
; CHECK-NEXT: .cfi_def_cfa_offset 64
128-
; CHECK-NEXT: .cfi_offset w19, -8
129-
; CHECK-NEXT: .cfi_offset w30, -16
130-
; CHECK-NEXT: str q0, [sp, #32]
131-
; CHECK-NEXT: ldrb w8, [sp, #47]
132-
; CHECK-NEXT: and w8, w8, #0x7f
133-
; CHECK-NEXT: strb w8, [sp, #47]
134-
; CHECK-NEXT: adrp x8, .LCPI8_0
135-
; CHECK-NEXT: ldr q0, [sp, #32]
136-
; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI8_0]
137-
; CHECK-NEXT: str q0, [sp, #16] // 16-byte Folded Spill
138-
; CHECK-NEXT: str q1, [sp] // 16-byte Folded Spill
139-
; CHECK-NEXT: bl __eqtf2
140-
; CHECK-NEXT: ldp q1, q0, [sp] // 32-byte Folded Reload
141-
; CHECK-NEXT: mov w19, w0
142-
; CHECK-NEXT: bl __unordtf2
143-
; CHECK-NEXT: cmp w0, #0
144-
; CHECK-NEXT: ccmp w19, #0, #4, eq
145-
; CHECK-NEXT: ldp x30, x19, [sp, #48] // 16-byte Folded Reload
146-
; CHECK-NEXT: cset w0, eq
147-
; CHECK-NEXT: add sp, sp, #64
117+
; CHECK-NEXT: mov x8, #9223090561878065151 // =0x7ffeffffffffffff
118+
; CHECK-NEXT: str q0, [sp, #-16]!
119+
; CHECK-NEXT: .cfi_def_cfa_offset 16
120+
; CHECK-NEXT: ldr x9, [sp, #8]
121+
; CHECK-NEXT: and x9, x9, #0x7fffffffffffffff
122+
; CHECK-NEXT: cmp x9, x8
123+
; CHECK-NEXT: cset w0, gt
124+
; CHECK-NEXT: add sp, sp, #16
148125
; CHECK-NEXT: ret
149126
%abs = tail call fp128 @llvm.fabs.f128(fp128 %arg)
150127
%ret = fcmp ueq fp128 %abs, 0xL00000000000000007FFF000000000000
@@ -154,29 +131,14 @@ define i1 @test_fp128_is_inf_or_nan(fp128 %arg) {
154131
define i1 @test_fp128_is_not_inf_or_nan(fp128 %arg) {
155132
; CHECK-LABEL: test_fp128_is_not_inf_or_nan:
156133
; CHECK: // %bb.0:
157-
; CHECK-NEXT: sub sp, sp, #64
158-
; CHECK-NEXT: stp x30, x19, [sp, #48] // 16-byte Folded Spill
159-
; CHECK-NEXT: .cfi_def_cfa_offset 64
160-
; CHECK-NEXT: .cfi_offset w19, -8
161-
; CHECK-NEXT: .cfi_offset w30, -16
162-
; CHECK-NEXT: str q0, [sp, #32]
163-
; CHECK-NEXT: ldrb w8, [sp, #47]
164-
; CHECK-NEXT: and w8, w8, #0x7f
165-
; CHECK-NEXT: strb w8, [sp, #47]
166-
; CHECK-NEXT: adrp x8, .LCPI9_0
167-
; CHECK-NEXT: ldr q0, [sp, #32]
168-
; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI9_0]
169-
; CHECK-NEXT: str q0, [sp, #16] // 16-byte Folded Spill
170-
; CHECK-NEXT: str q1, [sp] // 16-byte Folded Spill
171-
; CHECK-NEXT: bl __eqtf2
172-
; CHECK-NEXT: ldp q1, q0, [sp] // 32-byte Folded Reload
173-
; CHECK-NEXT: mov w19, w0
174-
; CHECK-NEXT: bl __unordtf2
175-
; CHECK-NEXT: cmp w0, #0
176-
; CHECK-NEXT: ccmp w19, #0, #4, eq
177-
; CHECK-NEXT: ldp x30, x19, [sp, #48] // 16-byte Folded Reload
178-
; CHECK-NEXT: cset w0, ne
179-
; CHECK-NEXT: add sp, sp, #64
134+
; CHECK-NEXT: mov x8, #9223090561878065152 // =0x7fff000000000000
135+
; CHECK-NEXT: str q0, [sp, #-16]!
136+
; CHECK-NEXT: .cfi_def_cfa_offset 16
137+
; CHECK-NEXT: ldr x9, [sp, #8]
138+
; CHECK-NEXT: and x9, x9, #0x7fffffffffffffff
139+
; CHECK-NEXT: cmp x9, x8
140+
; CHECK-NEXT: cset w0, lt
141+
; CHECK-NEXT: add sp, sp, #16
180142
; CHECK-NEXT: ret
181143
%abs = tail call fp128 @llvm.fabs.f128(fp128 %arg)
182144
%ret = fcmp one fp128 %abs, 0xL00000000000000007FFF000000000000
@@ -186,22 +148,14 @@ define i1 @test_fp128_is_not_inf_or_nan(fp128 %arg) {
186148
define i1 @test_fp128_is_inf(fp128 %arg) {
187149
; CHECK-LABEL: test_fp128_is_inf:
188150
; CHECK: // %bb.0:
189-
; CHECK-NEXT: sub sp, sp, #32
190-
; CHECK-NEXT: str x30, [sp, #16] // 8-byte Folded Spill
191-
; CHECK-NEXT: .cfi_def_cfa_offset 32
192-
; CHECK-NEXT: .cfi_offset w30, -16
193-
; CHECK-NEXT: str q0, [sp]
194-
; CHECK-NEXT: ldrb w8, [sp, #15]
195-
; CHECK-NEXT: and w8, w8, #0x7f
196-
; CHECK-NEXT: strb w8, [sp, #15]
197-
; CHECK-NEXT: adrp x8, .LCPI10_0
198-
; CHECK-NEXT: ldr q0, [sp]
199-
; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI10_0]
200-
; CHECK-NEXT: bl __eqtf2
201-
; CHECK-NEXT: cmp w0, #0
202-
; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Folded Reload
151+
; CHECK-NEXT: str q0, [sp, #-16]!
152+
; CHECK-NEXT: .cfi_def_cfa_offset 16
153+
; CHECK-NEXT: ldp x9, x8, [sp], #16
154+
; CHECK-NEXT: and x8, x8, #0x7fffffffffffffff
155+
; CHECK-NEXT: eor x8, x8, #0x7fff000000000000
156+
; CHECK-NEXT: orr x8, x9, x8
157+
; CHECK-NEXT: cmp x8, #0
203158
; CHECK-NEXT: cset w0, eq
204-
; CHECK-NEXT: add sp, sp, #32
205159
; CHECK-NEXT: ret
206160
%abs = tail call fp128 @llvm.fabs.f128(fp128 %arg)
207161
%ret = fcmp oeq fp128 %abs, 0xL00000000000000007FFF000000000000
@@ -211,22 +165,14 @@ define i1 @test_fp128_is_inf(fp128 %arg) {
211165
define i1 @test_fp128_is_not_inf(fp128 %arg) {
212166
; CHECK-LABEL: test_fp128_is_not_inf:
213167
; CHECK: // %bb.0:
214-
; CHECK-NEXT: sub sp, sp, #32
215-
; CHECK-NEXT: str x30, [sp, #16] // 8-byte Folded Spill
216-
; CHECK-NEXT: .cfi_def_cfa_offset 32
217-
; CHECK-NEXT: .cfi_offset w30, -16
218-
; CHECK-NEXT: str q0, [sp]
219-
; CHECK-NEXT: ldrb w8, [sp, #15]
220-
; CHECK-NEXT: and w8, w8, #0x7f
221-
; CHECK-NEXT: strb w8, [sp, #15]
222-
; CHECK-NEXT: adrp x8, .LCPI11_0
223-
; CHECK-NEXT: ldr q0, [sp]
224-
; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI11_0]
225-
; CHECK-NEXT: bl __netf2
226-
; CHECK-NEXT: cmp w0, #0
227-
; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Folded Reload
168+
; CHECK-NEXT: str q0, [sp, #-16]!
169+
; CHECK-NEXT: .cfi_def_cfa_offset 16
170+
; CHECK-NEXT: ldp x9, x8, [sp], #16
171+
; CHECK-NEXT: and x8, x8, #0x7fffffffffffffff
172+
; CHECK-NEXT: eor x8, x8, #0x7fff000000000000
173+
; CHECK-NEXT: orr x8, x9, x8
174+
; CHECK-NEXT: cmp x8, #0
228175
; CHECK-NEXT: cset w0, ne
229-
; CHECK-NEXT: add sp, sp, #32
230176
; CHECK-NEXT: ret
231177
%abs = tail call fp128 @llvm.fabs.f128(fp128 %arg)
232178
%ret = fcmp une fp128 %abs, 0xL00000000000000007FFF000000000000

llvm/test/CodeGen/AArch64/isinf.ll

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,22 +58,14 @@ define i32 @replace_isinf_call_f64(double %x) {
5858
define i32 @replace_isinf_call_f128(fp128 %x) {
5959
; CHECK-LABEL: replace_isinf_call_f128:
6060
; CHECK: // %bb.0:
61-
; CHECK-NEXT: sub sp, sp, #32
62-
; CHECK-NEXT: str x30, [sp, #16] // 8-byte Folded Spill
63-
; CHECK-NEXT: .cfi_def_cfa_offset 32
64-
; CHECK-NEXT: .cfi_offset w30, -16
65-
; CHECK-NEXT: str q0, [sp]
66-
; CHECK-NEXT: ldrb w8, [sp, #15]
67-
; CHECK-NEXT: and w8, w8, #0x7f
68-
; CHECK-NEXT: strb w8, [sp, #15]
69-
; CHECK-NEXT: adrp x8, .LCPI3_0
70-
; CHECK-NEXT: ldr q0, [sp]
71-
; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI3_0]
72-
; CHECK-NEXT: bl __eqtf2
73-
; CHECK-NEXT: cmp w0, #0
74-
; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Folded Reload
61+
; CHECK-NEXT: str q0, [sp, #-16]!
62+
; CHECK-NEXT: .cfi_def_cfa_offset 16
63+
; CHECK-NEXT: ldp x9, x8, [sp], #16
64+
; CHECK-NEXT: and x8, x8, #0x7fffffffffffffff
65+
; CHECK-NEXT: eor x8, x8, #0x7fff000000000000
66+
; CHECK-NEXT: orr x8, x9, x8
67+
; CHECK-NEXT: cmp x8, #0
7568
; CHECK-NEXT: cset w0, eq
76-
; CHECK-NEXT: add sp, sp, #32
7769
; CHECK-NEXT: ret
7870
%abs = tail call fp128 @llvm.fabs.f128(fp128 %x)
7971
%cmpinf = fcmp oeq fp128 %abs, 0xL00000000000000007FFF000000000000

0 commit comments

Comments
 (0)