//===-- VPlanUnroll.cpp - VPlan unroller ----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements explicit unrolling for VPlans.
///
//===----------------------------------------------------------------------===//

#include "VPRecipeBuilder.h"
#include "VPlan.h"
#include "VPlanAnalysis.h"
#include "VPlanCFG.h"
#include "VPlanHelpers.h"
#include "VPlanPatternMatch.h"
#include "VPlanTransforms.h"
#include "VPlanUtils.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/Analysis/IVDescriptors.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
#include <numeric>

using namespace llvm;
using namespace llvm::VPlanPatternMatch;

namespace {

/// Helper to hold state needed for unrolling. It holds the Plan to unroll by
/// UF. It also holds copies of VPValues across UF-1 unroll parts to facilitate
/// the unrolling transformation, where the original VPValues are retained for
/// part zero.
class UnrollState {
  /// Plan to unroll.
  VPlan &Plan;
  /// Unroll factor to unroll by.
  const unsigned UF;

  /// Unrolling may create recipes that should not be unrolled themselves.
  /// Those are tracked in ToSkip.
  SmallPtrSet<VPRecipeBase *, 8> ToSkip;

  // Associate with each VPValue of part 0 its unrolled instances of parts 1,
  // ..., UF-1.
  DenseMap<VPValue *, SmallVector<VPValue *>> VPV2Parts;

  /// Unroll replicate region \p VPR by cloning the region UF - 1 times.
  void unrollReplicateRegionByUF(VPRegionBlock *VPR);

  /// Unroll recipe \p R by cloning it UF - 1 times, unless it is uniform across
  /// all parts.
  void unrollRecipeByUF(VPRecipeBase &R);

  /// Unroll header phi recipe \p R. How exactly the recipe gets unrolled
  /// depends on the concrete header phi. Inserts newly created recipes at \p
  /// InsertPtForPhi.
  void unrollHeaderPHIByUF(VPHeaderPHIRecipe *R,
                           VPBasicBlock::iterator InsertPtForPhi);

  /// Unroll a widen induction recipe \p IV. This introduces recipes to compute
  /// the induction steps for each part.
  void unrollWidenInductionByUF(VPWidenInductionRecipe *IV,
                                VPBasicBlock::iterator InsertPtForPhi);

  VPValue *getConstantInt(unsigned Part) {
    Type *CanIVIntTy = Plan.getVectorLoopRegion()->getCanonicalIVType();
    return Plan.getConstantInt(CanIVIntTy, Part);
  }

public:
  UnrollState(VPlan &Plan, unsigned UF) : Plan(Plan), UF(UF) {}

  void unrollBlock(VPBlockBase *VPB);

  VPValue *getValueForPart(VPValue *V, unsigned Part) {
    if (Part == 0 || isa<VPIRValue, VPSymbolicValue>(V))
      return V;
    assert((VPV2Parts.contains(V) && VPV2Parts[V].size() >= Part) &&
           "accessed value does not exist");
    return VPV2Parts[V][Part - 1];
  }

  /// Given a single original recipe \p OrigR (of part zero), and its copy \p
  /// CopyR for part \p Part, map every VPValue defined by \p OrigR to its
  /// corresponding VPValue defined by \p CopyR.
  void addRecipeForPart(VPRecipeBase *OrigR, VPRecipeBase *CopyR,
                        unsigned Part) {
    for (const auto &[Idx, VPV] : enumerate(OrigR->definedValues())) {
      const auto &[V, _] = VPV2Parts.try_emplace(VPV);
      assert(V->second.size() == Part - 1 && "earlier parts not set");
      V->second.push_back(CopyR->getVPValue(Idx));
    }
  }

  /// Given a uniform recipe \p R, add it for all parts.
  void addUniformForAllParts(VPSingleDefRecipe *R) {
    const auto &[V, Inserted] = VPV2Parts.try_emplace(R);
    assert(Inserted && "uniform value already added");
    for (unsigned Part = 0; Part != UF; ++Part)
      V->second.push_back(R);
  }

  bool contains(VPValue *VPV) const { return VPV2Parts.contains(VPV); }

  /// Update \p R's operand at \p OpIdx with its corresponding VPValue for part
  /// \p P.
  void remapOperand(VPRecipeBase *R, unsigned OpIdx, unsigned Part) {
    auto *Op = R->getOperand(OpIdx);
    R->setOperand(OpIdx, getValueForPart(Op, Part));
  }

  /// Update \p R's operands with their corresponding VPValues for part \p P.
  void remapOperands(VPRecipeBase *R, unsigned Part) {
    for (const auto &[OpIdx, Op] : enumerate(R->operands()))
      R->setOperand(OpIdx, getValueForPart(Op, Part));
  }
};
} // namespace

static void addStartIndexForScalarSteps(VPScalarIVStepsRecipe *Steps,
                                        unsigned Part, VPlan &Plan) {
  if (Part == 0)
    return;

  VPBuilder Builder(Steps);
  Type *BaseIVTy = Steps->getOperand(0)->getScalarType();
  Type *IntStepTy =
      IntegerType::get(BaseIVTy->getContext(), BaseIVTy->getScalarSizeInBits());
  VPValue *StartIndex = Steps->getVFValue();
  if (Part > 1) {
    StartIndex = Builder.createOverflowingOp(
        Instruction::Mul,
        {StartIndex, Plan.getConstantInt(StartIndex->getScalarType(), Part)});
  }
  StartIndex = Builder.createScalarSExtOrTrunc(StartIndex, IntStepTy,
                                               Steps->getDebugLoc());

  if (BaseIVTy->isFloatingPointTy())
    StartIndex = Builder.createScalarCast(Instruction::SIToFP, StartIndex,
                                          BaseIVTy, Steps->getDebugLoc());

  Steps->setStartIndex(StartIndex);
}

void UnrollState::unrollReplicateRegionByUF(VPRegionBlock *VPR) {
  VPBlockBase *InsertPt = VPR->getSingleSuccessor();
  for (unsigned Part = 1; Part != UF; ++Part) {
    auto *Copy = VPR->clone();
    VPBlockUtils::insertBlockBefore(Copy, InsertPt);

    auto PartI = vp_depth_first_shallow(Copy->getEntry());
    auto Part0 = vp_depth_first_shallow(VPR->getEntry());
    for (const auto &[PartIVPBB, Part0VPBB] :
         zip(VPBlockUtils::blocksAs<VPBasicBlock>(PartI),
             VPBlockUtils::blocksAs<VPBasicBlock>(Part0))) {
      for (const auto &[PartIR, Part0R] : zip(*PartIVPBB, *Part0VPBB)) {
        remapOperands(&PartIR, Part);
        if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(&PartIR))
          addStartIndexForScalarSteps(Steps, Part, Plan);

        addRecipeForPart(&Part0R, &PartIR, Part);
      }
    }
  }
}

void UnrollState::unrollWidenInductionByUF(
    VPWidenInductionRecipe *IV, VPBasicBlock::iterator InsertPtForPhi) {
  VPBasicBlock *PH = cast<VPBasicBlock>(
      IV->getParent()->getEnclosingLoopRegion()->getSinglePredecessor());
  Type *IVTy = IV->getScalarType();
  auto &ID = IV->getInductionDescriptor();
  FastMathFlags FMF;
  VPIRFlags::WrapFlagsTy WrapFlags(false, false);
  if (auto *IntOrFPInd = dyn_cast<VPWidenIntOrFpInductionRecipe>(IV)) {
    FMF = IntOrFPInd->getFastMathFlagsOrNone();
    WrapFlags = IntOrFPInd->getNoWrapFlagsOrNone();
  }

  VPValue *ScalarStep = IV->getStepValue();
  VPBuilder Builder(PH);
  Type *VectorStepTy = IVTy->isPointerTy() ? ScalarStep->getScalarType() : IVTy;
  VPInstruction *VectorStep = Builder.createNaryOp(
      VPInstruction::WideIVStep, {&Plan.getVF(), ScalarStep}, VectorStepTy, FMF,
      IV->getDebugLoc());

  ToSkip.insert(VectorStep);

  // Now create recipes to compute the induction steps for part 1 .. UF. Part 0
  // remains the header phi. Parts > 0 are computed by adding Step to the
  // previous part. The header phi recipe will get 2 new operands: the step
  // value for a single part and the last part, used to compute the backedge
  // value during VPWidenInductionRecipe::execute.
  // %Part.0 = VPWidenInductionRecipe %Start, %ScalarStep, %VectorStep, %Part.3
  // %Part.1 = %Part.0 + %VectorStep
  // %Part.2 = %Part.1 + %VectorStep
  // %Part.3 = %Part.2 + %VectorStep
  //
  // The newly added recipes are added to ToSkip to avoid interleaving them
  // again.
  VPValue *Prev = IV;
  Builder.setInsertPoint(IV->getParent(), InsertPtForPhi);
  unsigned AddOpc;
  VPIRFlags AddFlags;
  if (IVTy->isPointerTy()) {
    AddOpc = VPInstruction::WidePtrAdd;
    AddFlags = GEPNoWrapFlags::none();
  } else if (IVTy->isFloatingPointTy()) {
    AddOpc = ID.getInductionOpcode();
    AddFlags = FMF;
  } else {
    AddOpc = Instruction::Add;
    AddFlags = WrapFlags;
    if (cast<VPWidenIntOrFpInductionRecipe>(IV)->isCanonical())
      AddFlags = VPIRFlags::WrapFlagsTy(/*NUW=*/true, /*NSW=*/false);
  }
  for (unsigned Part = 1; Part != UF; ++Part) {
    std::string Name =
        Part > 1 ? "step.add." + std::to_string(Part) : "step.add";

    VPInstruction *Add =
        Builder.createNaryOp(AddOpc,
                             {
                                 Prev,
                                 VectorStep,
                             },
                             AddFlags, IV->getDebugLoc(), Name);
    ToSkip.insert(Add);
    addRecipeForPart(IV, Add, Part);
    Prev = Add;
  }
  IV->addUnrolledPartOperands(VectorStep, Prev);
}

void UnrollState::unrollHeaderPHIByUF(VPHeaderPHIRecipe *R,
                                      VPBasicBlock::iterator InsertPtForPhi) {
  // First-order recurrences pass a single vector or scalar through their header
  // phis, irrespective of interleaving.
  if (isa<VPFirstOrderRecurrencePHIRecipe>(R))
    return;

  // Generate step vectors for each unrolled part.
  if (auto *IV = dyn_cast<VPWidenInductionRecipe>(R)) {
    unrollWidenInductionByUF(IV, InsertPtForPhi);
    return;
  }

  auto *RdxPhi = dyn_cast<VPReductionPHIRecipe>(R);
  if (RdxPhi && RdxPhi->isOrdered())
    return;

  auto InsertPt = std::next(R->getIterator());
  for (unsigned Part = 1; Part != UF; ++Part) {
    VPRecipeBase *Copy = R->clone();
    Copy->insertBefore(*R->getParent(), InsertPt);
    addRecipeForPart(R, Copy, Part);
    if (RdxPhi) {
      // If the start value is a ReductionStartVector, use the identity value
      // (second operand) for unrolled parts. If the scaling factor is > 1,
      // create a new ReductionStartVector with the scale factor and both
      // operands set to the identity value.
      if (auto *VPI = dyn_cast<VPInstruction>(RdxPhi->getStartValue())) {
        assert(VPI->getOpcode() == VPInstruction::ReductionStartVector &&
               "unexpected start VPInstruction");
        if (Part != 1)
          continue;
        VPValue *StartV;
        if (match(VPI->getOperand(2), m_One())) {
          StartV = VPI->getOperand(1);
        } else {
          auto *C = VPI->clone();
          C->setOperand(0, C->getOperand(1));
          C->insertAfter(VPI);
          StartV = C;
        }
        for (unsigned Part = 1; Part != UF; ++Part)
          VPV2Parts[VPI][Part - 1] = StartV;
      }
    } else {
      assert(isa<VPActiveLaneMaskPHIRecipe>(R) &&
             "unexpected header phi recipe not needing unrolled part");
    }
  }
}

