1 
2 #include "polly/Support/SCEVValidator.h"
3 #include "polly/ScopInfo.h"
4 #include "llvm/Analysis/RegionInfo.h"
5 #include "llvm/Analysis/ScalarEvolution.h"
6 #include "llvm/Analysis/ScalarEvolutionExpressions.h"
7 #include "llvm/Support/Debug.h"
8 
9 using namespace llvm;
10 using namespace polly;
11 
12 #define DEBUG_TYPE "polly-scev-validator"
13 
14 namespace SCEVType {
15 /// @brief The type of a SCEV
16 ///
17 /// To check for the validity of a SCEV we assign to each SCEV a type. The
18 /// possible types are INT, PARAM, IV and INVALID. The order of the types is
19 /// important. The subexpressions of SCEV with a type X can only have a type
20 /// that is smaller or equal than X.
21 enum TYPE {
22   // An integer value.
23   INT,
24 
25   // An expression that is constant during the execution of the Scop,
26   // but that may depend on parameters unknown at compile time.
27   PARAM,
28 
29   // An expression that may change during the execution of the SCoP.
30   IV,
31 
32   // An invalid expression.
33   INVALID
34 };
35 }
36 
37 /// @brief The result the validator returns for a SCEV expression.
38 class ValidatorResult {
39   /// @brief The type of the expression
40   SCEVType::TYPE Type;
41 
42   /// @brief The set of Parameters in the expression.
43   ParameterSetTy Parameters;
44 
45 public:
46   /// @brief The copy constructor
47   ValidatorResult(const ValidatorResult &Source) {
48     Type = Source.Type;
49     Parameters = Source.Parameters;
50   }
51 
52   /// @brief Construct a result with a certain type and no parameters.
53   ValidatorResult(SCEVType::TYPE Type) : Type(Type) {
54     assert(Type != SCEVType::PARAM && "Did you forget to pass the parameter");
55   }
56 
57   /// @brief Construct a result with a certain type and a single parameter.
58   ValidatorResult(SCEVType::TYPE Type, const SCEV *Expr) : Type(Type) {
59     Parameters.insert(Expr);
60   }
61 
62   /// @brief Get the type of the ValidatorResult.
63   SCEVType::TYPE getType() { return Type; }
64 
65   /// @brief Is the analyzed SCEV constant during the execution of the SCoP.
66   bool isConstant() { return Type == SCEVType::INT || Type == SCEVType::PARAM; }
67 
68   /// @brief Is the analyzed SCEV valid.
69   bool isValid() { return Type != SCEVType::INVALID; }
70 
71   /// @brief Is the analyzed SCEV of Type IV.
72   bool isIV() { return Type == SCEVType::IV; }
73 
74   /// @brief Is the analyzed SCEV of Type INT.
75   bool isINT() { return Type == SCEVType::INT; }
76 
77   /// @brief Is the analyzed SCEV of Type PARAM.
78   bool isPARAM() { return Type == SCEVType::PARAM; }
79 
80   /// @brief Get the parameters of this validator result.
81   const ParameterSetTy &getParameters() { return Parameters; }
82 
83   /// @brief Add the parameters of Source to this result.
84   void addParamsFrom(const ValidatorResult &Source) {
85     Parameters.insert(Source.Parameters.begin(), Source.Parameters.end());
86   }
87 
88   /// @brief Merge a result.
89   ///
90   /// This means to merge the parameters and to set the Type to the most
91   /// specific Type that matches both.
92   void merge(const ValidatorResult &ToMerge) {
93     Type = std::max(Type, ToMerge.Type);
94     addParamsFrom(ToMerge);
95   }
96 
97   void print(raw_ostream &OS) {
98     switch (Type) {
99     case SCEVType::INT:
100       OS << "SCEVType::INT";
101       break;
102     case SCEVType::PARAM:
103       OS << "SCEVType::PARAM";
104       break;
105     case SCEVType::IV:
106       OS << "SCEVType::IV";
107       break;
108     case SCEVType::INVALID:
109       OS << "SCEVType::INVALID";
110       break;
111     }
112   }
113 };
114 
115 raw_ostream &operator<<(raw_ostream &OS, class ValidatorResult &VR) {
116   VR.print(OS);
117   return OS;
118 }
119 
120 /// Check if a SCEV is valid in a SCoP.
121 struct SCEVValidator
122     : public SCEVVisitor<SCEVValidator, class ValidatorResult> {
123 private:
124   const Region *R;
125   Loop *Scope;
126   ScalarEvolution &SE;
127   InvariantLoadsSetTy *ILS;
128 
129 public:
130   SCEVValidator(const Region *R, Loop *Scope, ScalarEvolution &SE,
131                 InvariantLoadsSetTy *ILS)
132       : R(R), Scope(Scope), SE(SE), ILS(ILS) {}
133 
134   class ValidatorResult visitConstant(const SCEVConstant *Constant) {
135     return ValidatorResult(SCEVType::INT);
136   }
137 
138   class ValidatorResult visitTruncateExpr(const SCEVTruncateExpr *Expr) {
139     ValidatorResult Op = visit(Expr->getOperand());
140 
141     switch (Op.getType()) {
142     case SCEVType::INT:
143     case SCEVType::PARAM:
144       // We currently do not represent a truncate expression as an affine
145       // expression. If it is constant during Scop execution, we treat it as a
146       // parameter.
147       return ValidatorResult(SCEVType::PARAM, Expr);
148     case SCEVType::IV:
149       DEBUG(dbgs() << "INVALID: Truncation of SCEVType::IV expression");
150       return ValidatorResult(SCEVType::INVALID);
151     case SCEVType::INVALID:
152       return Op;
153     }
154 
155     llvm_unreachable("Unknown SCEVType");
156   }
157 
158   class ValidatorResult visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
159     return visit(Expr->getOperand());
160   }
161 
162   class ValidatorResult visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
163     // We currently allow only signed SCEV expressions. In the case of a
164     // signed value, a sign extend is a noop.
165     //
166     // TODO: Reconsider this when we add support for unsigned values.
167     return visit(Expr->getOperand());
168   }
169 
170   class ValidatorResult visitAddExpr(const SCEVAddExpr *Expr) {
171     ValidatorResult Return(SCEVType::INT);
172 
173     for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
174       ValidatorResult Op = visit(Expr->getOperand(i));
175       Return.merge(Op);
176 
177       // Early exit.
178       if (!Return.isValid())
179         break;
180     }
181 
182     // TODO: Check for NSW and NUW.
183     return Return;
184   }
185 
186   class ValidatorResult visitMulExpr(const SCEVMulExpr *Expr) {
187     ValidatorResult Return(SCEVType::INT);
188 
189     bool HasMultipleParams = false;
190 
191     for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
192       ValidatorResult Op = visit(Expr->getOperand(i));
193 
194       if (Op.isINT())
195         continue;
196 
197       if (Op.isPARAM() && Return.isPARAM()) {
198         HasMultipleParams = true;
199         continue;
200       }
201 
202       if ((Op.isIV() || Op.isPARAM()) && !Return.isINT()) {
203         DEBUG(dbgs() << "INVALID: More than one non-int operand in MulExpr\n"
204                      << "\tExpr: " << *Expr << "\n"
205                      << "\tPrevious expression type: " << Return << "\n"
206                      << "\tNext operand (" << Op
207                      << "): " << *Expr->getOperand(i) << "\n");
208 
209         return ValidatorResult(SCEVType::INVALID);
210       }
211 
212       Return.merge(Op);
213     }
214 
215     if (HasMultipleParams && Return.isValid())
216       return ValidatorResult(SCEVType::PARAM, Expr);
217 
218     // TODO: Check for NSW and NUW.
219     return Return;
220   }
221 
222   class ValidatorResult visitAddRecExpr(const SCEVAddRecExpr *Expr) {
223     if (!Expr->isAffine()) {
224       DEBUG(dbgs() << "INVALID: AddRec is not affine");
225       return ValidatorResult(SCEVType::INVALID);
226     }
227 
228     ValidatorResult Start = visit(Expr->getStart());
229     ValidatorResult Recurrence = visit(Expr->getStepRecurrence(SE));
230 
231     if (!Start.isValid())
232       return Start;
233 
234     if (!Recurrence.isValid())
235       return Recurrence;
236 
237     auto *L = Expr->getLoop();
238     if (R->contains(L) && (!Scope || !L->contains(Scope))) {
239       DEBUG(dbgs() << "INVALID: AddRec out of a loop whose exit value is not "
240                       "synthesizable");
241       return ValidatorResult(SCEVType::INVALID);
242     }
243 
244     if (R->contains(L)) {
245       if (Recurrence.isINT()) {
246         ValidatorResult Result(SCEVType::IV);
247         Result.addParamsFrom(Start);
248         return Result;
249       }
250 
251       DEBUG(dbgs() << "INVALID: AddRec within scop has non-int"
252                       "recurrence part");
253       return ValidatorResult(SCEVType::INVALID);
254     }
255 
256     assert(Start.isConstant() && Recurrence.isConstant() &&
257            "Expected 'Start' and 'Recurrence' to be constant");
258 
259     // Directly generate ValidatorResult for Expr if 'start' is zero.
260     if (Expr->getStart()->isZero())
261       return ValidatorResult(SCEVType::PARAM, Expr);
262 
263     // Translate AddRecExpr from '{start, +, inc}' into 'start + {0, +, inc}'
264     // if 'start' is not zero.
265     const SCEV *ZeroStartExpr = SE.getAddRecExpr(
266         SE.getConstant(Expr->getStart()->getType(), 0),
267         Expr->getStepRecurrence(SE), Expr->getLoop(), Expr->getNoWrapFlags());
268 
269     ValidatorResult ZeroStartResult =
270         ValidatorResult(SCEVType::PARAM, ZeroStartExpr);
271     ZeroStartResult.addParamsFrom(Start);
272 
273     return ZeroStartResult;
274   }
275 
276   class ValidatorResult visitSMaxExpr(const SCEVSMaxExpr *Expr) {
277     ValidatorResult Return(SCEVType::INT);
278 
279     for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
280       ValidatorResult Op = visit(Expr->getOperand(i));
281 
282       if (!Op.isValid())
283         return Op;
284 
285       Return.merge(Op);
286     }
287 
288     return Return;
289   }
290 
291   class ValidatorResult visitUMaxExpr(const SCEVUMaxExpr *Expr) {
292     // We do not support unsigned operations. If 'Expr' is constant during Scop
293     // execution we treat this as a parameter, otherwise we bail out.
294     for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
295       ValidatorResult Op = visit(Expr->getOperand(i));
296 
297       if (!Op.isConstant()) {
298         DEBUG(dbgs() << "INVALID: UMaxExpr has a non-constant operand");
299         return ValidatorResult(SCEVType::INVALID);
300       }
301     }
302 
303     return ValidatorResult(SCEVType::PARAM, Expr);
304   }
305 
306   ValidatorResult visitGenericInst(Instruction *I, const SCEV *S) {
307     if (R->contains(I)) {
308       DEBUG(dbgs() << "INVALID: UnknownExpr references an instruction "
309                       "within the region\n");
310       return ValidatorResult(SCEVType::INVALID);
311     }
312 
313     return ValidatorResult(SCEVType::PARAM, S);
314   }
315 
316   ValidatorResult visitLoadInstruction(Instruction *I, const SCEV *S) {
317     if (R->contains(I) && ILS) {
318       ILS->insert(cast<LoadInst>(I));
319       return ValidatorResult(SCEVType::PARAM, S);
320     }
321 
322     return visitGenericInst(I, S);
323   }
324 
325   ValidatorResult visitDivision(const SCEV *Dividend, const SCEV *Divisor,
326                                 const SCEV *DivExpr,
327                                 Instruction *SDiv = nullptr) {
328 
329     // First check if we might be able to model the division, thus if the
330     // divisor is constant. If so, check the dividend, otherwise check if
331     // the whole division can be seen as a parameter.
332     if (isa<SCEVConstant>(Divisor))
333       return visit(Dividend);
334 
335     // For signed divisions use the SDiv instruction to check for a parameter
336     // division, for unsigned divisions check the operands.
337     if (SDiv)
338       return visitGenericInst(SDiv, DivExpr);
339 
340     ValidatorResult LHS = visit(Dividend);
341     ValidatorResult RHS = visit(Divisor);
342     if (LHS.isConstant() && RHS.isConstant())
343       return ValidatorResult(SCEVType::PARAM, DivExpr);
344 
345     DEBUG(dbgs() << "INVALID: unsigned division of non-constant expressions");
346     return ValidatorResult(SCEVType::INVALID);
347   }
348 
349   ValidatorResult visitUDivExpr(const SCEVUDivExpr *Expr) {
350     auto *Dividend = Expr->getLHS();
351     auto *Divisor = Expr->getRHS();
352     return visitDivision(Dividend, Divisor, Expr);
353   }
354 
355   ValidatorResult visitSDivInstruction(Instruction *SDiv, const SCEV *Expr) {
356     assert(SDiv->getOpcode() == Instruction::SDiv &&
357            "Assumed SDiv instruction!");
358 
359     auto *Dividend = SE.getSCEV(SDiv->getOperand(0));
360     auto *Divisor = SE.getSCEV(SDiv->getOperand(1));
361     return visitDivision(Dividend, Divisor, Expr, SDiv);
362   }
363 
364   ValidatorResult visitSRemInstruction(Instruction *SRem, const SCEV *S) {
365     assert(SRem->getOpcode() == Instruction::SRem &&
366            "Assumed SRem instruction!");
367 
368     auto *Divisor = SRem->getOperand(1);
369     auto *CI = dyn_cast<ConstantInt>(Divisor);
370     if (!CI)
371       return visitGenericInst(SRem, S);
372 
373     auto *Dividend = SRem->getOperand(0);
374     auto *DividendSCEV = SE.getSCEV(Dividend);
375     return visit(DividendSCEV);
376   }
377 
378   ValidatorResult visitUnknown(const SCEVUnknown *Expr) {
379     Value *V = Expr->getValue();
380 
381     if (!Expr->getType()->isIntegerTy() && !Expr->getType()->isPointerTy()) {
382       DEBUG(dbgs() << "INVALID: UnknownExpr is not an integer or pointer");
383       return ValidatorResult(SCEVType::INVALID);
384     }
385 
386     if (isa<UndefValue>(V)) {
387       DEBUG(dbgs() << "INVALID: UnknownExpr references an undef value");
388       return ValidatorResult(SCEVType::INVALID);
389     }
390 
391     if (Instruction *I = dyn_cast<Instruction>(Expr->getValue())) {
392       switch (I->getOpcode()) {
393       case Instruction::Load:
394         return visitLoadInstruction(I, Expr);
395       case Instruction::SDiv:
396         return visitSDivInstruction(I, Expr);
397       case Instruction::SRem:
398         return visitSRemInstruction(I, Expr);
399       default:
400         return visitGenericInst(I, Expr);
401       }
402     }
403 
404     return ValidatorResult(SCEVType::PARAM, Expr);
405   }
406 };
407 
408 /// @brief Check whether a SCEV refers to an SSA name defined inside a region.
409 class SCEVInRegionDependences {
410   const Region *R;
411   Loop *Scope;
412   bool AllowLoops;
413   bool HasInRegionDeps = false;
414 
415 public:
416   SCEVInRegionDependences(const Region *R, Loop *Scope, bool AllowLoops)
417       : R(R), Scope(Scope), AllowLoops(AllowLoops) {}
418 
419   bool follow(const SCEV *S) {
420     if (auto Unknown = dyn_cast<SCEVUnknown>(S)) {
421       Instruction *Inst = dyn_cast<Instruction>(Unknown->getValue());
422 
423       // Return true when Inst is defined inside the region R.
424       if (Inst && R->contains(Inst)) {
425         HasInRegionDeps = true;
426         return false;
427       }
428     } else if (auto AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
429       if (!AllowLoops) {
430         if (!Scope) {
431           HasInRegionDeps = true;
432           return false;
433         }
434         auto *L = AddRec->getLoop();
435         if (R->contains(L) && !L->contains(Scope)) {
436           HasInRegionDeps = true;
437           return false;
438         }
439       }
440     }
441     return true;
442   }
443   bool isDone() { return false; }
444   bool hasDependences() { return HasInRegionDeps; }
445 };
446 
447 namespace polly {
448 /// Find all loops referenced in SCEVAddRecExprs.
449 class SCEVFindLoops {
450   SetVector<const Loop *> &Loops;
451 
452 public:
453   SCEVFindLoops(SetVector<const Loop *> &Loops) : Loops(Loops) {}
454 
455   bool follow(const SCEV *S) {
456     if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S))
457       Loops.insert(AddRec->getLoop());
458     return true;
459   }
460   bool isDone() { return false; }
461 };
462 
463 void findLoops(const SCEV *Expr, SetVector<const Loop *> &Loops) {
464   SCEVFindLoops FindLoops(Loops);
465   SCEVTraversal<SCEVFindLoops> ST(FindLoops);
466   ST.visitAll(Expr);
467 }
468 
469 /// Find all values referenced in SCEVUnknowns.
470 class SCEVFindValues {
471   ScalarEvolution &SE;
472   SetVector<Value *> &Values;
473 
474 public:
475   SCEVFindValues(ScalarEvolution &SE, SetVector<Value *> &Values)
476       : SE(SE), Values(Values) {}
477 
478   bool follow(const SCEV *S) {
479     const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(S);
480     if (!Unknown)
481       return true;
482 
483     Values.insert(Unknown->getValue());
484     Instruction *Inst = dyn_cast<Instruction>(Unknown->getValue());
485     if (!Inst || (Inst->getOpcode() != Instruction::SRem &&
486                   Inst->getOpcode() != Instruction::SDiv))
487       return false;
488 
489     auto *Dividend = SE.getSCEV(Inst->getOperand(1));
490     if (!isa<SCEVConstant>(Dividend))
491       return false;
492 
493     auto *Divisor = SE.getSCEV(Inst->getOperand(0));
494     SCEVFindValues FindValues(SE, Values);
495     SCEVTraversal<SCEVFindValues> ST(FindValues);
496     ST.visitAll(Dividend);
497     ST.visitAll(Divisor);
498 
499     return false;
500   }
501   bool isDone() { return false; }
502 };
503 
504 void findValues(const SCEV *Expr, ScalarEvolution &SE,
505                 SetVector<Value *> &Values) {
506   SCEVFindValues FindValues(SE, Values);
507   SCEVTraversal<SCEVFindValues> ST(FindValues);
508   ST.visitAll(Expr);
509 }
510 
511 bool hasScalarDepsInsideRegion(const SCEV *Expr, const Region *R,
512                                llvm::Loop *Scope, bool AllowLoops) {
513   SCEVInRegionDependences InRegionDeps(R, Scope, AllowLoops);
514   SCEVTraversal<SCEVInRegionDependences> ST(InRegionDeps);
515   ST.visitAll(Expr);
516   return InRegionDeps.hasDependences();
517 }
518 
519 bool isAffineExpr(const Region *R, llvm::Loop *Scope, const SCEV *Expr,
520                   ScalarEvolution &SE, InvariantLoadsSetTy *ILS) {
521   if (isa<SCEVCouldNotCompute>(Expr))
522     return false;
523 
524   SCEVValidator Validator(R, Scope, SE, ILS);
525   DEBUG({
526     dbgs() << "\n";
527     dbgs() << "Expr: " << *Expr << "\n";
528     dbgs() << "Region: " << R->getNameStr() << "\n";
529     dbgs() << " -> ";
530   });
531 
532   ValidatorResult Result = Validator.visit(Expr);
533 
534   DEBUG({
535     if (Result.isValid())
536       dbgs() << "VALID\n";
537     dbgs() << "\n";
538   });
539 
540   return Result.isValid();
541 }
542 
543 static bool isAffineParamExpr(Value *V, const Region *R, Loop *Scope,
544                               ScalarEvolution &SE, ParameterSetTy &Params) {
545   auto *E = SE.getSCEV(V);
546   if (isa<SCEVCouldNotCompute>(E))
547     return false;
548 
549   SCEVValidator Validator(R, Scope, SE, nullptr);
550   ValidatorResult Result = Validator.visit(E);
551   if (!Result.isConstant())
552     return false;
553 
554   auto ResultParams = Result.getParameters();
555   Params.insert(ResultParams.begin(), ResultParams.end());
556 
557   return true;
558 }
559 
560 bool isAffineParamConstraint(Value *V, const Region *R, llvm::Loop *Scope,
561                              ScalarEvolution &SE, ParameterSetTy &Params,
562                              bool OrExpr) {
563   if (auto *ICmp = dyn_cast<ICmpInst>(V)) {
564     return isAffineParamConstraint(ICmp->getOperand(0), R, Scope, SE, Params,
565                                    true) &&
566            isAffineParamConstraint(ICmp->getOperand(1), R, Scope, SE, Params,
567                                    true);
568   } else if (auto *BinOp = dyn_cast<BinaryOperator>(V)) {
569     auto Opcode = BinOp->getOpcode();
570     if (Opcode == Instruction::And || Opcode == Instruction::Or)
571       return isAffineParamConstraint(BinOp->getOperand(0), R, Scope, SE, Params,
572                                      false) &&
573              isAffineParamConstraint(BinOp->getOperand(1), R, Scope, SE, Params,
574                                      false);
575     /* Fall through */
576   }
577 
578   if (!OrExpr)
579     return false;
580 
581   return isAffineParamExpr(V, R, Scope, SE, Params);
582 }
583 
584 ParameterSetTy getParamsInAffineExpr(const Region *R, Loop *Scope,
585                                      const SCEV *Expr, ScalarEvolution &SE) {
586   if (isa<SCEVCouldNotCompute>(Expr))
587     return ParameterSetTy();
588 
589   InvariantLoadsSetTy ILS;
590   SCEVValidator Validator(R, Scope, SE, &ILS);
591   ValidatorResult Result = Validator.visit(Expr);
592   assert(Result.isValid() && "Requested parameters for an invalid SCEV!");
593 
594   return Result.getParameters();
595 }
596 
597 std::pair<const SCEVConstant *, const SCEV *>
598 extractConstantFactor(const SCEV *S, ScalarEvolution &SE) {
599 
600   auto *LeftOver = SE.getConstant(S->getType(), 1);
601   auto *ConstPart = cast<SCEVConstant>(SE.getConstant(S->getType(), 1));
602 
603   if (auto *Constant = dyn_cast<SCEVConstant>(S))
604     return std::make_pair(Constant, LeftOver);
605 
606   auto *AddRec = dyn_cast<SCEVAddRecExpr>(S);
607   if (AddRec) {
608     auto *StartExpr = AddRec->getStart();
609     if (StartExpr->isZero()) {
610       auto StepPair = extractConstantFactor(AddRec->getStepRecurrence(SE), SE);
611       auto *LeftOverAddRec =
612           SE.getAddRecExpr(StartExpr, StepPair.second, AddRec->getLoop(),
613                            AddRec->getNoWrapFlags());
614       return std::make_pair(StepPair.first, LeftOverAddRec);
615     }
616     return std::make_pair(ConstPart, S);
617   }
618 
619   if (auto *Add = dyn_cast<SCEVAddExpr>(S)) {
620     SmallVector<const SCEV *, 4> LeftOvers;
621     auto Op0Pair = extractConstantFactor(Add->getOperand(0), SE);
622     auto *Factor = Op0Pair.first;
623     if (SE.isKnownNegative(Factor)) {
624       Factor = cast<SCEVConstant>(SE.getNegativeSCEV(Factor));
625       LeftOvers.push_back(SE.getNegativeSCEV(Op0Pair.second));
626     } else {
627       LeftOvers.push_back(Op0Pair.second);
628     }
629 
630     for (unsigned u = 1, e = Add->getNumOperands(); u < e; u++) {
631       auto OpUPair = extractConstantFactor(Add->getOperand(u), SE);
632       // TODO: Use something smarter than equality here, e.g., gcd.
633       if (Factor == OpUPair.first)
634         LeftOvers.push_back(OpUPair.second);
635       else if (Factor == SE.getNegativeSCEV(OpUPair.first))
636         LeftOvers.push_back(SE.getNegativeSCEV(OpUPair.second));
637       else
638         return std::make_pair(ConstPart, S);
639     }
640 
641     auto *NewAdd = SE.getAddExpr(LeftOvers, Add->getNoWrapFlags());
642     return std::make_pair(Factor, NewAdd);
643   }
644 
645   auto *Mul = dyn_cast<SCEVMulExpr>(S);
646   if (!Mul)
647     return std::make_pair(ConstPart, S);
648 
649   for (auto *Op : Mul->operands())
650     if (isa<SCEVConstant>(Op))
651       ConstPart = cast<SCEVConstant>(SE.getMulExpr(ConstPart, Op));
652     else
653       LeftOver = SE.getMulExpr(LeftOver, Op);
654 
655   return std::make_pair(ConstPart, LeftOver);
656 }
657 }
658