|
29 | 29 | #include "llvm/Analysis/IVDescriptors.h"
|
30 | 30 | #include "llvm/Analysis/InstSimplifyFolder.h"
|
31 | 31 | #include "llvm/Analysis/LoopInfo.h"
|
| 32 | +#include "llvm/Analysis/ScalarEvolutionPatternMatch.h" |
32 | 33 | #include "llvm/Analysis/VectorUtils.h"
|
33 | 34 | #include "llvm/IR/Intrinsics.h"
|
34 | 35 | #include "llvm/IR/MDBuilder.h"
|
@@ -2539,6 +2540,46 @@ void VPlanTransforms::canonicalizeEVLLoops(VPlan &Plan) {
|
2539 | 2540 | LatchExitingBr->eraseFromParent();
|
2540 | 2541 | }
|
2541 | 2542 |
|
| 2543 | +void VPlanTransforms::replaceSymbolicStrides( |
| 2544 | + VPlan &Plan, PredicatedScalarEvolution &PSE, |
| 2545 | + const DenseMap<Value *, const SCEV *> &StridesMap) { |
| 2546 | + // Replace VPValues for known constant strides guaranteed by predicate scalar |
| 2547 | + // evolution. |
| 2548 | + auto CanUseVersionedStride = [&Plan](VPUser &U, unsigned) { |
| 2549 | + auto *R = cast<VPRecipeBase>(&U); |
| 2550 | + return R->getParent()->getParent() || |
| 2551 | + R->getParent() == Plan.getVectorLoopRegion()->getSinglePredecessor(); |
| 2552 | + }; |
| 2553 | + for (const SCEV *Stride : StridesMap.values()) { |
| 2554 | + using namespace SCEVPatternMatch; |
| 2555 | + auto *StrideV = cast<SCEVUnknown>(Stride)->getValue(); |
| 2556 | + const APInt *StrideConst; |
| 2557 | + if (!match(PSE.getSCEV(StrideV), m_scev_APInt(StrideConst))) |
| 2558 | + // Only handle constant strides for now. |
| 2559 | + continue; |
| 2560 | + |
| 2561 | + auto *CI = |
| 2562 | + Plan.getOrAddLiveIn(ConstantInt::get(Stride->getType(), *StrideConst)); |
| 2563 | + if (VPValue *StrideVPV = Plan.getLiveIn(StrideV)) |
| 2564 | + StrideVPV->replaceUsesWithIf(CI, CanUseVersionedStride); |
| 2565 | + |
| 2566 | + // The versioned value may not be used in the loop directly but through a |
| 2567 | + // sext/zext. Add new live-ins in those cases. |
| 2568 | + for (Value *U : StrideV->users()) { |
| 2569 | + if (!isa<SExtInst, ZExtInst>(U)) |
| 2570 | + continue; |
| 2571 | + VPValue *StrideVPV = Plan.getLiveIn(U); |
| 2572 | + if (!StrideVPV) |
| 2573 | + continue; |
| 2574 | + unsigned BW = U->getType()->getScalarSizeInBits(); |
| 2575 | + APInt C = |
| 2576 | + isa<SExtInst>(U) ? StrideConst->sext(BW) : StrideConst->zext(BW); |
| 2577 | + VPValue *CI = Plan.getOrAddLiveIn(ConstantInt::get(U->getType(), C)); |
| 2578 | + StrideVPV->replaceUsesWithIf(CI, CanUseVersionedStride); |
| 2579 | + } |
| 2580 | + } |
| 2581 | +} |
| 2582 | + |
2542 | 2583 | void VPlanTransforms::dropPoisonGeneratingRecipes(
|
2543 | 2584 | VPlan &Plan,
|
2544 | 2585 | const std::function<bool(BasicBlock *)> &BlockNeedsPredication) {
|
|
0 commit comments