const SCEV *Step,
const SCEV *MaxBECount,
unsigned BitWidth) {
- APInt Offset(BitWidth, 0);
-
- if (auto *SA = dyn_cast<SCEVAddExpr>(Start)) {
- // Peel off a constant offset, if possible. In the future we could consider
- // being smarter here and handle {Start+Step,+,Step} too.
- if (SA->getNumOperands() != 2 || !isa<SCEVConstant>(SA->getOperand(0)))
- return ConstantRange(BitWidth, /* isFullSet = */ true);
- Offset = cast<SCEVConstant>(SA->getOperand(0))->getAPInt();
- Start = SA->getOperand(1);
- }
-
// RangeOf({C?A:B,+,C?P:Q}) == RangeOf(C?{A,+,P}:{B,+,Q})
// == RangeOf({A,+,P}) union RangeOf({B,+,Q})
explicit SelectPattern(ScalarEvolution &SE, unsigned BitWidth,
const SCEV *S) {
Optional<unsigned> CastOp;
+ APInt Offset(BitWidth, 0);
assert(SE.getTypeSizeInBits(S->getType()) == BitWidth &&
"Should be!");
+ // Peel off a constant offset:
+ if (auto *SA = dyn_cast<SCEVAddExpr>(S)) {
+ // In the future we could consider being smarter here and handle
+ // {Start+Step,+,Step} too.
+ if (SA->getNumOperands() != 2 || !isa<SCEVConstant>(SA->getOperand(0)))
+ return;
+
+ Offset = cast<SCEVConstant>(SA->getOperand(0))->getAPInt();
+ S = SA->getOperand(1);
+ }
+
// Peel off a cast operation
if (auto *SCast = dyn_cast<SCEVCastExpr>(S)) {
CastOp = SCast->getSCEVType();
FalseValue = FalseValue.sext(BitWidth);
break;
}
+
+ // Re-apply the constant offset we peeled off earlier
+ TrueValue += Offset;
+ FalseValue += Offset;
}
bool isRecognized() { return Condition != nullptr; }
// FIXME: without the explicit `this` receiver below, MSVC errors out with
// C2352 and C2512 (otherwise it isn't needed).
- const SCEV *TrueStart = this->getConstant(StartPattern.TrueValue + Offset);
+ const SCEV *TrueStart = this->getConstant(StartPattern.TrueValue);
const SCEV *TrueStep = this->getConstant(StepPattern.TrueValue);
- const SCEV *FalseStart = this->getConstant(StartPattern.FalseValue + Offset);
+ const SCEV *FalseStart = this->getConstant(StartPattern.FalseValue);
const SCEV *FalseStep = this->getConstant(StepPattern.FalseValue);
ConstantRange TrueRange =
leave:
ret void
}
+
+define void @f6(i1 %c) {
+; CHECK-LABEL: Classifying expressions for: @f6
+entry:
+ %start = select i1 %c, i32 127, i32 0
+ %step = select i1 %c, i32 -2, i32 0
+ br label %loop
+
+loop:
+ %loop.iv = phi i16 [ 0, %entry ], [ %loop.iv.inc, %loop ]
+ %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ]
+; CHECK: %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ]
+; CHECK-NEXT: --> {%start,+,(1 + %step)<nuw><nsw>}<%loop> U: [0,128) S: [0,128)
+
+ %step.plus.one = add i32 %step, 1
+ %iv.next = add i32 %iv, %step.plus.one
+ %iv.sext = sext i32 %iv to i64
+; CHECK: %iv.sext = sext i32 %iv to i64
+; CHECK-NEXT: --> {(sext i32 %start to i64),+,(1 + (sext i32 %step to i64))<nsw>}<nsw><%loop> U: [0,128) S: [0,128)
+ %loop.iv.inc = add i16 %loop.iv, 1
+ %be.cond = icmp ne i16 %loop.iv.inc, 128
+ br i1 %be.cond, label %loop, label %leave
+
+leave:
+ ret void
+}
+
+define void @f7(i1 %c) {
+; CHECK-LABEL: Classifying expressions for: @f7
+entry:
+ %start = select i1 %c, i32 127, i32 0
+ %step = select i1 %c, i32 -1, i32 1
+ br label %loop
+
+loop:
+ %loop.iv = phi i16 [ 0, %entry ], [ %loop.iv.inc, %loop ]
+ %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ]
+ %iv.trunc = trunc i32 %iv to i16
+; CHECK: %iv.trunc = trunc i32 %iv to i16
+; CHECK-NEXT: --> {(trunc i32 %start to i16),+,(trunc i32 %step to i16)}<%loop> U: [0,128) S: [0,128)
+ %iv.next = add i32 %iv, %step
+
+ %iv.trunc.plus.one = add i16 %iv.trunc, 1
+; CHECK: %iv.trunc.plus.one = add i16 %iv.trunc, 1
+; CHECK-NEXT: --> {(1 + (trunc i32 %start to i16))<nuw><nsw>,+,(trunc i32 %step to i16)}<%loop> U: [1,129) S: [1,129)
+
+ %iv.trunc.plus.two = add i16 %iv.trunc, 2
+; CHECK: %iv.trunc.plus.two = add i16 %iv.trunc, 2
+; CHECK-NEXT: --> {(2 + (trunc i32 %start to i16))<nuw><nsw>,+,(trunc i32 %step to i16)}<%loop> U: [2,130) S: [2,130)
+
+ %loop.iv.inc = add i16 %loop.iv, 1
+ %be.cond = icmp ne i16 %loop.iv.inc, 128
+ br i1 %be.cond, label %loop, label %leave
+
+leave:
+ ret void
+}
+