/// Handle non-header-phi recipes.
void UnrollState::unrollRecipeByUF(VPRecipeBase &R) {
  if (match(&R, m_CombineOr(m_BranchOnCond(), m_BranchOnCount())))
    return;

  if (auto *VPI = dyn_cast<VPInstruction>(&R)) {
    if (vputils::onlyFirstPartUsed(VPI)) {
      addUniformForAllParts(VPI);
      return;
    }
  }
  if (auto *RepR = dyn_cast<VPReplicateRecipe>(&R)) {
    if (isa<StoreInst>(RepR->getUnderlyingValue()) &&
        RepR->getOperand(1)->isDefinedOutsideLoopRegions()) {
      // Stores to an invariant address only need to store the last part.
      remapOperands(&R, UF - 1);
      return;
    }
    if (match(RepR,
              m_Intrinsic<Intrinsic::experimental_noalias_scope_decl>())) {
      addUniformForAllParts(RepR);
      return;
    }
  }

  // Unroll non-uniform recipes.
  auto InsertPt = std::next(R.getIterator());
  VPBasicBlock &VPBB = *R.getParent();
  for (unsigned Part = 1; Part != UF; ++Part) {
    VPRecipeBase *Copy = R.clone();
    Copy->insertBefore(VPBB, InsertPt);
    addRecipeForPart(&R, Copy, Part);

    // Phi operands are updated once all other recipes have been unrolled.
    if (isa<VPWidenPHIRecipe>(Copy))
      continue;

    VPValue *Op;
    if (match(&R, m_VPInstruction<VPInstruction::FirstOrderRecurrenceSplice>(
                      m_VPValue(), m_VPValue(Op)))) {
      Copy->setOperand(0, getValueForPart(Op, Part - 1));
      Copy->setOperand(1, getValueForPart(Op, Part));
      continue;
    }
    if (match(&R, m_VPInstruction<VPInstruction::ExtractVectorForPart>(
                      m_VPValue(Op), m_VPValue()))) {
      Copy->setOperand(0, Op);
      Copy->setOperand(1, Plan.getConstantInt(64, Part));
      continue;
    }
    if (isa<VPVectorPointerRecipe, VPWidenCanonicalIVRecipe>(R)) {
      VPBuilder Builder(&R);
      const DataLayout &DL = Plan.getDataLayout();
      Type *IndexTy =
          isa<VPWidenCanonicalIVRecipe>(R)
              ? Plan.getVectorLoopRegion()->getCanonicalIVType()
              : DL.getIndexType(R.getVPSingleValue()->getScalarType());
      VPValue *VF = Builder.createScalarZExtOrTrunc(&Plan.getVF(), IndexTy,
                                                    DebugLoc::getUnknown());
      // VFxUF does not wrap, so VF * Part also cannot wrap.
      VPValue *VFxPart = Builder.createOverflowingOp(
          Instruction::Mul, {VF, Plan.getConstantInt(IndexTy, Part)},
          {true, true});
      if (auto *VecPtr = dyn_cast<VPVectorPointerRecipe>(Copy))
        VecPtr->addPerPartOffset(VFxPart);
      else
        cast<VPWidenCanonicalIVRecipe>(Copy)->addPerPartStep(VFxPart);
      continue;
    }
    if (auto *Red = dyn_cast<VPReductionRecipe>(&R)) {
      auto *Phi = dyn_cast<VPReductionPHIRecipe>(R.getOperand(0));
      if (Phi && Phi->isOrdered()) {
        auto &Parts = VPV2Parts[Phi];
        if (Part == 1) {
          Parts.clear();
          Parts.push_back(Red);
        }
        Parts.push_back(Copy->getVPSingleValue());
        Phi->setOperand(1, Copy->getVPSingleValue());
      }
    }
    if (auto *VEPR = dyn_cast<VPVectorEndPointerRecipe>(Copy)) {
      // Materialize PartN offset for VectorEndPointer.
      VEPR->setOperand(0, R.getOperand(0));
      VEPR->setOperand(1, R.getOperand(1));
      VEPR->materializeOffset(Part);
      continue;
    }

    remapOperands(Copy, Part);

    if (auto *ScalarIVSteps = dyn_cast<VPScalarIVStepsRecipe>(Copy))
      addStartIndexForScalarSteps(ScalarIVSteps, Part, Plan);

    if (match(Copy,
              m_VPInstruction<VPInstruction::CanonicalIVIncrementForPart>())) {
      VPBuilder Builder(Copy);
      VPValue *ScaledByPart = Builder.createOverflowingOp(
          Instruction::Mul, {Copy->getOperand(1), getConstantInt(Part)});
      Copy->setOperand(1, ScaledByPart);
    }
  }
  if (auto *VEPR = dyn_cast<VPVectorEndPointerRecipe>(&R)) {
    // Materialize Part0 offset for VectorEndPointer.
    VEPR->materializeOffset();
  }
  if (auto *WideCanIV = dyn_cast<VPWidenCanonicalIVRecipe>(&R)) {
    // Set Part0 step for WidenCanonicalIV.
    WideCanIV->addPerPartStep(getConstantInt(0));
  }
}

