Skip to content

Commit 2555d8f

Browse files
committed
address CR
1 parent c9e8bbd commit 2555d8f

File tree

4 files changed

+283
-147
lines changed

4 files changed

+283
-147
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4130,47 +4130,19 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
41304130
//
41314131
// This catches the 2 variable input case, constants are handled below as a
41324132
// class-like compare.
4133-
KnownFPClass LHSClass = computeKnownFPClass(LHS, fcAllFlags, /*Depth=*/0, Q);
4134-
KnownFPClass RHSClass = computeKnownFPClass(RHS, fcAllFlags, /*Depth=*/0, Q);
41354133
if (Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO) {
4134+
KnownFPClass RHSClass =
4135+
computeKnownFPClass(RHS, fcAllFlags, /*Depth=*/0, Q);
4136+
KnownFPClass LHSClass =
4137+
computeKnownFPClass(LHS, fcAllFlags, /*Depth=*/0, Q);
4138+
41364139
if (FMF.noNaNs() ||
41374140
(RHSClass.isKnownNeverNaN() && LHSClass.isKnownNeverNaN()))
41384141
return ConstantInt::get(RetTy, Pred == FCmpInst::FCMP_ORD);
41394142

41404143
if (RHSClass.isKnownAlwaysNaN() || LHSClass.isKnownAlwaysNaN())
41414144
return ConstantInt::get(RetTy, Pred == CmpInst::FCMP_UNO);
41424145
}
4143-
// floor(x) <= x --> true; x <= ceil(x) --> true
4144-
if (LHSClass.isKnownNeverNaN() &&
4145-
match(LHS, m_Intrinsic<Intrinsic::floor>(m_Specific(RHS))) ||
4146-
RHSClass.isKnownNeverNaN() &&
4147-
match(RHS, m_Intrinsic<Intrinsic::ceil>(m_Specific(LHS)))) {
4148-
switch (Pred) {
4149-
case FCmpInst::FCMP_OLE:
4150-
case FCmpInst::FCMP_ULE:
4151-
return getTrue(RetTy);
4152-
case FCmpInst::FCMP_OGT:
4153-
case FCmpInst::FCMP_UGT:
4154-
return getFalse(RetTy);
4155-
default:
4156-
break;
4157-
}
4158-
}
4159-
if (RHSClass.isKnownNeverNaN() &&
4160-
match(RHS, m_Intrinsic<Intrinsic::floor>(m_Specific(LHS))) ||
4161-
LHSClass.isKnownNeverNaN() &&
4162-
match(LHS, m_Intrinsic<Intrinsic::ceil>(m_Specific(RHS)))) {
4163-
switch (Pred) {
4164-
case FCmpInst::FCMP_OGE:
4165-
case FCmpInst::FCMP_UGE:
4166-
return getTrue(RetTy);
4167-
case FCmpInst::FCMP_OLT:
4168-
case FCmpInst::FCMP_ULT:
4169-
return getFalse(RetTy);
4170-
default:
4171-
break;
4172-
}
4173-
}
41744146

41754147
const APFloat *C = nullptr;
41764148
match(RHS, m_APFloatAllowPoison(C));

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8178,6 +8178,87 @@ static Instruction *foldFCmpFSubIntoFCmp(FCmpInst &I, Instruction *LHSI,
81788178
return nullptr;
81798179
}
81808180

