InstructionSimplify.cpp [plain text]
#define DEBUG_TYPE "instsimplify"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/Operator.h"
#include "llvm/Support/ConstantRange.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/PatternMatch.h"
#include "llvm/Support/ValueHandle.h"
using namespace llvm;
using namespace llvm::PatternMatch;
enum { RecursionLimit = 3 };
STATISTIC(NumExpand, "Number of expansions");
STATISTIC(NumFactor , "Number of factorizations");
STATISTIC(NumReassoc, "Number of reassociations");
struct Query {
const DataLayout *TD;
const TargetLibraryInfo *TLI;
const DominatorTree *DT;
Query(const DataLayout *td, const TargetLibraryInfo *tli,
const DominatorTree *dt) : TD(td), TLI(tli), DT(dt) {}
};
static Value *SimplifyAndInst(Value *, Value *, const Query &, unsigned);
static Value *SimplifyBinOp(unsigned, Value *, Value *, const Query &,
unsigned);
static Value *SimplifyCmpInst(unsigned, Value *, Value *, const Query &,
unsigned);
static Value *SimplifyOrInst(Value *, Value *, const Query &, unsigned);
static Value *SimplifyXorInst(Value *, Value *, const Query &, unsigned);
static Value *SimplifyTruncInst(Value *, Type *, const Query &, unsigned);
static Constant *getFalse(Type *Ty) {
assert(Ty->getScalarType()->isIntegerTy(1) &&
"Expected i1 type or a vector of i1!");
return Constant::getNullValue(Ty);
}
static Constant *getTrue(Type *Ty) {
assert(Ty->getScalarType()->isIntegerTy(1) &&
"Expected i1 type or a vector of i1!");
return Constant::getAllOnesValue(Ty);
}
static bool isSameCompare(Value *V, CmpInst::Predicate Pred, Value *LHS,
Value *RHS) {
CmpInst *Cmp = dyn_cast<CmpInst>(V);
if (!Cmp)
return false;
CmpInst::Predicate CPred = Cmp->getPredicate();
Value *CLHS = Cmp->getOperand(0), *CRHS = Cmp->getOperand(1);
if (CPred == Pred && CLHS == LHS && CRHS == RHS)
return true;
return CPred == CmpInst::getSwappedPredicate(Pred) && CLHS == RHS &&
CRHS == LHS;
}
static bool ValueDominatesPHI(Value *V, PHINode *P, const DominatorTree *DT) {
Instruction *I = dyn_cast<Instruction>(V);
if (!I)
return true;
if (!I->getParent() || !P->getParent() || !I->getParent()->getParent())
return false;
if (DT) {
if (!DT->isReachableFromEntry(P->getParent()))
return true;
if (!DT->isReachableFromEntry(I->getParent()))
return false;
return DT->dominates(I, P);
}
if (I->getParent() == &I->getParent()->getParent()->getEntryBlock() &&
!isa<InvokeInst>(I))
return true;
return false;
}
static Value *ExpandBinOp(unsigned Opcode, Value *LHS, Value *RHS,
unsigned OpcToExpand, const Query &Q,
unsigned MaxRecurse) {
Instruction::BinaryOps OpcodeToExpand = (Instruction::BinaryOps)OpcToExpand;
if (!MaxRecurse--)
return 0;
if (BinaryOperator *Op0 = dyn_cast<BinaryOperator>(LHS))
if (Op0->getOpcode() == OpcodeToExpand) {
Value *A = Op0->getOperand(0), *B = Op0->getOperand(1), *C = RHS;
if (Value *L = SimplifyBinOp(Opcode, A, C, Q, MaxRecurse))
if (Value *R = SimplifyBinOp(Opcode, B, C, Q, MaxRecurse)) {
if ((L == A && R == B) || (Instruction::isCommutative(OpcodeToExpand)
&& L == B && R == A)) {
++NumExpand;
return LHS;
}
if (Value *V = SimplifyBinOp(OpcodeToExpand, L, R, Q, MaxRecurse)) {
++NumExpand;
return V;
}
}
}
if (BinaryOperator *Op1 = dyn_cast<BinaryOperator>(RHS))
if (Op1->getOpcode() == OpcodeToExpand) {
Value *A = LHS, *B = Op1->getOperand(0), *C = Op1->getOperand(1);
if (Value *L = SimplifyBinOp(Opcode, A, B, Q, MaxRecurse))
if (Value *R = SimplifyBinOp(Opcode, A, C, Q, MaxRecurse)) {
if ((L == B && R == C) || (Instruction::isCommutative(OpcodeToExpand)
&& L == C && R == B)) {
++NumExpand;
return RHS;
}
if (Value *V = SimplifyBinOp(OpcodeToExpand, L, R, Q, MaxRecurse)) {
++NumExpand;
return V;
}
}
}
return 0;
}
static Value *FactorizeBinOp(unsigned Opcode, Value *LHS, Value *RHS,
unsigned OpcToExtract, const Query &Q,
unsigned MaxRecurse) {
Instruction::BinaryOps OpcodeToExtract = (Instruction::BinaryOps)OpcToExtract;
if (!MaxRecurse--)
return 0;
BinaryOperator *Op0 = dyn_cast<BinaryOperator>(LHS);
BinaryOperator *Op1 = dyn_cast<BinaryOperator>(RHS);
if (!Op0 || Op0->getOpcode() != OpcodeToExtract ||
!Op1 || Op1->getOpcode() != OpcodeToExtract)
return 0;
Value *A = Op0->getOperand(0), *B = Op0->getOperand(1);
Value *C = Op1->getOperand(0), *D = Op1->getOperand(1);
if (A == C || (Instruction::isCommutative(OpcodeToExtract) && A == D)) {
Value *DD = A == C ? D : C;
if (Value *V = SimplifyBinOp(Opcode, B, DD, Q, MaxRecurse)) {
if (V == B || V == DD) {
++NumFactor;
return V == B ? LHS : RHS;
}
if (Value *W = SimplifyBinOp(OpcodeToExtract, A, V, Q, MaxRecurse)) {
++NumFactor;
return W;
}
}
}
if (B == D || (Instruction::isCommutative(OpcodeToExtract) && B == C)) {
Value *CC = B == D ? C : D;
if (Value *V = SimplifyBinOp(Opcode, A, CC, Q, MaxRecurse)) {
if (V == A || V == CC) {
++NumFactor;
return V == A ? LHS : RHS;
}
if (Value *W = SimplifyBinOp(OpcodeToExtract, V, B, Q, MaxRecurse)) {
++NumFactor;
return W;
}
}
}
return 0;
}
static Value *SimplifyAssociativeBinOp(unsigned Opc, Value *LHS, Value *RHS,
const Query &Q, unsigned MaxRecurse) {
Instruction::BinaryOps Opcode = (Instruction::BinaryOps)Opc;
assert(Instruction::isAssociative(Opcode) && "Not an associative operation!");
if (!MaxRecurse--)
return 0;
BinaryOperator *Op0 = dyn_cast<BinaryOperator>(LHS);
BinaryOperator *Op1 = dyn_cast<BinaryOperator>(RHS);
if (Op0 && Op0->getOpcode() == Opcode) {
Value *A = Op0->getOperand(0);
Value *B = Op0->getOperand(1);
Value *C = RHS;
if (Value *V = SimplifyBinOp(Opcode, B, C, Q, MaxRecurse)) {
if (V == B) return LHS;
if (Value *W = SimplifyBinOp(Opcode, A, V, Q, MaxRecurse)) {
++NumReassoc;
return W;
}
}
}
if (Op1 && Op1->getOpcode() == Opcode) {
Value *A = LHS;
Value *B = Op1->getOperand(0);
Value *C = Op1->getOperand(1);
if (Value *V = SimplifyBinOp(Opcode, A, B, Q, MaxRecurse)) {
if (V == B) return RHS;
if (Value *W = SimplifyBinOp(Opcode, V, C, Q, MaxRecurse)) {
++NumReassoc;
return W;
}
}
}
if (!Instruction::isCommutative(Opcode))
return 0;
if (Op0 && Op0->getOpcode() == Opcode) {
Value *A = Op0->getOperand(0);
Value *B = Op0->getOperand(1);
Value *C = RHS;
if (Value *V = SimplifyBinOp(Opcode, C, A, Q, MaxRecurse)) {
if (V == A) return LHS;
if (Value *W = SimplifyBinOp(Opcode, V, B, Q, MaxRecurse)) {
++NumReassoc;
return W;
}
}
}
if (Op1 && Op1->getOpcode() == Opcode) {
Value *A = LHS;
Value *B = Op1->getOperand(0);
Value *C = Op1->getOperand(1);
if (Value *V = SimplifyBinOp(Opcode, C, A, Q, MaxRecurse)) {
if (V == C) return RHS;
if (Value *W = SimplifyBinOp(Opcode, B, V, Q, MaxRecurse)) {
++NumReassoc;
return W;
}
}
}
return 0;
}
static Value *ThreadBinOpOverSelect(unsigned Opcode, Value *LHS, Value *RHS,
const Query &Q, unsigned MaxRecurse) {
if (!MaxRecurse--)
return 0;
SelectInst *SI;
if (isa<SelectInst>(LHS)) {
SI = cast<SelectInst>(LHS);
} else {
assert(isa<SelectInst>(RHS) && "No select instruction operand!");
SI = cast<SelectInst>(RHS);
}
Value *TV;
Value *FV;
if (SI == LHS) {
TV = SimplifyBinOp(Opcode, SI->getTrueValue(), RHS, Q, MaxRecurse);
FV = SimplifyBinOp(Opcode, SI->getFalseValue(), RHS, Q, MaxRecurse);
} else {
TV = SimplifyBinOp(Opcode, LHS, SI->getTrueValue(), Q, MaxRecurse);
FV = SimplifyBinOp(Opcode, LHS, SI->getFalseValue(), Q, MaxRecurse);
}
if (TV == FV)
return TV;
if (TV && isa<UndefValue>(TV))
return FV;
if (FV && isa<UndefValue>(FV))
return TV;
if (TV == SI->getTrueValue() && FV == SI->getFalseValue())
return SI;
if ((FV && !TV) || (TV && !FV)) {
Instruction *Simplified = dyn_cast<Instruction>(FV ? FV : TV);
if (Simplified && Simplified->getOpcode() == Opcode) {
Value *UnsimplifiedBranch = FV ? SI->getTrueValue() : SI->getFalseValue();
Value *UnsimplifiedLHS = SI == LHS ? UnsimplifiedBranch : LHS;
Value *UnsimplifiedRHS = SI == LHS ? RHS : UnsimplifiedBranch;
if (Simplified->getOperand(0) == UnsimplifiedLHS &&
Simplified->getOperand(1) == UnsimplifiedRHS)
return Simplified;
if (Simplified->isCommutative() &&
Simplified->getOperand(1) == UnsimplifiedLHS &&
Simplified->getOperand(0) == UnsimplifiedRHS)
return Simplified;
}
}
return 0;
}
static Value *ThreadCmpOverSelect(CmpInst::Predicate Pred, Value *LHS,
Value *RHS, const Query &Q,
unsigned MaxRecurse) {
if (!MaxRecurse--)
return 0;
if (!isa<SelectInst>(LHS)) {
std::swap(LHS, RHS);
Pred = CmpInst::getSwappedPredicate(Pred);
}
assert(isa<SelectInst>(LHS) && "Not comparing with a select instruction!");
SelectInst *SI = cast<SelectInst>(LHS);
Value *Cond = SI->getCondition();
Value *TV = SI->getTrueValue();
Value *FV = SI->getFalseValue();
Value *TCmp = SimplifyCmpInst(Pred, TV, RHS, Q, MaxRecurse);
if (TCmp == Cond) {
TCmp = getTrue(Cond->getType());
} else if (!TCmp) {
if (!isSameCompare(Cond, Pred, TV, RHS))
return 0;
TCmp = getTrue(Cond->getType());
}
Value *FCmp = SimplifyCmpInst(Pred, FV, RHS, Q, MaxRecurse);
if (FCmp == Cond) {
FCmp = getFalse(Cond->getType());
} else if (!FCmp) {
if (!isSameCompare(Cond, Pred, FV, RHS))
return 0;
FCmp = getFalse(Cond->getType());
}
if (TCmp == FCmp)
return TCmp;
if (Cond->getType()->isVectorTy() != RHS->getType()->isVectorTy())
return 0;
if (match(FCmp, m_Zero()))
if (Value *V = SimplifyAndInst(Cond, TCmp, Q, MaxRecurse))
return V;
if (match(TCmp, m_One()))
if (Value *V = SimplifyOrInst(Cond, FCmp, Q, MaxRecurse))
return V;
if (match(FCmp, m_One()) && match(TCmp, m_Zero()))
if (Value *V =
SimplifyXorInst(Cond, Constant::getAllOnesValue(Cond->getType()),
Q, MaxRecurse))
return V;
return 0;
}
static Value *ThreadBinOpOverPHI(unsigned Opcode, Value *LHS, Value *RHS,
const Query &Q, unsigned MaxRecurse) {
if (!MaxRecurse--)
return 0;
PHINode *PI;
if (isa<PHINode>(LHS)) {
PI = cast<PHINode>(LHS);
if (!ValueDominatesPHI(RHS, PI, Q.DT))
return 0;
} else {
assert(isa<PHINode>(RHS) && "No PHI instruction operand!");
PI = cast<PHINode>(RHS);
if (!ValueDominatesPHI(LHS, PI, Q.DT))
return 0;
}
Value *CommonValue = 0;
for (unsigned i = 0, e = PI->getNumIncomingValues(); i != e; ++i) {
Value *Incoming = PI->getIncomingValue(i);
if (Incoming == PI) continue;
Value *V = PI == LHS ?
SimplifyBinOp(Opcode, Incoming, RHS, Q, MaxRecurse) :
SimplifyBinOp(Opcode, LHS, Incoming, Q, MaxRecurse);
if (!V || (CommonValue && V != CommonValue))
return 0;
CommonValue = V;
}
return CommonValue;
}
static Value *ThreadCmpOverPHI(CmpInst::Predicate Pred, Value *LHS, Value *RHS,
const Query &Q, unsigned MaxRecurse) {
if (!MaxRecurse--)
return 0;
if (!isa<PHINode>(LHS)) {
std::swap(LHS, RHS);
Pred = CmpInst::getSwappedPredicate(Pred);
}
assert(isa<PHINode>(LHS) && "Not comparing with a phi instruction!");
PHINode *PI = cast<PHINode>(LHS);
if (!ValueDominatesPHI(RHS, PI, Q.DT))
return 0;
Value *CommonValue = 0;
for (unsigned i = 0, e = PI->getNumIncomingValues(); i != e; ++i) {
Value *Incoming = PI->getIncomingValue(i);
if (Incoming == PI) continue;
Value *V = SimplifyCmpInst(Pred, Incoming, RHS, Q, MaxRecurse);
if (!V || (CommonValue && V != CommonValue))
return 0;
CommonValue = V;
}
return CommonValue;
}
static Value *SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
const Query &Q, unsigned MaxRecurse) {
if (Constant *CLHS = dyn_cast<Constant>(Op0)) {
if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
Constant *Ops[] = { CLHS, CRHS };
return ConstantFoldInstOperands(Instruction::Add, CLHS->getType(), Ops,
Q.TD, Q.TLI);
}
std::swap(Op0, Op1);
}
if (match(Op1, m_Undef()))
return Op1;
if (match(Op1, m_Zero()))
return Op0;
Value *Y = 0;
if (match(Op1, m_Sub(m_Value(Y), m_Specific(Op0))) ||
match(Op0, m_Sub(m_Value(Y), m_Specific(Op1))))
return Y;
if (match(Op0, m_Not(m_Specific(Op1))) ||
match(Op1, m_Not(m_Specific(Op0))))
return Constant::getAllOnesValue(Op0->getType());
if (MaxRecurse && Op0->getType()->isIntegerTy(1))
if (Value *V = SimplifyXorInst(Op0, Op1, Q, MaxRecurse-1))
return V;
if (Value *V = SimplifyAssociativeBinOp(Instruction::Add, Op0, Op1, Q,
MaxRecurse))
return V;
if (Value *V = FactorizeBinOp(Instruction::Add, Op0, Op1, Instruction::Mul,
Q, MaxRecurse))
return V;
return 0;
}
Value *llvm::SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
const DataLayout *TD, const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyAddInst(Op0, Op1, isNSW, isNUW, Query (TD, TLI, DT),
RecursionLimit);
}
static Constant *stripAndComputeConstantOffsets(const DataLayout *TD,
Value *&V,
bool AllowNonInbounds = false) {
assert(V->getType()->getScalarType()->isPointerTy());
if (!TD)
return ConstantInt::get(IntegerType::get(V->getContext(), 64), 0);
Type *IntPtrTy = TD->getIntPtrType(V->getType())->getScalarType();
APInt Offset = APInt::getNullValue(IntPtrTy->getIntegerBitWidth());
SmallPtrSet<Value *, 4> Visited;
Visited.insert(V);
do {
if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
if ((!AllowNonInbounds && !GEP->isInBounds()) ||
!GEP->accumulateConstantOffset(*TD, Offset))
break;
V = GEP->getPointerOperand();
} else if (Operator::getOpcode(V) == Instruction::BitCast) {
V = cast<Operator>(V)->getOperand(0);
} else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) {
if (GA->mayBeOverridden())
break;
V = GA->getAliasee();
} else {
break;
}
assert(V->getType()->getScalarType()->isPointerTy() &&
"Unexpected operand type!");
} while (Visited.insert(V));
Constant *OffsetIntPtr = ConstantInt::get(IntPtrTy, Offset);
if (V->getType()->isVectorTy())
return ConstantVector::getSplat(V->getType()->getVectorNumElements(),
OffsetIntPtr);
return OffsetIntPtr;
}
static Constant *computePointerDifference(const DataLayout *TD,
Value *LHS, Value *RHS) {
Constant *LHSOffset = stripAndComputeConstantOffsets(TD, LHS);
Constant *RHSOffset = stripAndComputeConstantOffsets(TD, RHS);
if (LHS != RHS)
return 0;
return ConstantExpr::getSub(LHSOffset, RHSOffset);
}
static Value *SimplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
const Query &Q, unsigned MaxRecurse) {
if (Constant *CLHS = dyn_cast<Constant>(Op0))
if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
Constant *Ops[] = { CLHS, CRHS };
return ConstantFoldInstOperands(Instruction::Sub, CLHS->getType(),
Ops, Q.TD, Q.TLI);
}
if (match(Op0, m_Undef()) || match(Op1, m_Undef()))
return UndefValue::get(Op0->getType());
if (match(Op1, m_Zero()))
return Op0;
if (Op0 == Op1)
return Constant::getNullValue(Op0->getType());
Value *X = 0;
if (match(Op0, m_Mul(m_Specific(Op1), m_ConstantInt<2>())) ||
match(Op0, m_Shl(m_Specific(Op1), m_One())))
return Op1;
Value *Y = 0, *Z = Op1;
if (MaxRecurse && match(Op0, m_Add(m_Value(X), m_Value(Y)))) { if (Value *V = SimplifyBinOp(Instruction::Sub, Y, Z, Q, MaxRecurse-1))
if (Value *W = SimplifyBinOp(Instruction::Add, X, V, Q, MaxRecurse-1)) {
++NumReassoc;
return W;
}
if (Value *V = SimplifyBinOp(Instruction::Sub, X, Z, Q, MaxRecurse-1))
if (Value *W = SimplifyBinOp(Instruction::Add, Y, V, Q, MaxRecurse-1)) {
++NumReassoc;
return W;
}
}
X = Op0;
if (MaxRecurse && match(Op1, m_Add(m_Value(Y), m_Value(Z)))) { if (Value *V = SimplifyBinOp(Instruction::Sub, X, Y, Q, MaxRecurse-1))
if (Value *W = SimplifyBinOp(Instruction::Sub, V, Z, Q, MaxRecurse-1)) {
++NumReassoc;
return W;
}
if (Value *V = SimplifyBinOp(Instruction::Sub, X, Z, Q, MaxRecurse-1))
if (Value *W = SimplifyBinOp(Instruction::Sub, V, Y, Q, MaxRecurse-1)) {
++NumReassoc;
return W;
}
}
Z = Op0;
if (MaxRecurse && match(Op1, m_Sub(m_Value(X), m_Value(Y)))) if (Value *V = SimplifyBinOp(Instruction::Sub, Z, X, Q, MaxRecurse-1))
if (Value *W = SimplifyBinOp(Instruction::Add, V, Y, Q, MaxRecurse-1)) {
++NumReassoc;
return W;
}
if (MaxRecurse && match(Op0, m_Trunc(m_Value(X))) &&
match(Op1, m_Trunc(m_Value(Y))))
if (X->getType() == Y->getType())
if (Value *V = SimplifyBinOp(Instruction::Sub, X, Y, Q, MaxRecurse-1))
if (Value *W = SimplifyTruncInst(V, Op0->getType(), Q, MaxRecurse-1))
return W;
if (match(Op0, m_PtrToInt(m_Value(X))) &&
match(Op1, m_PtrToInt(m_Value(Y))))
if (Constant *Result = computePointerDifference(Q.TD, X, Y))
return ConstantExpr::getIntegerCast(Result, Op0->getType(), true);
if (Value *V = FactorizeBinOp(Instruction::Sub, Op0, Op1, Instruction::Mul,
Q, MaxRecurse))
return V;
if (MaxRecurse && Op0->getType()->isIntegerTy(1))
if (Value *V = SimplifyXorInst(Op0, Op1, Q, MaxRecurse-1))
return V;
return 0;
}
Value *llvm::SimplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
const DataLayout *TD, const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifySubInst(Op0, Op1, isNSW, isNUW, Query (TD, TLI, DT),
RecursionLimit);
}
static Value *SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF,
const Query &Q, unsigned MaxRecurse) {
if (Constant *CLHS = dyn_cast<Constant>(Op0)) {
if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
Constant *Ops[] = { CLHS, CRHS };
return ConstantFoldInstOperands(Instruction::FAdd, CLHS->getType(),
Ops, Q.TD, Q.TLI);
}
std::swap(Op0, Op1);
}
if (match(Op1, m_NegZero()))
return Op0;
if (match(Op1, m_Zero()) &&
(FMF.noSignedZeros() || CannotBeNegativeZero(Op0)))
return Op0;
Value *SubOp = 0;
if (match(Op1, m_FSub(m_AnyZero(), m_Specific(Op0))))
SubOp = Op1;
else if (match(Op0, m_FSub(m_AnyZero(), m_Specific(Op1))))
SubOp = Op0;
if (SubOp) {
Instruction *FSub = cast<Instruction>(SubOp);
if ((FMF.noNaNs() || FSub->hasNoNaNs()) &&
(FMF.noInfs() || FSub->hasNoInfs()))
return Constant::getNullValue(Op0->getType());
}
return 0;
}
static Value *SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF,
const Query &Q, unsigned MaxRecurse) {
if (Constant *CLHS = dyn_cast<Constant>(Op0)) {
if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
Constant *Ops[] = { CLHS, CRHS };
return ConstantFoldInstOperands(Instruction::FSub, CLHS->getType(),
Ops, Q.TD, Q.TLI);
}
}
if (match(Op1, m_Zero()))
return Op0;
if (match(Op1, m_NegZero()) &&
(FMF.noSignedZeros() || CannotBeNegativeZero(Op0)))
return Op0;
Value *X;
if (match(Op0, m_AnyZero())) {
if (match(Op1, m_FSub(m_NegZero(), m_Value(X))))
return X;
if (FMF.noSignedZeros() && match(Op1, m_FSub(m_AnyZero(), m_Value(X))))
return X;
}
if (FMF.noNaNs() && FMF.noInfs() && Op0 == Op1)
return Constant::getNullValue(Op0->getType());
return 0;
}
static Value *SimplifyFMulInst(Value *Op0, Value *Op1,
FastMathFlags FMF,
const Query &Q,
unsigned MaxRecurse) {
if (Constant *CLHS = dyn_cast<Constant>(Op0)) {
if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
Constant *Ops[] = { CLHS, CRHS };
return ConstantFoldInstOperands(Instruction::FMul, CLHS->getType(),
Ops, Q.TD, Q.TLI);
}
std::swap(Op0, Op1);
}
if (match(Op1, m_FPOne()))
return Op0;
if (FMF.noNaNs() && FMF.noSignedZeros() && match(Op1, m_AnyZero()))
return Op1;
return 0;
}
static Value *SimplifyMulInst(Value *Op0, Value *Op1, const Query &Q,
unsigned MaxRecurse) {
if (Constant *CLHS = dyn_cast<Constant>(Op0)) {
if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
Constant *Ops[] = { CLHS, CRHS };
return ConstantFoldInstOperands(Instruction::Mul, CLHS->getType(),
Ops, Q.TD, Q.TLI);
}
std::swap(Op0, Op1);
}
if (match(Op1, m_Undef()))
return Constant::getNullValue(Op0->getType());
if (match(Op1, m_Zero()))
return Op1;
if (match(Op1, m_One()))
return Op0;
Value *X = 0;
if (match(Op0, m_Exact(m_IDiv(m_Value(X), m_Specific(Op1)))) || match(Op1, m_Exact(m_IDiv(m_Value(X), m_Specific(Op0))))) return X;
if (MaxRecurse && Op0->getType()->isIntegerTy(1))
if (Value *V = SimplifyAndInst(Op0, Op1, Q, MaxRecurse-1))
return V;
if (Value *V = SimplifyAssociativeBinOp(Instruction::Mul, Op0, Op1, Q,
MaxRecurse))
return V;
if (Value *V = ExpandBinOp(Instruction::Mul, Op0, Op1, Instruction::Add,
Q, MaxRecurse))
return V;
if (isa<SelectInst>(Op0) || isa<SelectInst>(Op1))
if (Value *V = ThreadBinOpOverSelect(Instruction::Mul, Op0, Op1, Q,
MaxRecurse))
return V;
if (isa<PHINode>(Op0) || isa<PHINode>(Op1))
if (Value *V = ThreadBinOpOverPHI(Instruction::Mul, Op0, Op1, Q,
MaxRecurse))
return V;
return 0;
}
Value *llvm::SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF,
const DataLayout *TD, const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyFAddInst(Op0, Op1, FMF, Query (TD, TLI, DT), RecursionLimit);
}
Value *llvm::SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF,
const DataLayout *TD, const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyFSubInst(Op0, Op1, FMF, Query (TD, TLI, DT), RecursionLimit);
}
Value *llvm::SimplifyFMulInst(Value *Op0, Value *Op1,
FastMathFlags FMF,
const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyFMulInst(Op0, Op1, FMF, Query (TD, TLI, DT), RecursionLimit);
}
Value *llvm::SimplifyMulInst(Value *Op0, Value *Op1, const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyMulInst(Op0, Op1, Query (TD, TLI, DT), RecursionLimit);
}
static Value *SimplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
const Query &Q, unsigned MaxRecurse) {
if (Constant *C0 = dyn_cast<Constant>(Op0)) {
if (Constant *C1 = dyn_cast<Constant>(Op1)) {
Constant *Ops[] = { C0, C1 };
return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, Q.TD, Q.TLI);
}
}
bool isSigned = Opcode == Instruction::SDiv;
if (match(Op1, m_Undef()))
return Op1;
if (match(Op0, m_Undef()))
return Constant::getNullValue(Op0->getType());
if (match(Op0, m_Zero()))
return Op0;
if (match(Op1, m_One()))
return Op0;
if (Op0->getType()->isIntegerTy(1))
return Op0;
if (Op0 == Op1)
return ConstantInt::get(Op0->getType(), 1);
Value *X = 0, *Y = 0;
if (match(Op0, m_Mul(m_Value(X), m_Value(Y))) && (X == Op1 || Y == Op1)) {
if (Y != Op1) std::swap(X, Y); OverflowingBinaryOperator *Mul = cast<OverflowingBinaryOperator>(Op0);
if ((isSigned && Mul->hasNoSignedWrap()) ||
(!isSigned && Mul->hasNoUnsignedWrap()))
return X;
if (BinaryOperator *Div = dyn_cast<BinaryOperator>(X))
if (Div->getOpcode() == Opcode && Div->getOperand(1) == Y)
return X;
}
if ((isSigned && match(Op0, m_SRem(m_Value(), m_Specific(Op1)))) ||
(!isSigned && match(Op0, m_URem(m_Value(), m_Specific(Op1)))))
return Constant::getNullValue(Op0->getType());
if (isa<SelectInst>(Op0) || isa<SelectInst>(Op1))
if (Value *V = ThreadBinOpOverSelect(Opcode, Op0, Op1, Q, MaxRecurse))
return V;
if (isa<PHINode>(Op0) || isa<PHINode>(Op1))
if (Value *V = ThreadBinOpOverPHI(Opcode, Op0, Op1, Q, MaxRecurse))
return V;
return 0;
}
static Value *SimplifySDivInst(Value *Op0, Value *Op1, const Query &Q,
unsigned MaxRecurse) {
if (Value *V = SimplifyDiv(Instruction::SDiv, Op0, Op1, Q, MaxRecurse))
return V;
return 0;
}
Value *llvm::SimplifySDivInst(Value *Op0, Value *Op1, const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifySDivInst(Op0, Op1, Query (TD, TLI, DT), RecursionLimit);
}
static Value *SimplifyUDivInst(Value *Op0, Value *Op1, const Query &Q,
unsigned MaxRecurse) {
if (Value *V = SimplifyDiv(Instruction::UDiv, Op0, Op1, Q, MaxRecurse))
return V;
return 0;
}
Value *llvm::SimplifyUDivInst(Value *Op0, Value *Op1, const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyUDivInst(Op0, Op1, Query (TD, TLI, DT), RecursionLimit);
}
static Value *SimplifyFDivInst(Value *Op0, Value *Op1, const Query &Q,
unsigned) {
if (match(Op0, m_Undef()))
return Op0;
if (match(Op1, m_Undef()))
return Op1;
return 0;
}
Value *llvm::SimplifyFDivInst(Value *Op0, Value *Op1, const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyFDivInst(Op0, Op1, Query (TD, TLI, DT), RecursionLimit);
}
static Value *SimplifyRem(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
const Query &Q, unsigned MaxRecurse) {
if (Constant *C0 = dyn_cast<Constant>(Op0)) {
if (Constant *C1 = dyn_cast<Constant>(Op1)) {
Constant *Ops[] = { C0, C1 };
return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, Q.TD, Q.TLI);
}
}
if (match(Op1, m_Undef()))
return Op1;
if (match(Op0, m_Undef()))
return Constant::getNullValue(Op0->getType());
if (match(Op0, m_Zero()))
return Op0;
if (match(Op1, m_Zero()))
return UndefValue::get(Op0->getType());
if (match(Op1, m_One()))
return Constant::getNullValue(Op0->getType());
if (Op0->getType()->isIntegerTy(1))
return Constant::getNullValue(Op0->getType());
if (Op0 == Op1)
return Constant::getNullValue(Op0->getType());
if (isa<SelectInst>(Op0) || isa<SelectInst>(Op1))
if (Value *V = ThreadBinOpOverSelect(Opcode, Op0, Op1, Q, MaxRecurse))
return V;
if (isa<PHINode>(Op0) || isa<PHINode>(Op1))
if (Value *V = ThreadBinOpOverPHI(Opcode, Op0, Op1, Q, MaxRecurse))
return V;
return 0;
}
static Value *SimplifySRemInst(Value *Op0, Value *Op1, const Query &Q,
unsigned MaxRecurse) {
if (Value *V = SimplifyRem(Instruction::SRem, Op0, Op1, Q, MaxRecurse))
return V;
return 0;
}
Value *llvm::SimplifySRemInst(Value *Op0, Value *Op1, const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifySRemInst(Op0, Op1, Query (TD, TLI, DT), RecursionLimit);
}
static Value *SimplifyURemInst(Value *Op0, Value *Op1, const Query &Q,
unsigned MaxRecurse) {
if (Value *V = SimplifyRem(Instruction::URem, Op0, Op1, Q, MaxRecurse))
return V;
return 0;
}
Value *llvm::SimplifyURemInst(Value *Op0, Value *Op1, const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyURemInst(Op0, Op1, Query (TD, TLI, DT), RecursionLimit);
}
static Value *SimplifyFRemInst(Value *Op0, Value *Op1, const Query &,
unsigned) {
if (match(Op0, m_Undef()))
return Op0;
if (match(Op1, m_Undef()))
return Op1;
return 0;
}
Value *llvm::SimplifyFRemInst(Value *Op0, Value *Op1, const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyFRemInst(Op0, Op1, Query (TD, TLI, DT), RecursionLimit);
}
static Value *SimplifyShift(unsigned Opcode, Value *Op0, Value *Op1,
const Query &Q, unsigned MaxRecurse) {
if (Constant *C0 = dyn_cast<Constant>(Op0)) {
if (Constant *C1 = dyn_cast<Constant>(Op1)) {
Constant *Ops[] = { C0, C1 };
return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, Q.TD, Q.TLI);
}
}
if (match(Op0, m_Zero()))
return Op0;
if (match(Op1, m_Zero()))
return Op0;
if (match(Op1, m_Undef()))
return Op1;
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1))
if (CI->getValue().getLimitedValue() >=
Op0->getType()->getScalarSizeInBits())
return UndefValue::get(Op0->getType());
if (isa<SelectInst>(Op0) || isa<SelectInst>(Op1))
if (Value *V = ThreadBinOpOverSelect(Opcode, Op0, Op1, Q, MaxRecurse))
return V;
if (isa<PHINode>(Op0) || isa<PHINode>(Op1))
if (Value *V = ThreadBinOpOverPHI(Opcode, Op0, Op1, Q, MaxRecurse))
return V;
return 0;
}
static Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
const Query &Q, unsigned MaxRecurse) {
if (Value *V = SimplifyShift(Instruction::Shl, Op0, Op1, Q, MaxRecurse))
return V;
if (match(Op0, m_Undef()))
return Constant::getNullValue(Op0->getType());
Value *X;
if (match(Op0, m_Exact(m_Shr(m_Value(X), m_Specific(Op1)))))
return X;
return 0;
}
Value *llvm::SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
const DataLayout *TD, const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyShlInst(Op0, Op1, isNSW, isNUW, Query (TD, TLI, DT),
RecursionLimit);
}
static Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
const Query &Q, unsigned MaxRecurse) {
if (Value *V = SimplifyShift(Instruction::LShr, Op0, Op1, Q, MaxRecurse))
return V;
if (Op0 == Op1)
return Constant::getNullValue(Op0->getType());
if (match(Op0, m_Undef()))
return Constant::getNullValue(Op0->getType());
Value *X;
if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1))) &&
cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap())
return X;
return 0;
}
Value *llvm::SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyLShrInst(Op0, Op1, isExact, Query (TD, TLI, DT),
RecursionLimit);
}
static Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
const Query &Q, unsigned MaxRecurse) {
if (Value *V = SimplifyShift(Instruction::AShr, Op0, Op1, Q, MaxRecurse))
return V;
if (Op0 == Op1)
return Constant::getNullValue(Op0->getType());
if (match(Op0, m_AllOnes()))
return Op0;
if (match(Op0, m_Undef()))
return Constant::getAllOnesValue(Op0->getType());
Value *X;
if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1))) &&
cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap())
return X;
return 0;
}
Value *llvm::SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyAShrInst(Op0, Op1, isExact, Query (TD, TLI, DT),
RecursionLimit);
}
static Value *SimplifyAndInst(Value *Op0, Value *Op1, const Query &Q,
unsigned MaxRecurse) {
if (Constant *CLHS = dyn_cast<Constant>(Op0)) {
if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
Constant *Ops[] = { CLHS, CRHS };
return ConstantFoldInstOperands(Instruction::And, CLHS->getType(),
Ops, Q.TD, Q.TLI);
}
std::swap(Op0, Op1);
}
if (match(Op1, m_Undef()))
return Constant::getNullValue(Op0->getType());
if (Op0 == Op1)
return Op0;
if (match(Op1, m_Zero()))
return Op1;
if (match(Op1, m_AllOnes()))
return Op0;
if (match(Op0, m_Not(m_Specific(Op1))) ||
match(Op1, m_Not(m_Specific(Op0))))
return Constant::getNullValue(Op0->getType());
Value *A = 0, *B = 0;
if (match(Op0, m_Or(m_Value(A), m_Value(B))) &&
(A == Op1 || B == Op1))
return Op1;
if (match(Op1, m_Or(m_Value(A), m_Value(B))) &&
(A == Op0 || B == Op0))
return Op0;
if (match(Op0, m_Neg(m_Specific(Op1))) ||
match(Op1, m_Neg(m_Specific(Op0)))) {
if (isKnownToBeAPowerOfTwo(Op0, true))
return Op0;
if (isKnownToBeAPowerOfTwo(Op1, true))
return Op1;
}
if (Value *V = SimplifyAssociativeBinOp(Instruction::And, Op0, Op1, Q,
MaxRecurse))
return V;
if (Value *V = ExpandBinOp(Instruction::And, Op0, Op1, Instruction::Or,
Q, MaxRecurse))
return V;
if (Value *V = ExpandBinOp(Instruction::And, Op0, Op1, Instruction::Xor,
Q, MaxRecurse))
return V;
if (Value *V = FactorizeBinOp(Instruction::And, Op0, Op1, Instruction::Or,
Q, MaxRecurse))
return V;
if (isa<SelectInst>(Op0) || isa<SelectInst>(Op1))
if (Value *V = ThreadBinOpOverSelect(Instruction::And, Op0, Op1, Q,
MaxRecurse))
return V;
if (isa<PHINode>(Op0) || isa<PHINode>(Op1))
if (Value *V = ThreadBinOpOverPHI(Instruction::And, Op0, Op1, Q,
MaxRecurse))
return V;
return 0;
}
Value *llvm::SimplifyAndInst(Value *Op0, Value *Op1, const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyAndInst(Op0, Op1, Query (TD, TLI, DT), RecursionLimit);
}
static Value *SimplifyOrInst(Value *Op0, Value *Op1, const Query &Q,
unsigned MaxRecurse) {
if (Constant *CLHS = dyn_cast<Constant>(Op0)) {
if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
Constant *Ops[] = { CLHS, CRHS };
return ConstantFoldInstOperands(Instruction::Or, CLHS->getType(),
Ops, Q.TD, Q.TLI);
}
std::swap(Op0, Op1);
}
if (match(Op1, m_Undef()))
return Constant::getAllOnesValue(Op0->getType());
if (Op0 == Op1)
return Op0;
if (match(Op1, m_Zero()))
return Op0;
if (match(Op1, m_AllOnes()))
return Op1;
if (match(Op0, m_Not(m_Specific(Op1))) ||
match(Op1, m_Not(m_Specific(Op0))))
return Constant::getAllOnesValue(Op0->getType());
Value *A = 0, *B = 0;
if (match(Op0, m_And(m_Value(A), m_Value(B))) &&
(A == Op1 || B == Op1))
return Op1;
if (match(Op1, m_And(m_Value(A), m_Value(B))) &&
(A == Op0 || B == Op0))
return Op0;
if (match(Op0, m_Not(m_And(m_Value(A), m_Value(B)))) &&
(A == Op1 || B == Op1))
return Constant::getAllOnesValue(Op1->getType());
if (match(Op1, m_Not(m_And(m_Value(A), m_Value(B)))) &&
(A == Op0 || B == Op0))
return Constant::getAllOnesValue(Op0->getType());
if (Value *V = SimplifyAssociativeBinOp(Instruction::Or, Op0, Op1, Q,
MaxRecurse))
return V;
if (Value *V = ExpandBinOp(Instruction::Or, Op0, Op1, Instruction::And, Q,
MaxRecurse))
return V;
if (Value *V = FactorizeBinOp(Instruction::Or, Op0, Op1, Instruction::And,
Q, MaxRecurse))
return V;
if (isa<SelectInst>(Op0) || isa<SelectInst>(Op1))
if (Value *V = ThreadBinOpOverSelect(Instruction::Or, Op0, Op1, Q,
MaxRecurse))
return V;
if (isa<PHINode>(Op0) || isa<PHINode>(Op1))
if (Value *V = ThreadBinOpOverPHI(Instruction::Or, Op0, Op1, Q, MaxRecurse))
return V;
return 0;
}
Value *llvm::SimplifyOrInst(Value *Op0, Value *Op1, const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyOrInst(Op0, Op1, Query (TD, TLI, DT), RecursionLimit);
}
static Value *SimplifyXorInst(Value *Op0, Value *Op1, const Query &Q,
unsigned MaxRecurse) {
if (Constant *CLHS = dyn_cast<Constant>(Op0)) {
if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
Constant *Ops[] = { CLHS, CRHS };
return ConstantFoldInstOperands(Instruction::Xor, CLHS->getType(),
Ops, Q.TD, Q.TLI);
}
std::swap(Op0, Op1);
}
if (match(Op1, m_Undef()))
return Op1;
if (match(Op1, m_Zero()))
return Op0;
if (Op0 == Op1)
return Constant::getNullValue(Op0->getType());
if (match(Op0, m_Not(m_Specific(Op1))) ||
match(Op1, m_Not(m_Specific(Op0))))
return Constant::getAllOnesValue(Op0->getType());
if (Value *V = SimplifyAssociativeBinOp(Instruction::Xor, Op0, Op1, Q,
MaxRecurse))
return V;
if (Value *V = FactorizeBinOp(Instruction::Xor, Op0, Op1, Instruction::And,
Q, MaxRecurse))
return V;
return 0;
}
Value *llvm::SimplifyXorInst(Value *Op0, Value *Op1, const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyXorInst(Op0, Op1, Query (TD, TLI, DT), RecursionLimit);
}
static Type *GetCompareTy(Value *Op) {
return CmpInst::makeCmpResultType(Op->getType());
}
static Value *ExtractEquivalentCondition(Value *V, CmpInst::Predicate Pred,
Value *LHS, Value *RHS) {
SelectInst *SI = dyn_cast<SelectInst>(V);
if (!SI)
return 0;
CmpInst *Cmp = dyn_cast<CmpInst>(SI->getCondition());
if (!Cmp)
return 0;
Value *CmpLHS = Cmp->getOperand(0), *CmpRHS = Cmp->getOperand(1);
if (Pred == Cmp->getPredicate() && LHS == CmpLHS && RHS == CmpRHS)
return Cmp;
if (Pred == CmpInst::getSwappedPredicate(Cmp->getPredicate()) &&
LHS == CmpRHS && RHS == CmpLHS)
return Cmp;
return 0;
}
static Constant *computePointerICmp(const DataLayout *TD,
const TargetLibraryInfo *TLI,
CmpInst::Predicate Pred,
Value *LHS, Value *RHS) {
LHS = LHS->stripPointerCasts();
RHS = RHS->stripPointerCasts();
if (llvm::isKnownNonNull(LHS, TLI) && isa<ConstantPointerNull>(RHS) &&
(Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE))
return ConstantInt::get(GetCompareTy(LHS),
!CmpInst::isTrueWhenEqual(Pred));
switch (Pred) {
default:
return 0;
case CmpInst::ICMP_EQ:
case CmpInst::ICMP_NE:
break;
case CmpInst::ICMP_UGT:
case CmpInst::ICMP_UGE:
case CmpInst::ICMP_ULT:
case CmpInst::ICMP_ULE:
Pred = ICmpInst::getSignedPredicate(Pred);
break;
}
Constant *LHSOffset = stripAndComputeConstantOffsets(TD, LHS);
Constant *RHSOffset = stripAndComputeConstantOffsets(TD, RHS);
if (LHS == RHS)
return ConstantExpr::getICmp(Pred, LHSOffset, RHSOffset);
if (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE) {
if (isa<AllocaInst>(LHS) &&
(isa<AllocaInst>(RHS) || isa<GlobalVariable>(RHS))) {
ConstantInt *LHSOffsetCI = dyn_cast<ConstantInt>(LHSOffset);
ConstantInt *RHSOffsetCI = dyn_cast<ConstantInt>(RHSOffset);
uint64_t LHSSize, RHSSize;
if (LHSOffsetCI && RHSOffsetCI &&
getObjectSize(LHS, LHSSize, TD, TLI) &&
getObjectSize(RHS, RHSSize, TD, TLI)) {
const APInt &LHSOffsetValue = LHSOffsetCI->getValue();
const APInt &RHSOffsetValue = RHSOffsetCI->getValue();
if (!LHSOffsetValue.isNegative() &&
!RHSOffsetValue.isNegative() &&
LHSOffsetValue.ult(LHSSize) &&
RHSOffsetValue.ult(RHSSize)) {
return ConstantInt::get(GetCompareTy(LHS),
!CmpInst::isTrueWhenEqual(Pred));
}
}
if (!cast<PointerType>(LHS->getType())->isEmptyTy() &&
!cast<PointerType>(RHS->getType())->isEmptyTy() &&
LHSOffset->isNullValue() &&
RHSOffset->isNullValue())
return ConstantInt::get(GetCompareTy(LHS),
!CmpInst::isTrueWhenEqual(Pred));
}
Constant *LHSNoBound = stripAndComputeConstantOffsets(TD, LHS, true);
Constant *RHSNoBound = stripAndComputeConstantOffsets(TD, RHS, true);
if (LHS == RHS)
return ConstantExpr::getICmp(Pred,
ConstantExpr::getAdd(LHSOffset, LHSNoBound),
ConstantExpr::getAdd(RHSOffset, RHSNoBound));
}
return 0;
}
static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const Query &Q, unsigned MaxRecurse) {
CmpInst::Predicate Pred = (CmpInst::Predicate)Predicate;
assert(CmpInst::isIntPredicate(Pred) && "Not an integer compare!");
if (Constant *CLHS = dyn_cast<Constant>(LHS)) {
if (Constant *CRHS = dyn_cast<Constant>(RHS))
return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, Q.TD, Q.TLI);
std::swap(LHS, RHS);
Pred = CmpInst::getSwappedPredicate(Pred);
}
Type *ITy = GetCompareTy(LHS); Type *OpTy = LHS->getType();
if (LHS == RHS || isa<UndefValue>(RHS))
return ConstantInt::get(ITy, CmpInst::isTrueWhenEqual(Pred));
if (OpTy->getScalarType()->isIntegerTy(1)) {
switch (Pred) {
default: break;
case ICmpInst::ICMP_EQ:
if (match(RHS, m_One()))
return LHS;
break;
case ICmpInst::ICMP_NE:
if (match(RHS, m_Zero()))
return LHS;
break;
case ICmpInst::ICMP_UGT:
if (match(RHS, m_Zero()))
return LHS;
break;
case ICmpInst::ICMP_UGE:
if (match(RHS, m_One()))
return LHS;
break;
case ICmpInst::ICMP_SLT:
if (match(RHS, m_Zero()))
return LHS;
break;
case ICmpInst::ICMP_SLE:
if (match(RHS, m_One()))
return LHS;
break;
}
}
if (match(RHS, m_Zero())) {
bool LHSKnownNonNegative, LHSKnownNegative;
switch (Pred) {
default: llvm_unreachable("Unknown ICmp predicate!");
case ICmpInst::ICMP_ULT:
return getFalse(ITy);
case ICmpInst::ICMP_UGE:
return getTrue(ITy);
case ICmpInst::ICMP_EQ:
case ICmpInst::ICMP_ULE:
if (isKnownNonZero(LHS, Q.TD))
return getFalse(ITy);
break;
case ICmpInst::ICMP_NE:
case ICmpInst::ICMP_UGT:
if (isKnownNonZero(LHS, Q.TD))
return getTrue(ITy);
break;
case ICmpInst::ICMP_SLT:
ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, Q.TD);
if (LHSKnownNegative)
return getTrue(ITy);
if (LHSKnownNonNegative)
return getFalse(ITy);
break;
case ICmpInst::ICMP_SLE:
ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, Q.TD);
if (LHSKnownNegative)
return getTrue(ITy);
if (LHSKnownNonNegative && isKnownNonZero(LHS, Q.TD))
return getFalse(ITy);
break;
case ICmpInst::ICMP_SGE:
ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, Q.TD);
if (LHSKnownNegative)
return getFalse(ITy);
if (LHSKnownNonNegative)
return getTrue(ITy);
break;
case ICmpInst::ICMP_SGT:
ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, Q.TD);
if (LHSKnownNegative)
return getFalse(ITy);
if (LHSKnownNonNegative && isKnownNonZero(LHS, Q.TD))
return getTrue(ITy);
break;
}
}
if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
ConstantRange RHS_CR = ICmpInst::makeConstantRange(Pred, CI->getValue());
if (RHS_CR.isEmptySet())
return ConstantInt::getFalse(CI->getContext());
if (RHS_CR.isFullSet())
return ConstantInt::getTrue(CI->getContext());
uint32_t Width = CI->getBitWidth();
APInt Lower = APInt(Width, 0);
APInt Upper = APInt(Width, 0);
ConstantInt *CI2;
if (match(LHS, m_URem(m_Value(), m_ConstantInt(CI2)))) {
Upper = CI2->getValue();
} else if (match(LHS, m_SRem(m_Value(), m_ConstantInt(CI2)))) {
Upper = CI2->getValue().abs();
Lower = (-Upper) + 1;
} else if (match(LHS, m_UDiv(m_ConstantInt(CI2), m_Value()))) {
Upper = CI2->getValue() + 1;
} else if (match(LHS, m_UDiv(m_Value(), m_ConstantInt(CI2)))) {
APInt NegOne = APInt::getAllOnesValue(Width);
if (!CI2->isZero())
Upper = NegOne.udiv(CI2->getValue()) + 1;
} else if (match(LHS, m_SDiv(m_Value(), m_ConstantInt(CI2)))) {
APInt IntMin = APInt::getSignedMinValue(Width);
APInt IntMax = APInt::getSignedMaxValue(Width);
APInt Val = CI2->getValue().abs();
if (!Val.isMinValue()) {
Lower = IntMin.sdiv(Val);
Upper = IntMax.sdiv(Val) + 1;
}
} else if (match(LHS, m_LShr(m_Value(), m_ConstantInt(CI2)))) {
APInt NegOne = APInt::getAllOnesValue(Width);
if (CI2->getValue().ult(Width))
Upper = NegOne.lshr(CI2->getValue()) + 1;
} else if (match(LHS, m_AShr(m_Value(), m_ConstantInt(CI2)))) {
APInt IntMin = APInt::getSignedMinValue(Width);
APInt IntMax = APInt::getSignedMaxValue(Width);
if (CI2->getValue().ult(Width)) {
Lower = IntMin.ashr(CI2->getValue());
Upper = IntMax.ashr(CI2->getValue()) + 1;
}
} else if (match(LHS, m_Or(m_Value(), m_ConstantInt(CI2)))) {
Lower = CI2->getValue();
} else if (match(LHS, m_And(m_Value(), m_ConstantInt(CI2)))) {
Upper = CI2->getValue() + 1;
}
if (Lower != Upper) {
ConstantRange LHS_CR = ConstantRange(Lower, Upper);
if (RHS_CR.contains(LHS_CR))
return ConstantInt::getTrue(RHS->getContext());
if (RHS_CR.inverse().contains(LHS_CR))
return ConstantInt::getFalse(RHS->getContext());
}
}
if (isa<CastInst>(LHS) && (isa<Constant>(RHS) || isa<CastInst>(RHS))) {
Instruction *LI = cast<CastInst>(LHS);
Value *SrcOp = LI->getOperand(0);
Type *SrcTy = SrcOp->getType();
Type *DstTy = LI->getType();
if (MaxRecurse && Q.TD && isa<PtrToIntInst>(LI) &&
Q.TD->getTypeSizeInBits(SrcTy) == DstTy->getPrimitiveSizeInBits()) {
if (Constant *RHSC = dyn_cast<Constant>(RHS)) {
if (Value *V = SimplifyICmpInst(Pred, SrcOp,
ConstantExpr::getIntToPtr(RHSC, SrcTy),
Q, MaxRecurse-1))
return V;
} else if (PtrToIntInst *RI = dyn_cast<PtrToIntInst>(RHS)) {
if (RI->getOperand(0)->getType() == SrcTy)
if (Value *V = SimplifyICmpInst(Pred, SrcOp, RI->getOperand(0),
Q, MaxRecurse-1))
return V;
}
}
if (isa<ZExtInst>(LHS)) {
if (ZExtInst *RI = dyn_cast<ZExtInst>(RHS)) {
if (MaxRecurse && SrcTy == RI->getOperand(0)->getType())
if (Value *V = SimplifyICmpInst(ICmpInst::getUnsignedPredicate(Pred),
SrcOp, RI->getOperand(0), Q,
MaxRecurse-1))
return V;
}
else if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
Constant *Trunc = ConstantExpr::getTrunc(CI, SrcTy);
Constant *RExt = ConstantExpr::getCast(CastInst::ZExt, Trunc, DstTy);
if (RExt == CI && MaxRecurse)
if (Value *V = SimplifyICmpInst(ICmpInst::getUnsignedPredicate(Pred),
SrcOp, Trunc, Q, MaxRecurse-1))
return V;
if (RExt != CI) {
switch (Pred) {
default: llvm_unreachable("Unknown ICmp predicate!");
case ICmpInst::ICMP_EQ:
case ICmpInst::ICMP_UGT:
case ICmpInst::ICMP_UGE:
return ConstantInt::getFalse(CI->getContext());
case ICmpInst::ICMP_NE:
case ICmpInst::ICMP_ULT:
case ICmpInst::ICMP_ULE:
return ConstantInt::getTrue(CI->getContext());
case ICmpInst::ICMP_SGT:
case ICmpInst::ICMP_SGE:
return CI->getValue().isNegative() ?
ConstantInt::getTrue(CI->getContext()) :
ConstantInt::getFalse(CI->getContext());
case ICmpInst::ICMP_SLT:
case ICmpInst::ICMP_SLE:
return CI->getValue().isNegative() ?
ConstantInt::getFalse(CI->getContext()) :
ConstantInt::getTrue(CI->getContext());
}
}
}
}
if (isa<SExtInst>(LHS)) {
if (SExtInst *RI = dyn_cast<SExtInst>(RHS)) {
if (MaxRecurse && SrcTy == RI->getOperand(0)->getType())
if (Value *V = SimplifyICmpInst(Pred, SrcOp, RI->getOperand(0),
Q, MaxRecurse-1))
return V;
}
else if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
Constant *Trunc = ConstantExpr::getTrunc(CI, SrcTy);
Constant *RExt = ConstantExpr::getCast(CastInst::SExt, Trunc, DstTy);
if (RExt == CI && MaxRecurse)
if (Value *V = SimplifyICmpInst(Pred, SrcOp, Trunc, Q, MaxRecurse-1))
return V;
if (RExt != CI) {
switch (Pred) {
default: llvm_unreachable("Unknown ICmp predicate!");
case ICmpInst::ICMP_EQ:
return ConstantInt::getFalse(CI->getContext());
case ICmpInst::ICMP_NE:
return ConstantInt::getTrue(CI->getContext());
case ICmpInst::ICMP_SGT:
case ICmpInst::ICMP_SGE:
return CI->getValue().isNegative() ?
ConstantInt::getTrue(CI->getContext()) :
ConstantInt::getFalse(CI->getContext());
case ICmpInst::ICMP_SLT:
case ICmpInst::ICMP_SLE:
return CI->getValue().isNegative() ?
ConstantInt::getFalse(CI->getContext()) :
ConstantInt::getTrue(CI->getContext());
case ICmpInst::ICMP_UGT:
case ICmpInst::ICMP_UGE:
if (MaxRecurse)
if (Value *V = SimplifyICmpInst(ICmpInst::ICMP_SLT, SrcOp,
Constant::getNullValue(SrcTy),
Q, MaxRecurse-1))
return V;
break;
case ICmpInst::ICMP_ULT:
case ICmpInst::ICMP_ULE:
if (MaxRecurse)
if (Value *V = SimplifyICmpInst(ICmpInst::ICMP_SGE, SrcOp,
Constant::getNullValue(SrcTy),
Q, MaxRecurse-1))
return V;
break;
}
}
}
}
}
BinaryOperator *LBO = dyn_cast<BinaryOperator>(LHS);
BinaryOperator *RBO = dyn_cast<BinaryOperator>(RHS);
if (MaxRecurse && (LBO || RBO)) {
Value *A = 0, *B = 0, *C = 0, *D = 0;
bool NoLHSWrapProblem = false, NoRHSWrapProblem = false;
if (LBO && LBO->getOpcode() == Instruction::Add) {
A = LBO->getOperand(0); B = LBO->getOperand(1);
NoLHSWrapProblem = ICmpInst::isEquality(Pred) ||
(CmpInst::isUnsigned(Pred) && LBO->hasNoUnsignedWrap()) ||
(CmpInst::isSigned(Pred) && LBO->hasNoSignedWrap());
}
if (RBO && RBO->getOpcode() == Instruction::Add) {
C = RBO->getOperand(0); D = RBO->getOperand(1);
NoRHSWrapProblem = ICmpInst::isEquality(Pred) ||
(CmpInst::isUnsigned(Pred) && RBO->hasNoUnsignedWrap()) ||
(CmpInst::isSigned(Pred) && RBO->hasNoSignedWrap());
}
if ((A == RHS || B == RHS) && NoLHSWrapProblem)
if (Value *V = SimplifyICmpInst(Pred, A == RHS ? B : A,
Constant::getNullValue(RHS->getType()),
Q, MaxRecurse-1))
return V;
if ((C == LHS || D == LHS) && NoRHSWrapProblem)
if (Value *V = SimplifyICmpInst(Pred,
Constant::getNullValue(LHS->getType()),
C == LHS ? D : C, Q, MaxRecurse-1))
return V;
if (A && C && (A == C || A == D || B == C || B == D) &&
NoLHSWrapProblem && NoRHSWrapProblem) {
Value *Y, *Z;
if (A == C) {
Y = B;
Z = D;
} else if (A == D) {
Y = B;
Z = C;
} else if (B == C) {
Y = A;
Z = D;
} else {
assert(B == D);
Y = A;
Z = C;
}
if (Value *V = SimplifyICmpInst(Pred, Y, Z, Q, MaxRecurse-1))
return V;
}
}
if (LBO && match(LBO, m_URem(m_Value(), m_Specific(RHS)))) {
bool KnownNonNegative, KnownNegative;
switch (Pred) {
default:
break;
case ICmpInst::ICMP_SGT:
case ICmpInst::ICMP_SGE:
ComputeSignBit(RHS, KnownNonNegative, KnownNegative, Q.TD);
if (!KnownNonNegative)
break;
case ICmpInst::ICMP_EQ:
case ICmpInst::ICMP_UGT:
case ICmpInst::ICMP_UGE:
return getFalse(ITy);
case ICmpInst::ICMP_SLT:
case ICmpInst::ICMP_SLE:
ComputeSignBit(RHS, KnownNonNegative, KnownNegative, Q.TD);
if (!KnownNonNegative)
break;
case ICmpInst::ICMP_NE:
case ICmpInst::ICMP_ULT:
case ICmpInst::ICMP_ULE:
return getTrue(ITy);
}
}
if (RBO && match(RBO, m_URem(m_Value(), m_Specific(LHS)))) {
bool KnownNonNegative, KnownNegative;
switch (Pred) {
default:
break;
case ICmpInst::ICMP_SGT:
case ICmpInst::ICMP_SGE:
ComputeSignBit(LHS, KnownNonNegative, KnownNegative, Q.TD);
if (!KnownNonNegative)
break;
case ICmpInst::ICMP_NE:
case ICmpInst::ICMP_UGT:
case ICmpInst::ICMP_UGE:
return getTrue(ITy);
case ICmpInst::ICMP_SLT:
case ICmpInst::ICMP_SLE:
ComputeSignBit(LHS, KnownNonNegative, KnownNegative, Q.TD);
if (!KnownNonNegative)
break;
case ICmpInst::ICMP_EQ:
case ICmpInst::ICMP_ULT:
case ICmpInst::ICMP_ULE:
return getFalse(ITy);
}
}
if (LBO && match(LBO, m_UDiv(m_Specific(RHS), m_Value()))) {
if (Pred == ICmpInst::ICMP_UGT)
return getFalse(ITy);
if (Pred == ICmpInst::ICMP_ULE)
return getTrue(ITy);
}
if (MaxRecurse && LBO && RBO && LBO->getOpcode() == RBO->getOpcode() &&
LBO->getOperand(1) == RBO->getOperand(1)) {
switch (LBO->getOpcode()) {
default: break;
case Instruction::UDiv:
case Instruction::LShr:
if (ICmpInst::isSigned(Pred))
break;
case Instruction::SDiv:
case Instruction::AShr:
if (!LBO->isExact() || !RBO->isExact())
break;
if (Value *V = SimplifyICmpInst(Pred, LBO->getOperand(0),
RBO->getOperand(0), Q, MaxRecurse-1))
return V;
break;
case Instruction::Shl: {
bool NUW = LBO->hasNoUnsignedWrap() && RBO->hasNoUnsignedWrap();
bool NSW = LBO->hasNoSignedWrap() && RBO->hasNoSignedWrap();
if (!NUW && !NSW)
break;
if (!NSW && ICmpInst::isSigned(Pred))
break;
if (Value *V = SimplifyICmpInst(Pred, LBO->getOperand(0),
RBO->getOperand(0), Q, MaxRecurse-1))
return V;
break;
}
}
}
Value *A, *B;
CmpInst::Predicate P = CmpInst::BAD_ICMP_PREDICATE;
CmpInst::Predicate EqP;
if (match(LHS, m_SMax(m_Value(A), m_Value(B))) && (A == RHS || B == RHS)) {
if (A != RHS) std::swap(A, B); EqP = CmpInst::ICMP_SGE; P = Pred;
} else if (match(RHS, m_SMax(m_Value(A), m_Value(B))) &&
(A == LHS || B == LHS)) {
if (A != LHS) std::swap(A, B); EqP = CmpInst::ICMP_SGE; P = CmpInst::getSwappedPredicate(Pred);
} else if (match(LHS, m_SMin(m_Value(A), m_Value(B))) &&
(A == RHS || B == RHS)) {
if (A != RHS) std::swap(A, B); EqP = CmpInst::ICMP_SLE; P = CmpInst::getSwappedPredicate(Pred);
} else if (match(RHS, m_SMin(m_Value(A), m_Value(B))) &&
(A == LHS || B == LHS)) {
if (A != LHS) std::swap(A, B); EqP = CmpInst::ICMP_SLE; P = Pred;
}
if (P != CmpInst::BAD_ICMP_PREDICATE) {
switch (P) {
default:
break;
case CmpInst::ICMP_EQ:
case CmpInst::ICMP_SLE:
if (Value *V = ExtractEquivalentCondition(LHS, EqP, A, B))
return V;
if (Value *V = ExtractEquivalentCondition(RHS, EqP, A, B))
return V;
if (MaxRecurse)
if (Value *V = SimplifyICmpInst(EqP, A, B, Q, MaxRecurse-1))
return V;
break;
case CmpInst::ICMP_NE:
case CmpInst::ICMP_SGT: {
CmpInst::Predicate InvEqP = CmpInst::getInversePredicate(EqP);
if (Value *V = ExtractEquivalentCondition(LHS, InvEqP, A, B))
return V;
if (Value *V = ExtractEquivalentCondition(RHS, InvEqP, A, B))
return V;
if (MaxRecurse)
if (Value *V = SimplifyICmpInst(InvEqP, A, B, Q, MaxRecurse-1))
return V;
break;
}
case CmpInst::ICMP_SGE:
return getTrue(ITy);
case CmpInst::ICMP_SLT:
return getFalse(ITy);
}
}
P = CmpInst::BAD_ICMP_PREDICATE;
if (match(LHS, m_UMax(m_Value(A), m_Value(B))) && (A == RHS || B == RHS)) {
if (A != RHS) std::swap(A, B); EqP = CmpInst::ICMP_UGE; P = Pred;
} else if (match(RHS, m_UMax(m_Value(A), m_Value(B))) &&
(A == LHS || B == LHS)) {
if (A != LHS) std::swap(A, B); EqP = CmpInst::ICMP_UGE; P = CmpInst::getSwappedPredicate(Pred);
} else if (match(LHS, m_UMin(m_Value(A), m_Value(B))) &&
(A == RHS || B == RHS)) {
if (A != RHS) std::swap(A, B); EqP = CmpInst::ICMP_ULE; P = CmpInst::getSwappedPredicate(Pred);
} else if (match(RHS, m_UMin(m_Value(A), m_Value(B))) &&
(A == LHS || B == LHS)) {
if (A != LHS) std::swap(A, B); EqP = CmpInst::ICMP_ULE; P = Pred;
}
if (P != CmpInst::BAD_ICMP_PREDICATE) {
switch (P) {
default:
break;
case CmpInst::ICMP_EQ:
case CmpInst::ICMP_ULE:
if (Value *V = ExtractEquivalentCondition(LHS, EqP, A, B))
return V;
if (Value *V = ExtractEquivalentCondition(RHS, EqP, A, B))
return V;
if (MaxRecurse)
if (Value *V = SimplifyICmpInst(EqP, A, B, Q, MaxRecurse-1))
return V;
break;
case CmpInst::ICMP_NE:
case CmpInst::ICMP_UGT: {
CmpInst::Predicate InvEqP = CmpInst::getInversePredicate(EqP);
if (Value *V = ExtractEquivalentCondition(LHS, InvEqP, A, B))
return V;
if (Value *V = ExtractEquivalentCondition(RHS, InvEqP, A, B))
return V;
if (MaxRecurse)
if (Value *V = SimplifyICmpInst(InvEqP, A, B, Q, MaxRecurse-1))
return V;
break;
}
case CmpInst::ICMP_UGE:
return getTrue(ITy);
case CmpInst::ICMP_ULT:
return getFalse(ITy);
}
}
Value *C, *D;
if (match(LHS, m_SMax(m_Value(A), m_Value(B))) &&
match(RHS, m_SMin(m_Value(C), m_Value(D))) &&
(A == C || A == D || B == C || B == D)) {
if (Pred == CmpInst::ICMP_SGE)
return getTrue(ITy);
if (Pred == CmpInst::ICMP_SLT)
return getFalse(ITy);
} else if (match(LHS, m_SMin(m_Value(A), m_Value(B))) &&
match(RHS, m_SMax(m_Value(C), m_Value(D))) &&
(A == C || A == D || B == C || B == D)) {
if (Pred == CmpInst::ICMP_SLE)
return getTrue(ITy);
if (Pred == CmpInst::ICMP_SGT)
return getFalse(ITy);
} else if (match(LHS, m_UMax(m_Value(A), m_Value(B))) &&
match(RHS, m_UMin(m_Value(C), m_Value(D))) &&
(A == C || A == D || B == C || B == D)) {
if (Pred == CmpInst::ICMP_UGE)
return getTrue(ITy);
if (Pred == CmpInst::ICMP_ULT)
return getFalse(ITy);
} else if (match(LHS, m_UMin(m_Value(A), m_Value(B))) &&
match(RHS, m_UMax(m_Value(C), m_Value(D))) &&
(A == C || A == D || B == C || B == D)) {
if (Pred == CmpInst::ICMP_ULE)
return getTrue(ITy);
if (Pred == CmpInst::ICMP_UGT)
return getFalse(ITy);
}
if (LHS->getType()->isPointerTy())
if (Constant *C = computePointerICmp(Q.TD, Q.TLI, Pred, LHS, RHS))
return C;
if (GetElementPtrInst *GLHS = dyn_cast<GetElementPtrInst>(LHS)) {
if (GEPOperator *GRHS = dyn_cast<GEPOperator>(RHS)) {
if (GLHS->getPointerOperand() == GRHS->getPointerOperand() &&
GLHS->hasAllConstantIndices() && GRHS->hasAllConstantIndices() &&
(ICmpInst::isEquality(Pred) ||
(GLHS->isInBounds() && GRHS->isInBounds() &&
Pred == ICmpInst::getSignedPredicate(Pred)))) {
Constant *Null = Constant::getNullValue(GLHS->getPointerOperandType());
SmallVector<Value *, 4> IndicesLHS(GLHS->idx_begin(), GLHS->idx_end());
Constant *NewLHS = ConstantExpr::getGetElementPtr(Null, IndicesLHS);
SmallVector<Value *, 4> IndicesRHS(GRHS->idx_begin(), GRHS->idx_end());
Constant *NewRHS = ConstantExpr::getGetElementPtr(Null, IndicesRHS);
return ConstantExpr::getICmp(Pred, NewLHS, NewRHS);
}
}
}
if (isa<SelectInst>(LHS) || isa<SelectInst>(RHS))
if (Value *V = ThreadCmpOverSelect(Pred, LHS, RHS, Q, MaxRecurse))
return V;
if (isa<PHINode>(LHS) || isa<PHINode>(RHS))
if (Value *V = ThreadCmpOverPHI(Pred, LHS, RHS, Q, MaxRecurse))
return V;
return 0;
}
Value *llvm::SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyICmpInst(Predicate, LHS, RHS, Query (TD, TLI, DT),
RecursionLimit);
}
static Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const Query &Q, unsigned MaxRecurse) {
CmpInst::Predicate Pred = (CmpInst::Predicate)Predicate;
assert(CmpInst::isFPPredicate(Pred) && "Not an FP compare!");
if (Constant *CLHS = dyn_cast<Constant>(LHS)) {
if (Constant *CRHS = dyn_cast<Constant>(RHS))
return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, Q.TD, Q.TLI);
std::swap(LHS, RHS);
Pred = CmpInst::getSwappedPredicate(Pred);
}
if (Pred == FCmpInst::FCMP_FALSE)
return ConstantInt::get(GetCompareTy(LHS), 0);
if (Pred == FCmpInst::FCMP_TRUE)
return ConstantInt::get(GetCompareTy(LHS), 1);
if (isa<UndefValue>(RHS)) return UndefValue::get(GetCompareTy(LHS));
if (LHS == RHS) {
if (CmpInst::isTrueWhenEqual(Pred))
return ConstantInt::get(GetCompareTy(LHS), 1);
if (CmpInst::isFalseWhenEqual(Pred))
return ConstantInt::get(GetCompareTy(LHS), 0);
}
if (Constant *RHSC = dyn_cast<Constant>(RHS)) {
if (ConstantFP *CFP = dyn_cast<ConstantFP>(RHSC)) {
if (CFP->getValueAPF().isNaN()) {
if (FCmpInst::isOrdered(Pred)) return ConstantInt::getFalse(CFP->getContext());
assert(FCmpInst::isUnordered(Pred) &&
"Comparison must be either ordered or unordered!");
return ConstantInt::getTrue(CFP->getContext());
}
if (CFP->getValueAPF().isInfinity()) {
if (CFP->getValueAPF().isNegative()) {
switch (Pred) {
case FCmpInst::FCMP_OLT:
return ConstantInt::getFalse(CFP->getContext());
case FCmpInst::FCMP_UGE:
return ConstantInt::getTrue(CFP->getContext());
default:
break;
}
} else {
switch (Pred) {
case FCmpInst::FCMP_OGT:
return ConstantInt::getFalse(CFP->getContext());
case FCmpInst::FCMP_ULE:
return ConstantInt::getTrue(CFP->getContext());
default:
break;
}
}
}
}
}
if (isa<SelectInst>(LHS) || isa<SelectInst>(RHS))
if (Value *V = ThreadCmpOverSelect(Pred, LHS, RHS, Q, MaxRecurse))
return V;
if (isa<PHINode>(LHS) || isa<PHINode>(RHS))
if (Value *V = ThreadCmpOverPHI(Pred, LHS, RHS, Q, MaxRecurse))
return V;
return 0;
}
Value *llvm::SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyFCmpInst(Predicate, LHS, RHS, Query (TD, TLI, DT),
RecursionLimit);
}
static Value *SimplifySelectInst(Value *CondVal, Value *TrueVal,
Value *FalseVal, const Query &Q,
unsigned MaxRecurse) {
if (ConstantInt *CB = dyn_cast<ConstantInt>(CondVal))
return CB->getZExtValue() ? TrueVal : FalseVal;
if (TrueVal == FalseVal)
return TrueVal;
if (isa<UndefValue>(CondVal)) { if (isa<Constant>(TrueVal))
return TrueVal;
return FalseVal;
}
if (isa<UndefValue>(TrueVal)) return FalseVal;
if (isa<UndefValue>(FalseVal)) return TrueVal;
return 0;
}
Value *llvm::SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifySelectInst(Cond, TrueVal, FalseVal, Query (TD, TLI, DT),
RecursionLimit);
}
static Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const Query &Q, unsigned) {
PointerType *PtrTy = dyn_cast<PointerType>(Ops[0]->getType());
if (!PtrTy)
return 0;
if (Ops.size() == 1)
return Ops[0];
if (isa<UndefValue>(Ops[0])) {
Type *LastType = GetElementPtrInst::getIndexedType(PtrTy, Ops.slice(1));
Type *GEPTy = PointerType::get(LastType, PtrTy->getAddressSpace());
return UndefValue::get(GEPTy);
}
if (Ops.size() == 2) {
if (ConstantInt *C = dyn_cast<ConstantInt>(Ops[1]))
if (C->isZero())
return Ops[0];
if (Q.TD) {
Type *Ty = PtrTy->getElementType();
if (Ty->isSized() && Q.TD->getTypeAllocSize(Ty) == 0)
return Ops[0];
}
}
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
if (!isa<Constant>(Ops[i]))
return 0;
return ConstantExpr::getGetElementPtr(cast<Constant>(Ops[0]), Ops.slice(1));
}
Value *llvm::SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyGEPInst(Ops, Query (TD, TLI, DT), RecursionLimit);
}
static Value *SimplifyInsertValueInst(Value *Agg, Value *Val,
ArrayRef<unsigned> Idxs, const Query &Q,
unsigned) {
if (Constant *CAgg = dyn_cast<Constant>(Agg))
if (Constant *CVal = dyn_cast<Constant>(Val))
return ConstantFoldInsertValueInstruction(CAgg, CVal, Idxs);
if (match(Val, m_Undef()))
return Agg;
if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(Val))
if (EV->getAggregateOperand()->getType() == Agg->getType() &&
EV->getIndices() == Idxs) {
if (match(Agg, m_Undef()))
return EV->getAggregateOperand();
if (Agg == EV->getAggregateOperand())
return Agg;
}
return 0;
}
Value *llvm::SimplifyInsertValueInst(Value *Agg, Value *Val,
ArrayRef<unsigned> Idxs,
const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyInsertValueInst(Agg, Val, Idxs, Query (TD, TLI, DT),
RecursionLimit);
}
static Value *SimplifyPHINode(PHINode *PN, const Query &Q) {
Value *CommonValue = 0;
bool HasUndefInput = false;
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
Value *Incoming = PN->getIncomingValue(i);
if (Incoming == PN) continue;
if (isa<UndefValue>(Incoming)) {
HasUndefInput = true;
continue;
}
if (CommonValue && Incoming != CommonValue)
return 0; CommonValue = Incoming;
}
if (!CommonValue)
return UndefValue::get(PN->getType());
if (HasUndefInput)
return ValueDominatesPHI(CommonValue, PN, Q.DT) ? CommonValue : 0;
return CommonValue;
}
static Value *SimplifyTruncInst(Value *Op, Type *Ty, const Query &Q, unsigned) {
if (Constant *C = dyn_cast<Constant>(Op))
return ConstantFoldInstOperands(Instruction::Trunc, Ty, C, Q.TD, Q.TLI);
return 0;
}
Value *llvm::SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyTruncInst(Op, Ty, Query (TD, TLI, DT), RecursionLimit);
}
static Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
const Query &Q, unsigned MaxRecurse) {
switch (Opcode) {
case Instruction::Add:
return SimplifyAddInst(LHS, RHS, false, false,
Q, MaxRecurse);
case Instruction::FAdd:
return SimplifyFAddInst(LHS, RHS, FastMathFlags(), Q, MaxRecurse);
case Instruction::Sub:
return SimplifySubInst(LHS, RHS, false, false,
Q, MaxRecurse);
case Instruction::FSub:
return SimplifyFSubInst(LHS, RHS, FastMathFlags(), Q, MaxRecurse);
case Instruction::Mul: return SimplifyMulInst (LHS, RHS, Q, MaxRecurse);
case Instruction::FMul:
return SimplifyFMulInst (LHS, RHS, FastMathFlags(), Q, MaxRecurse);
case Instruction::SDiv: return SimplifySDivInst(LHS, RHS, Q, MaxRecurse);
case Instruction::UDiv: return SimplifyUDivInst(LHS, RHS, Q, MaxRecurse);
case Instruction::FDiv: return SimplifyFDivInst(LHS, RHS, Q, MaxRecurse);
case Instruction::SRem: return SimplifySRemInst(LHS, RHS, Q, MaxRecurse);
case Instruction::URem: return SimplifyURemInst(LHS, RHS, Q, MaxRecurse);
case Instruction::FRem: return SimplifyFRemInst(LHS, RHS, Q, MaxRecurse);
case Instruction::Shl:
return SimplifyShlInst(LHS, RHS, false, false,
Q, MaxRecurse);
case Instruction::LShr:
return SimplifyLShrInst(LHS, RHS, false, Q, MaxRecurse);
case Instruction::AShr:
return SimplifyAShrInst(LHS, RHS, false, Q, MaxRecurse);
case Instruction::And: return SimplifyAndInst(LHS, RHS, Q, MaxRecurse);
case Instruction::Or: return SimplifyOrInst (LHS, RHS, Q, MaxRecurse);
case Instruction::Xor: return SimplifyXorInst(LHS, RHS, Q, MaxRecurse);
default:
if (Constant *CLHS = dyn_cast<Constant>(LHS))
if (Constant *CRHS = dyn_cast<Constant>(RHS)) {
Constant *COps[] = {CLHS, CRHS};
return ConstantFoldInstOperands(Opcode, LHS->getType(), COps, Q.TD,
Q.TLI);
}
if (Instruction::isAssociative(Opcode))
if (Value *V = SimplifyAssociativeBinOp(Opcode, LHS, RHS, Q, MaxRecurse))
return V;
if (isa<SelectInst>(LHS) || isa<SelectInst>(RHS))
if (Value *V = ThreadBinOpOverSelect(Opcode, LHS, RHS, Q, MaxRecurse))
return V;
if (isa<PHINode>(LHS) || isa<PHINode>(RHS))
if (Value *V = ThreadBinOpOverPHI(Opcode, LHS, RHS, Q, MaxRecurse))
return V;
return 0;
}
}
Value *llvm::SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
const DataLayout *TD, const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyBinOp(Opcode, LHS, RHS, Query (TD, TLI, DT), RecursionLimit);
}
static Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const Query &Q, unsigned MaxRecurse) {
if (CmpInst::isIntPredicate((CmpInst::Predicate)Predicate))
return SimplifyICmpInst(Predicate, LHS, RHS, Q, MaxRecurse);
return SimplifyFCmpInst(Predicate, LHS, RHS, Q, MaxRecurse);
}
Value *llvm::SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout *TD, const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyCmpInst(Predicate, LHS, RHS, Query (TD, TLI, DT),
RecursionLimit);
}
static bool IsIdempotent(Intrinsic::ID ID) {
switch (ID) {
default: return false;
case Intrinsic::fabs:
case Intrinsic::floor:
case Intrinsic::ceil:
case Intrinsic::trunc:
case Intrinsic::rint:
case Intrinsic::nearbyint:
case Intrinsic::round:
return true;
}
}
template <typename IterTy>
static Value *SimplifyIntrinsic(Intrinsic::ID IID, IterTy ArgBegin, IterTy ArgEnd,
const Query &Q, unsigned MaxRecurse) {
if (!IsIdempotent(IID))
return 0;
if (std::distance(ArgBegin, ArgEnd) == 1)
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(*ArgBegin))
if (II->getIntrinsicID() == IID)
return II;
return 0;
}
template <typename IterTy>
static Value *SimplifyCall(Value *V, IterTy ArgBegin, IterTy ArgEnd,
const Query &Q, unsigned MaxRecurse) {
Type *Ty = V->getType();
if (PointerType *PTy = dyn_cast<PointerType>(Ty))
Ty = PTy->getElementType();
FunctionType *FTy = cast<FunctionType>(Ty);
if (isa<UndefValue>(V))
return UndefValue::get(FTy->getReturnType());
Function *F = dyn_cast<Function>(V);
if (!F)
return 0;
if (unsigned IID = F->getIntrinsicID())
if (Value *Ret =
SimplifyIntrinsic((Intrinsic::ID) IID, ArgBegin, ArgEnd, Q, MaxRecurse))
return Ret;
if (!canConstantFoldCallTo(F))
return 0;
SmallVector<Constant *, 4> ConstantArgs;
ConstantArgs.reserve(ArgEnd - ArgBegin);
for (IterTy I = ArgBegin, E = ArgEnd; I != E; ++I) {
Constant *C = dyn_cast<Constant>(*I);
if (!C)
return 0;
ConstantArgs.push_back(C);
}
return ConstantFoldCall(F, ConstantArgs, Q.TLI);
}
Value *llvm::SimplifyCall(Value *V, User::op_iterator ArgBegin,
User::op_iterator ArgEnd, const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyCall(V, ArgBegin, ArgEnd, Query(TD, TLI, DT),
RecursionLimit);
}
Value *llvm::SimplifyCall(Value *V, ArrayRef<Value *> Args,
const DataLayout *TD, const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyCall(V, Args.begin(), Args.end(), Query(TD, TLI, DT),
RecursionLimit);
}
Value *llvm::SimplifyInstruction(Instruction *I, const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
Value *Result;
switch (I->getOpcode()) {
default:
Result = ConstantFoldInstruction(I, TD, TLI);
break;
case Instruction::FAdd:
Result = SimplifyFAddInst(I->getOperand(0), I->getOperand(1),
I->getFastMathFlags(), TD, TLI, DT);
break;
case Instruction::Add:
Result = SimplifyAddInst(I->getOperand(0), I->getOperand(1),
cast<BinaryOperator>(I)->hasNoSignedWrap(),
cast<BinaryOperator>(I)->hasNoUnsignedWrap(),
TD, TLI, DT);
break;
case Instruction::FSub:
Result = SimplifyFSubInst(I->getOperand(0), I->getOperand(1),
I->getFastMathFlags(), TD, TLI, DT);
break;
case Instruction::Sub:
Result = SimplifySubInst(I->getOperand(0), I->getOperand(1),
cast<BinaryOperator>(I)->hasNoSignedWrap(),
cast<BinaryOperator>(I)->hasNoUnsignedWrap(),
TD, TLI, DT);
break;
case Instruction::FMul:
Result = SimplifyFMulInst(I->getOperand(0), I->getOperand(1),
I->getFastMathFlags(), TD, TLI, DT);
break;
case Instruction::Mul:
Result = SimplifyMulInst(I->getOperand(0), I->getOperand(1), TD, TLI, DT);
break;
case Instruction::SDiv:
Result = SimplifySDivInst(I->getOperand(0), I->getOperand(1), TD, TLI, DT);
break;
case Instruction::UDiv:
Result = SimplifyUDivInst(I->getOperand(0), I->getOperand(1), TD, TLI, DT);
break;
case Instruction::FDiv:
Result = SimplifyFDivInst(I->getOperand(0), I->getOperand(1), TD, TLI, DT);
break;
case Instruction::SRem:
Result = SimplifySRemInst(I->getOperand(0), I->getOperand(1), TD, TLI, DT);
break;
case Instruction::URem:
Result = SimplifyURemInst(I->getOperand(0), I->getOperand(1), TD, TLI, DT);
break;
case Instruction::FRem:
Result = SimplifyFRemInst(I->getOperand(0), I->getOperand(1), TD, TLI, DT);
break;
case Instruction::Shl:
Result = SimplifyShlInst(I->getOperand(0), I->getOperand(1),
cast<BinaryOperator>(I)->hasNoSignedWrap(),
cast<BinaryOperator>(I)->hasNoUnsignedWrap(),
TD, TLI, DT);
break;
case Instruction::LShr:
Result = SimplifyLShrInst(I->getOperand(0), I->getOperand(1),
cast<BinaryOperator>(I)->isExact(),
TD, TLI, DT);
break;
case Instruction::AShr:
Result = SimplifyAShrInst(I->getOperand(0), I->getOperand(1),
cast<BinaryOperator>(I)->isExact(),
TD, TLI, DT);
break;
case Instruction::And:
Result = SimplifyAndInst(I->getOperand(0), I->getOperand(1), TD, TLI, DT);
break;
case Instruction::Or:
Result = SimplifyOrInst(I->getOperand(0), I->getOperand(1), TD, TLI, DT);
break;
case Instruction::Xor:
Result = SimplifyXorInst(I->getOperand(0), I->getOperand(1), TD, TLI, DT);
break;
case Instruction::ICmp:
Result = SimplifyICmpInst(cast<ICmpInst>(I)->getPredicate(),
I->getOperand(0), I->getOperand(1), TD, TLI, DT);
break;
case Instruction::FCmp:
Result = SimplifyFCmpInst(cast<FCmpInst>(I)->getPredicate(),
I->getOperand(0), I->getOperand(1), TD, TLI, DT);
break;
case Instruction::Select:
Result = SimplifySelectInst(I->getOperand(0), I->getOperand(1),
I->getOperand(2), TD, TLI, DT);
break;
case Instruction::GetElementPtr: {
SmallVector<Value*, 8> Ops(I->op_begin(), I->op_end());
Result = SimplifyGEPInst(Ops, TD, TLI, DT);
break;
}
case Instruction::InsertValue: {
InsertValueInst *IV = cast<InsertValueInst>(I);
Result = SimplifyInsertValueInst(IV->getAggregateOperand(),
IV->getInsertedValueOperand(),
IV->getIndices(), TD, TLI, DT);
break;
}
case Instruction::PHI:
Result = SimplifyPHINode(cast<PHINode>(I), Query (TD, TLI, DT));
break;
case Instruction::Call: {
CallSite CS(cast<CallInst>(I));
Result = SimplifyCall(CS.getCalledValue(), CS.arg_begin(), CS.arg_end(),
TD, TLI, DT);
break;
}
case Instruction::Trunc:
Result = SimplifyTruncInst(I->getOperand(0), I->getType(), TD, TLI, DT);
break;
}
return Result == I ? UndefValue::get(I->getType()) : Result;
}
static bool replaceAndRecursivelySimplifyImpl(Instruction *I, Value *SimpleV,
const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
bool Simplified = false;
SmallSetVector<Instruction *, 8> Worklist;
if (SimpleV) {
for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); UI != UE;
++UI)
if (*UI != I)
Worklist.insert(cast<Instruction>(*UI));
I->replaceAllUsesWith(SimpleV);
if (I->getParent())
I->eraseFromParent();
} else {
Worklist.insert(I);
}
for (unsigned Idx = 0; Idx != Worklist.size(); ++Idx) {
I = Worklist[Idx];
SimpleV = SimplifyInstruction(I, TD, TLI, DT);
if (!SimpleV)
continue;
Simplified = true;
for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); UI != UE;
++UI)
Worklist.insert(cast<Instruction>(*UI));
I->replaceAllUsesWith(SimpleV);
if (I->getParent())
I->eraseFromParent();
}
return Simplified;
}
bool llvm::recursivelySimplifyInstruction(Instruction *I,
const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return replaceAndRecursivelySimplifyImpl(I, 0, TD, TLI, DT);
}
bool llvm::replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV,
const DataLayout *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
assert(I != SimpleV && "replaceAndRecursivelySimplify(X,X) is not valid!");
assert(SimpleV && "Must provide a simplified value.");
return replaceAndRecursivelySimplifyImpl(I, SimpleV, TD, TLI, DT);
}