Skip to content

Commit baf2953

Browse files
authored
Optimize fptrunc(x)>=C1 --> x>=C2 (#99475)
Fix #85265 (comment)
1 parent 224e221 commit baf2953

File tree

2 files changed

+773
-0
lines changed

2 files changed

+773
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "InstCombineInternal.h"
14+
#include "llvm/ADT/APFloat.h"
1415
#include "llvm/ADT/APSInt.h"
1516
#include "llvm/ADT/SetVector.h"
1617
#include "llvm/ADT/Statistic.h"
@@ -21,8 +22,10 @@
2122
#include "llvm/Analysis/Utils/Local.h"
2223
#include "llvm/Analysis/VectorUtils.h"
2324
#include "llvm/IR/ConstantRange.h"
25+
#include "llvm/IR/Constants.h"
2426
#include "llvm/IR/DataLayout.h"
2527
#include "llvm/IR/InstrTypes.h"
28+
#include "llvm/IR/Instructions.h"
2629
#include "llvm/IR/IntrinsicInst.h"
2730
#include "llvm/IR/PatternMatch.h"
2831
#include "llvm/Support/KnownBits.h"
@@ -8222,6 +8225,98 @@ static Instruction *foldFCmpReciprocalAndZero(FCmpInst &I, Instruction *LHSI,
82228225
return new FCmpInst(Pred, LHSI->getOperand(1), RHSC, "", &I);
82238226
}
82248227

8228+
// Transform 'fptrunc(x) cmp C' to 'x cmp ext(C)' if possible.
8229+
// Patterns include:
8230+
// fptrunc(x) < C --> x < ext(C)
8231+
// fptrunc(x) <= C --> x <= ext(C)
8232+
// fptrunc(x) > C --> x > ext(C)
8233+
// fptrunc(x) >= C --> x >= ext(C)
8234+
// where 'ext(C)' is the extension of 'C' to the type of 'x' with a small bias
8235+
// due to precision loss.
8236+
static Instruction *foldFCmpFpTrunc(FCmpInst &I, const Instruction &FPTrunc,
8237+
const Constant &C) {
8238+
FCmpInst::Predicate Pred = I.getPredicate();
8239+
bool RoundDown = false;
8240+
8241+
if (Pred == FCmpInst::FCMP_OGE || Pred == FCmpInst::FCMP_UGE ||
8242+
Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_ULT)
8243+
RoundDown = true;
8244+
else if (Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_UGT ||
8245+
Pred == FCmpInst::FCMP_OLE || Pred == FCmpInst::FCMP_ULE)
8246+
RoundDown = false;
8247+
else
8248+
return nullptr;
8249+
8250+
const APFloat *CValue;
8251+
if (!match(&C, m_APFloat(CValue)))
8252+
return nullptr;
8253+
8254+
if (CValue->isNaN() || CValue->isInfinity())
8255+
return nullptr;
8256+
8257+
auto ConvertFltSema = [](const APFloat &Src, const fltSemantics &Sema) {
8258+
bool LosesInfo;
8259+
APFloat Dest = Src;
8260+
Dest.convert(Sema, APFloat::rmNearestTiesToEven, &LosesInfo);
8261+
return Dest;
8262+
};
8263+
8264+
auto NextValue = [](const APFloat &Value, bool RoundDown) {
8265+
APFloat NextValue = Value;
8266+
NextValue.next(RoundDown);
8267+
return NextValue;
8268+
};
8269+
8270+
APFloat NextCValue = NextValue(*CValue, RoundDown);
8271+
8272+
Type *DestType = FPTrunc.getOperand(0)->getType();
8273+
const fltSemantics &DestFltSema =
8274+
DestType->getScalarType()->getFltSemantics();
8275+
8276+
APFloat ExtCValue = ConvertFltSema(*CValue, DestFltSema);
8277+
APFloat ExtNextCValue = ConvertFltSema(NextCValue, DestFltSema);
8278+
8279+
// When 'NextCValue' is infinity, use an imaged 'NextCValue' that equals
8280+
// 'CValue + bias' to avoid the infinity after conversion. The bias is
8281+
// estimated as 'CValue - PrevCValue', where 'PrevCValue' is the previous
8282+
// value of 'CValue'.
8283+
if (NextCValue.isInfinity()) {
8284+
APFloat PrevCValue = NextValue(*CValue, !RoundDown);
8285+
APFloat Bias = ConvertFltSema(*CValue - PrevCValue, DestFltSema);
8286+
8287+
ExtNextCValue = ExtCValue + Bias;
8288+
}
8289+
8290+
APFloat ExtMidValue =
8291+
scalbn(ExtCValue + ExtNextCValue, -1, APFloat::rmNearestTiesToEven);
8292+
8293+
const fltSemantics &SrcFltSema =
8294+
C.getType()->getScalarType()->getFltSemantics();
8295+
8296+
// 'MidValue' might be rounded to 'NextCValue'. Correct it here.
8297+
APFloat MidValue = ConvertFltSema(ExtMidValue, SrcFltSema);
8298+
if (MidValue != *CValue)
8299+
ExtMidValue.next(!RoundDown);
8300+
8301+
// Check whether 'ExtMidValue' is a valid result since the assumption on
8302+
// imaged 'NextCValue' might not hold for new float types.
8303+
// ppc_fp128 can't pass here when converting from max float because of
8304+
// APFloat implementation.
8305+
if (NextCValue.isInfinity()) {
8306+
// ExtMidValue --- narrowed ---> Finite
8307+
if (ConvertFltSema(ExtMidValue, SrcFltSema).isInfinity())
8308+
return nullptr;
8309+
8310+
// NextExtMidValue --- narrowed ---> Infinity
8311+
APFloat NextExtMidValue = NextValue(ExtMidValue, RoundDown);
8312+
if (ConvertFltSema(NextExtMidValue, SrcFltSema).isFinite())
8313+
return nullptr;
8314+
}
8315+
8316+
return new FCmpInst(Pred, FPTrunc.getOperand(0),
8317+
ConstantFP::get(DestType, ExtMidValue), "", &I);
8318+
}
8319+
82258320
/// Optimize fabs(X) compared with zero.
82268321
static Instruction *foldFabsWithFcmpZero(FCmpInst &I, InstCombinerImpl &IC) {
82278322
Value *X;
@@ -8712,6 +8807,10 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
87128807
cast<LoadInst>(LHSI), GEP, GV, I))
87138808
return Res;
87148809
break;
8810+
case Instruction::FPTrunc:
8811+
if (Instruction *NV = foldFCmpFpTrunc(I, *LHSI, *RHSC))
8812+
return NV;
8813+
break;
87158814
}
87168815
}
87178816

0 commit comments

Comments
 (0)