bool isKnownPredicateWithRanges(ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS);
- /// Try to prove the condition described by "LHS Pred RHS" by ruling out
- /// integer overflow.
- ///
- /// For instance, this will return true for "A s< (A + C)<nsw>" if C is
- /// positive.
- bool isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred,
- const SCEV *LHS, const SCEV *RHS);
-
/// Try to split Pred LHS RHS into logical conjunctions (and's) and try to
/// prove them individually.
bool isKnownPredicateViaSplitting(ICmpInst::Predicate Pred, const SCEV *LHS,
return false;
}
-bool ScalarEvolution::isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred,
- const SCEV *LHS,
- const SCEV *RHS) {
-
- // Match Result to (X + Y)<ExpectedFlags> where Y is a constant integer.
- // Return Y via OutY.
- auto MatchBinaryAddToConst =
- [this](const SCEV *Result, const SCEV *X, APInt &OutY,
- SCEV::NoWrapFlags ExpectedFlags) {
- const SCEV *NonConstOp, *ConstOp;
- SCEV::NoWrapFlags FlagsPresent;
-
- if (!splitBinaryAdd(Result, ConstOp, NonConstOp, FlagsPresent) ||
- !isa<SCEVConstant>(ConstOp) || NonConstOp != X)
- return false;
-
- OutY = cast<SCEVConstant>(ConstOp)->getValue()->getValue();
- return (FlagsPresent & ExpectedFlags) == ExpectedFlags;
- };
-
- APInt C;
-
- switch (Pred) {
- default:
- break;
-
- case ICmpInst::ICMP_SGE:
- std::swap(LHS, RHS);
- case ICmpInst::ICMP_SLE:
- // X s<= (X + C)<nsw> if C >= 0
- if (MatchBinaryAddToConst(RHS, LHS, C, SCEV::FlagNSW) && C.isNonNegative())
- return true;
-
- // (X + C)<nsw> s<= X if C <= 0
- if (MatchBinaryAddToConst(LHS, RHS, C, SCEV::FlagNSW) &&
- !C.isStrictlyPositive())
- return true;
-
- case ICmpInst::ICMP_SGT:
- std::swap(LHS, RHS);
- case ICmpInst::ICMP_SLT:
- // X s< (X + C)<nsw> if C > 0
- if (MatchBinaryAddToConst(RHS, LHS, C, SCEV::FlagNSW) &&
- C.isStrictlyPositive())
- return true;
-
- // (X + C)<nsw> s< X if C < 0
- if (MatchBinaryAddToConst(LHS, RHS, C, SCEV::FlagNSW) && C.isNegative())
- return true;
- }
-
- return false;
-}
-
bool ScalarEvolution::isKnownPredicateViaSplitting(ICmpInst::Predicate Pred,
const SCEV *LHS,
const SCEV *RHS) {
[this](ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS) {
return isKnownPredicateWithRanges(Pred, LHS, RHS) ||
IsKnownPredicateViaMinOrMax(*this, Pred, LHS, RHS) ||
- IsKnownPredicateViaAddRecStart(*this, Pred, LHS, RHS) ||
- isKnownPredicateViaNoOverflow(Pred, LHS, RHS);
+ IsKnownPredicateViaAddRecStart(*this, Pred, LHS, RHS);
};
switch (Pred) {
ret void
}
-define void @func_21(i32* %length.ptr) {
-; CHECK-LABEL: @func_21(
-
-; This checks that the backedge condition, (I + 1) < Length - 1 implies
-; (I + 1) < Length
- entry:
- %length = load i32, i32* %length.ptr, !range !0
- %lim = sub i32 %length, 1
- %entry.cond = icmp sgt i32 %length, 1
- br i1 %entry.cond, label %loop, label %leave
-
- loop:
-; CHECK: loop:
- %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
- %iv.inc = add i32 %iv, 1
- %range.check = icmp slt i32 %iv, %length
- br i1 %range.check, label %be, label %leave
-; CHECK: br i1 true, label %be, label %leave.loopexit
-; CHECK: be:
-
- be:
- call void @side_effect()
- %be.cond = icmp slt i32 %iv.inc, %lim
- br i1 %be.cond, label %loop, label %leave
-
- leave:
- ret void
-}
-
-define void @func_22(i32* %length.ptr) {
-; CHECK-LABEL: @func_22(
-
-; This checks that the backedge condition, (I + 1) < Length - 1 implies
-; (I + 1) < Length
- entry:
- %length = load i32, i32* %length.ptr, !range !0
- %lim = sub i32 %length, 1
- %entry.cond = icmp sgt i32 %length, 1
- br i1 %entry.cond, label %loop, label %leave
-
- loop:
-; CHECK: loop:
- %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
- %iv.inc = add i32 %iv, 1
- %range.check = icmp sle i32 %iv, %length
- br i1 %range.check, label %be, label %leave
-; CHECK: br i1 true, label %be, label %leave.loopexit
-; CHECK: be:
-
- be:
- call void @side_effect()
- %be.cond = icmp sle i32 %iv.inc, %lim
- br i1 %be.cond, label %loop, label %leave
-
- leave:
- ret void
-}
-
define void @func_23(i32* %length.ptr) {
; CHECK-LABEL: @func_23(
entry: