@@ -3493,17 +3493,25 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS,
34933493 /// {X,+,N}/C => {Y,+,N}/C where Y=X-(X%N). Safe when C%N=0.
34943494 // We can currently only fold X%N if X is constant.
34953495 const SCEVConstant *StartC = dyn_cast<SCEVConstant>(AR->getStart());
3496- if (StartC && !DivInt.urem(StepInt) &&
3497- getZeroExtendExpr(AR, ExtTy) ==
3498- getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy),
3499- getZeroExtendExpr(Step, ExtTy),
3500- AR->getLoop(), SCEV::FlagAnyWrap)) {
3496+ if (StartC && !DivInt.urem(StepInt)) {
35013497 const APInt &StartInt = StartC->getAPInt();
35023498 const APInt &StartRem = StartInt.urem(StepInt);
3503- if (StartRem != 0) {
3504- const SCEV *NewLHS =
3505- getAddRecExpr(getConstant(StartInt - StartRem), Step,
3506- AR->getLoop(), SCEV::FlagNW);
3499+ bool NoWrap =
3500+ getZeroExtendExpr(AR, ExtTy) ==
3501+ getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy),
3502+ getZeroExtendExpr(Step, ExtTy), AR->getLoop(),
3503+ SCEV::FlagAnyWrap);
3504+
3505+ // With N <= C and both N, C as powers-of-2, the transformation
3506+ // {X,+,N}/C => {(X - X%N),+,N}/C preserves division results even
3507+ // if wrapping occurs, as the division results remain equivalent for
3508+ // all offsets in [[(X - X%N), X).
3509+ bool CanFoldWithWrap = StepInt.ule(DivInt) && // N <= C
3510+ StepInt.isPowerOf2() && DivInt.isPowerOf2();
3511+ if (StartRem != 0 && (NoWrap || CanFoldWithWrap)) {
3512+ const SCEV *NewLHS = getAddRecExpr(
3513+ getConstant(StartInt - StartRem), Step, AR->getLoop(),
3514+ NoWrap ? SCEV::FlagNW : SCEV::FlagAnyWrap);
35073515 if (LHS != NewLHS) {
35083516 LHS = NewLHS;
35093517
@@ -3770,13 +3778,11 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands,
37703778 return getOrCreateAddRecExpr(Operands, L, Flags);
37713779}
37723780
3773- const SCEV *
3774- ScalarEvolution::getGEPExpr(GEPOperator *GEP,
3775- const SmallVectorImpl<const SCEV *> &IndexExprs) {
3781+ const SCEV *ScalarEvolution::getGEPExpr(GEPOperator *GEP,
3782+ ArrayRef<const SCEV *> IndexExprs) {
37763783 const SCEV *BaseExpr = getSCEV(GEP->getPointerOperand());
37773784 // getSCEV(Base)->getType() has the same address space as Base->getType()
37783785 // because SCEV::getType() preserves the address space.
3779- Type *IntIdxTy = getEffectiveSCEVType(BaseExpr->getType());
37803786 GEPNoWrapFlags NW = GEP->getNoWrapFlags();
37813787 if (NW != GEPNoWrapFlags::none()) {
37823788 // We'd like to propagate flags from the IR to the corresponding SCEV nodes,
@@ -3789,13 +3795,20 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP,
37893795 NW = GEPNoWrapFlags::none();
37903796 }
37913797
3798+ return getGEPExpr(BaseExpr, IndexExprs, GEP->getSourceElementType(), NW);
3799+ }
3800+
3801+ const SCEV *ScalarEvolution::getGEPExpr(const SCEV *BaseExpr,
3802+ ArrayRef<const SCEV *> IndexExprs,
3803+ Type *SrcElementTy, GEPNoWrapFlags NW) {
37923804 SCEV::NoWrapFlags OffsetWrap = SCEV::FlagAnyWrap;
37933805 if (NW.hasNoUnsignedSignedWrap())
37943806 OffsetWrap = setFlags(OffsetWrap, SCEV::FlagNSW);
37953807 if (NW.hasNoUnsignedWrap())
37963808 OffsetWrap = setFlags(OffsetWrap, SCEV::FlagNUW);
37973809
3798- Type *CurTy = GEP->getType();
3810+ Type *CurTy = BaseExpr->getType();
3811+ Type *IntIdxTy = getEffectiveSCEVType(BaseExpr->getType());
37993812 bool FirstIter = true;
38003813 SmallVector<const SCEV *, 4> Offsets;
38013814 for (const SCEV *IndexExpr : IndexExprs) {
@@ -3814,7 +3827,7 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP,
38143827 if (FirstIter) {
38153828 assert(isa<PointerType>(CurTy) &&
38163829 "The first index of a GEP indexes a pointer");
3817- CurTy = GEP->getSourceElementType() ;
3830+ CurTy = SrcElementTy ;
38183831 FirstIter = false;
38193832 } else {
38203833 CurTy = GetElementPtrInst::getTypeAtIndex(CurTy, (uint64_t)0);
0 commit comments