From 8d25a7c3a01639636bde0ff17f2d8962010cfd29 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Thu, 13 Jan 2011 08:56:29 +0000 Subject: [PATCH] The most common simplification missed by instsimplify in unoptimized bitcode is "X != 0 -> X" when X is a boolean. This occurs a lot because of the way llvm-gcc converts gcc's conditional expressions. Add this, and a few other similar transforms for completeness. llvm-svn: 123372 --- llvm/lib/Analysis/InstructionSimplify.cpp | 107 +++++++++++++----- .../InstSimplify/2010-12-20-I1Arithmetic.ll | 7 ++ 2 files changed, 86 insertions(+), 28 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 030d61a651b0..b3a3acab6148 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -938,8 +938,8 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, Pred = CmpInst::getSwappedPredicate(Pred); } - // ITy - This is the return type of the compare we're considering. - const Type *ITy = GetCompareTy(LHS); + const Type *ITy = GetCompareTy(LHS); // The return type. + const Type *OpTy = LHS->getType(); // The operand type. // icmp X, X -> true/false // X icmp undef -> true/false. For example, icmp ugt %X, undef -> false @@ -947,6 +947,83 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, if (LHS == RHS || isa(RHS)) return ConstantInt::get(ITy, CmpInst::isTrueWhenEqual(Pred)); + // Special case logic when the operands have i1 type. + if (OpTy->isIntegerTy(1) || (OpTy->isVectorTy() && + cast(OpTy)->getElementType()->isIntegerTy(1))) { + switch (Pred) { + default: break; + case ICmpInst::ICMP_EQ: + // X == 1 -> X + if (match(RHS, m_One())) + return LHS; + break; + case ICmpInst::ICMP_NE: + // X != 0 -> X + if (match(RHS, m_Zero())) + return LHS; + break; + case ICmpInst::ICMP_UGT: + // X >u 0 -> X + if (match(RHS, m_Zero())) + return LHS; + break; + case ICmpInst::ICMP_UGE: + // X >=u 1 -> X + if (match(RHS, m_One())) + return LHS; + break; + case ICmpInst::ICMP_SLT: + // X X + if (match(RHS, m_Zero())) + return LHS; + break; + case ICmpInst::ICMP_SLE: + // X <=s -1 -> X + if (match(RHS, m_One())) + return LHS; + break; + } + } + + // See if we are doing a comparison with a constant. + if (ConstantInt *CI = dyn_cast(RHS)) { + switch (Pred) { + default: break; + case ICmpInst::ICMP_UGT: + if (CI->isMaxValue(false)) // A >u MAX -> FALSE + return ConstantInt::getFalse(CI->getContext()); + break; + case ICmpInst::ICMP_UGE: + if (CI->isMinValue(false)) // A >=u MIN -> TRUE + return ConstantInt::getTrue(CI->getContext()); + break; + case ICmpInst::ICMP_ULT: + if (CI->isMinValue(false)) // A FALSE + return ConstantInt::getFalse(CI->getContext()); + break; + case ICmpInst::ICMP_ULE: + if (CI->isMaxValue(false)) // A <=u MAX -> TRUE + return ConstantInt::getTrue(CI->getContext()); + break; + case ICmpInst::ICMP_SGT: + if (CI->isMaxValue(true)) // A >s MAX -> FALSE + return ConstantInt::getFalse(CI->getContext()); + break; + case ICmpInst::ICMP_SGE: + if (CI->isMinValue(true)) // A >=s MIN -> TRUE + return ConstantInt::getTrue(CI->getContext()); + break; + case ICmpInst::ICMP_SLT: + if (CI->isMinValue(true)) // A FALSE + return ConstantInt::getFalse(CI->getContext()); + break; + case ICmpInst::ICMP_SLE: + if (CI->isMaxValue(true)) // A <=s MAX -> TRUE + return ConstantInt::getTrue(CI->getContext()); + break; + } + } + // icmp , - Global/Stack value // addresses never equal each other! We already know that Op0 != Op1. if ((isa(LHS) || isa(LHS) || @@ -955,32 +1032,6 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, isa(RHS))) return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred)); - // See if we are doing a comparison with a constant. - if (ConstantInt *CI = dyn_cast(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; - } - } - // If the comparison is with the result of a select instruction, check whether // comparing with either branch of the select always yields the same value. if (isa(LHS) || isa(RHS)) diff --git a/llvm/test/Transforms/InstSimplify/2010-12-20-I1Arithmetic.ll b/llvm/test/Transforms/InstSimplify/2010-12-20-I1Arithmetic.ll index 8b795eaaab6b..3aa1bd60cfd6 100644 --- a/llvm/test/Transforms/InstSimplify/2010-12-20-I1Arithmetic.ll +++ b/llvm/test/Transforms/InstSimplify/2010-12-20-I1Arithmetic.ll @@ -20,3 +20,10 @@ define i1 @mul(i1 %x) { ret i1 %z ; CHECK: ret i1 %x } + +define i1 @ne(i1 %x) { +; CHECK: @ne + %z = icmp ne i1 %x, 0 + ret i1 %z +; CHECK: ret i1 %x +}