Skip to content

Commit a5397c0

Browse files
committedMar 4, 2015
[IndVarSimplify] use the "canonical" way to infer no-wrap.
Summary: rL225282 introduced an ad-hoc way to promote some additions to nuw or nsw. Since then SCEV has become smarter in directly proving no-wrap; and using the canonical "ext(A op B) == ext(A) op ext(B)" method of proving no-wrap is just as powerful now. Rip out the existing complexity in favor of getting SCEV to do all the heaving lifting internally. This change does not add any unit tests because it is supposed to be a non-functional change. Tests added in rL225282 and rL226075 are valid tests for this change. Reviewers: atrick, majnemer Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D7981 llvm-svn: 231306
1 parent 9e2c501 commit a5397c0

File tree

1 file changed

+40
-78
lines changed

1 file changed

+40
-78
lines changed
 

‎llvm/lib/Transforms/Utils/SimplifyIndVar.cpp

+40-78
Original file line numberDiff line numberDiff line change
@@ -270,95 +270,57 @@ bool SimplifyIndvar::eliminateIVUser(Instruction *UseInst,
270270
bool SimplifyIndvar::strengthenOverflowingOperation(BinaryOperator *BO,
271271
Value *IVOperand) {
272272

273-
// Currently we only handle instructions of the form "add <indvar> <value>"
274-
unsigned Op = BO->getOpcode();
275-
if (Op != Instruction::Add)
273+
// Fastpath: we don't have any work to do if `BO` is `nuw` and `nsw`.
274+
if (BO->hasNoUnsignedWrap() && BO->hasNoSignedWrap())
276275
return false;
277276

278-
// If BO is already both nuw and nsw then there is nothing left to do
279-
if (BO->hasNoUnsignedWrap() && BO->hasNoSignedWrap())
277+
const SCEV *(ScalarEvolution::*GetExprForBO)(const SCEV *, const SCEV *,
278+
SCEV::NoWrapFlags);
279+
280+
switch (BO->getOpcode()) {
281+
default:
280282
return false;
281283

282-
IntegerType *IT = cast<IntegerType>(IVOperand->getType());
283-
Value *OtherOperand = nullptr;
284-
if (BO->getOperand(0) == IVOperand) {
285-
OtherOperand = BO->getOperand(1);
286-
} else {
287-
assert(BO->getOperand(1) == IVOperand && "only other use!");
288-
OtherOperand = BO->getOperand(0);
284+
case Instruction::Add:
285+
GetExprForBO = &ScalarEvolution::getAddExpr;
286+
break;
287+
288+
case Instruction::Sub:
289+
GetExprForBO = &ScalarEvolution::getMinusSCEV;
290+
break;
291+
292+
case Instruction::Mul:
293+
GetExprForBO = &ScalarEvolution::getMulExpr;
294+
break;
289295
}
290296

291-
bool Changed = false;
292-
const SCEV *OtherOpSCEV = SE->getSCEV(OtherOperand);
293-
if (OtherOpSCEV == SE->getCouldNotCompute())
294-
return false;
297+
unsigned BitWidth = cast<IntegerType>(BO->getType())->getBitWidth();
298+
Type *WideTy = IntegerType::get(BO->getContext(), BitWidth * 2);
299+
const SCEV *LHS = SE->getSCEV(BO->getOperand(0));
300+
const SCEV *RHS = SE->getSCEV(BO->getOperand(1));
295301

296-
const SCEV *IVOpSCEV = SE->getSCEV(IVOperand);
297-
const SCEV *ZeroSCEV = SE->getConstant(IVOpSCEV->getType(), 0);
302+
bool Changed = false;
298303

299-
if (!BO->hasNoSignedWrap()) {
300-
// Upgrade the add to an "add nsw" if we can prove that it will never
301-
// sign-overflow or sign-underflow.
302-
303-
const SCEV *SignedMax =
304-
SE->getConstant(APInt::getSignedMaxValue(IT->getBitWidth()));
305-
const SCEV *SignedMin =
306-
SE->getConstant(APInt::getSignedMinValue(IT->getBitWidth()));
307-
308-
// The addition "IVOperand + OtherOp" does not sign-overflow if the result
309-
// is sign-representable in 2's complement in the given bit-width.
310-
//
311-
// If OtherOp is SLT 0, then for an IVOperand in [SignedMin - OtherOp,
312-
// SignedMax], "IVOperand + OtherOp" is in [SignedMin, SignedMax + OtherOp].
313-
// Everything in [SignedMin, SignedMax + OtherOp] is representable since
314-
// SignedMax + OtherOp is at least -1.
315-
//
316-
// If OtherOp is SGE 0, then for an IVOperand in [SignedMin, SignedMax -
317-
// OtherOp], "IVOperand + OtherOp" is in [SignedMin + OtherOp, SignedMax].
318-
// Everything in [SignedMin + OtherOp, SignedMax] is representable since
319-
// SignedMin + OtherOp is at most -1.
320-
//
321-
// It follows that for all values of IVOperand in [SignedMin - smin(0,
322-
// OtherOp), SignedMax - smax(0, OtherOp)] the result of the add is
323-
// representable (i.e. there is no sign-overflow).
324-
325-
const SCEV *UpperDelta = SE->getSMaxExpr(ZeroSCEV, OtherOpSCEV);
326-
const SCEV *UpperLimit = SE->getMinusSCEV(SignedMax, UpperDelta);
327-
328-
bool NeverSignedOverflows =
329-
SE->isKnownPredicate(ICmpInst::ICMP_SLE, IVOpSCEV, UpperLimit);
330-
331-
if (NeverSignedOverflows) {
332-
const SCEV *LowerDelta = SE->getSMinExpr(ZeroSCEV, OtherOpSCEV);
333-
const SCEV *LowerLimit = SE->getMinusSCEV(SignedMin, LowerDelta);
334-
335-
bool NeverSignedUnderflows =
336-
SE->isKnownPredicate(ICmpInst::ICMP_SGE, IVOpSCEV, LowerLimit);
337-
if (NeverSignedUnderflows) {
338-
BO->setHasNoSignedWrap(true);
339-
Changed = true;
340-
}
304+
if (!BO->hasNoUnsignedWrap()) {
305+
const SCEV *ExtendAfterOp = SE->getZeroExtendExpr(SE->getSCEV(BO), WideTy);
306+
const SCEV *OpAfterExtend = (SE->*GetExprForBO)(
307+
SE->getZeroExtendExpr(LHS, WideTy), SE->getZeroExtendExpr(RHS, WideTy),
308+
SCEV::FlagAnyWrap);
309+
if (ExtendAfterOp == OpAfterExtend) {
310+
BO->setHasNoUnsignedWrap();
311+
SE->forgetValue(BO);
312+
Changed = true;
341313
}
342314
}
343315

344-
if (!BO->hasNoUnsignedWrap()) {
345-
// Upgrade the add computing "IVOperand + OtherOp" to an "add nuw" if we can
346-
// prove that it will never unsigned-overflow (i.e. the result will always
347-
// be representable in the given bit-width).
348-
//
349-
// "IVOperand + OtherOp" is unsigned-representable in 2's complement iff it
350-
// does not produce a carry. "IVOperand + OtherOp" produces no carry iff
351-
// IVOperand ULE (UnsignedMax - OtherOp).
352-
353-
const SCEV *UnsignedMax =
354-
SE->getConstant(APInt::getMaxValue(IT->getBitWidth()));
355-
const SCEV *UpperLimit = SE->getMinusSCEV(UnsignedMax, OtherOpSCEV);
356-
357-
bool NeverUnsignedOverflows =
358-
SE->isKnownPredicate(ICmpInst::ICMP_ULE, IVOpSCEV, UpperLimit);
359-
360-
if (NeverUnsignedOverflows) {
361-
BO->setHasNoUnsignedWrap(true);
316+
if (!BO->hasNoSignedWrap()) {
317+
const SCEV *ExtendAfterOp = SE->getSignExtendExpr(SE->getSCEV(BO), WideTy);
318+
const SCEV *OpAfterExtend = (SE->*GetExprForBO)(
319+
SE->getSignExtendExpr(LHS, WideTy), SE->getSignExtendExpr(RHS, WideTy),
320+
SCEV::FlagAnyWrap);
321+
if (ExtendAfterOp == OpAfterExtend) {
322+
BO->setHasNoSignedWrap();
323+
SE->forgetValue(BO);
362324
Changed = true;
363325
}
364326
}

0 commit comments

Comments
 (0)
Please sign in to comment.