mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-29 14:40:25 +00:00
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
This commit is contained in:
parent
1ba3b6c565
commit
210c5d4880
@ -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;
|
||||
}
|
||||
|
||||
|
@ -5941,26 +5941,14 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
|
||||
}
|
||||
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
|
||||
// Fold trivial predicates.
|
||||
if (I.getPredicate() == FCmpInst::FCMP_FALSE)
|
||||
return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), 0));
|
||||
if (I.getPredicate() == FCmpInst::FCMP_TRUE)
|
||||
return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), 1));
|
||||
|
||||
if (Value *V = SimplifyFCmpInst(I.getPredicate(), Op0, Op1, TD))
|
||||
return ReplaceInstUsesWith(I, V);
|
||||
|
||||
// Simplify 'fcmp pred X, X'
|
||||
if (Op0 == Op1) {
|
||||
switch (I.getPredicate()) {
|
||||
default: llvm_unreachable("Unknown predicate!");
|
||||
case FCmpInst::FCMP_UEQ: // True if unordered or equal
|
||||
case FCmpInst::FCMP_UGE: // True if unordered, greater than, or equal
|
||||
case FCmpInst::FCMP_ULE: // True if unordered, less than, or equal
|
||||
return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), 1));
|
||||
case FCmpInst::FCMP_OGT: // True if ordered and greater than
|
||||
case FCmpInst::FCMP_OLT: // True if ordered and less than
|
||||
case FCmpInst::FCMP_ONE: // True if ordered and operands are unequal
|
||||
return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), 0));
|
||||
|
||||
case FCmpInst::FCMP_UNO: // True if unordered: isnan(X) | isnan(Y)
|
||||
case FCmpInst::FCMP_ULT: // True if unordered or less than
|
||||
case FCmpInst::FCMP_UGT: // True if unordered or greater than
|
||||
@ -5981,23 +5969,8 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
|
||||
}
|
||||
}
|
||||
|
||||
if (isa<UndefValue>(Op1)) // fcmp pred X, undef -> undef
|
||||
return ReplaceInstUsesWith(I, UndefValue::get(I.getType()));
|
||||
|
||||
// Handle fcmp with constant RHS
|
||||
if (Constant *RHSC = dyn_cast<Constant>(Op1)) {
|
||||
// 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(I.getPredicate())) // True if ordered and...
|
||||
return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context));
|
||||
assert(FCmpInst::isUnordered(I.getPredicate()) &&
|
||||
"Comparison must be either ordered or unordered!");
|
||||
// True if unordered.
|
||||
return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context));
|
||||
}
|
||||
}
|
||||
|
||||
if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
|
||||
switch (LHSI->getOpcode()) {
|
||||
case Instruction::PHI:
|
||||
@ -6055,24 +6028,11 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
|
||||
}
|
||||
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
const Type *Ty = Op0->getType();
|
||||
|
||||
// icmp X, X
|
||||
if (Op0 == Op1)
|
||||
return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(),
|
||||
I.isTrueWhenEqual()));
|
||||
|
||||
if (isa<UndefValue>(Op1)) // X icmp undef -> undef
|
||||
return ReplaceInstUsesWith(I, UndefValue::get(I.getType()));
|
||||
|
||||
// icmp <global/alloca*/null>, <global/alloca*/null> - Global/Stack value
|
||||
// addresses never equal each other! We already know that Op0 != Op1.
|
||||
if ((isa<GlobalValue>(Op0) || isa<AllocaInst>(Op0) ||
|
||||
isa<ConstantPointerNull>(Op0)) &&
|
||||
(isa<GlobalValue>(Op1) || isa<AllocaInst>(Op1) ||
|
||||
isa<ConstantPointerNull>(Op1)))
|
||||
return ReplaceInstUsesWith(I, ConstantInt::get(Type::getInt1Ty(*Context),
|
||||
!I.isTrueWhenEqual()));
|
||||
if (Value *V = SimplifyICmpInst(I.getPredicate(), Op0, Op1, TD))
|
||||
return ReplaceInstUsesWith(I, V);
|
||||
|
||||
const Type *Ty = Op0->getType();
|
||||
|
||||
// icmp's with boolean values can always be turned into bitwise operations
|
||||
if (Ty == Type::getInt1Ty(*Context)) {
|
||||
@ -6137,27 +6097,24 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
|
||||
|
||||
// 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.
|
||||
// them being folded in the code below. The SimplifyICmpInst code has
|
||||
// already handled the edge cases for us, so we just assert on them.
|
||||
switch (I.getPredicate()) {
|
||||
default: break;
|
||||
case ICmpInst::ICMP_ULE:
|
||||
if (CI->isMaxValue(false)) // A <=u MAX -> TRUE
|
||||
return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context));
|
||||
assert(!CI->isMaxValue(false)); // A <=u MAX -> TRUE
|
||||
return new ICmpInst(ICmpInst::ICMP_ULT, Op0,
|
||||
AddOne(CI));
|
||||
case ICmpInst::ICMP_SLE:
|
||||
if (CI->isMaxValue(true)) // A <=s MAX -> TRUE
|
||||
return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context));
|
||||
assert(!CI->isMaxValue(true)); // A <=s MAX -> TRUE
|
||||
return new ICmpInst(ICmpInst::ICMP_SLT, Op0,
|
||||
AddOne(CI));
|
||||
case ICmpInst::ICMP_UGE:
|
||||
if (CI->isMinValue(false)) // A >=u MIN -> TRUE
|
||||
return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context));
|
||||
assert(!CI->isMinValue(false)); // A >=u MIN -> TRUE
|
||||
return new ICmpInst(ICmpInst::ICMP_UGT, Op0,
|
||||
SubOne(CI));
|
||||
case ICmpInst::ICMP_SGE:
|
||||
if (CI->isMinValue(true)) // A >=s MIN -> TRUE
|
||||
return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context));
|
||||
assert(!CI->isMinValue(true)); // A >=s MIN -> TRUE
|
||||
return new ICmpInst(ICmpInst::ICMP_SGT, Op0,
|
||||
SubOne(CI));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user