1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 11:42:57 +01:00

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
This commit is contained in:
Duncan Sands 2011-01-13 08:56:29 +00:00
parent cc474b4864
commit 36b007d63b
2 changed files with 86 additions and 28 deletions

View File

@ -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<UndefValue>(RHS))
return ConstantInt::get(ITy, CmpInst::isTrueWhenEqual(Pred));
// Special case logic when the operands have i1 type.
if (OpTy->isIntegerTy(1) || (OpTy->isVectorTy() &&
cast<VectorType>(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 <s 0 -> 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<ConstantInt>(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 <u MIN -> 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 <s MIN -> 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/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) ||
@ -955,32 +1032,6 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *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;
}
}
// 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<SelectInst>(LHS) || isa<SelectInst>(RHS))

View File

@ -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
}