diff options
author | Chris Lattner <sabre@nondot.org> | 2009-11-09 23:55:12 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-11-09 23:55:12 +0000 |
commit | 210c5d4880b525e064088b6fec713260128c16eb (patch) | |
tree | a2e5f400cc8972843f091742aa7b9750479c2748 /lib/Analysis | |
parent | 1ba3b6c5654ac6c0cf6ff278e0130c6f2f5ef97d (diff) | |
download | external_llvm-210c5d4880b525e064088b6fec713260128c16eb.zip external_llvm-210c5d4880b525e064088b6fec713260128c16eb.tar.gz external_llvm-210c5d4880b525e064088b6fec713260128c16eb.tar.bz2 |
pull a bunch of logic out of instcombine into instsimplify for compare
simplification, this handles the foldable fcmp x,x cases among many others.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@86627 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis')
-rw-r--r-- | lib/Analysis/InstructionSimplify.cpp | 98 |
1 files changed, 93 insertions, 5 deletions
diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 0369ab3..367a7d4 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -31,6 +31,10 @@ Value *llvm::SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, return 0; } +static const Type *GetCompareTy(Value *Op) { + return CmpInst::makeCmpResultType(Op->getType()); +} + /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can /// fold the result. If not, this returns null. @@ -43,13 +47,59 @@ Value *llvm::SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, if (Constant *CRHS = dyn_cast<Constant>(RHS)) return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, TD); - // If this is an integer compare and the LHS and RHS are the same, fold it. + // ITy - This is the return type of the compare we're considering. + const Type *ITy = GetCompareTy(LHS); + + // icmp X, X -> true/false if (LHS == RHS) - if (ICmpInst::isTrueWhenEqual(Pred)) - return ConstantInt::getTrue(LHS->getContext()); - else - return ConstantInt::getFalse(LHS->getContext()); + return ConstantInt::get(ITy, CmpInst::isTrueWhenEqual(Pred)); + + // If we have a constant, make sure it is on the RHS. + if (isa<Constant>(LHS)) { + std::swap(LHS, RHS); + Pred = CmpInst::getSwappedPredicate(Pred); + } + if (isa<UndefValue>(RHS)) // X icmp undef -> undef + return UndefValue::get(ITy); + + // icmp <global/alloca*/null>, <global/alloca*/null> - Global/Stack value + // addresses never equal each other! We already know that Op0 != Op1. + if ((isa<GlobalValue>(LHS) || isa<AllocaInst>(LHS) || + isa<ConstantPointerNull>(LHS)) && + (isa<GlobalValue>(RHS) || isa<AllocaInst>(RHS) || + isa<ConstantPointerNull>(RHS))) + return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred)); + + // See if we are doing a comparison with a constant. + if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) { + // If we have an icmp le or icmp ge instruction, turn it into the + // appropriate icmp lt or icmp gt instruction. This allows us to rely on + // them being folded in the code below. + switch (Pred) { + default: break; + case ICmpInst::ICMP_ULE: + if (CI->isMaxValue(false)) // A <=u MAX -> TRUE + return ConstantInt::getTrue(CI->getContext()); + break; + case ICmpInst::ICMP_SLE: + if (CI->isMaxValue(true)) // A <=s MAX -> TRUE + return ConstantInt::getTrue(CI->getContext()); + break; + case ICmpInst::ICMP_UGE: + if (CI->isMinValue(false)) // A >=u MIN -> TRUE + return ConstantInt::getTrue(CI->getContext()); + break; + case ICmpInst::ICMP_SGE: + if (CI->isMinValue(true)) // A >=s MIN -> TRUE + return ConstantInt::getTrue(CI->getContext()); + break; + } + + + } + + return 0; } @@ -64,6 +114,44 @@ Value *llvm::SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, if (Constant *CRHS = dyn_cast<Constant>(RHS)) return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, TD); + // Fold trivial predicates. + if (Pred == FCmpInst::FCMP_FALSE) + return ConstantInt::get(GetCompareTy(LHS), 0); + if (Pred == FCmpInst::FCMP_TRUE) + return ConstantInt::get(GetCompareTy(LHS), 1); + + // If we have a constant, make sure it is on the RHS. + if (isa<Constant>(LHS)) { + std::swap(LHS, RHS); + Pred = CmpInst::getSwappedPredicate(Pred); + } + + if (isa<UndefValue>(RHS)) // fcmp pred X, undef -> undef + return UndefValue::get(GetCompareTy(LHS)); + + // fcmp x,x -> true/false. Not all compares are foldable. + if (LHS == RHS) { + if (CmpInst::isTrueWhenEqual(Pred)) + return ConstantInt::get(GetCompareTy(LHS), 1); + if (CmpInst::isFalseWhenEqual(Pred)) + return ConstantInt::get(GetCompareTy(LHS), 0); + } + + // Handle fcmp with constant RHS + if (Constant *RHSC = dyn_cast<Constant>(RHS)) { + // If the constant is a nan, see if we can fold the comparison based on it. + if (ConstantFP *CFP = dyn_cast<ConstantFP>(RHSC)) { + if (CFP->getValueAPF().isNaN()) { + if (FCmpInst::isOrdered(Pred)) // True "if ordered and foo" + return ConstantInt::getFalse(CFP->getContext()); + assert(FCmpInst::isUnordered(Pred) && + "Comparison must be either ordered or unordered!"); + // True if unordered. + return ConstantInt::getTrue(CFP->getContext()); + } + } + } + return 0; } |