InstCombineCompares.cpp [plain text]
#include "InstCombine.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/ConstantRange.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/PatternMatch.h"
using namespace llvm;
using namespace PatternMatch;
static Constant *AddOne(Constant *C) {
return ConstantExpr::getAdd(C, ConstantInt::get(C->getType(), 1));
}
static Constant *SubOne(ConstantInt *C) {
return ConstantExpr::getSub(C, ConstantInt::get(C->getType(), 1));
}
static ConstantInt *ExtractElement(Constant *V, Constant *Idx) {
return cast<ConstantInt>(ConstantExpr::getExtractElement(V, Idx));
}
static bool HasAddOverflow(ConstantInt *Result,
ConstantInt *In1, ConstantInt *In2,
bool IsSigned) {
if (IsSigned)
if (In2->getValue().isNegative())
return Result->getValue().sgt(In1->getValue());
else
return Result->getValue().slt(In1->getValue());
else
return Result->getValue().ult(In1->getValue());
}
static bool AddWithOverflow(Constant *&Result, Constant *In1,
Constant *In2, bool IsSigned = false) {
Result = ConstantExpr::getAdd(In1, In2);
if (const VectorType *VTy = dyn_cast<VectorType>(In1->getType())) {
for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) {
Constant *Idx = ConstantInt::get(Type::getInt32Ty(In1->getContext()), i);
if (HasAddOverflow(ExtractElement(Result, Idx),
ExtractElement(In1, Idx),
ExtractElement(In2, Idx),
IsSigned))
return true;
}
return false;
}
return HasAddOverflow(cast<ConstantInt>(Result),
cast<ConstantInt>(In1), cast<ConstantInt>(In2),
IsSigned);
}
static bool HasSubOverflow(ConstantInt *Result,
ConstantInt *In1, ConstantInt *In2,
bool IsSigned) {
if (IsSigned)
if (In2->getValue().isNegative())
return Result->getValue().slt(In1->getValue());
else
return Result->getValue().sgt(In1->getValue());
else
return Result->getValue().ugt(In1->getValue());
}
static bool SubWithOverflow(Constant *&Result, Constant *In1,
Constant *In2, bool IsSigned = false) {
Result = ConstantExpr::getSub(In1, In2);
if (const VectorType *VTy = dyn_cast<VectorType>(In1->getType())) {
for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) {
Constant *Idx = ConstantInt::get(Type::getInt32Ty(In1->getContext()), i);
if (HasSubOverflow(ExtractElement(Result, Idx),
ExtractElement(In1, Idx),
ExtractElement(In2, Idx),
IsSigned))
return true;
}
return false;
}
return HasSubOverflow(cast<ConstantInt>(Result),
cast<ConstantInt>(In1), cast<ConstantInt>(In2),
IsSigned);
}
static bool isSignBitCheck(ICmpInst::Predicate pred, ConstantInt *RHS,
bool &TrueIfSigned) {
switch (pred) {
case ICmpInst::ICMP_SLT: TrueIfSigned = true;
return RHS->isZero();
case ICmpInst::ICMP_SLE: TrueIfSigned = true;
return RHS->isAllOnesValue();
case ICmpInst::ICMP_SGT: TrueIfSigned = false;
return RHS->isAllOnesValue();
case ICmpInst::ICMP_UGT:
TrueIfSigned = true;
return RHS->getValue() ==
APInt::getSignedMaxValue(RHS->getType()->getPrimitiveSizeInBits());
case ICmpInst::ICMP_UGE:
TrueIfSigned = true;
return RHS->getValue().isSignBit();
default:
return false;
}
}
static bool isHighOnes(const ConstantInt *CI) {
return (~CI->getValue() + 1).isPowerOf2();
}
static void ComputeSignedMinMaxValuesFromKnownBits(const APInt& KnownZero,
const APInt& KnownOne,
APInt& Min, APInt& Max) {
assert(KnownZero.getBitWidth() == KnownOne.getBitWidth() &&
KnownZero.getBitWidth() == Min.getBitWidth() &&
KnownZero.getBitWidth() == Max.getBitWidth() &&
"KnownZero, KnownOne and Min, Max must have equal bitwidth.");
APInt UnknownBits = ~(KnownZero|KnownOne);
Min = KnownOne;
Max = KnownOne|UnknownBits;
if (UnknownBits.isNegative()) { Min.set(Min.getBitWidth()-1);
Max.clear(Max.getBitWidth()-1);
}
}
static void ComputeUnsignedMinMaxValuesFromKnownBits(const APInt &KnownZero,
const APInt &KnownOne,
APInt &Min, APInt &Max) {
assert(KnownZero.getBitWidth() == KnownOne.getBitWidth() &&
KnownZero.getBitWidth() == Min.getBitWidth() &&
KnownZero.getBitWidth() == Max.getBitWidth() &&
"Ty, KnownZero, KnownOne and Min, Max must have equal bitwidth.");
APInt UnknownBits = ~(KnownZero|KnownOne);
Min = KnownOne;
Max = KnownOne|UnknownBits;
}
Instruction *InstCombiner::
FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
CmpInst &ICI, ConstantInt *AndCst) {
if (!GEP->isInBounds() && TD == 0) return 0;
ConstantArray *Init = dyn_cast<ConstantArray>(GV->getInitializer());
if (Init == 0 || Init->getNumOperands() > 1024) return 0;
if (GEP->getNumOperands() < 3 ||
!isa<ConstantInt>(GEP->getOperand(1)) ||
!cast<ConstantInt>(GEP->getOperand(1))->isZero() ||
isa<Constant>(GEP->getOperand(2)))
return 0;
SmallVector<unsigned, 4> LaterIndices;
const Type *EltTy = cast<ArrayType>(Init->getType())->getElementType();
for (unsigned i = 3, e = GEP->getNumOperands(); i != e; ++i) {
ConstantInt *Idx = dyn_cast<ConstantInt>(GEP->getOperand(i));
if (Idx == 0) return 0;
uint64_t IdxVal = Idx->getZExtValue();
if ((unsigned)IdxVal != IdxVal) return 0;
if (const StructType *STy = dyn_cast<StructType>(EltTy))
EltTy = STy->getElementType(IdxVal);
else if (const ArrayType *ATy = dyn_cast<ArrayType>(EltTy)) {
if (IdxVal >= ATy->getNumElements()) return 0;
EltTy = ATy->getElementType();
} else {
return 0; }
LaterIndices.push_back(IdxVal);
}
enum { Overdefined = -3, Undefined = -2 };
int FirstTrueElement = Undefined, SecondTrueElement = Undefined;
int FirstFalseElement = Undefined, SecondFalseElement = Undefined;
int TrueRangeEnd = Undefined, FalseRangeEnd = Undefined;
uint64_t MagicBitvector = 0;
Constant *CompareRHS = cast<Constant>(ICI.getOperand(1));
for (unsigned i = 0, e = Init->getNumOperands(); i != e; ++i) {
Constant *Elt = Init->getOperand(i);
if (!LaterIndices.empty())
Elt = ConstantExpr::getExtractValue(Elt, LaterIndices.data(),
LaterIndices.size());
if (AndCst) Elt = ConstantExpr::getAnd(Elt, AndCst);
Constant *C = ConstantFoldCompareInstOperands(ICI.getPredicate(), Elt,
CompareRHS, TD);
if (isa<UndefValue>(C)) {
if (TrueRangeEnd == (int)i-1)
TrueRangeEnd = i;
if (FalseRangeEnd == (int)i-1)
FalseRangeEnd = i;
continue;
}
if (!isa<ConstantInt>(C)) return 0;
bool IsTrueForElt = !cast<ConstantInt>(C)->isZero();
if (IsTrueForElt) {
if (FirstTrueElement == Undefined)
FirstTrueElement = TrueRangeEnd = i; else {
if (SecondTrueElement == Undefined)
SecondTrueElement = i;
else
SecondTrueElement = Overdefined;
if (TrueRangeEnd == (int)i-1)
TrueRangeEnd = i;
else
TrueRangeEnd = Overdefined;
}
} else {
if (FirstFalseElement == Undefined)
FirstFalseElement = FalseRangeEnd = i; else {
if (SecondFalseElement == Undefined)
SecondFalseElement = i;
else
SecondFalseElement = Overdefined;
if (FalseRangeEnd == (int)i-1)
FalseRangeEnd = i;
else
FalseRangeEnd = Overdefined;
}
}
if (i < 64 && IsTrueForElt)
MagicBitvector |= 1ULL << i;
if ((i & 8) == 0 && i >= 64 && SecondTrueElement == Overdefined &&
SecondFalseElement == Overdefined && TrueRangeEnd == Overdefined &&
FalseRangeEnd == Overdefined)
return 0;
}
Value *Idx = GEP->getOperand(2);
if (!GEP->isInBounds() &&
Idx->getType()->getPrimitiveSizeInBits() > TD->getPointerSizeInBits())
Idx = Builder->CreateTrunc(Idx, TD->getIntPtrType(Idx->getContext()));
if (SecondTrueElement != Overdefined) {
if (FirstTrueElement == Undefined)
return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(GEP->getContext()));
Value *FirstTrueIdx = ConstantInt::get(Idx->getType(), FirstTrueElement);
if (SecondTrueElement == Undefined)
return new ICmpInst(ICmpInst::ICMP_EQ, Idx, FirstTrueIdx);
Value *C1 = Builder->CreateICmpEQ(Idx, FirstTrueIdx);
Value *SecondTrueIdx = ConstantInt::get(Idx->getType(), SecondTrueElement);
Value *C2 = Builder->CreateICmpEQ(Idx, SecondTrueIdx);
return BinaryOperator::CreateOr(C1, C2);
}
if (SecondFalseElement != Overdefined) {
if (FirstFalseElement == Undefined)
return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(GEP->getContext()));
Value *FirstFalseIdx = ConstantInt::get(Idx->getType(), FirstFalseElement);
if (SecondFalseElement == Undefined)
return new ICmpInst(ICmpInst::ICMP_NE, Idx, FirstFalseIdx);
Value *C1 = Builder->CreateICmpNE(Idx, FirstFalseIdx);
Value *SecondFalseIdx = ConstantInt::get(Idx->getType(),SecondFalseElement);
Value *C2 = Builder->CreateICmpNE(Idx, SecondFalseIdx);
return BinaryOperator::CreateAnd(C1, C2);
}
if (TrueRangeEnd != Overdefined) {
assert(TrueRangeEnd != FirstTrueElement && "Should emit single compare");
if (FirstTrueElement) {
Value *Offs = ConstantInt::get(Idx->getType(), -FirstTrueElement);
Idx = Builder->CreateAdd(Idx, Offs);
}
Value *End = ConstantInt::get(Idx->getType(),
TrueRangeEnd-FirstTrueElement+1);
return new ICmpInst(ICmpInst::ICMP_ULT, Idx, End);
}
if (FalseRangeEnd != Overdefined) {
assert(FalseRangeEnd != FirstFalseElement && "Should emit single compare");
if (FirstFalseElement) {
Value *Offs = ConstantInt::get(Idx->getType(), -FirstFalseElement);
Idx = Builder->CreateAdd(Idx, Offs);
}
Value *End = ConstantInt::get(Idx->getType(),
FalseRangeEnd-FirstFalseElement);
return new ICmpInst(ICmpInst::ICMP_UGT, Idx, End);
}
if (Init->getNumOperands() <= 32 ||
(TD && Init->getNumOperands() <= 64 && TD->isLegalInteger(64))) {
const Type *Ty;
if (Init->getNumOperands() <= 32)
Ty = Type::getInt32Ty(Init->getContext());
else
Ty = Type::getInt64Ty(Init->getContext());
Value *V = Builder->CreateIntCast(Idx, Ty, false);
V = Builder->CreateLShr(ConstantInt::get(Ty, MagicBitvector), V);
V = Builder->CreateAnd(ConstantInt::get(Ty, 1), V);
return new ICmpInst(ICmpInst::ICMP_NE, V, ConstantInt::get(Ty, 0));
}
return 0;
}
static Value *EvaluateGEPOffsetExpression(User *GEP, Instruction &I,
InstCombiner &IC) {
TargetData &TD = *IC.getTargetData();
gep_type_iterator GTI = gep_type_begin(GEP);
unsigned i, e = GEP->getNumOperands();
int64_t Offset = 0;
for (i = 1; i != e; ++i, ++GTI) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(GEP->getOperand(i))) {
if (CI->isZero()) continue;
if (const StructType *STy = dyn_cast<StructType>(*GTI)) {
Offset += TD.getStructLayout(STy)->getElementOffset(CI->getZExtValue());
} else {
uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType());
Offset += Size*CI->getSExtValue();
}
} else {
break;
}
}
if (i == e) return 0;
Value *VariableIdx = GEP->getOperand(i);
uint64_t VariableScale = TD.getTypeAllocSize(GTI.getIndexedType());
for (++i, ++GTI; i != e; ++i, ++GTI) {
ConstantInt *CI = dyn_cast<ConstantInt>(GEP->getOperand(i));
if (!CI) return 0;
if (CI->isZero()) continue;
if (const StructType *STy = dyn_cast<StructType>(*GTI)) {
Offset += TD.getStructLayout(STy)->getElementOffset(CI->getZExtValue());
} else {
uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType());
Offset += Size*CI->getSExtValue();
}
}
unsigned IntPtrWidth = TD.getPointerSizeInBits();
if (Offset == 0) {
if (VariableIdx->getType()->getPrimitiveSizeInBits() > IntPtrWidth)
VariableIdx = new TruncInst(VariableIdx,
TD.getIntPtrType(VariableIdx->getContext()),
VariableIdx->getName(), &I);
return VariableIdx;
}
uint64_t PtrSizeMask = ~0ULL >> (64-IntPtrWidth);
Offset &= PtrSizeMask;
VariableScale &= PtrSizeMask;
int64_t NewOffs = Offset / (int64_t)VariableScale;
if (Offset != NewOffs*(int64_t)VariableScale)
return 0;
const Type *IntPtrTy = TD.getIntPtrType(VariableIdx->getContext());
if (VariableIdx->getType() != IntPtrTy)
VariableIdx = CastInst::CreateIntegerCast(VariableIdx, IntPtrTy,
true ,
VariableIdx->getName(), &I);
Constant *OffsetVal = ConstantInt::get(IntPtrTy, NewOffs);
return BinaryOperator::CreateAdd(VariableIdx, OffsetVal, "offset", &I);
}
Instruction *InstCombiner::FoldGEPICmp(GEPOperator *GEPLHS, Value *RHS,
ICmpInst::Predicate Cond,
Instruction &I) {
if (BitCastInst *BCI = dyn_cast<BitCastInst>(RHS))
RHS = BCI->getOperand(0);
Value *PtrBase = GEPLHS->getOperand(0);
if (TD && PtrBase == RHS && GEPLHS->isInBounds()) {
Value *Offset = EvaluateGEPOffsetExpression(GEPLHS, I, *this);
if (Offset == 0)
Offset = EmitGEPOffset(GEPLHS);
return new ICmpInst(ICmpInst::getSignedPredicate(Cond), Offset,
Constant::getNullValue(Offset->getType()));
} else if (GEPOperator *GEPRHS = dyn_cast<GEPOperator>(RHS)) {
if (PtrBase != GEPRHS->getOperand(0)) {
bool IndicesTheSame = GEPLHS->getNumOperands()==GEPRHS->getNumOperands();
IndicesTheSame &= GEPLHS->getOperand(0)->getType() ==
GEPRHS->getOperand(0)->getType();
if (IndicesTheSame)
for (unsigned i = 1, e = GEPLHS->getNumOperands(); i != e; ++i)
if (GEPLHS->getOperand(i) != GEPRHS->getOperand(i)) {
IndicesTheSame = false;
break;
}
if (IndicesTheSame)
return new ICmpInst(ICmpInst::getSignedPredicate(Cond),
GEPLHS->getOperand(0), GEPRHS->getOperand(0));
return 0;
}
bool AllZeros = true;
for (unsigned i = 1, e = GEPLHS->getNumOperands(); i != e; ++i)
if (!isa<Constant>(GEPLHS->getOperand(i)) ||
!cast<Constant>(GEPLHS->getOperand(i))->isNullValue()) {
AllZeros = false;
break;
}
if (AllZeros)
return FoldGEPICmp(GEPRHS, GEPLHS->getOperand(0),
ICmpInst::getSwappedPredicate(Cond), I);
AllZeros = true;
for (unsigned i = 1, e = GEPRHS->getNumOperands(); i != e; ++i)
if (!isa<Constant>(GEPRHS->getOperand(i)) ||
!cast<Constant>(GEPRHS->getOperand(i))->isNullValue()) {
AllZeros = false;
break;
}
if (AllZeros)
return FoldGEPICmp(GEPLHS, GEPRHS->getOperand(0), Cond, I);
if (GEPLHS->getNumOperands() == GEPRHS->getNumOperands()) {
unsigned NumDifferences = 0; unsigned DiffOperand = 0; for (unsigned i = 1, e = GEPRHS->getNumOperands(); i != e; ++i)
if (GEPLHS->getOperand(i) != GEPRHS->getOperand(i)) {
if (GEPLHS->getOperand(i)->getType()->getPrimitiveSizeInBits() !=
GEPRHS->getOperand(i)->getType()->getPrimitiveSizeInBits()) {
NumDifferences = 2;
break;
} else {
if (NumDifferences++) break;
DiffOperand = i;
}
}
if (NumDifferences == 0) return ReplaceInstUsesWith(I, ConstantInt::get(Type::getInt1Ty(I.getContext()),
ICmpInst::isTrueWhenEqual(Cond)));
else if (NumDifferences == 1) {
Value *LHSV = GEPLHS->getOperand(DiffOperand);
Value *RHSV = GEPRHS->getOperand(DiffOperand);
return new ICmpInst(ICmpInst::getSignedPredicate(Cond), LHSV, RHSV);
}
}
if (TD &&
(isa<ConstantExpr>(GEPLHS) || GEPLHS->hasOneUse()) &&
(isa<ConstantExpr>(GEPRHS) || GEPRHS->hasOneUse())) {
Value *L = EmitGEPOffset(GEPLHS);
Value *R = EmitGEPOffset(GEPRHS);
return new ICmpInst(ICmpInst::getSignedPredicate(Cond), L, R);
}
}
return 0;
}
Instruction *InstCombiner::FoldICmpAddOpCst(ICmpInst &ICI,
Value *X, ConstantInt *CI,
ICmpInst::Predicate Pred,
Value *TheAdd) {
if (CI->isZero()) {
bool isTrue = ICmpInst::isTrueWhenEqual(Pred);
return ReplaceInstUsesWith(ICI, ConstantInt::get(ICI.getType(), isTrue));
}
if (Pred == ICmpInst::ICMP_EQ)
return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(X->getContext()));
if (Pred == ICmpInst::ICMP_NE)
return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(X->getContext()));
bool isNUW = false, isNSW = false;
if (BinaryOperator *Add = dyn_cast<BinaryOperator>(TheAdd)) {
isNUW = Add->hasNoUnsignedWrap();
isNSW = Add->hasNoSignedWrap();
}
if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_ULE) {
if (isNUW)
return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(X->getContext()));
Value *R =
ConstantExpr::getSub(ConstantInt::getAllOnesValue(CI->getType()), CI);
return new ICmpInst(ICmpInst::ICMP_UGT, X, R);
}
if (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_UGE) {
if (isNUW)
return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(X->getContext()));
return new ICmpInst(ICmpInst::ICMP_ULT, X, ConstantExpr::getNeg(CI));
}
unsigned BitWidth = CI->getType()->getPrimitiveSizeInBits();
ConstantInt *SMax = ConstantInt::get(X->getContext(),
APInt::getSignedMaxValue(BitWidth));
if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SLE) {
if (isNSW) {
bool isTrue = CI->getValue().isNegative();
return ReplaceInstUsesWith(ICI, ConstantInt::get(ICI.getType(), isTrue));
}
return new ICmpInst(ICmpInst::ICMP_SGT, X, ConstantExpr::getSub(SMax, CI));
}
if (isNSW) {
bool isTrue = !CI->getValue().isNegative();
return ReplaceInstUsesWith(ICI, ConstantInt::get(ICI.getType(), isTrue));
}
assert(Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE);
Constant *C = ConstantInt::get(X->getContext(), CI->getValue()-1);
return new ICmpInst(ICmpInst::ICMP_SLT, X, ConstantExpr::getSub(SMax, C));
}
Instruction *InstCombiner::FoldICmpDivCst(ICmpInst &ICI, BinaryOperator *DivI,
ConstantInt *DivRHS) {
ConstantInt *CmpRHS = cast<ConstantInt>(ICI.getOperand(1));
const APInt &CmpRHSV = CmpRHS->getValue();
bool DivIsSigned = DivI->getOpcode() == Instruction::SDiv;
if (!ICI.isEquality() && DivIsSigned != ICI.isSigned())
return 0;
if (DivRHS->isZero())
return 0; if (DivIsSigned && DivRHS->isAllOnesValue())
return 0; if (DivRHS->isOne())
return 0;
Constant *Prod = ConstantExpr::getMul(CmpRHS, DivRHS);
bool ProdOV = (DivIsSigned ? ConstantExpr::getSDiv(Prod, DivRHS) :
ConstantExpr::getUDiv(Prod, DivRHS)) != CmpRHS;
ICmpInst::Predicate Pred = ICI.getPredicate();
int LoOverflow = 0, HiOverflow = 0;
Constant *LoBound = 0, *HiBound = 0;
if (!DivIsSigned) { LoBound = Prod;
HiOverflow = LoOverflow = ProdOV;
if (!HiOverflow)
HiOverflow = AddWithOverflow(HiBound, LoBound, DivRHS, false);
} else if (DivRHS->getValue().isStrictlyPositive()) { if (CmpRHSV == 0) { LoBound = cast<ConstantInt>(ConstantExpr::getNeg(SubOne(DivRHS)));
HiBound = DivRHS;
} else if (CmpRHSV.isStrictlyPositive()) { LoBound = Prod; HiOverflow = LoOverflow = ProdOV;
if (!HiOverflow)
HiOverflow = AddWithOverflow(HiBound, Prod, DivRHS, true);
} else { HiBound = AddOne(Prod);
LoOverflow = HiOverflow = ProdOV ? -1 : 0;
if (!LoOverflow) {
ConstantInt* DivNeg =
cast<ConstantInt>(ConstantExpr::getNeg(DivRHS));
LoOverflow = AddWithOverflow(LoBound, HiBound, DivNeg, true) ? -1 : 0;
}
}
} else if (DivRHS->getValue().isNegative()) { if (CmpRHSV == 0) { LoBound = AddOne(DivRHS);
HiBound = cast<ConstantInt>(ConstantExpr::getNeg(DivRHS));
if (HiBound == DivRHS) { HiOverflow = 1; HiBound = 0; }
} else if (CmpRHSV.isStrictlyPositive()) { HiBound = AddOne(Prod);
HiOverflow = LoOverflow = ProdOV ? -1 : 0;
if (!LoOverflow)
LoOverflow = AddWithOverflow(LoBound, HiBound, DivRHS, true) ? -1 : 0;
} else { LoBound = Prod; LoOverflow = HiOverflow = ProdOV;
if (!HiOverflow)
HiOverflow = SubWithOverflow(HiBound, Prod, DivRHS, true);
}
Pred = ICmpInst::getSwappedPredicate(Pred);
}
Value *X = DivI->getOperand(0);
switch (Pred) {
default: llvm_unreachable("Unhandled icmp opcode!");
case ICmpInst::ICMP_EQ:
if (LoOverflow && HiOverflow)
return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(ICI.getContext()));
if (HiOverflow)
return new ICmpInst(DivIsSigned ? ICmpInst::ICMP_SGE :
ICmpInst::ICMP_UGE, X, LoBound);
if (LoOverflow)
return new ICmpInst(DivIsSigned ? ICmpInst::ICMP_SLT :
ICmpInst::ICMP_ULT, X, HiBound);
return ReplaceInstUsesWith(ICI,
InsertRangeTest(X, LoBound, HiBound, DivIsSigned,
true));
case ICmpInst::ICMP_NE:
if (LoOverflow && HiOverflow)
return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(ICI.getContext()));
if (HiOverflow)
return new ICmpInst(DivIsSigned ? ICmpInst::ICMP_SLT :
ICmpInst::ICMP_ULT, X, LoBound);
if (LoOverflow)
return new ICmpInst(DivIsSigned ? ICmpInst::ICMP_SGE :
ICmpInst::ICMP_UGE, X, HiBound);
return ReplaceInstUsesWith(ICI, InsertRangeTest(X, LoBound, HiBound,
DivIsSigned, false));
case ICmpInst::ICMP_ULT:
case ICmpInst::ICMP_SLT:
if (LoOverflow == +1) return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(ICI.getContext()));
if (LoOverflow == -1) return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(ICI.getContext()));
return new ICmpInst(Pred, X, LoBound);
case ICmpInst::ICMP_UGT:
case ICmpInst::ICMP_SGT:
if (HiOverflow == +1) return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(ICI.getContext()));
else if (HiOverflow == -1) return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(ICI.getContext()));
if (Pred == ICmpInst::ICMP_UGT)
return new ICmpInst(ICmpInst::ICMP_UGE, X, HiBound);
else
return new ICmpInst(ICmpInst::ICMP_SGE, X, HiBound);
}
}
Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
Instruction *LHSI,
ConstantInt *RHS) {
const APInt &RHSV = RHS->getValue();
switch (LHSI->getOpcode()) {
case Instruction::Trunc:
if (ICI.isEquality() && LHSI->hasOneUse()) {
unsigned DstBits = LHSI->getType()->getPrimitiveSizeInBits(),
SrcBits = LHSI->getOperand(0)->getType()->getPrimitiveSizeInBits();
APInt Mask(APInt::getHighBitsSet(SrcBits, SrcBits-DstBits));
APInt KnownZero(SrcBits, 0), KnownOne(SrcBits, 0);
ComputeMaskedBits(LHSI->getOperand(0), Mask, KnownZero, KnownOne);
if ((KnownZero|KnownOne).countLeadingOnes() >= SrcBits-DstBits) {
APInt NewRHS(RHS->getValue());
NewRHS.zext(SrcBits);
NewRHS |= KnownOne;
return new ICmpInst(ICI.getPredicate(), LHSI->getOperand(0),
ConstantInt::get(ICI.getContext(), NewRHS));
}
}
break;
case Instruction::Xor: if (ConstantInt *XorCST = dyn_cast<ConstantInt>(LHSI->getOperand(1))) {
if ((ICI.getPredicate() == ICmpInst::ICMP_SLT && RHSV == 0) ||
(ICI.getPredicate() == ICmpInst::ICMP_SGT && RHSV.isAllOnesValue())) {
Value *CompareVal = LHSI->getOperand(0);
if (!XorCST->getValue().isNegative()) {
ICI.setOperand(0, CompareVal);
Worklist.Add(LHSI);
return &ICI;
}
bool isTrueIfPositive = ICI.getPredicate() == ICmpInst::ICMP_SGT;
isTrueIfPositive ^= true;
if (isTrueIfPositive)
return new ICmpInst(ICmpInst::ICMP_SGT, CompareVal,
SubOne(RHS));
else
return new ICmpInst(ICmpInst::ICMP_SLT, CompareVal,
AddOne(RHS));
}
if (LHSI->hasOneUse()) {
if (!ICI.isEquality() && XorCST->getValue().isSignBit()) {
const APInt &SignBit = XorCST->getValue();
ICmpInst::Predicate Pred = ICI.isSigned()
? ICI.getUnsignedPredicate()
: ICI.getSignedPredicate();
return new ICmpInst(Pred, LHSI->getOperand(0),
ConstantInt::get(ICI.getContext(),
RHSV ^ SignBit));
}
if (!ICI.isEquality() && XorCST->getValue().isMaxSignedValue()) {
const APInt &NotSignBit = XorCST->getValue();
ICmpInst::Predicate Pred = ICI.isSigned()
? ICI.getUnsignedPredicate()
: ICI.getSignedPredicate();
Pred = ICI.getSwappedPredicate(Pred);
return new ICmpInst(Pred, LHSI->getOperand(0),
ConstantInt::get(ICI.getContext(),
RHSV ^ NotSignBit));
}
}
}
break;
case Instruction::And: if (LHSI->hasOneUse() && isa<ConstantInt>(LHSI->getOperand(1)) &&
LHSI->getOperand(0)->hasOneUse()) {
ConstantInt *AndCST = cast<ConstantInt>(LHSI->getOperand(1));
if (TruncInst *Cast = dyn_cast<TruncInst>(LHSI->getOperand(0))) {
if (Cast->hasOneUse() &&
(ICI.isEquality() ||
(AndCST->getValue().isNonNegative() && RHSV.isNonNegative()))) {
uint32_t BitWidth =
cast<IntegerType>(Cast->getOperand(0)->getType())->getBitWidth();
APInt NewCST = AndCST->getValue();
NewCST.zext(BitWidth);
APInt NewCI = RHSV;
NewCI.zext(BitWidth);
Value *NewAnd =
Builder->CreateAnd(Cast->getOperand(0),
ConstantInt::get(ICI.getContext(), NewCST),
LHSI->getName());
return new ICmpInst(ICI.getPredicate(), NewAnd,
ConstantInt::get(ICI.getContext(), NewCI));
}
}
BinaryOperator *Shift = dyn_cast<BinaryOperator>(LHSI->getOperand(0));
if (Shift && !Shift->isShift())
Shift = 0;
ConstantInt *ShAmt;
ShAmt = Shift ? dyn_cast<ConstantInt>(Shift->getOperand(1)) : 0;
const Type *Ty = Shift ? Shift->getType() : 0; const Type *AndTy = AndCST->getType();
if (ShAmt) {
bool CanFold = Shift->isLogicalShift();
if (!CanFold) {
uint32_t TyBits = Ty->getPrimitiveSizeInBits();
int ShAmtVal = TyBits - ShAmt->getLimitedValue(TyBits);
uint32_t BitWidth = AndTy->getPrimitiveSizeInBits();
if ((APInt::getHighBitsSet(BitWidth, BitWidth-ShAmtVal) &
AndCST->getValue()) == 0)
CanFold = true;
}
if (CanFold) {
Constant *NewCst;
if (Shift->getOpcode() == Instruction::Shl)
NewCst = ConstantExpr::getLShr(RHS, ShAmt);
else
NewCst = ConstantExpr::getShl(RHS, ShAmt);
if (ConstantExpr::get(Shift->getOpcode(),
NewCst, ShAmt) != RHS) {
if (ICI.getPredicate() == ICmpInst::ICMP_EQ)
return ReplaceInstUsesWith(ICI,
ConstantInt::getFalse(ICI.getContext()));
if (ICI.getPredicate() == ICmpInst::ICMP_NE)
return ReplaceInstUsesWith(ICI,
ConstantInt::getTrue(ICI.getContext()));
} else {
ICI.setOperand(1, NewCst);
Constant *NewAndCST;
if (Shift->getOpcode() == Instruction::Shl)
NewAndCST = ConstantExpr::getLShr(AndCST, ShAmt);
else
NewAndCST = ConstantExpr::getShl(AndCST, ShAmt);
LHSI->setOperand(1, NewAndCST);
LHSI->setOperand(0, Shift->getOperand(0));
Worklist.Add(Shift); return &ICI;
}
}
}
if (Shift && Shift->hasOneUse() && RHSV == 0 &&
ICI.isEquality() && !Shift->isArithmeticShift() &&
!isa<Constant>(Shift->getOperand(0))) {
Value *NS;
if (Shift->getOpcode() == Instruction::LShr) {
NS = Builder->CreateShl(AndCST, Shift->getOperand(1), "tmp");
} else {
NS = Builder->CreateLShr(AndCST, Shift->getOperand(1), "tmp");
}
Value *NewAnd =
Builder->CreateAnd(Shift->getOperand(0), NS, LHSI->getName());
ICI.setOperand(0, NewAnd);
return &ICI;
}
}
if (LoadInst *LI = dyn_cast<LoadInst>(LHSI->getOperand(0))) {
if (GetElementPtrInst *GEP =
dyn_cast<GetElementPtrInst>(LI->getOperand(0)))
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)))
if (GV->isConstant() && GV->hasDefinitiveInitializer() &&
!LI->isVolatile() && isa<ConstantInt>(LHSI->getOperand(1))) {
ConstantInt *C = cast<ConstantInt>(LHSI->getOperand(1));
if (Instruction *Res = FoldCmpLoadFromIndexedGlobal(GEP, GV,ICI, C))
return Res;
}
}
break;
case Instruction::Or: {
if (!ICI.isEquality() || !RHS->isNullValue() || !LHSI->hasOneUse())
break;
Value *P, *Q;
if (match(LHSI, m_Or(m_PtrToInt(m_Value(P)), m_PtrToInt(m_Value(Q))))) {
Value *ICIP = Builder->CreateICmp(ICI.getPredicate(), P,
Constant::getNullValue(P->getType()));
Value *ICIQ = Builder->CreateICmp(ICI.getPredicate(), Q,
Constant::getNullValue(Q->getType()));
Instruction *Op;
if (ICI.getPredicate() == ICmpInst::ICMP_EQ)
Op = BinaryOperator::CreateAnd(ICIP, ICIQ);
else
Op = BinaryOperator::CreateOr(ICIP, ICIQ);
return Op;
}
break;
}
case Instruction::Shl: { ConstantInt *ShAmt = dyn_cast<ConstantInt>(LHSI->getOperand(1));
if (!ShAmt) break;
uint32_t TypeBits = RHSV.getBitWidth();
if (ShAmt->uge(TypeBits))
break;
if (ICI.isEquality()) {
Constant *Comp =
ConstantExpr::getShl(ConstantExpr::getLShr(RHS, ShAmt),
ShAmt);
if (Comp != RHS) { bool IsICMP_NE = ICI.getPredicate() == ICmpInst::ICMP_NE;
Constant *Cst =
ConstantInt::get(Type::getInt1Ty(ICI.getContext()), IsICMP_NE);
return ReplaceInstUsesWith(ICI, Cst);
}
if (LHSI->hasOneUse()) {
uint32_t ShAmtVal = (uint32_t)ShAmt->getLimitedValue(TypeBits);
Constant *Mask =
ConstantInt::get(ICI.getContext(), APInt::getLowBitsSet(TypeBits,
TypeBits-ShAmtVal));
Value *And =
Builder->CreateAnd(LHSI->getOperand(0),Mask, LHSI->getName()+".mask");
return new ICmpInst(ICI.getPredicate(), And,
ConstantInt::get(ICI.getContext(),
RHSV.lshr(ShAmtVal)));
}
}
bool TrueIfSigned = false;
if (LHSI->hasOneUse() &&
isSignBitCheck(ICI.getPredicate(), RHS, TrueIfSigned)) {
Constant *Mask = ConstantInt::get(ICI.getContext(), APInt(TypeBits, 1) <<
(TypeBits-ShAmt->getZExtValue()-1));
Value *And =
Builder->CreateAnd(LHSI->getOperand(0), Mask, LHSI->getName()+".mask");
return new ICmpInst(TrueIfSigned ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ,
And, Constant::getNullValue(And->getType()));
}
break;
}
case Instruction::LShr: case Instruction::AShr: {
ConstantInt *ShAmt = dyn_cast<ConstantInt>(LHSI->getOperand(1));
if (!ShAmt || !ICI.isEquality()) break;
uint32_t TypeBits = RHSV.getBitWidth();
if (ShAmt->uge(TypeBits))
break;
uint32_t ShAmtVal = (uint32_t)ShAmt->getLimitedValue(TypeBits);
APInt Comp = RHSV << ShAmtVal;
if (LHSI->getOpcode() == Instruction::LShr)
Comp = Comp.lshr(ShAmtVal);
else
Comp = Comp.ashr(ShAmtVal);
if (Comp != RHSV) { bool IsICMP_NE = ICI.getPredicate() == ICmpInst::ICMP_NE;
Constant *Cst = ConstantInt::get(Type::getInt1Ty(ICI.getContext()),
IsICMP_NE);
return ReplaceInstUsesWith(ICI, Cst);
}
if (LHSI->hasOneUse() &&
MaskedValueIsZero(LHSI->getOperand(0),
APInt::getLowBitsSet(Comp.getBitWidth(), ShAmtVal))) {
return new ICmpInst(ICI.getPredicate(), LHSI->getOperand(0),
ConstantExpr::getShl(RHS, ShAmt));
}
if (LHSI->hasOneUse()) {
APInt Val(APInt::getHighBitsSet(TypeBits, TypeBits - ShAmtVal));
Constant *Mask = ConstantInt::get(ICI.getContext(), Val);
Value *And = Builder->CreateAnd(LHSI->getOperand(0),
Mask, LHSI->getName()+".mask");
return new ICmpInst(ICI.getPredicate(), And,
ConstantExpr::getShl(RHS, ShAmt));
}
break;
}
case Instruction::SDiv:
case Instruction::UDiv:
if (ConstantInt *DivRHS = dyn_cast<ConstantInt>(LHSI->getOperand(1)))
if (Instruction *R = FoldICmpDivCst(ICI, cast<BinaryOperator>(LHSI),
DivRHS))
return R;
break;
case Instruction::Add:
if (!ICI.isEquality()) {
ConstantInt *LHSC = dyn_cast<ConstantInt>(LHSI->getOperand(1));
if (!LHSC) break;
const APInt &LHSV = LHSC->getValue();
ConstantRange CR = ICI.makeConstantRange(ICI.getPredicate(), RHSV)
.subtract(LHSV);
if (ICI.isSigned()) {
if (CR.getLower().isSignBit()) {
return new ICmpInst(ICmpInst::ICMP_SLT, LHSI->getOperand(0),
ConstantInt::get(ICI.getContext(),CR.getUpper()));
} else if (CR.getUpper().isSignBit()) {
return new ICmpInst(ICmpInst::ICMP_SGE, LHSI->getOperand(0),
ConstantInt::get(ICI.getContext(),CR.getLower()));
}
} else {
if (CR.getLower().isMinValue()) {
return new ICmpInst(ICmpInst::ICMP_ULT, LHSI->getOperand(0),
ConstantInt::get(ICI.getContext(),CR.getUpper()));
} else if (CR.getUpper().isMinValue()) {
return new ICmpInst(ICmpInst::ICMP_UGE, LHSI->getOperand(0),
ConstantInt::get(ICI.getContext(),CR.getLower()));
}
}
}
break;
}
if (ICI.isEquality()) {
bool isICMP_NE = ICI.getPredicate() == ICmpInst::ICMP_NE;
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(LHSI)) {
switch (BO->getOpcode()) {
case Instruction::SRem:
if (RHSV == 0 && isa<ConstantInt>(BO->getOperand(1)) &&BO->hasOneUse()){
const APInt &V = cast<ConstantInt>(BO->getOperand(1))->getValue();
if (V.sgt(1) && V.isPowerOf2()) {
Value *NewRem =
Builder->CreateURem(BO->getOperand(0), BO->getOperand(1),
BO->getName());
return new ICmpInst(ICI.getPredicate(), NewRem,
Constant::getNullValue(BO->getType()));
}
}
break;
case Instruction::Add:
if (ConstantInt *BOp1C = dyn_cast<ConstantInt>(BO->getOperand(1))) {
if (BO->hasOneUse())
return new ICmpInst(ICI.getPredicate(), BO->getOperand(0),
ConstantExpr::getSub(RHS, BOp1C));
} else if (RHSV == 0) {
Value *BOp0 = BO->getOperand(0), *BOp1 = BO->getOperand(1);
if (Value *NegVal = dyn_castNegVal(BOp1))
return new ICmpInst(ICI.getPredicate(), BOp0, NegVal);
else if (Value *NegVal = dyn_castNegVal(BOp0))
return new ICmpInst(ICI.getPredicate(), NegVal, BOp1);
else if (BO->hasOneUse()) {
Value *Neg = Builder->CreateNeg(BOp1);
Neg->takeName(BO);
return new ICmpInst(ICI.getPredicate(), BOp0, Neg);
}
}
break;
case Instruction::Xor:
if (Constant *BOC = dyn_cast<Constant>(BO->getOperand(1)))
return new ICmpInst(ICI.getPredicate(), BO->getOperand(0),
ConstantExpr::getXor(RHS, BOC));
case Instruction::Sub:
if (RHSV == 0)
return new ICmpInst(ICI.getPredicate(), BO->getOperand(0),
BO->getOperand(1));
break;
case Instruction::Or:
if (ConstantInt *BOC = dyn_cast<ConstantInt>(BO->getOperand(1))) {
Constant *NotCI = ConstantExpr::getNot(RHS);
if (!ConstantExpr::getAnd(BOC, NotCI)->isNullValue())
return ReplaceInstUsesWith(ICI,
ConstantInt::get(Type::getInt1Ty(ICI.getContext()),
isICMP_NE));
}
break;
case Instruction::And:
if (ConstantInt *BOC = dyn_cast<ConstantInt>(BO->getOperand(1))) {
if ((RHSV & ~BOC->getValue()) != 0)
return ReplaceInstUsesWith(ICI,
ConstantInt::get(Type::getInt1Ty(ICI.getContext()),
isICMP_NE));
if (RHS == BOC && RHSV.isPowerOf2())
return new ICmpInst(isICMP_NE ? ICmpInst::ICMP_EQ :
ICmpInst::ICMP_NE, LHSI,
Constant::getNullValue(RHS->getType()));
if (BOC->getValue().isSignBit()) {
Value *X = BO->getOperand(0);
Constant *Zero = Constant::getNullValue(X->getType());
ICmpInst::Predicate pred = isICMP_NE ?
ICmpInst::ICMP_SLT : ICmpInst::ICMP_SGE;
return new ICmpInst(pred, X, Zero);
}
if (RHSV == 0 && isHighOnes(BOC)) {
Value *X = BO->getOperand(0);
Constant *NegX = ConstantExpr::getNeg(BOC);
ICmpInst::Predicate pred = isICMP_NE ?
ICmpInst::ICMP_UGE : ICmpInst::ICMP_ULT;
return new ICmpInst(pred, X, NegX);
}
}
default: break;
}
} else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(LHSI)) {
switch (II->getIntrinsicID()) {
case Intrinsic::bswap:
Worklist.Add(II);
ICI.setOperand(0, II->getArgOperand(0));
ICI.setOperand(1, ConstantInt::get(II->getContext(), RHSV.byteSwap()));
return &ICI;
case Intrinsic::ctlz:
case Intrinsic::cttz:
if (RHSV == RHS->getType()->getBitWidth()) {
Worklist.Add(II);
ICI.setOperand(0, II->getArgOperand(0));
ICI.setOperand(1, ConstantInt::get(RHS->getType(), 0));
return &ICI;
}
break;
case Intrinsic::ctpop:
if (RHS->isZero()) {
Worklist.Add(II);
ICI.setOperand(0, II->getArgOperand(0));
ICI.setOperand(1, RHS);
return &ICI;
}
break;
default:
break;
}
}
}
return 0;
}
Instruction *InstCombiner::visitICmpInstWithCastAndCast(ICmpInst &ICI) {
const CastInst *LHSCI = cast<CastInst>(ICI.getOperand(0));
Value *LHSCIOp = LHSCI->getOperand(0);
const Type *SrcTy = LHSCIOp->getType();
const Type *DestTy = LHSCI->getType();
Value *RHSCIOp;
if (TD && LHSCI->getOpcode() == Instruction::PtrToInt &&
TD->getPointerSizeInBits() ==
cast<IntegerType>(DestTy)->getBitWidth()) {
Value *RHSOp = 0;
if (Constant *RHSC = dyn_cast<Constant>(ICI.getOperand(1))) {
RHSOp = ConstantExpr::getIntToPtr(RHSC, SrcTy);
} else if (PtrToIntInst *RHSC = dyn_cast<PtrToIntInst>(ICI.getOperand(1))) {
RHSOp = RHSC->getOperand(0);
if (LHSCIOp->getType() != RHSOp->getType())
RHSOp = Builder->CreateBitCast(RHSOp, LHSCIOp->getType());
}
if (RHSOp)
return new ICmpInst(ICI.getPredicate(), LHSCIOp, RHSOp);
}
if (LHSCI->getOpcode() != Instruction::ZExt &&
LHSCI->getOpcode() != Instruction::SExt)
return 0;
bool isSignedExt = LHSCI->getOpcode() == Instruction::SExt;
bool isSignedCmp = ICI.isSigned();
if (CastInst *CI = dyn_cast<CastInst>(ICI.getOperand(1))) {
RHSCIOp = CI->getOperand(0);
if (RHSCIOp->getType() != LHSCIOp->getType())
return 0;
if (CI->getOpcode() != LHSCI->getOpcode())
return 0;
if (ICI.isEquality())
return new ICmpInst(ICI.getPredicate(), LHSCIOp, RHSCIOp);
if (isSignedCmp && isSignedExt)
return new ICmpInst(ICI.getPredicate(), LHSCIOp, RHSCIOp);
return new ICmpInst(ICI.getUnsignedPredicate(), LHSCIOp, RHSCIOp);
}
ConstantInt *CI = dyn_cast<ConstantInt>(ICI.getOperand(1));
if (!CI)
return 0;
Constant *Res1 = ConstantExpr::getTrunc(CI, SrcTy);
Constant *Res2 = ConstantExpr::getCast(LHSCI->getOpcode(),
Res1, DestTy);
if (Res2 == CI) {
if (ICI.isEquality())
return new ICmpInst(ICI.getPredicate(), LHSCIOp, Res1);
if (isSignedExt && isSignedCmp)
return new ICmpInst(ICI.getPredicate(), LHSCIOp, Res1);
return new ICmpInst(ICI.getUnsignedPredicate(), LHSCIOp, Res1);
}
if (ICI.getPredicate() == ICmpInst::ICMP_EQ)
return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(ICI.getContext()));
if (ICI.getPredicate() == ICmpInst::ICMP_NE)
return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(ICI.getContext()));
Value *Result;
if (isSignedCmp) {
if (cast<ConstantInt>(CI)->getValue().isNegative())
Result = ConstantInt::getFalse(ICI.getContext()); else
Result = ConstantInt::getTrue(ICI.getContext()); } else {
if (isSignedExt) {
Constant *NegOne = Constant::getAllOnesValue(SrcTy);
Result = Builder->CreateICmpSGT(LHSCIOp, NegOne, ICI.getName());
} else {
Result = ConstantInt::getTrue(ICI.getContext());
}
}
if (ICI.getPredicate() == ICmpInst::ICMP_ULT ||
ICI.getPredicate() == ICmpInst::ICMP_SLT)
return ReplaceInstUsesWith(ICI, Result);
assert((ICI.getPredicate()==ICmpInst::ICMP_UGT ||
ICI.getPredicate()==ICmpInst::ICMP_SGT) &&
"ICmp should be folded!");
if (Constant *CI = dyn_cast<Constant>(Result))
return ReplaceInstUsesWith(ICI, ConstantExpr::getNot(CI));
return BinaryOperator::CreateNot(Result);
}
Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
bool Changed = false;
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
if (getComplexity(Op0) < getComplexity(Op1)) {
I.swapOperands();
std::swap(Op0, Op1);
Changed = true;
}
if (Value *V = SimplifyICmpInst(I.getPredicate(), Op0, Op1, TD))
return ReplaceInstUsesWith(I, V);
const Type *Ty = Op0->getType();
if (Ty->isIntegerTy(1)) {
switch (I.getPredicate()) {
default: llvm_unreachable("Invalid icmp instruction!");
case ICmpInst::ICMP_EQ: { Value *Xor = Builder->CreateXor(Op0, Op1, I.getName()+"tmp");
return BinaryOperator::CreateNot(Xor);
}
case ICmpInst::ICMP_NE: return BinaryOperator::CreateXor(Op0, Op1);
case ICmpInst::ICMP_UGT:
std::swap(Op0, Op1); case ICmpInst::ICMP_ULT:{ Value *Not = Builder->CreateNot(Op0, I.getName()+"tmp");
return BinaryOperator::CreateAnd(Not, Op1);
}
case ICmpInst::ICMP_SGT:
std::swap(Op0, Op1); case ICmpInst::ICMP_SLT: { Value *Not = Builder->CreateNot(Op1, I.getName()+"tmp");
return BinaryOperator::CreateAnd(Not, Op0);
}
case ICmpInst::ICMP_UGE:
std::swap(Op0, Op1); case ICmpInst::ICMP_ULE: { Value *Not = Builder->CreateNot(Op0, I.getName()+"tmp");
return BinaryOperator::CreateOr(Not, Op1);
}
case ICmpInst::ICMP_SGE:
std::swap(Op0, Op1); case ICmpInst::ICMP_SLE: { Value *Not = Builder->CreateNot(Op1, I.getName()+"tmp");
return BinaryOperator::CreateOr(Not, Op0);
}
}
}
unsigned BitWidth = 0;
if (TD)
BitWidth = TD->getTypeSizeInBits(Ty->getScalarType());
else if (Ty->isIntOrIntVectorTy())
BitWidth = Ty->getScalarSizeInBits();
bool isSignBit = false;
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
Value *A = 0, *B = 0;
if (I.isEquality() && CI->isZero() &&
match(Op0, m_Sub(m_Value(A), m_Value(B)))) {
return new ICmpInst(I.getPredicate(), A, B);
}
switch (I.getPredicate()) {
default: break;
case ICmpInst::ICMP_ULE:
assert(!CI->isMaxValue(false)); return new ICmpInst(ICmpInst::ICMP_ULT, Op0,
ConstantInt::get(CI->getContext(), CI->getValue()+1));
case ICmpInst::ICMP_SLE:
assert(!CI->isMaxValue(true)); return new ICmpInst(ICmpInst::ICMP_SLT, Op0,
ConstantInt::get(CI->getContext(), CI->getValue()+1));
case ICmpInst::ICMP_UGE:
assert(!CI->isMinValue(false)); return new ICmpInst(ICmpInst::ICMP_UGT, Op0,
ConstantInt::get(CI->getContext(), CI->getValue()-1));
case ICmpInst::ICMP_SGE:
assert(!CI->isMinValue(true)); return new ICmpInst(ICmpInst::ICMP_SGT, Op0,
ConstantInt::get(CI->getContext(), CI->getValue()-1));
}
bool UnusedBit;
isSignBit = isSignBitCheck(I.getPredicate(), CI, UnusedBit);
}
if (BitWidth != 0) {
APInt Op0KnownZero(BitWidth, 0), Op0KnownOne(BitWidth, 0);
APInt Op1KnownZero(BitWidth, 0), Op1KnownOne(BitWidth, 0);
if (SimplifyDemandedBits(I.getOperandUse(0),
isSignBit ? APInt::getSignBit(BitWidth)
: APInt::getAllOnesValue(BitWidth),
Op0KnownZero, Op0KnownOne, 0))
return &I;
if (SimplifyDemandedBits(I.getOperandUse(1),
APInt::getAllOnesValue(BitWidth),
Op1KnownZero, Op1KnownOne, 0))
return &I;
APInt Op0Min(BitWidth, 0), Op0Max(BitWidth, 0);
APInt Op1Min(BitWidth, 0), Op1Max(BitWidth, 0);
if (I.isSigned()) {
ComputeSignedMinMaxValuesFromKnownBits(Op0KnownZero, Op0KnownOne,
Op0Min, Op0Max);
ComputeSignedMinMaxValuesFromKnownBits(Op1KnownZero, Op1KnownOne,
Op1Min, Op1Max);
} else {
ComputeUnsignedMinMaxValuesFromKnownBits(Op0KnownZero, Op0KnownOne,
Op0Min, Op0Max);
ComputeUnsignedMinMaxValuesFromKnownBits(Op1KnownZero, Op1KnownOne,
Op1Min, Op1Max);
}
if (!isa<Constant>(Op0) && Op0Min == Op0Max)
return new ICmpInst(I.getPredicate(),
ConstantInt::get(I.getContext(), Op0Min), Op1);
if (!isa<Constant>(Op1) && Op1Min == Op1Max)
return new ICmpInst(I.getPredicate(), Op0,
ConstantInt::get(I.getContext(), Op1Min));
switch (I.getPredicate()) {
default: llvm_unreachable("Unknown icmp opcode!");
case ICmpInst::ICMP_EQ:
if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max))
return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
break;
case ICmpInst::ICMP_NE:
if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max))
return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
break;
case ICmpInst::ICMP_ULT:
if (Op0Max.ult(Op1Min)) return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
if (Op0Min.uge(Op1Max)) return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
if (Op1Min == Op0Max) return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1);
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
if (Op1Max == Op0Min+1) return new ICmpInst(ICmpInst::ICMP_EQ, Op0,
ConstantInt::get(CI->getContext(), CI->getValue()-1));
if (CI->isMinValue(true))
return new ICmpInst(ICmpInst::ICMP_SGT, Op0,
Constant::getAllOnesValue(Op0->getType()));
}
break;
case ICmpInst::ICMP_UGT:
if (Op0Min.ugt(Op1Max)) return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
if (Op0Max.ule(Op1Min)) return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
if (Op1Max == Op0Min) return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1);
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
if (Op1Min == Op0Max-1) return new ICmpInst(ICmpInst::ICMP_EQ, Op0,
ConstantInt::get(CI->getContext(), CI->getValue()+1));
if (CI->isMaxValue(true))
return new ICmpInst(ICmpInst::ICMP_SLT, Op0,
Constant::getNullValue(Op0->getType()));
}
break;
case ICmpInst::ICMP_SLT:
if (Op0Max.slt(Op1Min)) return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
if (Op0Min.sge(Op1Max)) return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
if (Op1Min == Op0Max) return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1);
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
if (Op1Max == Op0Min+1) return new ICmpInst(ICmpInst::ICMP_EQ, Op0,
ConstantInt::get(CI->getContext(), CI->getValue()-1));
}
break;
case ICmpInst::ICMP_SGT:
if (Op0Min.sgt(Op1Max)) return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
if (Op0Max.sle(Op1Min)) return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
if (Op1Max == Op0Min) return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1);
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
if (Op1Min == Op0Max-1) return new ICmpInst(ICmpInst::ICMP_EQ, Op0,
ConstantInt::get(CI->getContext(), CI->getValue()+1));
}
break;
case ICmpInst::ICMP_SGE:
assert(!isa<ConstantInt>(Op1) && "ICMP_SGE with ConstantInt not folded!");
if (Op0Min.sge(Op1Max)) return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
if (Op0Max.slt(Op1Min)) return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
break;
case ICmpInst::ICMP_SLE:
assert(!isa<ConstantInt>(Op1) && "ICMP_SLE with ConstantInt not folded!");
if (Op0Max.sle(Op1Min)) return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
if (Op0Min.sgt(Op1Max)) return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
break;
case ICmpInst::ICMP_UGE:
assert(!isa<ConstantInt>(Op1) && "ICMP_UGE with ConstantInt not folded!");
if (Op0Min.uge(Op1Max)) return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
if (Op0Max.ult(Op1Min)) return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
break;
case ICmpInst::ICMP_ULE:
assert(!isa<ConstantInt>(Op1) && "ICMP_ULE with ConstantInt not folded!");
if (Op0Max.ule(Op1Min)) return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
if (Op0Min.ugt(Op1Max)) return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
break;
}
if (I.isSigned() &&
((Op0KnownZero.isNegative() && Op1KnownZero.isNegative()) ||
(Op0KnownOne.isNegative() && Op1KnownOne.isNegative())))
return new ICmpInst(I.getUnsignedPredicate(), Op0, Op1);
}
if (I.hasOneUse())
if (SelectInst *SI = dyn_cast<SelectInst>(*I.use_begin()))
if ((SI->getOperand(1) == Op0 && SI->getOperand(2) == Op1) ||
(SI->getOperand(2) == Op0 && SI->getOperand(1) == Op1))
return 0;
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
if (Instruction *Res = visitICmpInstWithInstAndIntCst(I, LHSI, CI))
return Res;
}
if (Constant *RHSC = dyn_cast<Constant>(Op1)) {
if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
switch (LHSI->getOpcode()) {
case Instruction::GetElementPtr:
if (RHSC->isNullValue() &&
cast<GetElementPtrInst>(LHSI)->hasAllZeroIndices())
return new ICmpInst(I.getPredicate(), LHSI->getOperand(0),
Constant::getNullValue(LHSI->getOperand(0)->getType()));
break;
case Instruction::PHI:
if (LHSI->getParent() == I.getParent())
if (Instruction *NV = FoldOpIntoPhi(I, true))
return NV;
break;
case Instruction::Select: {
Value *Op1 = 0, *Op2 = 0;
if (Constant *C = dyn_cast<Constant>(LHSI->getOperand(1)))
Op1 = ConstantExpr::getICmp(I.getPredicate(), C, RHSC);
if (Constant *C = dyn_cast<Constant>(LHSI->getOperand(2)))
Op2 = ConstantExpr::getICmp(I.getPredicate(), C, RHSC);
if ((Op1 && Op2) || (LHSI->hasOneUse() && (Op1 || Op2))) {
if (!Op1)
Op1 = Builder->CreateICmp(I.getPredicate(), LHSI->getOperand(1),
RHSC, I.getName());
if (!Op2)
Op2 = Builder->CreateICmp(I.getPredicate(), LHSI->getOperand(2),
RHSC, I.getName());
return SelectInst::Create(LHSI->getOperand(0), Op1, Op2);
}
break;
}
case Instruction::IntToPtr:
if (RHSC->isNullValue() && TD &&
TD->getIntPtrType(RHSC->getContext()) ==
LHSI->getOperand(0)->getType())
return new ICmpInst(I.getPredicate(), LHSI->getOperand(0),
Constant::getNullValue(LHSI->getOperand(0)->getType()));
break;
case Instruction::Load:
if (GetElementPtrInst *GEP =
dyn_cast<GetElementPtrInst>(LHSI->getOperand(0))) {
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)))
if (GV->isConstant() && GV->hasDefinitiveInitializer() &&
!cast<LoadInst>(LHSI)->isVolatile())
if (Instruction *Res = FoldCmpLoadFromIndexedGlobal(GEP, GV, I))
return Res;
}
break;
}
}
if (GEPOperator *GEP = dyn_cast<GEPOperator>(Op0))
if (Instruction *NI = FoldGEPICmp(GEP, Op1, I.getPredicate(), I))
return NI;
if (GEPOperator *GEP = dyn_cast<GEPOperator>(Op1))
if (Instruction *NI = FoldGEPICmp(GEP, Op0,
ICmpInst::getSwappedPredicate(I.getPredicate()), I))
return NI;
if (BitCastInst *CI = dyn_cast<BitCastInst>(Op0)) {
if (Op0->getType()->isPointerTy() &&
(isa<Constant>(Op1) || isa<BitCastInst>(Op1))) {
Op0 = CI->getOperand(0);
if (BitCastInst *CI2 = dyn_cast<BitCastInst>(Op1))
Op1 = CI2->getOperand(0);
if (Op0->getType() != Op1->getType()) {
if (Constant *Op1C = dyn_cast<Constant>(Op1)) {
Op1 = ConstantExpr::getBitCast(Op1C, Op0->getType());
} else {
Op1 = Builder->CreateBitCast(Op1, Op0->getType());
}
}
return new ICmpInst(I.getPredicate(), Op0, Op1);
}
}
if (isa<CastInst>(Op0)) {
if (isa<Constant>(Op1) || isa<CastInst>(Op1))
if (Instruction *R = visitICmpInstWithCastAndCast(I))
return R;
}
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
if (BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1)) {
if (Op0I->getOpcode() == Op1I->getOpcode() && Op0I->hasOneUse() &&
Op1I->hasOneUse() && Op0I->getOperand(1) == Op1I->getOperand(1)) {
switch (Op0I->getOpcode()) {
default: break;
case Instruction::Add:
case Instruction::Sub:
case Instruction::Xor:
if (I.isEquality()) return new ICmpInst(I.getPredicate(), Op0I->getOperand(0),
Op1I->getOperand(0));
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0I->getOperand(1))) {
if (CI->getValue().isSignBit()) {
ICmpInst::Predicate Pred = I.isSigned()
? I.getUnsignedPredicate()
: I.getSignedPredicate();
return new ICmpInst(Pred, Op0I->getOperand(0),
Op1I->getOperand(0));
}
if (CI->getValue().isMaxSignedValue()) {
ICmpInst::Predicate Pred = I.isSigned()
? I.getUnsignedPredicate()
: I.getSignedPredicate();
Pred = I.getSwappedPredicate(Pred);
return new ICmpInst(Pred, Op0I->getOperand(0),
Op1I->getOperand(0));
}
}
break;
case Instruction::Mul:
if (!I.isEquality())
break;
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0I->getOperand(1))) {
if (!CI->isZero() && !CI->isOne()) {
const APInt &AP = CI->getValue();
ConstantInt *Mask = ConstantInt::get(I.getContext(),
APInt::getLowBitsSet(AP.getBitWidth(),
AP.getBitWidth() -
AP.countTrailingZeros()));
Value *And1 = Builder->CreateAnd(Op0I->getOperand(0), Mask);
Value *And2 = Builder->CreateAnd(Op1I->getOperand(0), Mask);
return new ICmpInst(I.getPredicate(), And1, And2);
}
}
break;
}
}
}
}
{ Value *A, *B;
if (match(Op0, m_Not(m_Value(A))) &&
match(Op1, m_Not(m_Value(B))))
return new ICmpInst(I.getPredicate(), B, A);
}
if (I.isEquality()) {
Value *A, *B, *C, *D;
if (match(Op0, m_Neg(m_Value(A))) &&
match(Op1, m_Neg(m_Value(B))))
return new ICmpInst(I.getPredicate(), A, B);
if (match(Op0, m_Xor(m_Value(A), m_Value(B)))) {
if (A == Op1 || B == Op1) { Value *OtherVal = A == Op1 ? B : A;
return new ICmpInst(I.getPredicate(), OtherVal,
Constant::getNullValue(A->getType()));
}
if (match(Op1, m_Xor(m_Value(C), m_Value(D)))) {
ConstantInt *C1, *C2;
if (match(B, m_ConstantInt(C1)) &&
match(D, m_ConstantInt(C2)) && Op1->hasOneUse()) {
Constant *NC = ConstantInt::get(I.getContext(),
C1->getValue() ^ C2->getValue());
Value *Xor = Builder->CreateXor(C, NC, "tmp");
return new ICmpInst(I.getPredicate(), A, Xor);
}
if (A == C) return new ICmpInst(I.getPredicate(), B, D);
if (A == D) return new ICmpInst(I.getPredicate(), B, C);
if (B == C) return new ICmpInst(I.getPredicate(), A, D);
if (B == D) return new ICmpInst(I.getPredicate(), A, C);
}
}
if (match(Op1, m_Xor(m_Value(A), m_Value(B))) &&
(A == Op0 || B == Op0)) {
Value *OtherVal = A == Op0 ? B : A;
return new ICmpInst(I.getPredicate(), OtherVal,
Constant::getNullValue(A->getType()));
}
if (match(Op0, m_Sub(m_Specific(Op1), m_Value(B))))
return new ICmpInst(I.getPredicate(), B,
Constant::getNullValue(B->getType()));
if (match(Op1, m_Sub(m_Specific(Op0), m_Value(B))))
return new ICmpInst(I.getPredicate(), B,
Constant::getNullValue(B->getType()));
if (Op0->hasOneUse() && Op1->hasOneUse() &&
match(Op0, m_And(m_Value(A), m_Value(B))) &&
match(Op1, m_And(m_Value(C), m_Value(D)))) {
Value *X = 0, *Y = 0, *Z = 0;
if (A == C) {
X = B; Y = D; Z = A;
} else if (A == D) {
X = B; Y = C; Z = A;
} else if (B == C) {
X = A; Y = D; Z = B;
} else if (B == D) {
X = A; Y = C; Z = B;
}
if (X) { Op1 = Builder->CreateXor(X, Y, "tmp");
Op1 = Builder->CreateAnd(Op1, Z, "tmp");
I.setOperand(0, Op1);
I.setOperand(1, Constant::getNullValue(Op1->getType()));
return &I;
}
}
}
{
Value *X; ConstantInt *Cst;
if (match(Op0, m_Add(m_Value(X), m_ConstantInt(Cst))) && Op1 == X)
return FoldICmpAddOpCst(I, X, Cst, I.getPredicate(), Op0);
if (match(Op1, m_Add(m_Value(X), m_ConstantInt(Cst))) && Op0 == X)
return FoldICmpAddOpCst(I, X, Cst, I.getSwappedPredicate(), Op1);
}
return Changed ? &I : 0;
}
Instruction *InstCombiner::FoldFCmp_IntToFP_Cst(FCmpInst &I,
Instruction *LHSI,
Constant *RHSC) {
if (!isa<ConstantFP>(RHSC)) return 0;
const APFloat &RHS = cast<ConstantFP>(RHSC)->getValueAPF();
int MantissaWidth = LHSI->getType()->getFPMantissaWidth();
if (MantissaWidth == -1) return 0;
unsigned InputSize = LHSI->getOperand(0)->getType()->getScalarSizeInBits();
bool LHSUnsigned = isa<UIToFPInst>(LHSI);
if (LHSUnsigned)
++InputSize;
if ((int)InputSize > MantissaWidth)
return 0;
assert(!RHS.isNaN() && "NaN comparison not already folded!");
ICmpInst::Predicate Pred;
switch (I.getPredicate()) {
default: llvm_unreachable("Unexpected predicate!");
case FCmpInst::FCMP_UEQ:
case FCmpInst::FCMP_OEQ:
Pred = ICmpInst::ICMP_EQ;
break;
case FCmpInst::FCMP_UGT:
case FCmpInst::FCMP_OGT:
Pred = LHSUnsigned ? ICmpInst::ICMP_UGT : ICmpInst::ICMP_SGT;
break;
case FCmpInst::FCMP_UGE:
case FCmpInst::FCMP_OGE:
Pred = LHSUnsigned ? ICmpInst::ICMP_UGE : ICmpInst::ICMP_SGE;
break;
case FCmpInst::FCMP_ULT:
case FCmpInst::FCMP_OLT:
Pred = LHSUnsigned ? ICmpInst::ICMP_ULT : ICmpInst::ICMP_SLT;
break;
case FCmpInst::FCMP_ULE:
case FCmpInst::FCMP_OLE:
Pred = LHSUnsigned ? ICmpInst::ICMP_ULE : ICmpInst::ICMP_SLE;
break;
case FCmpInst::FCMP_UNE:
case FCmpInst::FCMP_ONE:
Pred = ICmpInst::ICMP_NE;
break;
case FCmpInst::FCMP_ORD:
return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
case FCmpInst::FCMP_UNO:
return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
}
const IntegerType *IntTy = cast<IntegerType>(LHSI->getOperand(0)->getType());
unsigned IntWidth = IntTy->getScalarSizeInBits();
if (!LHSUnsigned) {
APFloat SMax(RHS.getSemantics(), APFloat::fcZero, false);
SMax.convertFromAPInt(APInt::getSignedMaxValue(IntWidth), true,
APFloat::rmNearestTiesToEven);
if (SMax.compare(RHS) == APFloat::cmpLessThan) { if (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_SLT ||
Pred == ICmpInst::ICMP_SLE)
return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
}
} else {
APFloat UMax(RHS.getSemantics(), APFloat::fcZero, false);
UMax.convertFromAPInt(APInt::getMaxValue(IntWidth), false,
APFloat::rmNearestTiesToEven);
if (UMax.compare(RHS) == APFloat::cmpLessThan) { if (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_ULT ||
Pred == ICmpInst::ICMP_ULE)
return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
}
}
if (!LHSUnsigned) {
APFloat SMin(RHS.getSemantics(), APFloat::fcZero, false);
SMin.convertFromAPInt(APInt::getSignedMinValue(IntWidth), true,
APFloat::rmNearestTiesToEven);
if (SMin.compare(RHS) == APFloat::cmpGreaterThan) { if (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_SGT ||
Pred == ICmpInst::ICMP_SGE)
return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
}
}
Constant *RHSInt = LHSUnsigned
? ConstantExpr::getFPToUI(RHSC, IntTy)
: ConstantExpr::getFPToSI(RHSC, IntTy);
if (!RHS.isZero()) {
bool Equal = LHSUnsigned
? ConstantExpr::getUIToFP(RHSInt, RHSC->getType()) == RHSC
: ConstantExpr::getSIToFP(RHSInt, RHSC->getType()) == RHSC;
if (!Equal) {
switch (Pred) {
default: llvm_unreachable("Unexpected integer comparison!");
case ICmpInst::ICMP_NE: return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
case ICmpInst::ICMP_EQ: return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
case ICmpInst::ICMP_ULE:
if (RHS.isNegative())
return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
break;
case ICmpInst::ICMP_SLE:
if (RHS.isNegative())
Pred = ICmpInst::ICMP_SLT;
break;
case ICmpInst::ICMP_ULT:
if (RHS.isNegative())
return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
Pred = ICmpInst::ICMP_ULE;
break;
case ICmpInst::ICMP_SLT:
if (!RHS.isNegative())
Pred = ICmpInst::ICMP_SLE;
break;
case ICmpInst::ICMP_UGT:
if (RHS.isNegative())
return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
break;
case ICmpInst::ICMP_SGT:
if (RHS.isNegative())
Pred = ICmpInst::ICMP_SGE;
break;
case ICmpInst::ICMP_UGE:
if (!RHS.isNegative())
return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
Pred = ICmpInst::ICMP_UGT;
break;
case ICmpInst::ICMP_SGE:
if (!RHS.isNegative())
Pred = ICmpInst::ICMP_SGT;
break;
}
}
}
return new ICmpInst(Pred, LHSI->getOperand(0), RHSInt);
}
Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
bool Changed = false;
if (getComplexity(I.getOperand(0)) < getComplexity(I.getOperand(1))) {
I.swapOperands();
Changed = true;
}
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
if (Value *V = SimplifyFCmpInst(I.getPredicate(), Op0, Op1, TD))
return ReplaceInstUsesWith(I, V);
if (Op0 == Op1) {
switch (I.getPredicate()) {
default: llvm_unreachable("Unknown predicate!");
case FCmpInst::FCMP_UNO: case FCmpInst::FCMP_ULT: case FCmpInst::FCMP_UGT: case FCmpInst::FCMP_UNE: I.setPredicate(FCmpInst::FCMP_UNO);
I.setOperand(1, Constant::getNullValue(Op0->getType()));
return &I;
case FCmpInst::FCMP_ORD: case FCmpInst::FCMP_OEQ: case FCmpInst::FCMP_OGE: case FCmpInst::FCMP_OLE: I.setPredicate(FCmpInst::FCMP_ORD);
I.setOperand(1, Constant::getNullValue(Op0->getType()));
return &I;
}
}
if (Constant *RHSC = dyn_cast<Constant>(Op1)) {
if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
switch (LHSI->getOpcode()) {
case Instruction::PHI:
if (LHSI->getParent() == I.getParent())
if (Instruction *NV = FoldOpIntoPhi(I, true))
return NV;
break;
case Instruction::SIToFP:
case Instruction::UIToFP:
if (Instruction *NV = FoldFCmp_IntToFP_Cst(I, LHSI, RHSC))
return NV;
break;
case Instruction::Select: {
Value *Op1 = 0, *Op2 = 0;
if (LHSI->hasOneUse()) {
if (Constant *C = dyn_cast<Constant>(LHSI->getOperand(1))) {
Op1 = ConstantExpr::getCompare(I.getPredicate(), C, RHSC);
Op2 = Builder->CreateFCmp(I.getPredicate(),
LHSI->getOperand(2), RHSC, I.getName());
} else if (Constant *C = dyn_cast<Constant>(LHSI->getOperand(2))) {
Op2 = ConstantExpr::getCompare(I.getPredicate(), C, RHSC);
Op1 = Builder->CreateFCmp(I.getPredicate(), LHSI->getOperand(1),
RHSC, I.getName());
}
}
if (Op1)
return SelectInst::Create(LHSI->getOperand(0), Op1, Op2);
break;
}
case Instruction::Load:
if (GetElementPtrInst *GEP =
dyn_cast<GetElementPtrInst>(LHSI->getOperand(0))) {
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)))
if (GV->isConstant() && GV->hasDefinitiveInitializer() &&
!cast<LoadInst>(LHSI)->isVolatile())
if (Instruction *Res = FoldCmpLoadFromIndexedGlobal(GEP, GV, I))
return Res;
}
break;
}
}
return Changed ? &I : 0;
}