Skip to content

Commit 25e1a77

Browse files
committed
[SDAG] Reverse the canonicalization of isInf/isNanOrInf
1 parent 91f4a78 commit 25e1a77

File tree

9 files changed

+518
-544
lines changed

9 files changed

+518
-544
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: 39 additions & 87 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
@@ -62,29 +60,14 @@ define i1 @test_is_not_inf(double %arg) {
6260
define i1 @test_fp128_is_inf_or_nan(fp128 %arg) {
6361
; CHECK-LABEL: test_fp128_is_inf_or_nan:
6462
; CHECK: // %bb.0:
65-
; CHECK-NEXT: sub sp, sp, #64
66-
; CHECK-NEXT: stp x30, x19, [sp, #48] // 16-byte Folded Spill
67-
; CHECK-NEXT: .cfi_def_cfa_offset 64
68-
; CHECK-NEXT: .cfi_offset w19, -8
69-
; CHECK-NEXT: .cfi_offset w30, -16
70-
; CHECK-NEXT: str q0, [sp, #32]
71-
; CHECK-NEXT: ldrb w8, [sp, #47]
72-
; CHECK-NEXT: and w8, w8, #0x7f
73-
; CHECK-NEXT: strb w8, [sp, #47]
74-
; CHECK-NEXT: adrp x8, .LCPI4_0
75-
; CHECK-NEXT: ldr q0, [sp, #32]
76-
; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI4_0]
77-
; CHECK-NEXT: str q0, [sp, #16] // 16-byte Folded Spill
78-
; CHECK-NEXT: str q1, [sp] // 16-byte Folded Spill
79-
; CHECK-NEXT: bl __eqtf2
80-
; CHECK-NEXT: ldp q1, q0, [sp] // 32-byte Folded Reload
81-
; CHECK-NEXT: mov w19, w0
82-
; CHECK-NEXT: bl __unordtf2
83-
; CHECK-NEXT: cmp w0, #0
84-
; CHECK-NEXT: ccmp w19, #0, #4, eq
85-
; CHECK-NEXT: ldp x30, x19, [sp, #48] // 16-byte Folded Reload
86-
; CHECK-NEXT: cset w0, eq
87-
; CHECK-NEXT: add sp, sp, #64
63+
; CHECK-NEXT: mov x8, #9223090561878065151 // =0x7ffeffffffffffff
64+
; CHECK-NEXT: str q0, [sp, #-16]!
65+
; CHECK-NEXT: .cfi_def_cfa_offset 16
66+
; CHECK-NEXT: ldr x9, [sp, #8]
67+
; CHECK-NEXT: and x9, x9, #0x7fffffffffffffff
68+
; CHECK-NEXT: cmp x9, x8
69+
; CHECK-NEXT: cset w0, gt
70+
; CHECK-NEXT: add sp, sp, #16
8871
; CHECK-NEXT: ret
8972
%abs = tail call fp128 @llvm.fabs.f128(fp128 %arg)
9073
%ret = fcmp ueq fp128 %abs, 0xL00000000000000007FFF000000000000
@@ -94,29 +77,14 @@ define i1 @test_fp128_is_inf_or_nan(fp128 %arg) {
9477
define i1 @test_fp128_is_not_inf_or_nan(fp128 %arg) {
9578
; CHECK-LABEL: test_fp128_is_not_inf_or_nan:
9679
; CHECK: // %bb.0:
97-
; CHECK-NEXT: sub sp, sp, #64
98-
; CHECK-NEXT: stp x30, x19, [sp, #48] // 16-byte Folded Spill
99-
; CHECK-NEXT: .cfi_def_cfa_offset 64
100-
; CHECK-NEXT: .cfi_offset w19, -8
101-
; CHECK-NEXT: .cfi_offset w30, -16
102-
; CHECK-NEXT: str q0, [sp, #32]
103-
; CHECK-NEXT: ldrb w8, [sp, #47]
104-
; CHECK-NEXT: and w8, w8, #0x7f
105-
; CHECK-NEXT: strb w8, [sp, #47]
106-
; CHECK-NEXT: adrp x8, .LCPI5_0
107-
; CHECK-NEXT: ldr q0, [sp, #32]
108-
; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI5_0]
109-
; CHECK-NEXT: str q0, [sp, #16] // 16-byte Folded Spill
110-
; CHECK-NEXT: str q1, [sp] // 16-byte Folded Spill
111-
; CHECK-NEXT: bl __eqtf2
112-
; CHECK-NEXT: ldp q1, q0, [sp] // 32-byte Folded Reload
113-
; CHECK-NEXT: mov w19, w0
114-
; CHECK-NEXT: bl __unordtf2
115-
; CHECK-NEXT: cmp w0, #0
116-
; CHECK-NEXT: ccmp w19, #0, #4, eq
117-
; CHECK-NEXT: ldp x30, x19, [sp, #48] // 16-byte Folded Reload
118-
; CHECK-NEXT: cset w0, ne
119-
; CHECK-NEXT: add sp, sp, #64
80+
; CHECK-NEXT: mov x8, #9223090561878065152 // =0x7fff000000000000
81+
; CHECK-NEXT: str q0, [sp, #-16]!
82+
; CHECK-NEXT: .cfi_def_cfa_offset 16
83+
; CHECK-NEXT: ldr x9, [sp, #8]
84+
; CHECK-NEXT: and x9, x9, #0x7fffffffffffffff
85+
; CHECK-NEXT: cmp x9, x8
86+
; CHECK-NEXT: cset w0, lt
87+
; CHECK-NEXT: add sp, sp, #16
12088
; CHECK-NEXT: ret
12189
%abs = tail call fp128 @llvm.fabs.f128(fp128 %arg)
12290
%ret = fcmp one fp128 %abs, 0xL00000000000000007FFF000000000000
@@ -126,22 +94,14 @@ define i1 @test_fp128_is_not_inf_or_nan(fp128 %arg) {
12694
define i1 @test_fp128_is_inf(fp128 %arg) {
12795
; CHECK-LABEL: test_fp128_is_inf:
12896
; CHECK: // %bb.0:
129-
; CHECK-NEXT: sub sp, sp, #32
130-
; CHECK-NEXT: str x30, [sp, #16] // 8-byte Folded Spill
131-
; CHECK-NEXT: .cfi_def_cfa_offset 32
132-
; CHECK-NEXT: .cfi_offset w30, -16
133-
; CHECK-NEXT: str q0, [sp]
134-
; CHECK-NEXT: ldrb w8, [sp, #15]
135-
; CHECK-NEXT: and w8, w8, #0x7f
136-
; CHECK-NEXT: strb w8, [sp, #15]
137-
; CHECK-NEXT: adrp x8, .LCPI6_0
138-
; CHECK-NEXT: ldr q0, [sp]
139-
; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI6_0]
140-
; CHECK-NEXT: bl __eqtf2
141-
; CHECK-NEXT: cmp w0, #0
142-
; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Folded Reload
97+
; CHECK-NEXT: str q0, [sp, #-16]!
98+
; CHECK-NEXT: .cfi_def_cfa_offset 16
99+
; CHECK-NEXT: ldp x9, x8, [sp], #16
100+
; CHECK-NEXT: and x8, x8, #0x7fffffffffffffff
101+
; CHECK-NEXT: eor x8, x8, #0x7fff000000000000
102+
; CHECK-NEXT: orr x8, x9, x8
103+
; CHECK-NEXT: cmp x8, #0
143104
; CHECK-NEXT: cset w0, eq
144-
; CHECK-NEXT: add sp, sp, #32
145105
; CHECK-NEXT: ret
146106
%abs = tail call fp128 @llvm.fabs.f128(fp128 %arg)
147107
%ret = fcmp oeq fp128 %abs, 0xL00000000000000007FFF000000000000
@@ -151,22 +111,14 @@ define i1 @test_fp128_is_inf(fp128 %arg) {
151111
define i1 @test_fp128_is_not_inf(fp128 %arg) {
152112
; CHECK-LABEL: test_fp128_is_not_inf:
153113
; CHECK: // %bb.0:
154-
; CHECK-NEXT: sub sp, sp, #32
155-
; CHECK-NEXT: str x30, [sp, #16] // 8-byte Folded Spill
156-
; CHECK-NEXT: .cfi_def_cfa_offset 32
157-
; CHECK-NEXT: .cfi_offset w30, -16
158-
; CHECK-NEXT: str q0, [sp]
159-
; CHECK-NEXT: ldrb w8, [sp, #15]
160-
; CHECK-NEXT: and w8, w8, #0x7f
161-
; CHECK-NEXT: strb w8, [sp, #15]
162-
; CHECK-NEXT: adrp x8, .LCPI7_0
163-
; CHECK-NEXT: ldr q0, [sp]
164-
; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI7_0]
165-
; CHECK-NEXT: bl __netf2
166-
; CHECK-NEXT: cmp w0, #0
167-
; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Folded Reload
114+
; CHECK-NEXT: str q0, [sp, #-16]!
115+
; CHECK-NEXT: .cfi_def_cfa_offset 16
116+
; CHECK-NEXT: ldp x9, x8, [sp], #16
117+
; CHECK-NEXT: and x8, x8, #0x7fffffffffffffff
118+
; CHECK-NEXT: eor x8, x8, #0x7fff000000000000
119+
; CHECK-NEXT: orr x8, x9, x8
120+
; CHECK-NEXT: cmp x8, #0
168121
; CHECK-NEXT: cset w0, ne
169-
; CHECK-NEXT: add sp, sp, #32
170122
; CHECK-NEXT: ret
171123
%abs = tail call fp128 @llvm.fabs.f128(fp128 %arg)
172124
%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)