void UnrollState::unrollBlock(VPBlockBase *VPB) {
  auto *VPR = dyn_cast<VPRegionBlock>(VPB);
  if (VPR) {
    if (VPR->isReplicator())
      return unrollReplicateRegionByUF(VPR);

    // Traverse blocks in region in RPO to ensure defs are visited before uses
    // across blocks.
    ReversePostOrderTraversal<VPBlockShallowTraversalWrapper<VPBlockBase *>>
        RPOT(VPR->getEntry());
    for (VPBlockBase *VPB : RPOT)
      unrollBlock(VPB);
    return;
  }

  // VPB is a VPBasicBlock; unroll it, i.e., unroll its recipes.
  auto *VPBB = cast<VPBasicBlock>(VPB);
  auto InsertPtForPhi = VPBB->getFirstNonPhi();
  for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
    if (ToSkip.contains(&R) || isa<VPIRInstruction>(&R))
      continue;

    // Add all VPValues for all parts to AnyOf, FirstActiveLaneMask and
    // ComputeReductionResult which combine all parts to compute the final
    // value.
    VPValue *Op1;
    if (match(&R, m_VPInstruction<VPInstruction::AnyOf>(m_VPValue(Op1))) ||
        match(&R,
              m_VPInstruction<VPInstruction::ConcatVectors>(m_VPValue(Op1))) ||
        match(&R, m_FirstActiveLane(m_VPValue(Op1))) ||
        match(&R, m_LastActiveLane(m_VPValue(Op1))) ||
        match(&R, m_ComputeReductionResult(m_VPValue(Op1)))) {
      auto *VPI = cast<VPInstruction>(&R);
      addUniformForAllParts(VPI);
      for (unsigned Part = 1; Part != UF; ++Part)
        VPI->addOperand(getValueForPart(Op1, Part));
      continue;
    }
    VPValue *Op0;
    if (match(&R, m_ExtractLane(m_VPValue(Op0), m_VPValue(Op1)))) {
      auto *VPI = cast<VPInstruction>(&R);
      addUniformForAllParts(VPI);
      for (unsigned Part = 1; Part != UF; ++Part)
        VPI->addOperand(getValueForPart(Op1, Part));
      continue;
    }

    VPValue *Op2;
    if (match(&R, m_ExtractLastActive(m_VPValue(), m_VPValue(Op1),
                                      m_VPValue(Op2)))) {
      auto *VPI = cast<VPInstruction>(&R);
      addUniformForAllParts(VPI);
      for (unsigned Part = 1; Part != UF; ++Part) {
        VPI->addOperand(getValueForPart(Op1, Part));
        VPI->addOperand(getValueForPart(Op2, Part));
      }
      continue;
    }

    if (Plan.hasScalarVFOnly()) {
      if (match(&R, m_ExtractLastPart(m_VPValue(Op0))) ||
          match(&R, m_ExtractPenultimateElement(m_VPValue(Op0)))) {
        auto *I = cast<VPInstruction>(&R);
        bool IsPenultimatePart =
            I->getOpcode() == VPInstruction::ExtractPenultimateElement;
        unsigned PartIdx = IsPenultimatePart ? UF - 2 : UF - 1;
        // For scalar VF, directly use the scalar part value.
        I->replaceAllUsesWith(getValueForPart(Op0, PartIdx));
        continue;
      }
    }
    // For vector VF, the penultimate element is always extracted from the last part.
    if (match(&R, m_ExtractLastLaneOfLastPart(m_VPValue(Op0))) ||
        match(&R, m_ExtractPenultimateElement(m_VPValue(Op0)))) {
      addUniformForAllParts(cast<VPSingleDefRecipe>(&R));
      R.setOperand(0, getValueForPart(Op0, UF - 1));
      continue;
    }

    if (match(&R,
              m_WideActiveLaneMask(m_VPValue(), m_VPValue(), m_VPValue()))) {
      auto *ALM = cast<VPInstruction>(&R);
      ALM->setOperand(2, getConstantInt(UF));
      continue;
    }

    if (match(&R,
              m_CombineOr(m_VPInstruction<VPInstruction::WideVectorLoad>(),
                          m_VPInstruction<VPInstruction::WideVectorStore>()))) {
      cast<VPInstruction>(&R)->setOperand(0, Plan.getConstantInt(64, UF));
      continue;
    }

    auto *SingleDef = dyn_cast<VPSingleDefRecipe>(&R);
    if (SingleDef && vputils::isUniformAcrossVFsAndUFs(SingleDef)) {
      addUniformForAllParts(SingleDef);
      continue;
    }

    if (auto *H = dyn_cast<VPHeaderPHIRecipe>(&R)) {
      unrollHeaderPHIByUF(H, InsertPtForPhi);
      continue;
    }

    unrollRecipeByUF(R);
  }
}

void VPlanTransforms::unrollByUF(VPlan &Plan, unsigned UF) {
  assert(UF > 0 && "Unroll factor must be positive");
  Plan.setUF(UF);
  llvm::scope_exit Cleanup([&Plan, UF]() {
    auto Iter = vp_depth_first_deep(Plan.getEntry());
    // Remove recipes that are redundant after unrolling.
    for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(Iter)) {
      for (VPInstruction &VPI :
           make_early_inc_range(make_isa_range<VPInstruction>(*VPBB))) {
        if (VPI.getOpcode() == VPInstruction::CanonicalIVIncrementForPart &&
            VPI.getOperand(1) == &Plan.getVF()) {
          VPI.replaceAllUsesWith(VPI.getOperand(0));
          VPI.eraseFromParent();
        }
      }
    }

    Type *TCTy = Plan.getTripCount()->getScalarType();
    Plan.getUF().replaceAllUsesWith(Plan.getConstantInt(TCTy, UF));
  });
  if (UF == 1) {
    return;
  }

  UnrollState Unroller(Plan, UF);

  // Iterate over all blocks in the plan starting from Entry, and unroll
  // recipes inside them. This includes the vector preheader and middle blocks,
  // which may set up or post-process per-part values.
  ReversePostOrderTraversal<VPBlockShallowTraversalWrapper<VPBlockBase *>> RPOT(
      Plan.getEntry());
  for (VPBlockBase *VPB : RPOT)
    Unroller.unrollBlock(VPB);

  unsigned Part = 1;
  // Remap operands of cloned header phis to update backedge values. The header
  // phis cloned during unrolling are just after the header phi for part 0.
  // Reset Part to 1 when reaching the first (part 0) recipe of a block.
  for (VPRecipeBase &H :
       Plan.getVectorLoopRegion()->getEntryBasicBlock()->phis()) {
    // The second operand of Fixed Order Recurrence phi's, feeding the spliced
    // value across the backedge, needs to remap to the last part of the spliced
    // value.
    if (isa<VPFirstOrderRecurrencePHIRecipe>(&H)) {
      Unroller.remapOperand(&H, 1, UF - 1);
      continue;
    }
    if (Unroller.contains(H.getVPSingleValue())) {
      Part = 1;
      continue;
    }
    Unroller.remapOperands(&H, Part);
    Part++;
  }

  VPlanTransforms::removeDeadRecipes(Plan);
}

