1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00

[NFC][ConstantRange] Add 'icmp' helper method

"Does the predicate hold between two ranges?"

Not very surprisingly, some places were already doing this check,
without explicitly naming the algorithm, cleanup them all.
This commit is contained in:
Roman Lebedev 2021-04-10 17:58:47 +03:00
parent ed7f139243
commit c6f9ab66c8
7 changed files with 67 additions and 23 deletions

View File

@ -474,11 +474,9 @@ public:
const auto &CR = getConstantRange(); const auto &CR = getConstantRange();
const auto &OtherCR = Other.getConstantRange(); const auto &OtherCR = Other.getConstantRange();
if (ConstantRange::makeSatisfyingICmpRegion(Pred, OtherCR).contains(CR)) if (CR.icmp(Pred, OtherCR))
return ConstantInt::getTrue(Ty); return ConstantInt::getTrue(Ty);
if (ConstantRange::makeSatisfyingICmpRegion( if (CR.icmp(CmpInst::getInversePredicate(Pred), OtherCR))
CmpInst::getInversePredicate(Pred), OtherCR)
.contains(CR))
return ConstantInt::getFalse(Ty); return ConstantInt::getFalse(Ty);
return nullptr; return nullptr;

View File

@ -124,6 +124,10 @@ public:
static ConstantRange makeExactICmpRegion(CmpInst::Predicate Pred, static ConstantRange makeExactICmpRegion(CmpInst::Predicate Pred,
const APInt &Other); const APInt &Other);
/// Does the predicate \p Pred hold between ranges this and \p Other?
/// NOTE: false does not mean that inverse predicate holds!
bool icmp(CmpInst::Predicate Pred, const ConstantRange &Other) const;
/// Produce the largest range containing all X such that "X BinOp Y" is /// Produce the largest range containing all X such that "X BinOp Y" is
/// guaranteed not to wrap (overflow) for *all* Y in Other. However, there may /// guaranteed not to wrap (overflow) for *all* Y in Other. However, there may
/// be *some* Y in Other for which additional X not contained in the result /// be *some* Y in Other for which additional X not contained in the result

View File

@ -3451,13 +3451,10 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
auto LHS_CR = getConstantRangeFromMetadata( auto LHS_CR = getConstantRangeFromMetadata(
*LHS_Instr->getMetadata(LLVMContext::MD_range)); *LHS_Instr->getMetadata(LLVMContext::MD_range));
auto Satisfied_CR = ConstantRange::makeSatisfyingICmpRegion(Pred, RHS_CR); if (LHS_CR.icmp(Pred, RHS_CR))
if (Satisfied_CR.contains(LHS_CR))
return ConstantInt::getTrue(RHS->getContext()); return ConstantInt::getTrue(RHS->getContext());
auto InversedSatisfied_CR = ConstantRange::makeSatisfyingICmpRegion( if (LHS_CR.icmp(CmpInst::getInversePredicate(Pred), RHS_CR))
CmpInst::getInversePredicate(Pred), RHS_CR);
if (InversedSatisfied_CR.contains(LHS_CR))
return ConstantInt::getFalse(RHS->getContext()); return ConstantInt::getFalse(RHS->getContext());
} }
} }

View File

