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