/// Add a lane offset to the start index of \p Steps.
static void addLaneToStartIndex(VPScalarIVStepsRecipe *Steps, unsigned Lane,
                                VPlan &Plan, VPRecipeBase *InsertPt) {
  assert(Lane > 0 && "Zero lane adds no offset to start index");
  Type *BaseIVTy = Steps->getOperand(0)->getScalarType();

  VPValue *OldStartIndex = Steps->getStartIndex();
  VPValue *LaneOffset;
  unsigned AddOpcode;
  // TODO: Retrieve the flags from Steps unconditionally.
  VPIRFlags Flags;
  if (BaseIVTy->isFloatingPointTy()) {
    // The start index counts upwards, so accumulate with FAdd regardless of the
    // induction opcode; see VPScalarIVStepsRecipe.
    LaneOffset = Plan.getOrAddLiveIn(ConstantFP::get(BaseIVTy, Lane));
    AddOpcode = Instruction::FAdd;
    Flags = VPIRFlags(FastMathFlags());
  } else {
    unsigned BaseIVBits = BaseIVTy->getScalarSizeInBits();
    LaneOffset = Plan.getConstantInt(
        APInt(BaseIVBits, Lane, /*isSigned*/ false, /*implicitTrunc*/ true));
    AddOpcode = Instruction::Add;
    Flags = VPIRFlags(VPIRFlags::WrapFlagsTy(false, false));
  }

  VPValue *NewStartIndex = LaneOffset;
  if (OldStartIndex) {
    VPBuilder Builder(InsertPt);
    NewStartIndex =
        Builder.createNaryOp(AddOpcode, {OldStartIndex, LaneOffset}, Flags);
  }
  Steps->setStartIndex(NewStartIndex);
}

/// Create a single-scalar clone of \p DefR (must be a VPReplicateRecipe,
/// VPInstruction or VPScalarIVStepsRecipe) for lane \p Lane. Use \p
/// Def2LaneDefs to look up scalar definitions for operands of \DefR.
static VPValue *
cloneForLane(VPlan &Plan, VPBuilder &Builder, Type *IdxTy,
             VPSingleDefRecipe *DefR, VPLane Lane,
             const DenseMap<VPValue *, SmallVector<VPValue *>> &Def2LaneDefs) {
  assert((isa<VPInstruction, VPReplicateRecipe, VPScalarIVStepsRecipe>(DefR)) &&
         "DefR must be a VPReplicateRecipe, VPInstruction or "
         "VPScalarIVStepsRecipe");
  VPValue *Op;
  if (match(DefR, m_VPInstruction<VPInstruction::Unpack>(m_VPValue(Op)))) {
    auto LaneDefs = Def2LaneDefs.find(Op);
    if (LaneDefs != Def2LaneDefs.end())
      return LaneDefs->second[Lane.getKnownLane()];

    VPValue *Idx = Plan.getConstantInt(IdxTy, Lane.getKnownLane());
    return Builder.createNaryOp(Instruction::ExtractElement, {Op, Idx});
  }

  // Collect the operands at Lane, creating extracts as needed.
  SmallVector<VPValue *> NewOps;
  for (VPValue *Op : DefR->operands()) {
    // If Op is a definition that has been unrolled, directly use the clone for
    // the corresponding lane.
    auto LaneDefs = Def2LaneDefs.find(Op);
    if (LaneDefs != Def2LaneDefs.end()) {
      NewOps.push_back(LaneDefs->second[Lane.getKnownLane()]);
      continue;
    }
    if (Lane.getKind() == VPLane::Kind::ScalableLast) {
      // Look through mandatory Unpack.
      [[maybe_unused]] bool Matched =
          match(Op, m_VPInstruction<VPInstruction::Unpack>(m_VPValue(Op)));
      assert(Matched && "original op must have been Unpack");
      auto *ExtractPart =
          Builder.createNaryOp(VPInstruction::ExtractLastPart, {Op});
      NewOps.push_back(
          Builder.createNaryOp(VPInstruction::ExtractLastLane, {ExtractPart}));
      continue;
    }
    if (vputils::isSingleScalar(Op)) {
      NewOps.push_back(Op);
      continue;
    }

    VPValue *Idx = Plan.getConstantInt(IdxTy, Lane.getKnownLane());
    VPValue *Ext = Builder.createNaryOp(Instruction::ExtractElement, {Op, Idx});
    NewOps.push_back(Ext);
  }

  VPSingleDefRecipe *New;
  if (auto *RepR = dyn_cast<VPReplicateRecipe>(DefR)) {
    // TODO: have cloning of replicate recipes also provide the desired result
    // coupled with setting its operands to NewOps (deriving IsSingleScalar and
    // Mask from the operands?)
    New = VPBuilder::createSingleScalarOp(
        RepR->getOpcode(), NewOps, /*Mask=*/nullptr, *RepR, *RepR,
        RepR->getDebugLoc(), RepR->getScalarType(), RepR->getUnderlyingInstr());
  } else {
    New = DefR->clone();
    for (const auto &[Idx, Op] : enumerate(NewOps)) {
      New->setOperand(Idx, Op);
    }
    if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(New)) {
      // Skip lane 0: an absent start index is implicitly zero.
      unsigned KnownLane = Lane.getKnownLane();
      if (KnownLane != 0)
        addLaneToStartIndex(Steps, KnownLane, Plan, DefR);
    }
  }
  New->insertBefore(DefR);
  return New;
}

