Index: lib/Analysis/ScalarEvolution.cpp =================================================================== --- lib/Analysis/ScalarEvolution.cpp +++ lib/Analysis/ScalarEvolution.cpp @@ -4328,8 +4328,33 @@ case Instruction::ZExt: return getZeroExtendExpr(getSCEV(U->getOperand(0)), U->getType()); - case Instruction::SExt: - return getSignExtendExpr(getSCEV(U->getOperand(0)), U->getType()); + case Instruction::SExt: { + // Converting 'sext of addRec' to 'addRec of sext' + // i.e. (sext i32 Addrec{2,+,2}<%for.body4> to i64) + // will be transformed into: + // addrec{(sext i32 '2' to i64),+,(sext i32 '2' to i64)}<%for.body4> + const SCEVAddRecExpr *AddRec = + dyn_cast(getSCEV(U->getOperand(0))); + if (AddRec && (AddRec->getNoWrapFlags(SCEV::FlagNSW) || + AddRec->getNoWrapFlags(SCEV::FlagNUW))) { + SmallVector Operands; + for (SCEVAddRecExpr::op_iterator I = AddRec->op_begin(), + E = AddRec->op_end(); + I != E; ++I) { + const SCEV *addRecOpr = *I; + addRecOpr = getSignExtendExpr(addRecOpr, U->getType()); + Operands.push_back(addRecOpr); + } + if (AddRec->getNoWrapFlags(SCEV::FlagNSW)) + return getAddRecExpr(Operands, AddRec->getLoop(), + AddRec->getNoWrapFlags(SCEV::FlagNSW)); + else + return getAddRecExpr(Operands, AddRec->getLoop(), + AddRec->getNoWrapFlags(SCEV::FlagNUW)); + } else { + return getSignExtendExpr(getSCEV(U->getOperand(0)), U->getType()); + } + } case Instruction::BitCast: // BitCasts are no-op casts so we just eliminate the cast. Index: lib/Transforms/Utils/SimplifyIndVar.cpp =================================================================== --- lib/Transforms/Utils/SimplifyIndVar.cpp +++ lib/Transforms/Utils/SimplifyIndVar.cpp @@ -292,6 +292,18 @@ case Instruction::Mul: GetExprForBO = &ScalarEvolution::getMulExpr; break; + + case Instruction::Shl: + // shift by operand should be constant. + if (dyn_cast(BO->getOperand(1))) { + // shift should be marked with 'nsw' or 'nuw'. + if (!BO->hasNoUnsignedWrap() && !BO->hasNoSignedWrap()) + return false; + GetExprForBO = &ScalarEvolution::getMulExpr; + break; + } else { + return false; + } } unsigned BitWidth = cast(BO->getType())->getBitWidth(); Index: test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll =================================================================== --- test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll +++ test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll @@ -11,7 +11,7 @@ %idx.inc = add nsw i32 %idx, 1 %idx.inc.sext = sext i32 %idx.inc to i64 ; CHECK: %idx.inc.sext = sext i32 %idx.inc to i64 -; CHECK-NEXT: --> {(1 + (sext i32 %start to i64)),+,1}<%loop> +; CHECK-NEXT: --> {(sext i32 (1 + %start) to i64),+,1}<%loop> %condition = icmp eq i32 %counter, 1 %counter.inc = add i32 %counter, 1 br i1 %condition, label %exit, label %loop @@ -71,7 +71,7 @@ %idx = phi i8 [ %start.inc, %entry ], [ %idx.inc, %loop ] %idx.sext = sext i8 %idx to i16 ; CHECK: %idx.sext = sext i8 %idx to i16 -; CHECK-NEXT: --> {(1 + (sext i8 %start to i16)),+,1}<%loop> +; CHECK-NEXT: --> {(sext i8 (1 + %start) to i16),+,1}<%loop> %idx.inc = add nsw i8 %idx, 1 %condition = load volatile i1, i1* %c br i1 %condition, label %exit, label %loop