Skip to content

Commit 7804fb1

Browse files
committed
Optimize fptrunc(x)>=C1 --> x>=C2 Fix round value & add scalable vector test
1 parent 73b1f0b commit 7804fb1

File tree

2 files changed

+120
-49
lines changed

2 files changed

+120
-49
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 57 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "llvm/IR/Instructions.h"
3333
#include "llvm/IR/IntrinsicInst.h"
3434
#include "llvm/IR/PatternMatch.h"
35+
#include "llvm/IR/Type.h"
3536
#include "llvm/IR/Value.h"
3637
#include "llvm/Support/Casting.h"
3738
#include "llvm/Support/KnownBits.h"
@@ -7895,47 +7896,73 @@ static Instruction *foldFCmpReciprocalAndZero(FCmpInst &I, Instruction *LHSI,
78957896
static Instruction *foldFCmpFpTrunc(FCmpInst &I, Instruction *LHSI,
78967897
Constant *RHSC) {
78977898
FCmpInst::Predicate Pred = I.getPredicate();
7899+
bool RoundDown = false;
7900+
7901+
if ((Pred == FCmpInst::FCMP_OGE) || (Pred == FCmpInst::FCMP_UGE) ||
7902+
(Pred == FCmpInst::FCMP_OLT) || (Pred == FCmpInst::FCMP_ULT))
7903+
RoundDown = true;
7904+
else if ((Pred == FCmpInst::FCMP_OGT) || (Pred == FCmpInst::FCMP_UGT) ||
7905+
(Pred == FCmpInst::FCMP_OLE) || (Pred == FCmpInst::FCMP_ULE))
7906+
RoundDown = false;
7907+
else
7908+
return nullptr;
78987909

7899-
// Check that predicates are valid.
7900-
if ((Pred != FCmpInst::FCMP_OGT) && (Pred != FCmpInst::FCMP_OLT) &&
7901-
(Pred != FCmpInst::FCMP_OGE) && (Pred != FCmpInst::FCMP_OLE))
7910+
const APFloat *RValue;
7911+
if (!match(RHSC, m_APFloat(RValue)))
79027912
return nullptr;
79037913

7904-
if (ConstantFP *ConstRFp = dyn_cast<ConstantFP>(RHSC)) {
7905-
Type *LType = LHSI->getOperand(0)->getType();
7906-
bool lossInfo;
7907-
APFloat RValue = ConstRFp->getValue();
7908-
RValue.convert(LType->getFltSemantics(), APFloat::rmNearestTiesToEven,
7909-
&lossInfo);
7914+
Type *LType = LHSI->getOperand(0)->getType();
7915+
Type *RType = RHSC->getType();
7916+
Type *LEleType = LType->getScalarType();
7917+
Type *REleType = RType->getScalarType();
79107918

7911-
return new FCmpInst(Pred, LHSI->getOperand(0),
7912-
ConstantFP::get(LType, RValue), "", &I);
7913-
}
7919+
APFloat NextRValue = *RValue;
7920+
NextRValue.next(RoundDown);
79147921

7915-
if (RHSC->getType()->isVectorTy()) {
7916-
Type *LVecType = LHSI->getOperand(0)->getType();
7917-
Type *LEleType = dyn_cast<VectorType>(LVecType)->getElementType();
7922+
// Round RValue to suitable value
7923+
APFloat ExtRValue = *RValue;
7924+
APFloat ExtNextRValue = NextRValue;
7925+
bool lossInfo;
7926+
ExtRValue.convert(LEleType->getFltSemantics(), APFloat::rmNearestTiesToEven,
7927+
&lossInfo);
7928+
ExtNextRValue.convert(LEleType->getFltSemantics(),
7929+
APFloat::rmNearestTiesToEven, &lossInfo);
79187930

7919-
FixedVectorType *VecType = dyn_cast<FixedVectorType>(RHSC->getType());
7920-
uint64_t EleNum = VecType->getNumElements();
7931+
APFloat RoundValue{LEleType->getFltSemantics()};
7932+
{
7933+
APFloat Two{LEleType->getFltSemantics(), 2};
7934+
APFloat LowBound = RoundDown ? ExtNextRValue : ExtRValue;
7935+
APFloat UpBound = RoundDown ? ExtRValue : ExtNextRValue;
7936+
7937+
while (true) {
7938+
APFloat DupUpBound = UpBound;
7939+
DupUpBound.next(true);
7940+
if (DupUpBound == LowBound) {
7941+
RoundValue = RoundDown ? UpBound : LowBound;
7942+
break;
7943+
}
79217944

7922-
std::vector<Constant *> EleVec(EleNum);
7923-
for (uint64_t Idx = 0; Idx < EleNum; ++Idx) {
7924-
bool lossInfo;
7925-
APFloat EleValue =
7926-
dyn_cast<ConstantFP>(RHSC->getAggregateElement(Idx))->getValueAPF();
7927-
EleValue.convert(LEleType->getFltSemantics(),
7945+
APFloat Mid = (LowBound + UpBound) / Two;
7946+
APFloat TruncMid = Mid;
7947+
TruncMid.convert(REleType->getFltSemantics(),
79287948
APFloat::rmNearestTiesToEven, &lossInfo);
7929-
EleVec[Idx] = ConstantFP::get(LEleType, EleValue);
7930-
}
7931-
7932-
ArrayRef<Constant *> EleArr(EleVec);
79337949

7934-
return new FCmpInst(Pred, LHSI->getOperand(0), ConstantVector::get(EleArr),
7935-
"", &I);
7950+
if (TruncMid == *RValue) {
7951+
if (RoundDown)
7952+
UpBound = Mid;
7953+
else
7954+
LowBound = Mid;
7955+
} else {
7956+
if (RoundDown)
7957+
LowBound = Mid;
7958+
else
7959+
UpBound = Mid;
7960+
}
7961+
}
79367962
}
79377963

7938-
return nullptr;
7964+
return new FCmpInst(Pred, LHSI->getOperand(0),
7965+
ConstantFP::get(LType, RoundValue), "", &I);
79397966
}
79407967

79417968
/// Optimize fabs(X) compared with zero.

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

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,62 @@
55
define i1 @fcmp_trunc(double %0) {
66
; CHECK-LABEL: define i1 @fcmp_trunc(
77
; CHECK-SAME: double [[TMP0:%.*]]) {
8-
; CHECK-NEXT: [[RESULT:%.*]] = fcmp oge double [[TMP0]], 1.000000e+02
8+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp oge double [[TMP0]], 0x4058FFFFF0000000
99
; CHECK-NEXT: ret i1 [[RESULT]]
1010
;
1111
%trunc = fptrunc double %0 to float
1212
%result = fcmp oge float %trunc, 1.000000e+02
1313
ret i1 %result
1414
}
1515

16+
define i1 @fcmp_trunc_ult(double %0) {
17+
; CHECK-LABEL: define i1 @fcmp_trunc_ult(
18+
; CHECK-SAME: double [[TMP0:%.*]]) {
19+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ult double [[TMP0]], 0x4068FFFFF0000000
20+
; CHECK-NEXT: ret i1 [[RESULT]]
21+
;
22+
%trunc = fptrunc double %0 to float
23+
%result = fcmp ult float %trunc, 2.000000e+02
24+
ret i1 %result
25+
}
26+
27+
define i1 @fcmp_trunc_ole(double %0) {
28+
; CHECK-LABEL: define i1 @fcmp_trunc_ole(
29+
; CHECK-SAME: double [[TMP0:%.*]]) {
30+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ole double [[TMP0]], 0x4072C00010000000
31+
; CHECK-NEXT: ret i1 [[RESULT]]
32+
;
33+
%trunc = fptrunc double %0 to float
34+
%result = fcmp ole float %trunc, 3.000000e+02
35+
ret i1 %result
36+
}
37+
38+
define i1 @fcmp_trunc_ogt(double %0) {
39+
; CHECK-LABEL: define i1 @fcmp_trunc_ogt(
40+
; CHECK-SAME: double [[TMP0:%.*]]) {
41+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ogt double [[TMP0]], 0x4079000010000000
42+
; CHECK-NEXT: ret i1 [[RESULT]]
43+
;
44+
%trunc = fptrunc double %0 to float
45+
%result = fcmp ogt float %trunc, 4.000000e+02
46+
ret i1 %result
47+
}
48+
49+
define i1 @fcmp_trunc_zero(double %0) {
50+
; CHECK-LABEL: define i1 @fcmp_trunc_zero(
51+
; CHECK-SAME: double [[TMP0:%.*]]) {
52+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp oge double [[TMP0]], 0xB690000000000000
53+
; CHECK-NEXT: ret i1 [[RESULT]]
54+
;
55+
%trunc = fptrunc double %0 to float
56+
%result = fcmp oge float %trunc, 0.000000
57+
ret i1 %result
58+
}
59+
1660
define i1 @fcmp_trunc_with_nnan(double %0) {
1761
; CHECK-LABEL: define i1 @fcmp_trunc_with_nnan(
1862
; CHECK-SAME: double [[TMP0:%.*]]) {
19-
; CHECK-NEXT: [[RESULT:%.*]] = fcmp nnan oge double [[TMP0]], 1.000000e+02
63+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp nnan oge double [[TMP0]], 0x4058FFFFF0000000
2064
; CHECK-NEXT: ret i1 [[RESULT]]
2165
;
2266
%trunc = fptrunc double %0 to float
@@ -27,7 +71,7 @@ define i1 @fcmp_trunc_with_nnan(double %0) {
2771
define i1 @fcmp_trunc_with_ninf(double %0) {
2872
; CHECK-LABEL: define i1 @fcmp_trunc_with_ninf(
2973
; CHECK-SAME: double [[TMP0:%.*]]) {
30-
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ninf oge double [[TMP0]], 1.000000e+02
74+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp ninf oge double [[TMP0]], 0x4058FFFFF0000000
3175
; CHECK-NEXT: ret i1 [[RESULT]]
3276
;
3377
%trunc = fptrunc double %0 to float
@@ -38,7 +82,7 @@ define i1 @fcmp_trunc_with_ninf(double %0) {
3882
define i1 @fcmp_trunc_with_nsz(double %0) {
3983
; CHECK-LABEL: define i1 @fcmp_trunc_with_nsz(
4084
; CHECK-SAME: double [[TMP0:%.*]]) {
41-
; CHECK-NEXT: [[RESULT:%.*]] = fcmp nsz oge double [[TMP0]], 1.000000e+02
85+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp nsz oge double [[TMP0]], 0x4058FFFFF0000000
4286
; CHECK-NEXT: ret i1 [[RESULT]]
4387
;
4488
%trunc = fptrunc double %0 to float
@@ -49,7 +93,7 @@ define i1 @fcmp_trunc_with_nsz(double %0) {
4993
define i1 @fcmp_trunc_with_reassoc(double %0) {
5094
; CHECK-LABEL: define i1 @fcmp_trunc_with_reassoc(
5195
; CHECK-SAME: double [[TMP0:%.*]]) {
52-
; CHECK-NEXT: [[RESULT:%.*]] = fcmp reassoc oge double [[TMP0]], 1.000000e+02
96+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp reassoc oge double [[TMP0]], 0x4058FFFFF0000000
5397
; CHECK-NEXT: ret i1 [[RESULT]]
5498
;
5599
%trunc = fptrunc double %0 to float
@@ -60,7 +104,7 @@ define i1 @fcmp_trunc_with_reassoc(double %0) {
60104
define i1 @fcmp_trunc_with_fast(double %0) {
61105
; CHECK-LABEL: define i1 @fcmp_trunc_with_fast(
62106
; CHECK-SAME: double [[TMP0:%.*]]) {
63-
; CHECK-NEXT: [[RESULT:%.*]] = fcmp fast oge double [[TMP0]], 1.000000e+02
107+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp fast oge double [[TMP0]], 0x4058FFFFF0000000
64108
; CHECK-NEXT: ret i1 [[RESULT]]
65109
;
66110
%trunc = fptrunc double %0 to float
@@ -71,29 +115,29 @@ define i1 @fcmp_trunc_with_fast(double %0) {
71115
define <4 x i1> @fcmp_vec_trunc(<4 x double> %0) {
72116
; CHECK-LABEL: define <4 x i1> @fcmp_vec_trunc(
73117
; CHECK-SAME: <4 x double> [[TMP0:%.*]]) {
74-
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <4 x double> [[TMP0]], <double 1.000000e+00, double 2.000000e+00, double 3.000000e+00, double 4.000000e+00>
118+
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <4 x double> [[TMP0]], <double 0x3FEFFFFFF0000000, double 0x3FEFFFFFF0000000, double 0x3FEFFFFFF0000000, double 0x3FEFFFFFF0000000>
75119
; CHECK-NEXT: ret <4 x i1> [[CMP]]
76120
;
77121
%vec = fptrunc <4 x double> %0 to <4 x float>
78-
%cmp = fcmp olt <4 x float> %vec, <float 1.0, float 2.0, float 3.0, float 4.0>
122+
%cmp = fcmp olt <4 x float> %vec, <float 1.0, float 1.0, float 1.0, float 1.0>
79123
ret <4 x i1> %cmp
80124
}
81125

82-
define <4 x i1> @fcmp_vec_trunc_with_flag(<4 x double> %0) {
83-
; CHECK-LABEL: define <4 x i1> @fcmp_vec_trunc_with_flag(
84-
; CHECK-SAME: <4 x double> [[TMP0:%.*]]) {
85-
; CHECK-NEXT: [[CMP:%.*]] = fcmp fast olt <4 x double> [[TMP0]], <double 1.000000e+00, double 2.000000e+00, double 3.000000e+00, double 4.000000e+00>
86-
; CHECK-NEXT: ret <4 x i1> [[CMP]]
126+
define <1 x i1> @fcmp_vec_trunc_scalar(<1 x double> %0) {
127+
; CHECK-LABEL: define <1 x i1> @fcmp_vec_trunc_scalar(
128+
; CHECK-SAME: <1 x double> [[TMP0:%.*]]) {
129+
; CHECK-NEXT: [[CMP:%.*]] = fcmp fast olt <1 x double> [[TMP0]], <double 0x3FEFFFFFF0000000>
130+
; CHECK-NEXT: ret <1 x i1> [[CMP]]
87131
;
88-
%vec = fptrunc <4 x double> %0 to <4 x float>
89-
%cmp = fcmp fast olt <4 x float> %vec, <float 1.0, float 2.0, float 3.0, float 4.0>
90-
ret <4 x i1> %cmp
132+
%vec = fptrunc <1 x double> %0 to <1 x float>
133+
%cmp = fcmp fast olt <1 x float> %vec, <float 1.0>
134+
ret <1 x i1> %cmp
91135
}
92136

93137
define i1 @fcmp_trunc_fp128(fp128 %0) {
94138
; CHECK-LABEL: define i1 @fcmp_trunc_fp128(
95139
; CHECK-SAME: fp128 [[TMP0:%.*]]) {
96-
; CHECK-NEXT: [[RESULT:%.*]] = fcmp fast oge fp128 [[TMP0]], 0xL00000000000000004005900000000000
140+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp fast oge fp128 [[TMP0]], 0xL000000000000000040058FFFFF000000
97141
; CHECK-NEXT: ret i1 [[RESULT]]
98142
;
99143
%trunc = fptrunc fp128 %0 to float
@@ -104,7 +148,7 @@ define i1 @fcmp_trunc_fp128(fp128 %0) {
104148
define i1 @fcmp_trunc_x86_fp80(x86_fp80 %0) {
105149
; CHECK-LABEL: define i1 @fcmp_trunc_x86_fp80(
106150
; CHECK-SAME: x86_fp80 [[TMP0:%.*]]) {
107-
; CHECK-NEXT: [[RESULT:%.*]] = fcmp fast oge x86_fp80 [[TMP0]], 0xK4005C800000000000000
151+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp fast oge x86_fp80 [[TMP0]], 0xK4005C7FFFF8000000000
108152
; CHECK-NEXT: ret i1 [[RESULT]]
109153
;
110154
%trunc = fptrunc x86_fp80 %0 to float
@@ -115,7 +159,7 @@ define i1 @fcmp_trunc_x86_fp80(x86_fp80 %0) {
115159
define i1 @fcmp_trunc_ppc_fp128(ppc_fp128 %0) {
116160
; CHECK-LABEL: define i1 @fcmp_trunc_ppc_fp128(
117161
; CHECK-SAME: ppc_fp128 [[TMP0:%.*]]) {
118-
; CHECK-NEXT: [[RESULT:%.*]] = fcmp fast oge ppc_fp128 [[TMP0]], 0xM40590000000000000000000000000000
162+
; CHECK-NEXT: [[RESULT:%.*]] = fcmp fast oge ppc_fp128 [[TMP0]], 0xM4058FFFFF0000000BD00000000000000
119163
; CHECK-NEXT: ret i1 [[RESULT]]
120164
;
121165
%trunc = fptrunc ppc_fp128 %0 to float

0 commit comments

Comments
 (0)