/// Converts the frequency \p Freq with which a block is entered to branch
/// weights for the branch guarding it, or nullptr if \p Freq is unknown or
/// estimated.
static MDNode *
convertFrequencyToBranchWeights(std::optional<VPExecutionFrequency> Freq,
                                LLVMContext &Ctx) {
  if (!Freq || Freq->IsEstimated)
    return nullptr;
  BranchProbability P = vputils::getExecutionProbability(Freq->Freq);

  // Use the numerators of P and its complement as weights and reduce them via
  // gcd to keep them small. Neither is zero, as P is neither zero nor one.
  uint32_t Taken = P.getNumerator();
  uint32_t NotTaken = P.getCompl().getNumerator();
  uint32_t GCD = std::gcd(Taken, NotTaken);
  return MDBuilder(Ctx).createBranchWeights(Taken / GCD, NotTaken / GCD);
}

/// Convert recipes in region blocks to operate on a single lane 0.
/// VPReplicateRecipes are converted to single-scalar ones, branch-on-mask is
/// converted into BranchOnCond, PredInstPhi recipes are replaced by scalar phi
/// recipes with an additional poison operand, and extracts are created as
/// needed.
static void convertRecipesInRegionBlocksToSingleScalar(VPlan &Plan, Type *IdxTy,
                                                       VPBlockBase *Entry,
                                                       ElementCount VF) {
  VPValue *Idx0 = Plan.getZero(IdxTy);
  for (VPBlockBase *VPB : vp_depth_first_shallow(Entry)) {
    for (VPRecipeBase &OldR : make_early_inc_range(cast<VPBasicBlock>(*VPB))) {
      assert(
          !isa<VPWidenPHIRecipe>(&OldR) &&
          !match(&OldR,
                 m_CombineOr(
                     m_InsertElement(m_VPValue(), m_VPValue(), m_VPValue()),
                     m_ExtractElement(m_VPValue(), m_VPValue()))) &&
          "must not contain wide phis, inserts or extracts before conversion");

      VPBuilder Builder(&OldR);
      DebugLoc OldDL = OldR.getDebugLoc();
      // For scalar VF, operands are already scalar; no extraction needed.
      if (!VF.isScalar()) {
        for (const auto &[I, Op] : enumerate(OldR.operands())) {
          // Skip operands that don't need extraction: values defined in the
          // same block (already scalar), or values that are already single
          // scalars.
          // TODO: Support isSingleScalar for VPScalarIVStepsRecipe.
          auto *DefR = Op->getDefiningRecipe();
          if ((isa_and_present<VPScalarIVStepsRecipe>(DefR) &&
               DefR->getParent() == VPB) ||
              vputils::isSingleScalar(Op))
            continue;

          // Extract lane zero from values defined outside the region.
          VPValue *Extract = Builder.createNaryOp(Instruction::ExtractElement,
                                                  {Op, Idx0}, OldDL);
          OldR.setOperand(I, Extract);
        }
      }

      if (auto *RepR = dyn_cast<VPReplicateRecipe>(&OldR)) {
        auto *NewR = VPBuilder::createSingleScalarOp(
            RepR->getOpcode(), to_vector(RepR->operands()), /*Mask=*/nullptr,
            *RepR, *RepR, OldDL, RepR->getScalarType(),
            RepR->getUnderlyingInstr());
        NewR->insertBefore(RepR);
        RepR->replaceAllUsesWith(NewR);
        RepR->eraseFromParent();
      } else if (auto *BranchOnMask = dyn_cast<VPBranchOnMaskRecipe>(&OldR)) {
        // Turn the frequency of the predicated block into branch weights.
        auto *BOC = Builder.createNaryOp(VPInstruction::BranchOnCond,
                                         {BranchOnMask->getOperand(0)}, OldDL);
        if (MDNode *Weights = convertFrequencyToBranchWeights(
                BranchOnMask->getExecutionFrequency(), Plan.getContext()))
          BOC->setMetadata(LLVMContext::MD_prof, Weights);
        BranchOnMask->eraseFromParent();
      } else if (auto *PredPhi = dyn_cast<VPPredInstPHIRecipe>(&OldR)) {
        VPValue *PredOp = PredPhi->getOperand(0);
        Type *PredTy = PredOp->getScalarType();
        VPValue *Poison = Plan.getPoison(PredTy);
        VPPhi *NewPhi = Builder.createScalarPhi({Poison, PredOp}, OldDL);
        PredPhi->replaceAllUsesWith(NewPhi);
        PredPhi->eraseFromParent();
      } else {
        // TODO: Support isSingleScalar for VPScalarIVStepsRecipe.
        assert((isa<VPScalarIVStepsRecipe>(OldR) ||
                (isa<VPInstruction>(OldR) &&
                 vputils::isSingleScalar(OldR.getVPSingleValue()))) &&
               "unexpected unhandled recipe");
      }
    }
  }
}