8181+
static Instruction *foldFCmpWithFloorAndCeil(FCmpInst &I,
8182+
InstCombinerImpl &CI) {
8183+
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
8184+
const CmpInst::Predicate Pred = I.getPredicate();
8185+
Type *OpType = LHS->getType();
8186+
8187+
// fcmp ole floor(x), x => fcmp ord x, 0
8188+
// fcmp ogt floor(x), x => false
8189+
if (match(LHS, m_Intrinsic<Intrinsic::floor>(m_Specific(RHS)))) {
8190+
if (Pred == FCmpInst::FCMP_OLE ||
8191+
Pred == FCmpInst::FCMP_ULE &&
8192+
isKnownNeverNaN(LHS, 0,
8193+
CI.getSimplifyQuery().getWithInstruction(&I))) {
8194+
return new FCmpInst(FCmpInst::FCMP_ORD, RHS, ConstantFP::getZero(OpType),
8195+
"", &I);
8196+
}
8197+
if (Pred == FCmpInst::FCMP_OGT ||
8198+
Pred == FCmpInst::FCMP_UGT &&
8199+
isKnownNeverNaN(LHS, 0,
8200+
CI.getSimplifyQuery().getWithInstruction(&I))) {
8201+
return CI.replaceInstUsesWith(I, ConstantInt::getFalse(I.getType()));
8202+
}
8203+
}
8204+
8205+
// fcmp oge x, floor(x) => fcmp ord x, 0
8206+
// fcmp olt x, floor(x) => false
8207+
if (match(RHS, m_Intrinsic<Intrinsic::floor>(m_Specific(LHS)))) {
8208+
if (Pred == FCmpInst::FCMP_OGE ||
8209+
Pred == FCmpInst::FCMP_UGE &&
8210+
isKnownNeverNaN(RHS, 0,
8211+
CI.getSimplifyQuery().getWithInstruction(&I))) {
8212+
return new FCmpInst(FCmpInst::FCMP_ORD, RHS, ConstantFP::getZero(OpType),
8213+
"", &I);
8214+
}
8215+
if (Pred == FCmpInst::FCMP_OLT ||
8216+
Pred == FCmpInst::FCMP_ULT &&
8217+
isKnownNeverNaN(RHS, 0,
8218+
CI.getSimplifyQuery().getWithInstruction(&I))) {
8219+
return CI.replaceInstUsesWith(I, ConstantInt::getFalse(I.getType()));
8220+
}
8221+
}
8222+
8223+
// fcmp oge ceil(x), x => fcmp ord x, 0
8224+
// fcmp olt ceil(x), x => false
8225+
if (match(LHS, m_Intrinsic<Intrinsic::ceil>(m_Specific(RHS)))) {
8226+
if (Pred == FCmpInst::FCMP_OGE ||
8227+
Pred == FCmpInst::FCMP_UGE &&
8228+
isKnownNeverNaN(LHS, 0,
8229+
CI.getSimplifyQuery().getWithInstruction(&I))) {
8230+
return new FCmpInst(FCmpInst::FCMP_ORD, RHS, ConstantFP::getZero(OpType),
8231+
"", &I);
8232+
}
8233+
if (Pred == FCmpInst::FCMP_OLT ||
8234+
Pred == FCmpInst::FCMP_ULT &&
8235+
isKnownNeverNaN(LHS, 0,
8236+
CI.getSimplifyQuery().getWithInstruction(&I))) {
8237+
return CI.replaceInstUsesWith(I, ConstantInt::getFalse(I.getType()));
8238+
}
8239+
}
8240+
8241+
// fcmp ole x, ceil(x) => fcmp ord x, 0
8242+
// fcmp ogt x, ceil(x) => false
8243+
if (match(RHS, m_Intrinsic<Intrinsic::ceil>(m_Specific(LHS)))) {
8244+
if (Pred == FCmpInst::FCMP_OLE ||
8245+
Pred == FCmpInst::FCMP_ULE &&
8246+
isKnownNeverNaN(RHS, 0,
8247+
CI.getSimplifyQuery().getWithInstruction(&I))) {
8248+
return new FCmpInst(FCmpInst::FCMP_ORD, RHS, ConstantFP::getZero(OpType),
8249+
"", &I);
8250+
}
8251+
if (Pred == FCmpInst::FCMP_OGT ||
8252+
Pred == FCmpInst::FCMP_UGT &&
8253+
isKnownNeverNaN(RHS, 0,
8254+
CI.getSimplifyQuery().getWithInstruction(&I))) {
8255+
return CI.replaceInstUsesWith(I, ConstantInt::getFalse(I.getType()));
8256+
}
8257+
}
8258+
8259+
return nullptr;
8260+
}
8261+
81818262
Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
81828263
bool Changed = false;
81838264

@@ -8382,6 +8463,9 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
83828463
if (Instruction *R = foldSqrtWithFcmpZero(I, *this))
83838464
return R;
83848465