@ -9843,10 +9843,9 @@ bool ScalarEvolution::isKnownPredicateViaConstantRanges(
// This code is split out from isKnownPredicate because it is called from // This code is split out from isKnownPredicate because it is called from
// within isLoopEntryGuardedByCond. // within isLoopEntryGuardedByCond.
auto CheckRanges = auto CheckRanges = [&](const ConstantRange &RangeLHS,
[&](const ConstantRange &RangeLHS, const ConstantRange &RangeRHS) { const ConstantRange &RangeRHS) {
return ConstantRange::makeSatisfyingICmpRegion(Pred, RangeRHS) return RangeLHS.icmp(Pred, RangeRHS);
.contains(RangeLHS);
}; };
// The check at the top of the function catches the case where the values are // The check at the top of the function catches the case where the values are
@ -11148,12 +11147,9 @@ bool ScalarEvolution::isImpliedCondOperandsViaRanges(ICmpInst::Predicate Pred,
// We can also compute the range of values for `LHS` that satisfy the // We can also compute the range of values for `LHS` that satisfy the
// consequent, "`LHS` `Pred` `RHS`": // consequent, "`LHS` `Pred` `RHS`":
const APInt &ConstRHS = cast<SCEVConstant>(RHS)->getAPInt(); const APInt &ConstRHS = cast<SCEVConstant>(RHS)->getAPInt();
ConstantRange SatisfyingLHSRange =
ConstantRange::makeSatisfyingICmpRegion(Pred, ConstRHS);
// The antecedent implies the consequent if every value of `LHS` that // The antecedent implies the consequent if every value of `LHS` that
// satisfies the antecedent also satisfies the consequent. // satisfies the antecedent also satisfies the consequent.
return SatisfyingLHSRange.contains(LHSRange); return LHSRange.icmp(Pred, ConstRHS);
} }
bool ScalarEvolution::doesIVOverflowOnLT(const SCEV *RHS, const SCEV *Stride, bool ScalarEvolution::doesIVOverflowOnLT(const SCEV *RHS, const SCEV *Stride,

View File

@ -181,6 +181,11 @@ bool ConstantRange::getEquivalentICmp(CmpInst::Predicate &Pred,
return Success; return Success;
} }
bool ConstantRange::icmp(CmpInst::Predicate Pred,
const ConstantRange &Other) const {
return makeSatisfyingICmpRegion(Pred, Other).contains(*this);
}
/// Exact mul nuw region for single element RHS. /// Exact mul nuw region for single element RHS.
static ConstantRange makeExactMulNUWRegion(const APInt &V) { static ConstantRange makeExactMulNUWRegion(const APInt &V) {
unsigned BitWidth = V.getBitWidth(); unsigned BitWidth = V.getBitWidth();

View File

@ -7328,13 +7328,10 @@ struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
auto AllowedRegion = auto AllowedRegion =
ConstantRange::makeAllowedICmpRegion(CmpI->getPredicate(), RHSAARange); ConstantRange::makeAllowedICmpRegion(CmpI->getPredicate(), RHSAARange);
auto SatisfyingRegion = ConstantRange::makeSatisfyingICmpRegion(
CmpI->getPredicate(), RHSAARange);
if (AllowedRegion.intersectWith(LHSAARange).isEmptySet()) if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
MustFalse = true; MustFalse = true;
if (SatisfyingRegion.contains(LHSAARange)) if (LHSAARange.icmp(CmpI->getPredicate(), RHSAARange))
MustTrue = true; MustTrue = true;
assert((!MustTrue || !MustFalse) && assert((!MustTrue || !MustFalse) &&

View File

@ -6,9 +6,10 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/IR/ConstantRange.h" #include "llvm/IR/ConstantRange.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/IR/Instructions.h" #include "llvm/IR/Instructions.h"
#include "llvm/IR/Operator.h" #include "llvm/IR/Operator.h"
#include "llvm/Support/KnownBits.h" #include "llvm/Support/KnownBits.h"
@ -1509,6 +1510,52 @@ TEST(ConstantRange, MakeSatisfyingICmpRegion) {
ConstantRange(APInt(8, 4), APInt(8, -128))); ConstantRange(APInt(8, 4), APInt(8, -128)));
} }
static bool icmp(CmpInst::Predicate Pred, const APInt &LHS, const APInt &RHS) {
switch (Pred) {
case CmpInst::Predicate::ICMP_EQ:
return LHS.eq(RHS);
case CmpInst::Predicate::ICMP_NE:
return LHS.ne(RHS);
case CmpInst::Predicate::ICMP_UGT:
return LHS.ugt(RHS);
case CmpInst::Predicate::ICMP_UGE:
return LHS.uge(RHS);
case CmpInst::Predicate::ICMP_ULT:
return LHS.ult(RHS);
case CmpInst::Predicate::ICMP_ULE:
return LHS.ule(RHS);
case CmpInst::Predicate::ICMP_SGT:
return LHS.sgt(RHS);
case CmpInst::Predicate::ICMP_SGE:
return LHS.sge(RHS);
case CmpInst::Predicate::ICMP_SLT:
return LHS.slt(RHS);
case CmpInst::Predicate::ICMP_SLE:
return LHS.sle(RHS);
default:
llvm_unreachable("Not an ICmp predicate!");
}
}
void ICmpTestImpl(CmpInst::Predicate Pred) {
unsigned Bits = 4;
EnumerateTwoConstantRanges(
Bits, [&](const ConstantRange &CR1, const ConstantRange &CR2) {
bool Exhaustive = true;
ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
ForeachNumInConstantRange(
CR2, [&](const APInt &N2) { Exhaustive &= icmp(Pred, N1, N2); });
});
EXPECT_EQ(CR1.icmp(Pred, CR2), Exhaustive);
});
}
TEST(ConstantRange, ICmp) {
for (auto Pred : seq<unsigned>(CmpInst::Predicate::FIRST_ICMP_PREDICATE,
1 + CmpInst::Predicate::LAST_ICMP_PREDICATE))
ICmpTestImpl((CmpInst::Predicate)Pred);
}
TEST(ConstantRange, MakeGuaranteedNoWrapRegion) { TEST(ConstantRange, MakeGuaranteedNoWrapRegion) {
const int IntMin4Bits = 8; const int IntMin4Bits = 8;
const int IntMax4Bits = 7; const int IntMax4Bits = 7;