/// Update recipes in the cloned blocks rooted at \p NewEntry to match \p Lane,
/// using the original blocks rooted at \p OldEntry as reference.
static void processLaneForReplicateRegion(VPlan &Plan, Type *IdxTy,
                                          unsigned Lane, VPBasicBlock *OldEntry,
                                          VPBasicBlock *NewEntry) {
  DenseMap<VPValue *, VPValue *> Old2NewVPValues;
  VPValue *IdxLane = Plan.getConstantInt(IdxTy, Lane);
  for (const auto &[OldBB, NewBB] :
       zip_equal(vp_depth_first_shallow(OldEntry),
                 vp_depth_first_shallow(NewEntry))) {
    for (auto &&[OldR, NewR] :
         zip_equal(*cast<VPBasicBlock>(OldBB), *cast<VPBasicBlock>(NewBB))) {
      for (const auto &[OldV, NewV] :
           zip_equal(OldR.definedValues(), NewR.definedValues()))
        Old2NewVPValues[OldV] = NewV;

      // Remap operands to use lane-specific values.
      for (const auto &[I, OldOp] : enumerate(NewR.operands())) {
        // Use cloned value if operand was defined in the region.
        if (auto *NewOp = Old2NewVPValues.lookup(OldOp))
          NewR.setOperand(I, NewOp);
      }

      if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(&NewR)) {
        addLaneToStartIndex(Steps, Lane, Plan, Steps);
      } else if (match(&NewR, m_ExtractElement(m_VPValue(), m_VPValue()))) {
        assert(match(NewR.getOperand(1), m_ZeroInt()) &&
               "extract indices must be zero");
        NewR.setOperand(1, IdxLane);
      } else if (auto *NewPhi = dyn_cast<VPPhi>(&NewR)) {
        auto *OldPhi = cast<VPPhi>(&OldR);
        assert(vputils::onlyFirstLaneUsed(OldPhi) &&
               "VPPhis expected to have only first lane used");
        auto *BVUser = dyn_cast_or_null<VPInstruction>(OldPhi->getSingleUser());
        if (BVUser && match(BVUser, m_BuildVector())) {
          assert(BVUser->getOperand(0) == OldPhi &&
                 "Unexpected first operand of build vector user");
          BVUser->setOperand(Lane, NewPhi);
        }
      }
    }
  }
}

/// Dissolve a single replicate region by replicating its blocks for each lane
/// of \p VF. The region is disconnected, its blocks are reparented, cloned for
/// each lane, and reconnected in sequence.
static void dissolveReplicateRegion(VPRegionBlock *Region, ElementCount VF,
                                    VPlan &Plan, Type *IdxTy) {
  auto *FirstLaneEntry = cast<VPBasicBlock>(Region->getEntry());
  auto *FirstLaneExiting = cast<VPBasicBlock>(Region->getExiting());

  // Disconnect and dissolve the region.
  VPBlockBase *Predecessor = Region->getSinglePredecessor();
  assert(Predecessor && "Replicate region must have a single predecessor");
  auto *Successor = cast<VPBasicBlock>(Region->getSingleSuccessor());
  VPBlockUtils::disconnectBlocks(Predecessor, Region);
  VPBlockUtils::disconnectBlocks(Region, Successor);

  VPRegionBlock *ParentRegion = Region->getParent();
  for (VPBlockBase *VPB : vp_depth_first_shallow(FirstLaneEntry))
    VPB->setParent(ParentRegion);

  // Process the original blocks for lane 0: converting their recipes to
  // single-scalar.
  convertRecipesInRegionBlocksToSingleScalar(Plan, IdxTy, FirstLaneEntry, VF);

  // For scalar VF, just wire the blocks and return; no cloning or packing
  // needed.
  if (VF.isScalar()) {
    VPBlockUtils::connectBlocks(Predecessor, FirstLaneEntry);
    VPBlockUtils::connectBlocks(FirstLaneExiting, Successor);
    return;
  }

  // Create a BuildVector in successor block for every VPPhi in (first lane's)
  // exiting block having vector uses. All their
  // operands are initialized to poison and will be replaced when processing
  // each clone, except for the operand of the first lane which set here.
  // BuildVectors are recorded to be replaced later by chains of insert-element
  // and widen phis.
  unsigned NumLanes = VF.getFixedValue();
  SmallVector<VPInstruction *> BuildVectors;
  for (auto &R : FirstLaneExiting->phis()) {
    auto *Phi = cast<VPPhi>(&R);
    if (vputils::onlyFirstLaneUsed(Phi))
      continue;

    Type *ScalarTy = Phi->getScalarType();
    VPValue *Poison = Plan.getPoison(ScalarTy);
    SmallVector<VPValue *> BVOps(NumLanes, Poison);
    auto *BV = new VPInstruction(VPInstruction::BuildVector, BVOps);
    BuildVectors.push_back(BV);
    Phi->replaceAllUsesWith(BV);
    BV->setOperand(0, Phi);
    BV->insertBefore(*Successor, Successor->getFirstNonPhi());
  }

  // Clone converted blocks for remaining lanes and process each in reverse
  // order, connecting each lane's Exiting block to the subsequent lane's entry.
  VPBlockBase *NextLaneEntry = Successor;
  for (int Lane = NumLanes - 1; Lane > 0; --Lane) {
    const auto &[CurrentLaneEntry, CurrentLaneExiting] =
        VPBlockUtils::cloneFrom(FirstLaneEntry);
    for (VPBlockBase *VPB : vp_depth_first_shallow(CurrentLaneEntry))
      VPB->setParent(ParentRegion);
    processLaneForReplicateRegion(Plan, IdxTy, Lane,
                                  cast<VPBasicBlock>(FirstLaneEntry),
                                  cast<VPBasicBlock>(CurrentLaneEntry));
    VPBlockUtils::connectBlocks(CurrentLaneExiting, NextLaneEntry);
    NextLaneEntry = CurrentLaneEntry;
  }

  // Connect Predecessor to FirstLaneEntry, and FirstLaneRegionExit to
  // NextLaneEntry which is the second lane region entry. The latter is
  // done last so that earlier clonings from FirstLaneEntry stop at
  // FirstLaneExiting.
  VPBlockUtils::connectBlocks(Predecessor, FirstLaneEntry);
  VPBlockUtils::connectBlocks(FirstLaneExiting, NextLaneEntry);

  // Fold BuildVector fed by scalar phis into VPWidenPHIRecipes with
  // InsertElement per lane.
  // TODO: check if this folding should be dropped.
  for (VPInstruction *BV : BuildVectors) {
    assert(BV->getNumOperands() == NumLanes &&
           "BuildVector must have one operand per lane");
    for (const auto &[Idx, Op] : enumerate(BV->operands())) {
      auto *ScalarPhi = cast<VPPhi>(Op);
      auto DL = ScalarPhi->getDebugLoc();
      auto *PredOp = cast<VPSingleDefRecipe>(ScalarPhi->getOperand(1));
      VPValue *Poison = ScalarPhi->getOperand(0);
      VPValue *PrevVal = Idx == 0 ? Poison : BV->getOperand(Idx - 1);
      auto Builder = VPBuilder::getToInsertAfter(PredOp->getDefiningRecipe());
      auto *Insert = Builder.createNaryOp(
          Instruction::InsertElement,
          {PrevVal, PredOp, Plan.getConstantInt(64, Idx)}, DL);
      Builder.setInsertPoint(ScalarPhi);
      auto *NewPhi = Builder.createWidenPhi({PrevVal, Insert}, DL);
      ScalarPhi->replaceAllUsesWith(NewPhi);
      ScalarPhi->eraseFromParent();
    }
    BV->replaceAllUsesWith(BV->getOperand(NumLanes - 1));
    BV->eraseFromParent();
  }
}