8466+
if (Instruction *R = foldFCmpWithFloorAndCeil(I, *this))
8467+
return R;
8468+
83858469
if (match(Op0, m_FNeg(m_Value(X)))) {
83868470
// fcmp pred (fneg X), C --> fcmp swap(pred) X, -C
83878471
Constant *C;
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3+
4+
define i1 @floor_x_ole(float %x) {
5+
; CHECK-LABEL: @floor_x_ole(
6+
; CHECK-NEXT: [[RET:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
7+
; CHECK-NEXT: ret i1 [[RET]]
8+
;
9+
%floor = call float @llvm.floor.f32(float %x)
10+
%ret = fcmp ole float %floor, %x
11+
ret i1 %ret
12+
}
13+
14+
define i1 @floor_x_ule(float %x) {
15+
; CHECK-LABEL: @floor_x_ule(
16+
; CHECK-NEXT: [[RET:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
17+
; CHECK-NEXT: ret i1 [[RET]]
18+
;
19+
%floor = call nnan float @llvm.floor.f32(float %x)
20+
%ret = fcmp ule float %floor, %x
21+
ret i1 %ret
22+
}
23+
24+
define i1 @floor_x_ogt(float %x) {
25+
; CHECK-LABEL: @floor_x_ogt(
26+
; CHECK-NEXT: ret i1 false
27+
;
28+
%floor = call float @llvm.floor.f32(float %x)
29+
%ret = fcmp ogt float %floor, %x
30+
ret i1 %ret
31+
}
32+
33+
define i1 @floor_x_ugt(float %x) {
34+
; CHECK-LABEL: @floor_x_ugt(
35+
; CHECK-NEXT: ret i1 false
36+
;
37+
%floor = call nnan float @llvm.floor.f32(float %x)
38+
%ret = fcmp ugt float %floor, %x
39+
ret i1 %ret
40+
}
41+
42+
define i1 @x_floor_oge(float %x) {
43+
; CHECK-LABEL: @x_floor_oge(
44+
; CHECK-NEXT: [[FLOOR:%.*]] = call float @llvm.floor.f32(float [[X:%.*]])
45+
; CHECK-NEXT: [[RET:%.*]] = fcmp ord float [[FLOOR]], 0.000000e+00
46+
; CHECK-NEXT: ret i1 [[RET]]
47+
;
48+
%floor = call float @llvm.floor.f32(float %x)
49+
%ret = fcmp oge float %x, %floor
50+
ret i1 %ret
51+
}
52+
53+
define i1 @x_floor_uge(float %x) {
54+
; CHECK-LABEL: @x_floor_uge(
55+
; CHECK-NEXT: ret i1 true
56+
;
57+
%floor = call nnan float @llvm.floor.f32(float %x)
58+
%ret = fcmp uge float %x, %floor
59+
ret i1 %ret
60+
}
61+
62+
define i1 @x_floor_olt(float %x) {
63+
; CHECK-LABEL: @x_floor_olt(
64+
; CHECK-NEXT: ret i1 false
65+
;
66+
%floor = call float @llvm.floor.f32(float %x)
67+
%ret = fcmp olt float %x, %floor
68+
ret i1 %ret
69+
}
70+
71+
define i1 @x_floor_ult(float nofpclass(nan) %x) {
72+
; CHECK-LABEL: @x_floor_ult(
73+
; CHECK-NEXT: ret i1 false
74+
;
75+
%floor = call float @llvm.floor.f32(float %x)
76+
%ret = fcmp ult float %x, %floor
77+
ret i1 %ret
78+
}
79+
80+
define <2 x i1> @x_floor_olt_vec(<2 x float> %x) {
81+
; CHECK-LABEL: @x_floor_olt_vec(
82+
; CHECK-NEXT: ret <2 x i1> zeroinitializer
83+
;
84+
%floor = call <2 x float> @llvm.floor.f32(<2 x float> %x)
85+
%ret = fcmp olt <2 x float> %x, %floor
86+
ret <2 x i1> %ret
87+
}
88+
89+
define i1 @x_floor_ole_neg(float %x) {
90+
; CHECK-LABEL: @x_floor_ole_neg(
91+
; CHECK-NEXT: [[FLOOR:%.*]] = call float @llvm.floor.f32(float [[X:%.*]])
92+
; CHECK-NEXT: [[RET:%.*]] = fcmp ole float [[X]], [[FLOOR]]
93+
; CHECK-NEXT: ret i1 [[RET]]
94+
;
95+
%floor = call float @llvm.floor.f32(float %x)
96+
%ret = fcmp ole float %x, %floor
97+
ret i1 %ret
98+
}
99+
100+
define i1 @ceil_x_oge(float %x) {
101+
; CHECK-LABEL: @ceil_x_oge(
102+
; CHECK-NEXT: [[RET:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
103+
; CHECK-NEXT: ret i1 [[RET]]
104+
;
105+
%ceil = call float @llvm.ceil.f32(float %x)
106+
%ret = fcmp oge float %ceil, %x
107+
ret i1 %ret
108+
}
109+
110+
define i1 @ceil_x_uge(float %x) {
111+
; CHECK-LABEL: @ceil_x_uge(
112+
; CHECK-NEXT: [[RET:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
113+
; CHECK-NEXT: ret i1 [[RET]]
114+
;
115+
%ceil = call nnan float @llvm.ceil.f32(float %x)
116+
%ret = fcmp uge float %ceil, %x
117+
ret i1 %ret
118+
}
119+
120+
define i1 @ceil_x_olt(float %x) {
121+
; CHECK-LABEL: @ceil_x_olt(
122+
; CHECK-NEXT: ret i1 false
123+
;
124+
%ceil = call float @llvm.ceil.f32(float %x)
125+
%ret = fcmp olt float %ceil, %x
126+
ret i1 %ret
127+
}
128+
129+
define i1 @ceil_x_ult(float %x) {
130+
; CHECK-LABEL: @ceil_x_ult(
131+
; CHECK-NEXT: ret i1 false
132+
;
133+
%ceil = call nnan float @llvm.ceil.f32(float %x)
134+
%ret = fcmp ult float %ceil, %x
135+
ret i1 %ret
136+
}
137+
138+
define i1 @x_ceil_ole(float %x) {
139+
; CHECK-LABEL: @x_ceil_ole(
140+
; CHECK-NEXT: [[CEIL:%.*]] = call float @llvm.ceil.f32(float [[X:%.*]])
141+
; CHECK-NEXT: [[RET:%.*]] = fcmp ord float [[CEIL]], 0.000000e+00
142+
; CHECK-NEXT: ret i1 [[RET]]
143+
;
144+
%ceil = call float @llvm.ceil.f32(float %x)
145+
%ret = fcmp ole float %x, %ceil
146+
ret i1 %ret
147+
}
148+
149+
define i1 @x_ceil_ule(float %x) {
150+
; CHECK-LABEL: @x_ceil_ule(
151+
; CHECK-NEXT: ret i1 true
152+
;
153+
%ceil = call nnan float @llvm.ceil.f32(float %x)
154+
%ret = fcmp ule float %x, %ceil
155+
ret i1 %ret
156+
}
157+
158+
define i1 @x_ceil_ogt(float %x) {
159+
; CHECK-LABEL: @x_ceil_ogt(
160+
; CHECK-NEXT: ret i1 false
161+
;
162+
%ceil = call float @llvm.ceil.f32(float %x)
163+
%ret = fcmp ogt float %x, %ceil
164+
ret i1 %ret
165+
}
166+
167+
define i1 @x_ceil_ugt(float nofpclass(nan) %x) {
168+
; CHECK-LABEL: @x_ceil_ugt(
169+
; CHECK-NEXT: ret i1 false
170+
;
171+
%ceil = call float @llvm.ceil.f32(float %x)
172+
%ret = fcmp ugt float %x, %ceil
173+
ret i1 %ret
174+
}
175+
176+
define <2 x i1> @x_ceil_ogt_vec(<2 x float> %x) {
177+
; CHECK-LABEL: @x_ceil_ogt_vec(
178+
; CHECK-NEXT: ret <2 x i1> zeroinitializer
179+
;
180+
%ceil = call <2 x float> @llvm.ceil.f32(<2 x float> %x)
181+
%ret = fcmp ogt <2 x float> %x, %ceil
182+
ret <2 x i1> %ret
183+
}
184+
185+
define i1 @x_ceil_oge_neg(float %x) {
186+
; CHECK-LABEL: @x_ceil_oge_neg(
187+
; CHECK-NEXT: [[CEIL:%.*]] = call float @llvm.ceil.f32(float [[X:%.*]])
188+
; CHECK-NEXT: [[RET:%.*]] = fcmp oge float [[X]], [[CEIL]]
189+
; CHECK-NEXT: ret i1 [[RET]]
190+
;
191+
%ceil = call float @llvm.ceil.f32(float %x)
192+
%ret = fcmp oge float %x, %ceil
193+
ret i1 %ret
194+
}

0 commit comments

Comments
 (0)