if (AR->getNoWrapFlags(SCEV::FlagNUW))
return getAddRecExpr(getZeroExtendExpr(Start, Ty),
getZeroExtendExpr(Step, Ty),
- // FIXME: Can use SCEV::FlagNUW
- L, SCEV::FlagAnyWrap);
+ L, AR->getNoWrapFlags());
// Check whether the backedge-taken count is SCEVCouldNotCompute.
// Note that this serves two purposes: It filters out loops that are
getAddExpr(getZeroExtendExpr(Start, WideTy),
getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy),
getZeroExtendExpr(Step, WideTy)));
- if (getZeroExtendExpr(Add, WideTy) == OperandExtendedAdd)
+ if (getZeroExtendExpr(Add, WideTy) == OperandExtendedAdd) {
+ // Cache knowledge of AR NUW, which is propagated to this AddRec.
+ const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNUW);
// Return the expression with the addrec on the outside.
return getAddRecExpr(getZeroExtendExpr(Start, Ty),
getZeroExtendExpr(Step, Ty),
- // FIXME: can use FlagNUW
- L, SCEV::FlagAnyWrap);
-
+ L, AR->getNoWrapFlags());
+ }
// Similar to above, only this time treat the step value as signed.
// This covers loops that count down.
const SCEV *SMul = getMulExpr(CastedMaxBECount, Step);
getAddExpr(getZeroExtendExpr(Start, WideTy),
getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy),
getSignExtendExpr(Step, WideTy)));
- if (getZeroExtendExpr(Add, WideTy) == OperandExtendedAdd)
+ if (getZeroExtendExpr(Add, WideTy) == OperandExtendedAdd) {
+ // Cache knowledge of AR NW, which is propagated to this AddRec.
+ // Negative step causes unsigned wrap, but it still can't self-wrap.
+ const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNW);
// Return the expression with the addrec on the outside.
return getAddRecExpr(getZeroExtendExpr(Start, Ty),
getSignExtendExpr(Step, Ty),
- // FIXME: can use FlagNW
- L, SCEV::FlagAnyWrap);
+ L, AR->getNoWrapFlags());
+ }
}
// If the backedge is guarded by a comparison with the pre-inc value
if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_ULT, AR, N) ||
(isLoopEntryGuardedByCond(L, ICmpInst::ICMP_ULT, Start, N) &&
isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_ULT,
- AR->getPostIncExpr(*this), N)))
+ AR->getPostIncExpr(*this), N))) {
+ // Cache knowledge of AR NUW, which is propagated to this AddRec.
+ const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNUW);
// Return the expression with the addrec on the outside.
return getAddRecExpr(getZeroExtendExpr(Start, Ty),
getZeroExtendExpr(Step, Ty),
- // FIXME: can use FlagNUW
- L, SCEV::FlagAnyWrap);
+ L, AR->getNoWrapFlags());
+ }
} else if (isKnownNegative(Step)) {
const SCEV *N = getConstant(APInt::getMaxValue(BitWidth) -
getSignedRange(Step).getSignedMin());
if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_UGT, AR, N) ||
(isLoopEntryGuardedByCond(L, ICmpInst::ICMP_UGT, Start, N) &&
isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_UGT,
- AR->getPostIncExpr(*this), N)))
- // Return the expression with the addrec on the outside. The
- // negative step causes unsigned wrap, but it still can't self-wrap.
+ AR->getPostIncExpr(*this), N))) {
+ // Cache knowledge of AR NW, which is propagated to this AddRec.
+ // Negative step causes unsigned wrap, but it still can't self-wrap.
+ const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNW);
+ // Return the expression with the addrec on the outside.
return getAddRecExpr(getZeroExtendExpr(Start, Ty),
getSignExtendExpr(Step, Ty),
- // FIXME: can use FlagNW
- L, SCEV::FlagAnyWrap);
+ L, AR->getNoWrapFlags());
+ }
}
}
}
if (AR->getNoWrapFlags(SCEV::FlagNSW))
return getAddRecExpr(getSignExtendExpr(Start, Ty),
getSignExtendExpr(Step, Ty),
- // FIXME: can use SCEV::FlagNSW
- L, SCEV::FlagAnyWrap);
+ L, SCEV::FlagNSW);
// Check whether the backedge-taken count is SCEVCouldNotCompute.
// Note that this serves two purposes: It filters out loops that are
getAddExpr(getSignExtendExpr(Start, WideTy),
getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy),
getSignExtendExpr(Step, WideTy)));
- if (getSignExtendExpr(Add, WideTy) == OperandExtendedAdd)
+ if (getSignExtendExpr(Add, WideTy) == OperandExtendedAdd) {
+ // Cache knowledge of AR NSW, which is propagated to this AddRec.
+ const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNSW);
// Return the expression with the addrec on the outside.
return getAddRecExpr(getSignExtendExpr(Start, Ty),
getSignExtendExpr(Step, Ty),
- // FIXME: can use SCEV::FlagNSW
- L, SCEV::FlagAnyWrap);
-
+ L, AR->getNoWrapFlags());
+ }
// Similar to above, only this time treat the step value as unsigned.
// This covers loops that count up with an unsigned step.
const SCEV *UMul = getMulExpr(CastedMaxBECount, Step);
getAddExpr(getSignExtendExpr(Start, WideTy),
getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy),
getZeroExtendExpr(Step, WideTy)));
- if (getSignExtendExpr(Add, WideTy) == OperandExtendedAdd)
+ if (getSignExtendExpr(Add, WideTy) == OperandExtendedAdd) {
+ // Cache knowledge of AR NSW, which is propagated to this AddRec.
+ const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNSW);
// Return the expression with the addrec on the outside.
return getAddRecExpr(getSignExtendExpr(Start, Ty),
getZeroExtendExpr(Step, Ty),
- // FIXME: can use SCEV::FlagNSW
- L, SCEV::FlagAnyWrap);
+ L, AR->getNoWrapFlags());
+ }
}
// If the backedge is guarded by a comparison with the pre-inc value
if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SLT, AR, N) ||
(isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SLT, Start, N) &&
isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SLT,
- AR->getPostIncExpr(*this), N)))
+ AR->getPostIncExpr(*this), N))) {
+ // Cache knowledge of AR NSW, which is propagated to this AddRec.
+ const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNSW);
// Return the expression with the addrec on the outside.
return getAddRecExpr(getSignExtendExpr(Start, Ty),
getSignExtendExpr(Step, Ty),
- // FIXME: can use SCEV::FlagNSW
- L, SCEV::FlagAnyWrap);
+ L, AR->getNoWrapFlags());
+ }
} else if (isKnownNegative(Step)) {
const SCEV *N = getConstant(APInt::getSignedMaxValue(BitWidth) -
getSignedRange(Step).getSignedMin());
if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SGT, AR, N) ||
(isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SGT, Start, N) &&
isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SGT,
- AR->getPostIncExpr(*this), N)))
+ AR->getPostIncExpr(*this), N))) {
+ // Cache knowledge of AR NSW, which is propagated to this AddRec.
+ const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNSW);
// Return the expression with the addrec on the outside.
return getAddRecExpr(getSignExtendExpr(Start, Ty),
getSignExtendExpr(Step, Ty),
- // FIXME: can use SCEV::FlagNSW
- L, SCEV::FlagAnyWrap);
+ L, AR->getNoWrapFlags());
+ }
}
}
}
for (SCEVAddRecExpr::op_iterator I = AR->op_begin(), E = AR->op_end();
I != E; ++I)
Ops.push_back(getAnyExtendExpr(*I, Ty));
- // FIXME: can use AR->getNoWrapFlags(SCEV::FlagNW)
- return getAddRecExpr(Ops, AR->getLoop(), SCEV::FlagAnyWrap);
+ return getAddRecExpr(Ops, AR->getLoop(), SCEV::FlagNW);
}
// As a special case, fold anyext(undef) to undef. We don't want to
#endif
// If FlagNSW is true and all the operands are non-negative, infer FlagNUW.
- if (!(Flags & SCEV::FlagNUW) && (Flags & SCEV::FlagNSW)) {
+ // And vice-versa.
+ int SignOrUnsignMask = SCEV::FlagNUW | SCEV::FlagNSW;
+ SCEV::NoWrapFlags SignOrUnsignWrap = maskFlags(Flags, SignOrUnsignMask);
+ if (SignOrUnsignWrap && (SignOrUnsignWrap != SignOrUnsignMask)) {
bool All = true;
for (SmallVectorImpl<const SCEV *>::const_iterator I = Ops.begin(),
E = Ops.end(); I != E; ++I)
All = false;
break;
}
- if (All) Flags = setFlags(Flags, SCEV::FlagNUW);
+ if (All) Flags = setFlags(Flags, (SCEV::NoWrapFlags)SignOrUnsignMask);
}
// Sort by complexity, this groups all similar expression types together.
// Build the new addrec. Propagate the NUW and NSW flags if both the
// outer add and the inner addrec are guaranteed to have no overflow.
- // FIXME: Always propagate NW
- // AddRec->getNoWrapFlags(setFlags(Flags, SCEV::FlagNW))
- Flags = AddRec->getNoWrapFlags(Flags);
+ // Always propagate NW.
+ Flags = AddRec->getNoWrapFlags(setFlags(Flags, SCEV::FlagNW));
const SCEV *NewRec = getAddRecExpr(AddRecOps, AddRecLoop, Flags);
// If all of the other operands were loop invariant, we are done.
#endif
// If FlagNSW is true and all the operands are non-negative, infer FlagNUW.
- if (!(Flags & SCEV::FlagNUW) && (Flags & SCEV::FlagNSW)) {
+ // And vice-versa.
+ int SignOrUnsignMask = SCEV::FlagNUW | SCEV::FlagNSW;
+ SCEV::NoWrapFlags SignOrUnsignWrap = maskFlags(Flags, SignOrUnsignMask);
+ if (SignOrUnsignWrap && (SignOrUnsignWrap != SignOrUnsignMask)) {
bool All = true;
for (SmallVectorImpl<const SCEV *>::const_iterator I = Ops.begin(),
E = Ops.end(); I != E; ++I)
All = false;
break;
}
- if (All) Flags = setFlags(Flags, SCEV::FlagNUW);
+ if (All) Flags = setFlags(Flags, (SCEV::NoWrapFlags)SignOrUnsignMask);
}
// Sort by complexity, this groups all similar expression types together.
// outer mul and the inner addrec are guaranteed to have no overflow.
//
// No self-wrap cannot be guaranteed after changing the step size, but
- // will be infered if either NUW or NSW is true.
+ // will be inferred if either NUW or NSW is true.
Flags = AddRec->getNoWrapFlags(clearFlags(Flags, SCEV::FlagNW));
const SCEV *NewRec = getAddRecExpr(NewOps, AddRecLoop, Flags);
for (unsigned i = 0, e = AR->getNumOperands(); i != e; ++i)
Operands.push_back(getUDivExpr(AR->getOperand(i), RHS));
return getAddRecExpr(Operands, AR->getLoop(),
- // FIXME: AR->getNoWrapFlags(SCEV::FlagNW)
- SCEV::FlagAnyWrap);
+ SCEV::FlagNW);
}
// (A*B)/C --> A*(B/C) if safe and B/C can be folded.
if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(LHS)) {
if (const SCEVAddRecExpr *StepChrec = dyn_cast<SCEVAddRecExpr>(Step))
if (StepChrec->getLoop() == L) {
Operands.append(StepChrec->op_begin(), StepChrec->op_end());
- // FIXME: can use maskFlags(Flags, SCEV::FlagNW)
- return getAddRecExpr(Operands, L, SCEV::FlagAnyWrap);
+ return getAddRecExpr(Operands, L, maskFlags(Flags, SCEV::FlagNW));
}
Operands.push_back(Step);
// with a SCEVCouldNotCompute as the cached BE count).
// If FlagNSW is true and all the operands are non-negative, infer FlagNUW.
- if (!(Flags & SCEV::FlagNUW) && (Flags & SCEV::FlagNSW)) {
+ // And vice-versa.
+ int SignOrUnsignMask = SCEV::FlagNUW | SCEV::FlagNSW;
+ SCEV::NoWrapFlags SignOrUnsignWrap = maskFlags(Flags, SignOrUnsignMask);
+ if (SignOrUnsignWrap && (SignOrUnsignWrap != SignOrUnsignMask)) {
bool All = true;
for (SmallVectorImpl<const SCEV *>::const_iterator I = Operands.begin(),
E = Operands.end(); I != E; ++I)
All = false;
break;
}
- if (All) Flags = setFlags(Flags, SCEV::FlagNUW);
+ if (All) Flags = setFlags(Flags, (SCEV::NoWrapFlags)SignOrUnsignMask);
}
// Canonicalize nested AddRecs in by nesting them in order of loop depth.
if (AllInvariant) {
// Create a recurrence for the outer loop with the same step size.
//
- // FIXME:
// The outer recurrence keeps its NW flag but only keeps NUW/NSW if the
// inner recurrence has the same property.
- // maskFlags(Flags, SCEV::FlagNW | NestedAR->getNoWrapFlags());
- SCEV::NoWrapFlags OuterFlags = SCEV::FlagAnyWrap;
+ SCEV::NoWrapFlags OuterFlags =
+ maskFlags(Flags, SCEV::FlagNW | NestedAR->getNoWrapFlags());
NestedOperands[0] = getAddRecExpr(Operands, L, OuterFlags);
AllInvariant = true;
if (AllInvariant) {
// Ok, both add recurrences are valid after the transformation.
//
- // FIXME:
// The inner recurrence keeps its NW flag but only keeps NUW/NSW if
// the outer recurrence has the same property.
- // maskFlags(NestedAR->getNoWrapFlags(), SCEV::FlagNW | Flags);
- SCEV::NoWrapFlags InnerFlags = SCEV::FlagAnyWrap;
+ SCEV::NoWrapFlags InnerFlags =
+ maskFlags(NestedAR->getNoWrapFlags(), SCEV::FlagNW | Flags);
return getAddRecExpr(NestedOperands, NestedLoop, InnerFlags);
}
}
}
/// getMinusSCEV - Return LHS-RHS. Minus is represented in SCEV as A+B*-1.
-///
-/// FIXME: prohibit FlagNUW here, as soon as getMinusSCEVForExitTest goes.
const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
SCEV::NoWrapFlags Flags) {
+ assert(!maskFlags(Flags, SCEV::FlagNUW) && "subtraction does not have NUW");
+
// Fast path: X - X --> 0.
if (LHS == RHS)
return getConstant(LHS->getType(), 0);
return getUMinExpr(PromotedLHS, PromotedRHS);
}
+/// getPointerBase - Transitively follow the chain of pointer-type operands
+/// until reaching a SCEV that does not have a single pointer operand. This
+/// returns a SCEVUnknown pointer for well-formed pointer-type expressions,
+/// but corner cases do exist.
+const SCEV *ScalarEvolution::getPointerBase(const SCEV *V) {
+ // A pointer operand may evaluate to a nonpointer expression, such as null.
+ if (!V->getType()->isPointerTy())
+ return V;
+
+ if (const SCEVCastExpr *Cast = dyn_cast<SCEVCastExpr>(V)) {
+ return getPointerBase(Cast->getOperand());
+ }
+ else if (const SCEVNAryExpr *NAry = dyn_cast<SCEVNAryExpr>(V)) {
+ const SCEV *PtrOp = 0;
+ for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end();
+ I != E; ++I) {
+ if ((*I)->getType()->isPointerTy()) {
+ // Cannot find the base of an expression with multiple pointer operands.
+ if (PtrOp)
+ return V;
+ PtrOp = *I;
+ }
+ }
+ if (!PtrOp)
+ return V;
+ return getPointerBase(PtrOp);
+ }
+ return V;
+}
+
/// PushDefUseChildren - Push users of the given Instruction
/// onto the given Worklist.
static void
// unsigned but we may have a negative index from the base
// pointer.
if (GEP->isInBounds())
- // FIXME: should be SCEV::FlagNW
- Flags = setFlags(Flags, SCEV::FlagNSW);
+ Flags = setFlags(Flags, SCEV::FlagNW);
}
const SCEV *StartVal = getSCEV(StartValueV);
if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
// If there's no unsigned wrap, the value will never be less than its
// initial value.
- // FIXME: can broaden to FlagNW?
if (AddRec->getNoWrapFlags(SCEV::FlagNUW))
if (const SCEVConstant *C = dyn_cast<SCEVConstant>(AddRec->getStart()))
if (!C->getValue()->isZero())
return ComputeBackedgeTakenCountExhaustively(L, ExitCond, !L->contains(TBB));
}
-static const SCEVAddRecExpr *
-isSimpleUnwrappingAddRec(const SCEV *S, const Loop *L) {
- const SCEVAddRecExpr *SA = dyn_cast<SCEVAddRecExpr>(S);
-
- // The SCEV must be an addrec of this loop.
- if (!SA || SA->getLoop() != L || !SA->isAffine())
- return 0;
-
- // The SCEV must be known to not wrap in some way to be interesting.
- if (!SA->getNoWrapFlags(SCEV::FlagNW))
- return 0;
-
- // The stride must be a constant so that we know if it is striding up or down.
- if (!isa<SCEVConstant>(SA->getOperand(1)))
- return 0;
- return SA;
-}
-
-/// getMinusSCEVForExitTest - When considering an exit test for a loop with a
-/// "x != y" exit test, we turn this into a computation that evaluates x-y != 0,
-/// and this function returns the expression to use for x-y. We know and take
-/// advantage of the fact that this subtraction is only being used in a
-/// comparison by zero context.
-///
-/// FIXME: this can be completely removed once AddRec FlagNWs are propagated.
-static const SCEV *getMinusSCEVForExitTest(const SCEV *LHS, const SCEV *RHS,
- const Loop *L, ScalarEvolution &SE) {
- // If either LHS or RHS is an AddRec SCEV (of this loop) that is known to not
- // self-wrap, then we know that the value will either become the other one
- // (and thus the loop terminates), that the loop will terminate through some
- // other exit condition first, or that the loop has undefined behavior. This
- // information is useful when the addrec has a stride that is != 1 or -1,
- // because it means we can't "miss" the exit value.
- //
- // In any of these three cases, it is safe to turn the exit condition into a
- // "counting down" AddRec (to zero) by subtracting the two inputs as normal,
- // but since we know that the "end cannot be missed" we can force the
- // resulting AddRec to be a NUW addrec. Since it is counting down, this means
- // that the AddRec *cannot* pass zero.
-
- // See if LHS and RHS are addrec's we can handle.
- const SCEVAddRecExpr *LHSA = isSimpleUnwrappingAddRec(LHS, L);
- const SCEVAddRecExpr *RHSA = isSimpleUnwrappingAddRec(RHS, L);
-
- // If neither addrec is interesting, just return a minus.
- if (RHSA == 0 && LHSA == 0)
- return SE.getMinusSCEV(LHS, RHS);
-
- // If only one of LHS and RHS are an AddRec of this loop, make sure it is LHS.
- if (RHSA && LHSA == 0) {
- // Safe because a-b === b-a for comparisons against zero.
- std::swap(LHS, RHS);
- std::swap(LHSA, RHSA);
- }
-
- // Handle the case when only one is advancing in a non-overflowing way.
- if (RHSA == 0) {
- // If RHS is loop varying, then we can't predict when LHS will cross it.
- if (!SE.isLoopInvariant(RHS, L))
- return SE.getMinusSCEV(LHS, RHS);
-
- // If LHS has a positive stride, then we compute RHS-LHS, because the loop
- // is counting up until it crosses RHS (which must be larger than LHS). If
- // it is negative, we compute LHS-RHS because we're counting down to RHS.
- const ConstantInt *Stride =
- cast<SCEVConstant>(LHSA->getOperand(1))->getValue();
- if (Stride->getValue().isNegative())
- std::swap(LHS, RHS);
-
- return SE.getMinusSCEV(RHS, LHS, SCEV::FlagNUW);
- }
-
- // If both LHS and RHS are interesting, we have something like:
- // a+i*4 != b+i*8.
- const ConstantInt *LHSStride =
- cast<SCEVConstant>(LHSA->getOperand(1))->getValue();
- const ConstantInt *RHSStride =
- cast<SCEVConstant>(RHSA->getOperand(1))->getValue();
-
- // If the strides are equal, then this is just a (complex) loop invariant
- // comparison of a and b.
- if (LHSStride == RHSStride)
- return SE.getMinusSCEV(LHSA->getStart(), RHSA->getStart());
-
- // If the signs of the strides differ, then the negative stride is counting
- // down to the positive stride.
- if (LHSStride->getValue().isNegative() != RHSStride->getValue().isNegative()){
- if (RHSStride->getValue().isNegative())
- std::swap(LHS, RHS);
- } else {
- // If LHS's stride is smaller than RHS's stride, then "b" must be less than
- // "a" and "b" is RHS is counting up (catching up) to LHS. This is true
- // whether the strides are positive or negative.
- if (RHSStride->getValue().slt(LHSStride->getValue()))
- std::swap(LHS, RHS);
- }
-
- return SE.getMinusSCEV(LHS, RHS, SCEV::FlagNUW);
-}
-
/// ComputeBackedgeTakenCountFromExitCondICmp - Compute the number of times the
/// backedge of the specified loop will execute if its exit condition
/// were a conditional branch of the ICmpInst ExitCond, TBB, and FBB.
switch (Cond) {
case ICmpInst::ICMP_NE: { // while (X != Y)
// Convert to: while (X-Y != 0)
- // FIXME: Once AddRec FlagNW are propagated, should be:
- // BackedgeTakenInfo BTI = HowFarToZero(getMinusSCEV(LHS, RHS), L);
- BackedgeTakenInfo BTI = HowFarToZero(getMinusSCEVForExitTest(LHS, RHS, L,
- *this), L);
+ BackedgeTakenInfo BTI = HowFarToZero(getMinusSCEV(LHS, RHS), L);
if (BTI.hasAnyInfo()) return BTI;
break;
}
AddRec = cast<SCEVAddRecExpr>(
getAddRecExpr(NewOps, AddRec->getLoop(),
- // FIXME: AddRec->getNoWrapFlags(SCEV::FlagNW)
- SCEV::FlagAnyWrap));
+ AddRec->getNoWrapFlags(SCEV::FlagNW)));
break;
}
SmallVector<const SCEV *, 4> Operands(op_begin(), op_end());
Operands[0] = SE.getConstant(SC->getType(), 0);
const SCEV *Shifted = SE.getAddRecExpr(Operands, getLoop(),
- // FIXME: getNoWrapFlags(FlagNW)
- FlagAnyWrap);
+ getNoWrapFlags(FlagNW));
if (const SCEVAddRecExpr *ShiftedAddRec =
dyn_cast<SCEVAddRecExpr>(Shifted))
return ShiftedAddRec->getNumIterationsInRange(