/// Collect and dissolve all replicate regions in the vector loop, replicating
/// their blocks and recipes for each lane of \p VF.
static void replicateReplicateRegionsByVF(VPlan &Plan, ElementCount VF,
                                          Type *IdxTy) {
  // Collect all replicate regions before modifying the CFG.
  SmallVector<VPRegionBlock *> ReplicateRegions;
  for (VPRegionBlock *Region : VPBlockUtils::blocksOnly<VPRegionBlock>(
           vp_depth_first_shallow(Plan.getVectorLoopRegion()->getEntry()))) {
    if (Region->isReplicator())
      ReplicateRegions.push_back(Region);
  }

  assert((ReplicateRegions.empty() || !VF.isScalable()) &&
         "cannot replicate across scalable VFs");

  // Dissolve replicate regions by replicating their blocks for each lane.
  // Traversing regions in reverse ensures that the successor of every region
  // being processed is a basic-block, rather than another region.
  for (VPRegionBlock *Region : reverse(ReplicateRegions))
    dissolveReplicateRegion(Region, VF, Plan, IdxTy);

  VPlanTransforms::mergeBlocksIntoPredecessors(Plan);
}

void VPlanTransforms::replicateByVF(VPlan &Plan, ElementCount VF) {
  Type *IdxTy = IntegerType::get(
      Plan.getScalarHeader()->getIRBasicBlock()->getContext(), 32);

  if (Plan.hasScalarVFOnly()) {
    // When Plan is only unrolled by UF, replicating by VF amounts to dissolving
    // replicate regions.
    replicateReplicateRegionsByVF(Plan, VF, IdxTy);
    return;
  }

  // Visit all VPBBs outside the loop region and directly inside the top-level
  // loop region.
  auto VPBBsOutsideLoopRegion = VPBlockUtils::blocksOnly<VPBasicBlock>(
      vp_depth_first_shallow(Plan.getEntry()));
  auto VPBBsInsideLoopRegion = VPBlockUtils::blocksOnly<VPBasicBlock>(
      vp_depth_first_shallow(Plan.getVectorLoopRegion()->getEntry()));
  auto VPBBsToUnroll =
      concat<VPBasicBlock *>(VPBBsOutsideLoopRegion, VPBBsInsideLoopRegion);
  // A mapping of current VPValue definitions to collections of new VPValues
  // defined per lane. Serves to hook-up potential users of current VPValue
  // definition that are replicated-per-VF later.
  DenseMap<VPValue *, SmallVector<VPValue *>> Def2LaneDefs;
  // The removal of current recipes being replaced by new ones needs to be
  // delayed after Def2LaneDefs is no longer in use.
  SmallVector<VPSingleDefRecipe *> ToRemove;
  for (VPBasicBlock *VPBB : VPBBsToUnroll) {
    for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
      if (!vputils::doesGeneratePerAllLanes(&R))
        continue;

      auto *DefR = cast<VPSingleDefRecipe>(&R);
      VPBuilder Builder(DefR);
      if (DefR->user_empty()) {
        // Create single-scalar version of DefR for all lanes.
        for (unsigned I = 0; I != VF.getKnownMinValue(); ++I)
          cloneForLane(Plan, Builder, IdxTy, DefR, VPLane(I), Def2LaneDefs);
        DefR->eraseFromParent();
        continue;
      }
      /// Create single-scalar version of DefR for all lanes.
      SmallVector<VPValue *> LaneDefs;
      for (unsigned I = 0; I != VF.getKnownMinValue(); ++I)
        LaneDefs.push_back(
            cloneForLane(Plan, Builder, IdxTy, DefR, VPLane(I), Def2LaneDefs));

      Def2LaneDefs[DefR] = LaneDefs;
      // Pack the lanes for vector users.
      if (!vputils::onlyScalarValuesUsed(DefR)) {
        DefR->replaceUsesWithIf(
            Builder.createNaryOp(VPInstruction::BuildVector, LaneDefs),
            [DefR](VPUser *U) { return !U->usesScalars(DefR); });
      }
      /// Users that only demand the first lane can use the definition for lane
      /// 0.
      DefR->replaceUsesWithIf(LaneDefs[0], [DefR](VPUser *U) {
        if (U->usesFirstLaneOnly(DefR))
          return true;
        auto *VPI = dyn_cast<VPInstruction>(U);
        return VPI && Instruction::isCast(VPI->getOpcode());
      });
      ToRemove.push_back(DefR);
    }
  }

  replicateReplicateRegionsByVF(Plan, VF, IdxTy);
  // Replace the lane extracts created when dissolving replicate regions.
  for (VPSingleDefRecipe *DefR : reverse(ToRemove)) {
    for (VPUser *U : to_vector(DefR->users())) {
      uint64_t Lane;
      [[maybe_unused]] bool Match =
          match(U, m_ExtractElement(m_Specific(DefR), m_ConstantInt(Lane)));
      assert(Match && "unexpected remaining user");
      auto *Ext = cast<VPInstruction>(U);
      Ext->replaceAllUsesWith(Def2LaneDefs.at(DefR)[Lane]);
      Ext->eraseFromParent();
    }
    DefR->eraseFromParent();
  }
}
