Skip to content

Commit 5cc33ac

Browse files
committed
llvm#99475 Exclude nan and inf from fcmp fold
1 parent 7804fb1 commit 5cc33ac

File tree

2 files changed

+156
-8
lines changed

2 files changed

+156
-8
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7892,17 +7892,17 @@ static Instruction *foldFCmpReciprocalAndZero(FCmpInst &I, Instruction *LHSI,
78927892
return new FCmpInst(Pred, LHSI->getOperand(1), RHSC, "", &I);
78937893
}
78947894

7895-
// Fold trunc(x) < constant --> x < constant if possible.
7895+
// Fold fptrunc(x) < constant --> x < constant if possible.
78967896
static Instruction *foldFCmpFpTrunc(FCmpInst &I, Instruction *LHSI,
78977897
Constant *RHSC) {
78987898
FCmpInst::Predicate Pred = I.getPredicate();
78997899
bool RoundDown = false;
79007900

7901-
if ((Pred == FCmpInst::FCMP_OGE) || (Pred == FCmpInst::FCMP_UGE) ||
7902-
(Pred == FCmpInst::FCMP_OLT) || (Pred == FCmpInst::FCMP_ULT))
7901+
if (Pred == FCmpInst::FCMP_OGE || Pred == FCmpInst::FCMP_UGE ||
7902+
Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_ULT)
79037903
RoundDown = true;
7904-
else if ((Pred == FCmpInst::FCMP_OGT) || (Pred == FCmpInst::FCMP_UGT) ||
7905-
(Pred == FCmpInst::FCMP_OLE) || (Pred == FCmpInst::FCMP_ULE))
7904+
else if (Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_UGT ||
7905+
Pred == FCmpInst::FCMP_OLE || Pred == FCmpInst::FCMP_ULE)
79067906
RoundDown = false;
79077907
else
79087908
return nullptr;
@@ -7911,6 +7911,10 @@ static Instruction *foldFCmpFpTrunc(FCmpInst &I, Instruction *LHSI,
79117911
if (!match(RHSC, m_APFloat(RValue)))
79127912
return nullptr;
79137913

7914+
// RHSC should not be nan or infinity.
7915+
if (RValue->isNaN() || RValue->isInfinity())
7916+
return nullptr;
7917+
79147918
Type *LType = LHSI->getOperand(0)->getType();
79157919
Type *RType = RHSC->getType();
79167920
Type *LEleType = LType->getScalarType();
@@ -7928,16 +7932,26 @@ static Instruction *foldFCmpFpTrunc(FCmpInst &I, Instruction *LHSI,
79287932
ExtNextRValue.convert(LEleType->getFltSemantics(),
79297933
APFloat::rmNearestTiesToEven, &lossInfo);
79307934

7935+
// Binary search to find the maximal (or minimal) value after RValue promotion.
7936+
// RValue can't have special comparison rules, which means nan or inf is not
7937+
// allowed here.
79317938
APFloat RoundValue{LEleType->getFltSemantics()};
79327939
{
79337940
APFloat Two{LEleType->getFltSemantics(), 2};
7941+
7942+
// The (negative) maximum of RValue will become infinity when rounded up (down).
7943+
// Set the limit of ExtNextRValue.
7944+
if (NextRValue.isInfinity()) {
7945+
ExtNextRValue = ExtRValue * Two;
7946+
}
7947+
79347948
APFloat LowBound = RoundDown ? ExtNextRValue : ExtRValue;
79357949
APFloat UpBound = RoundDown ? ExtRValue : ExtNextRValue;
79367950

79377951
while (true) {
7938-
APFloat DupUpBound = UpBound;
7939-
DupUpBound.next(true);
7940-
if (DupUpBound == LowBound) {
7952+
APFloat UpBoundNext = UpBound;
7953+
UpBoundNext.next(true);
7954+
if (UpBoundNext == LowBound) {
79417955
RoundValue = RoundDown ? UpBound : LowBound;
79427956
break;
79437957
}

llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,137 @@ define i1 @fcmp_trunc_ppc_fp128(ppc_fp128 %0) {
167167
ret i1 %result
168168
}
169169

170+
define i1 @fcmp_trunc_nan(double %0) {
171+
; CHECK-LABEL: define i1 @fcmp_trunc_nan(
172+
; CHECK-SAME: double [[TMP0:%.*]]) {
173+
; CHECK-NEXT: ret i1 false
174+
;
175+
%trunc = fptrunc double %0 to float
176+
%result = fcmp oge float %trunc, 0x7FF8000000000000
177+
ret i1 %result
178+
}
179+
180+
; denomalized 0x00000001
181+
define i1 @fcmp_trunc_d1(double %0) {
182+
; CHECK-LABEL: define i1 @fcmp_trunc_d1(
183+
; CHECK-SAME: double [[TMP0:%.*]]) {
184+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp oge double [[TMP0]], 0x3690000000000001
185+
; CHECK-NEXT: ret i1 [[RESULT]]
186+
;
187+
%trunc = fptrunc double %0 to float
188+
%result = fcmp oge float %trunc, 1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125e-45
189+
ret i1 %result
190+
}
191+
192+
; denomalized 0x00000001 ole
193+
define i1 @fcmp_trunc_d1_ole(double %0) {
194+
; CHECK-LABEL: define i1 @fcmp_trunc_d1_ole(
195+
; CHECK-SAME: double [[TMP0:%.*]]) {
196+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ole double [[TMP0]], 0x36A7FFFFFFFFFFFF
197+
; CHECK-NEXT: ret i1 [[RESULT]]
198+
;
199+
%trunc = fptrunc double %0 to float
200+
%result = fcmp ole float %trunc, 1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125e-45
201+
ret i1 %result
202+
}
203+
204+
; denomalized 0x00000002
205+
define i1 @fcmp_trunc_d2(double %0) {
206+
; CHECK-LABEL: define i1 @fcmp_trunc_d2(
207+
; CHECK-SAME: double [[TMP0:%.*]]) {
208+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp oge double [[TMP0]], 0x36A8000000000000
209+
; CHECK-NEXT: ret i1 [[RESULT]]
210+
;
211+
%trunc = fptrunc double %0 to float
212+
%result = fcmp oge float %trunc, 2.8025969286496341418474591665798322625605238837530315435141365677795821653717212029732763767242431640625e-45
213+
ret i1 %result
214+
}
215+
216+
; denomalized 0x7fffff
217+
define i1 @fcmp_trunc_d3(double %0) {
218+
; CHECK-LABEL: define i1 @fcmp_trunc_d3(
219+
; CHECK-SAME: double [[TMP0:%.*]]) {
220+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ogt double [[TMP0]], 0x380FFFFFDFFFFFFF
221+
; CHECK-NEXT: ret i1 [[RESULT]]
222+
;
223+
%trunc = fptrunc double %0 to float
224+
%result = fcmp ogt float %trunc, 1.175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875e-38
225+
ret i1 %result
226+
}
227+
228+
; denomalized 0x80000001
229+
define i1 @fcmp_trunc_d4(double %0) {
230+
; CHECK-LABEL: define i1 @fcmp_trunc_d4(
231+
; CHECK-SAME: double [[TMP0:%.*]]) {
232+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ogt double [[TMP0]], 0xB690000000000001
233+
; CHECK-NEXT: ret i1 [[RESULT]]
234+
;
235+
%trunc = fptrunc double %0 to float
236+
%result = fcmp ogt float %trunc, -1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125e-45
237+
ret i1 %result
238+
}
239+
240+
; denomalized 0x80000001
241+
define i1 @fcmp_trunc_d5(double %0) {
242+
; CHECK-LABEL: define i1 @fcmp_trunc_d5(
243+
; CHECK-SAME: double [[TMP0:%.*]]) {
244+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp olt double [[TMP0]], 0xB80FFFFFDFFFFFFF
245+
; CHECK-NEXT: ret i1 [[RESULT]]
246+
;
247+
%trunc = fptrunc double %0 to float
248+
%result = fcmp olt float %trunc, -1.175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875e-38
249+
ret i1 %result
250+
}
251+
252+
253+
; +0
254+
define i1 @fcmp_trunc_p0(double %0) {
255+
; CHECK-LABEL: define i1 @fcmp_trunc_p0(
256+
; CHECK-SAME: double [[TMP0:%.*]]) {
257+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp oge double [[TMP0]], 0xB690000000000000
258+
; CHECK-NEXT: ret i1 [[RESULT]]
259+
;
260+
%trunc = fptrunc double %0 to float
261+
%result = fcmp oge float %trunc, 0x00000000
262+
ret i1 %result
263+
}
264+
265+
266+
; -0
267+
define i1 @fcmp_trunc_n0(double %0) {
268+
; CHECK-LABEL: define i1 @fcmp_trunc_n0(
269+
; CHECK-SAME: double [[TMP0:%.*]]) {
270+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ogt double [[TMP0]], 0x3690000000000000
271+
; CHECK-NEXT: ret i1 [[RESULT]]
272+
;
273+
%trunc = fptrunc double %0 to float
274+
%result = fcmp ogt float %trunc, 0x8000000000000000
275+
ret i1 %result
276+
}
277+
278+
279+
; max representable
280+
define i1 @fcmp_trunc_mx(double %0) {
281+
; CHECK-LABEL: define i1 @fcmp_trunc_mx(
282+
; CHECK-SAME: double [[TMP0:%.*]]) {
283+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ogt double [[TMP0]], 0x47EFFFFFEFFFFFFF
284+
; CHECK-NEXT: ret i1 [[RESULT]]
285+
;
286+
%trunc = fptrunc double %0 to float
287+
%result = fcmp ogt float %trunc, 0x47EFFFFFE0000000
288+
ret i1 %result
289+
}
290+
291+
; min representable
292+
define i1 @fcmp_trunc_mn(double %0) {
293+
; CHECK-LABEL: define i1 @fcmp_trunc_mn(
294+
; CHECK-SAME: double [[TMP0:%.*]]) {
295+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp olt double [[TMP0]], 0xC7EFFFFFEFFFFFFF
296+
; CHECK-NEXT: ret i1 [[RESULT]]
297+
;
298+
%trunc = fptrunc double %0 to float
299+
%result = fcmp olt float %trunc, -3.4028234663852885981170418348451692544e38
300+
ret i1 %result
301+
}
302+
303+

0 commit comments

Comments
 (0)