Skip to content

Commit 60e0059

Browse files
committed
Refactor foldFCmpFpTrunc & Add more test cases
1 parent 5cc33ac commit 60e0059

File tree

2 files changed

+335
-35
lines changed

2 files changed

+335
-35
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7923,7 +7923,7 @@ static Instruction *foldFCmpFpTrunc(FCmpInst &I, Instruction *LHSI,
79237923
APFloat NextRValue = *RValue;
79247924
NextRValue.next(RoundDown);
79257925

7926-
// Round RValue to suitable value
7926+
// Promote 'RValue' and 'NextRValue' to 'LType'.
79277927
APFloat ExtRValue = *RValue;
79287928
APFloat ExtNextRValue = NextRValue;
79297929
bool lossInfo;
@@ -7932,46 +7932,53 @@ static Instruction *foldFCmpFpTrunc(FCmpInst &I, Instruction *LHSI,
79327932
ExtNextRValue.convert(LEleType->getFltSemantics(),
79337933
APFloat::rmNearestTiesToEven, &lossInfo);
79347934

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.
7938-
APFloat RoundValue{LEleType->getFltSemantics()};
7939-
{
7940-
APFloat Two{LEleType->getFltSemantics(), 2};
7935+
// The (negative) maximum of 'RValue' may become infinity when rounded up
7936+
// (down). Set the limit of 'ExtNextRValue'.
7937+
if (NextRValue.isInfinity())
7938+
ExtNextRValue = scalbn(ExtRValue, 1, APFloat::rmNearestTiesToEven);
79417939

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-
}
7940+
// Binary search to find the maximal (or minimal) value after 'RValue'
7941+
// promotion. 'RValue' should obey normal comparison rules, which means nan or
7942+
// inf is not allowed here.
7943+
APFloat RoundValue{LEleType->getFltSemantics()};
79477944

7948-
APFloat LowBound = RoundDown ? ExtNextRValue : ExtRValue;
7949-
APFloat UpBound = RoundDown ? ExtRValue : ExtNextRValue;
7945+
APFloat LowBound = RoundDown ? ExtNextRValue : ExtRValue;
7946+
APFloat UpBound = RoundDown ? ExtRValue : ExtNextRValue;
79507947

7951-
while (true) {
7952-
APFloat UpBoundNext = UpBound;
7953-
UpBoundNext.next(true);
7954-
if (UpBoundNext == LowBound) {
7955-
RoundValue = RoundDown ? UpBound : LowBound;
7956-
break;
7957-
}
7948+
auto IsRoundingFound = [](const APFloat &LowBound, const APFloat &UpBound) {
7949+
APFloat UpBoundNext = UpBound;
7950+
UpBoundNext.next(true);
7951+
return LowBound == UpBoundNext;
7952+
};
79587953

7959-
APFloat Mid = (LowBound + UpBound) / Two;
7960-
APFloat TruncMid = Mid;
7961-
TruncMid.convert(REleType->getFltSemantics(),
7954+
auto EqualRValueAfterTrunc = [&](const APFloat &ExtValue) {
7955+
APFloat TruncValue = ExtValue;
7956+
TruncValue.convert(REleType->getFltSemantics(),
79627957
APFloat::rmNearestTiesToEven, &lossInfo);
7958+
return TruncValue == *RValue;
7959+
};
79637960

7964-
if (TruncMid == *RValue) {
7965-
if (RoundDown)
7966-
UpBound = Mid;
7967-
else
7968-
LowBound = Mid;
7969-
} else {
7970-
if (RoundDown)
7971-
LowBound = Mid;
7972-
else
7973-
UpBound = Mid;
7974-
}
7961+
while (true) {
7962+
// Finish searching when 'LowBound' is next to 'UpBound'.
7963+
if (IsRoundingFound(LowBound, UpBound)) {
7964+
RoundValue = RoundDown ? UpBound : LowBound;
7965+
break;
7966+
}
7967+
7968+
APFloat Mid = scalbn(LowBound + UpBound, -1, APFloat::rmNearestTiesToEven);
7969+
bool EqualRValue = EqualRValueAfterTrunc(Mid);
7970+
7971+
// 'EqualRValue' indicates whether Mid is qualified to be the final round
7972+
// value. if 'EqualRValue' == true, 'Mid' might be the final round value
7973+
// if 'RoundDown' == true, 'UpBound' can't be the final round value
7974+
// if 'RoudnDown' == false, 'DownBound' can't be the final round value
7975+
// if 'EqualRValue' == false, 'Mid' can't be the final round value
7976+
// if 'RoundDown' == true, 'DownBound' can't be the final round value
7977+
// if 'RoundDown' == false, 'UpBound' can't be the final round value
7978+
if (EqualRValue == RoundDown) {
7979+
UpBound = Mid;
7980+
} else {
7981+
LowBound = Mid;
79757982
}
79767983
}
79777984

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

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,296 @@ define i1 @fcmp_trunc_mn(double %0) {
301301
}
302302

303303

304+
define i1 @fcmp_trunc_literal_nan(double %0) {
305+
; CHECK-LABEL: define i1 @fcmp_trunc_literal_nan(
306+
; CHECK-SAME: double [[TMP0:%.*]]) {
307+
; CHECK-NEXT: ret i1 false
308+
;
309+
%trunc = fptrunc double %0 to float
310+
%result = fcmp oge float %trunc, 0x7FF8000000000000
311+
ret i1 %result
312+
}
313+
314+
define i1 @fcmp_trunc_literal_positive_inf(double %0) {
315+
; CHECK-LABEL: define i1 @fcmp_trunc_literal_positive_inf(
316+
; CHECK-SAME: double [[TMP0:%.*]]) {
317+
; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double [[TMP0]] to float
318+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp oeq float [[TRUNC]], 0x7FF0000000000000
319+
; CHECK-NEXT: ret i1 [[RESULT]]
320+
;
321+
%trunc = fptrunc double %0 to float
322+
%result = fcmp oge float %trunc, 0x7FF0000000000000
323+
ret i1 %result
324+
}
325+
326+
327+
define i1 @fcmp_trunc_literal_negative_inf(double %0) {
328+
; CHECK-LABEL: define i1 @fcmp_trunc_literal_negative_inf(
329+
; CHECK-SAME: double [[TMP0:%.*]]) {
330+
; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double [[TMP0]] to float
331+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp uno float [[TRUNC]], 0.000000e+00
332+
; CHECK-NEXT: ret i1 [[RESULT]]
333+
;
334+
%trunc = fptrunc double %0 to float
335+
%result = fcmp ult float %trunc, 0xFFF0000000000000
336+
ret i1 %result
337+
}
338+
339+
340+
define i1 @fcmp_trunc_nan_ugt(double %0) {
341+
; CHECK-LABEL: define i1 @fcmp_trunc_nan_ugt(
342+
; CHECK-SAME: double [[TMP0:%.*]]) {
343+
; CHECK-NEXT: ret i1 true
344+
;
345+
%trunc = fptrunc double %0 to float
346+
%result = fcmp ugt float %trunc, 0x7FF8000000000000
347+
ret i1 %result
348+
}
349+
350+
define i1 @fcmp_trunc_inf_uge(double %0) {
351+
; CHECK-LABEL: define i1 @fcmp_trunc_inf_uge(
352+
; CHECK-SAME: double [[TMP0:%.*]]) {
353+
; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double [[TMP0]] to float
354+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ueq float [[TRUNC]], 0x7FF0000000000000
355+
; CHECK-NEXT: ret i1 [[RESULT]]
356+
;
357+
%trunc = fptrunc double %0 to float
358+
%result = fcmp uge float %trunc, 0x7FF0000000000000
359+
ret i1 %result
360+
}
361+
362+
363+
define i1 @fcmp_trunc_ninf_olt(double %0) {
364+
; CHECK-LABEL: define i1 @fcmp_trunc_ninf_olt(
365+
; CHECK-SAME: double [[TMP0:%.*]]) {
366+
; CHECK-NEXT: ret i1 false
367+
;
368+
%trunc = fptrunc double %0 to float
369+
%result = fcmp olt float %trunc, 0xFFF0000000000000
370+
ret i1 %result
371+
}
372+
373+
374+
define i1 @fcmp_trunc_uge(double %0) {
375+
; CHECK-LABEL: define i1 @fcmp_trunc_uge(
376+
; CHECK-SAME: double [[TMP0:%.*]]) {
377+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp uge double [[TMP0]], 0x405EBFFFF0000000
378+
; CHECK-NEXT: ret i1 [[RESULT]]
379+
;
380+
%trunc = fptrunc double %0 to float
381+
%result = fcmp uge float %trunc, 123.0
382+
ret i1 %result
383+
}
384+
385+
386+
define i1 @fcmp_trunc_neg_uge(double %0) {
387+
; CHECK-LABEL: define i1 @fcmp_trunc_neg_uge(
388+
; CHECK-SAME: double [[TMP0:%.*]]) {
389+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp uge double [[TMP0]], 0xC05EC00010000000
390+
; CHECK-NEXT: ret i1 [[RESULT]]
391+
;
392+
%trunc = fptrunc double %0 to float
393+
%result = fcmp uge float %trunc, -123.0
394+
ret i1 %result
395+
}
396+
397+
398+
define i1 @fcmp_trunc_oge(double %0) {
399+
; CHECK-LABEL: define i1 @fcmp_trunc_oge(
400+
; CHECK-SAME: double [[TMP0:%.*]]) {
401+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp oge double [[TMP0]], 0x405EBFFFF0000000
402+
; CHECK-NEXT: ret i1 [[RESULT]]
403+
;
404+
%trunc = fptrunc double %0 to float
405+
%result = fcmp oge float %trunc, 123.0
406+
ret i1 %result
407+
}
408+
409+
410+
define i1 @fcmp_trunc_neg_oge(double %0) {
411+
; CHECK-LABEL: define i1 @fcmp_trunc_neg_oge(
412+
; CHECK-SAME: double [[TMP0:%.*]]) {
413+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp oge double [[TMP0]], 0xC05EC00010000000
414+
; CHECK-NEXT: ret i1 [[RESULT]]
415+
;
416+
%trunc = fptrunc double %0 to float
417+
%result = fcmp oge float %trunc, -123.0
418+
ret i1 %result
419+
}
420+
421+
422+
define i1 @fcmp_trunc_ugt(double %0) {
423+
; CHECK-LABEL: define i1 @fcmp_trunc_ugt(
424+
; CHECK-SAME: double [[TMP0:%.*]]) {
425+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ugt double [[TMP0]], 0x40FE0F3010000000
426+
; CHECK-NEXT: ret i1 [[RESULT]]
427+
;
428+
%trunc = fptrunc double %0 to float
429+
%result = fcmp ugt float %trunc, 123123.0
430+
ret i1 %result
431+
}
432+
433+
434+
define i1 @fcmp_trunc_neg_ugt(double %0) {
435+
; CHECK-LABEL: define i1 @fcmp_trunc_neg_ugt(
436+
; CHECK-SAME: double [[TMP0:%.*]]) {
437+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ugt double [[TMP0]], 0xC0FE1B8FF0000000
438+
; CHECK-NEXT: ret i1 [[RESULT]]
439+
;
440+
%trunc = fptrunc double %0 to float
441+
%result = fcmp ugt float %trunc, -123321.0
442+
ret i1 %result
443+
}
444+
445+
446+
define i1 @fcmp_trunc_neg_ogt(double %0) {
447+
; CHECK-LABEL: define i1 @fcmp_trunc_neg_ogt(
448+
; CHECK-SAME: double [[TMP0:%.*]]) {
449+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ogt double [[TMP0]], 0xC0FE1B8FF0000000
450+
; CHECK-NEXT: ret i1 [[RESULT]]
451+
;
452+
%trunc = fptrunc double %0 to float
453+
%result = fcmp ogt float %trunc, -123321.0
454+
ret i1 %result
455+
}
456+
457+
458+
459+
define i1 @fcmp_trunc_ule(double %0) {
460+
; CHECK-LABEL: define i1 @fcmp_trunc_ule(
461+
; CHECK-SAME: double [[TMP0:%.*]]) {
462+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ule double [[TMP0]], 0x408ED80010000000
463+
; CHECK-NEXT: ret i1 [[RESULT]]
464+
;
465+
%trunc = fptrunc double %0 to float
466+
%result = fcmp ule float %trunc, 987.0
467+
ret i1 %result
468+
}
469+
470+
471+
472+
define i1 @fcmp_trunc_neg_ule(double %0) {
473+
; CHECK-LABEL: define i1 @fcmp_trunc_neg_ule(
474+
; CHECK-SAME: double [[TMP0:%.*]]) {
475+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ule double [[TMP0]], 0xC088A7FFF0000000
476+
; CHECK-NEXT: ret i1 [[RESULT]]
477+
;
478+
%trunc = fptrunc double %0 to float
479+
%result = fcmp ule float %trunc, -789.0
480+
ret i1 %result
481+
}
482+
483+
484+
485+
define i1 @fcmp_trunc_neg_ole(double %0) {
486+
; CHECK-LABEL: define i1 @fcmp_trunc_neg_ole(
487+
; CHECK-SAME: double [[TMP0:%.*]]) {
488+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ole double [[TMP0]], 0xC088A7FFF0000000
489+
; CHECK-NEXT: ret i1 [[RESULT]]
490+
;
491+
%trunc = fptrunc double %0 to float
492+
%result = fcmp ole float %trunc, -789.0
493+
ret i1 %result
494+
}
495+
496+
497+
define i1 @fcmp_trunc_neg_ult(double %0) {
498+
; CHECK-LABEL: define i1 @fcmp_trunc_neg_ult(
499+
; CHECK-SAME: double [[TMP0:%.*]]) {
500+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ult double [[TMP0]], 0xC088A80010000000
501+
; CHECK-NEXT: ret i1 [[RESULT]]
502+
;
503+
%trunc = fptrunc double %0 to float
504+
%result = fcmp ult float %trunc, -789.0
505+
ret i1 %result
506+
}
507+
508+
509+
510+
define i1 @fcmp_trunc_olt(double %0) {
511+
; CHECK-LABEL: define i1 @fcmp_trunc_olt(
512+
; CHECK-SAME: double [[TMP0:%.*]]) {
513+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp olt double [[TMP0]], 0x408ED7FFF0000000
514+
; CHECK-NEXT: ret i1 [[RESULT]]
515+
;
516+
%trunc = fptrunc double %0 to float
517+
%result = fcmp olt float %trunc, 987.0
518+
ret i1 %result
519+
}
520+
521+
522+
523+
define i1 @fcmp_trunc_neg_olt(double %0) {
524+
; CHECK-LABEL: define i1 @fcmp_trunc_neg_olt(
525+
; CHECK-SAME: double [[TMP0:%.*]]) {
526+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp olt double [[TMP0]], 0xC088A80010000000
527+
; CHECK-NEXT: ret i1 [[RESULT]]
528+
;
529+
%trunc = fptrunc double %0 to float
530+
%result = fcmp olt float %trunc, -789.0
531+
ret i1 %result
532+
}
533+
534+
535+
define i1 @fcmp_trunc_neg_nsz_uge(double %0) {
536+
; CHECK-LABEL: define i1 @fcmp_trunc_neg_nsz_uge(
537+
; CHECK-SAME: double [[TMP0:%.*]]) {
538+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp nsz uge double [[TMP0]], 0xC05EC00010000000
539+
; CHECK-NEXT: ret i1 [[RESULT]]
540+
;
541+
%trunc = fptrunc double %0 to float
542+
%result = fcmp nsz uge float %trunc, -123.0
543+
ret i1 %result
544+
}
545+
546+
547+
548+
define i1 @fcmp_trunc_reassoc_ugt(double %0) {
549+
; CHECK-LABEL: define i1 @fcmp_trunc_reassoc_ugt(
550+
; CHECK-SAME: double [[TMP0:%.*]]) {
551+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp reassoc ugt double [[TMP0]], 0x40889F8210000000
552+
; CHECK-NEXT: ret i1 [[RESULT]]
553+
;
554+
%trunc = fptrunc double %0 to float
555+
%result = fcmp reassoc ugt float %trunc, 787.9384765625
556+
ret i1 %result
557+
}
558+
559+
560+
define i1 @fcmp_trunc_neg_reassoc_ugt(double %0) {
561+
; CHECK-LABEL: define i1 @fcmp_trunc_neg_reassoc_ugt(
562+
; CHECK-SAME: double [[TMP0:%.*]]) {
563+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp reassoc ugt double [[TMP0]], 0xC0889F81F0000000
564+
; CHECK-NEXT: ret i1 [[RESULT]]
565+
;
566+
%trunc = fptrunc double %0 to float
567+
%result = fcmp reassoc ugt float %trunc, -787.9384765625
568+
ret i1 %result
569+
}
570+
571+
572+
573+
define i1 @fcmp_trunc_fast_ult(double %0) {
574+
; CHECK-LABEL: define i1 @fcmp_trunc_fast_ult(
575+
; CHECK-SAME: double [[TMP0:%.*]]) {
576+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp fast uge double [[TMP0]], 0x40F8E8E010000001
577+
; CHECK-NEXT: ret i1 [[RESULT]]
578+
;
579+
%trunc = fptrunc double %0 to float
580+
%result = fcmp fast uge float %trunc, 102030.0078125
581+
ret i1 %result
582+
}
583+
584+
585+
define i1 @fcmp_trunc_neg_fast_ult(double %0) {
586+
; CHECK-LABEL: define i1 @fcmp_trunc_neg_fast_ult(
587+
; CHECK-SAME: double [[TMP0:%.*]]) {
588+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp fast uge double [[TMP0]], 0xC0F8E8E02FFFFFFF
589+
; CHECK-NEXT: ret i1 [[RESULT]]
590+
;
591+
%trunc = fptrunc double %0 to float
592+
%result = fcmp fast uge float %trunc, -102030.0078125
593+
ret i1 %result
594+
}
595+
596+

0 commit comments

Comments
 (0)