//===- InterleavedAccessPass.cpp ------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file implements the Interleaved Access pass, which identifies
// interleaved memory accesses and transforms them into target specific
// intrinsics.
//
// An interleaved load reads data from memory into several vectors, with
// DE-interleaving the data on a factor. An interleaved store writes several
// vectors to memory with RE-interleaving the data on a factor.
//
// As interleaved accesses are difficult to identified in CodeGen (mainly
// because the VECTOR_SHUFFLE DAG node is quite different from the shufflevector
// IR), we identify and transform them to intrinsics in this pass so the
// intrinsics can be easily matched into target specific instructions later in
// CodeGen.
//
// E.g. An interleaved load (Factor = 2):
//        %wide.vec = load <8 x i32>, <8 x i32>* %ptr
//        %v0 = shuffle <8 x i32> %wide.vec, <8 x i32> poison, <0, 2, 4, 6>
//        %v1 = shuffle <8 x i32> %wide.vec, <8 x i32> poison, <1, 3, 5, 7>
//
// It could be transformed into a ld2 intrinsic in AArch64 backend or a vld2
// intrinsic in ARM backend.
//
// In X86, this can be further optimized into a set of target
// specific loads followed by an optimized sequence of shuffles.
//
// E.g. An interleaved store (Factor = 3):
//        %i.vec = shuffle <8 x i32> %v0, <8 x i32> %v1,
//                                    <0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11>
//        store <12 x i32> %i.vec, <12 x i32>* %ptr
//
// It could be transformed into a st3 intrinsic in AArch64 backend or a vst3
// intrinsic in ARM backend.
//
// Similarly, a set of interleaved stores can be transformed into an optimized
// sequence of shuffles followed by a set of target specific stores for X86.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/CodeGen/InterleavedAccess.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Utils/Local.h"
#include <cassert>
#include <utility>

using namespace llvm;

#define DEBUG_TYPE "interleaved-access"

static cl::opt<bool> LowerInterleavedAccesses(
    "lower-interleaved-accesses",
    cl::desc("Enable lowering interleaved accesses to intrinsics"),
    cl::init(true), cl::Hidden);

namespace {

class InterleavedAccessImpl {
  friend class InterleavedAccess;

public:
  InterleavedAccessImpl() = default;
  InterleavedAccessImpl(DominatorTree *DT, const TargetLowering *TLI)
      : DT(DT), TLI(TLI), MaxFactor(TLI->getMaxSupportedInterleaveFactor()) {}
  bool runOnFunction(Function &F);

private:
  DominatorTree *DT = nullptr;
  const TargetLowering *TLI = nullptr;

  /// The maximum supported interleave factor.
  unsigned MaxFactor = 0u;

  /// Transform an interleaved load into target specific intrinsics.
  bool lowerInterleavedLoad(Instruction *Load,
                            SmallSetVector<Instruction *, 32> &DeadInsts);

  /// Transform an interleaved store into target specific intrinsics.
  bool lowerInterleavedStore(Instruction *Store,
                             SmallSetVector<Instruction *, 32> &DeadInsts);

  /// Transform a load and a deinterleave intrinsic into target specific
  /// instructions.
  bool lowerDeinterleaveIntrinsic(IntrinsicInst *II,
                                  SmallSetVector<Instruction *, 32> &DeadInsts);

  /// Transform an interleave intrinsic and a store into target specific
  /// instructions.
  bool lowerInterleaveIntrinsic(IntrinsicInst *II,
                                SmallSetVector<Instruction *, 32> &DeadInsts);

  /// Returns true if the uses of an interleaved load by the
  /// extractelement instructions in \p Extracts can be replaced by uses of the
  /// shufflevector instructions in \p Shuffles instead. If so, the necessary
  /// replacements are also performed.
  bool tryReplaceExtracts(ArrayRef<ExtractElementInst *> Extracts,
                          ArrayRef<ShuffleVectorInst *> Shuffles);

  /// Given a number of shuffles of the form shuffle(binop(x,y)), convert them
  /// to binop(shuffle(x), shuffle(y)) to allow the formation of an
  /// interleaving load. Any newly created shuffles that operate on \p LI will
  /// be added to \p Shuffles. Returns true, if any changes to the IR have been
  /// made.
  bool replaceBinOpShuffles(ArrayRef<ShuffleVectorInst *> BinOpShuffles,
                            SmallVectorImpl<ShuffleVectorInst *> &Shuffles,
                            Instruction *LI);
};

class InterleavedAccess : public FunctionPass {
  InterleavedAccessImpl Impl;

public:
  static char ID;

  InterleavedAccess() : FunctionPass(ID) {}

  StringRef getPassName() const override { return "Interleaved Access Pass"; }

  bool runOnFunction(Function &F) override;

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.addRequired<DominatorTreeWrapperPass>();
    AU.setPreservesCFG();
  }
};

} // end anonymous namespace.

PreservedAnalyses InterleavedAccessPass::run(Function &F,
                                             FunctionAnalysisManager &FAM) {
  auto *DT = &FAM.getResult<DominatorTreeAnalysis>(F);
  auto *TLI = TM->getSubtargetImpl(F)->getTargetLowering();
  InterleavedAccessImpl Impl(DT, TLI);
  bool Changed = Impl.runOnFunction(F);

  if (!Changed)
    return PreservedAnalyses::all();

  PreservedAnalyses PA;
  PA.preserveSet<CFGAnalyses>();
  return PA;
}

char InterleavedAccess::ID = 0;

bool InterleavedAccess::runOnFunction(Function &F) {
  if (skipFunction(F))
    return false;

  auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
  if (!TPC || !LowerInterleavedAccesses)
    return false;

  LLVM_DEBUG(dbgs() << "*** " << getPassName() << ": " << F.getName() << "\n");

  Impl.DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
  auto &TM = TPC->getTM<TargetMachine>();
  Impl.TLI = TM.getSubtargetImpl(F)->getTargetLowering();
  Impl.MaxFactor = Impl.TLI->getMaxSupportedInterleaveFactor();

  return Impl.runOnFunction(F);
}

INITIALIZE_PASS_BEGIN(InterleavedAccess, DEBUG_TYPE,
    "Lower interleaved memory accesses to target specific intrinsics", false,
    false)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_END(InterleavedAccess, DEBUG_TYPE,
    "Lower interleaved memory accesses to target specific intrinsics", false,
    false)

FunctionPass *llvm::createInterleavedAccessPass() {
  return new InterleavedAccess();
}

/// Check if the mask is a DE-interleave mask for an interleaved load.
///
/// E.g. DE-interleave masks (Factor = 2) could be:
///     <0, 2, 4, 6>    (mask of index 0 to extract even elements)
///     <1, 3, 5, 7>    (mask of index 1 to extract odd elements)
static bool isDeInterleaveMask(ArrayRef<int> Mask, unsigned &Factor,
                               unsigned &Index, unsigned MaxFactor,
                               unsigned NumLoadElements) {
  if (Mask.size() < 2)
    return false;

  // Check potential Factors.
  for (Factor = 2; Factor <= MaxFactor; Factor++) {
    // Make sure we don't produce a load wider than the input load.
    if (Mask.size() * Factor > NumLoadElements)
      return false;
    if (ShuffleVectorInst::isDeInterleaveMaskOfFactor(Mask, Factor, Index))
      return true;
  }

  return false;
}

/// Check if the mask can be used in an interleaved store.
//
/// It checks for a more general pattern than the RE-interleave mask.
/// I.e. <x, y, ... z, x+1, y+1, ...z+1, x+2, y+2, ...z+2, ...>
/// E.g. For a Factor of 2 (LaneLen=4): <4, 32, 5, 33, 6, 34, 7, 35>
/// E.g. For a Factor of 3 (LaneLen=4): <4, 32, 16, 5, 33, 17, 6, 34, 18, 7, 35, 19>
/// E.g. For a Factor of 4 (LaneLen=2): <8, 2, 12, 4, 9, 3, 13, 5>
///
/// The particular case of an RE-interleave mask is:
/// I.e. <0, LaneLen, ... , LaneLen*(Factor - 1), 1, LaneLen + 1, ...>
/// E.g. For a Factor of 2 (LaneLen=4): <0, 4, 1, 5, 2, 6, 3, 7>
static bool isReInterleaveMask(ShuffleVectorInst *SVI, unsigned &Factor,
                               unsigned MaxFactor) {
  unsigned NumElts = SVI->getShuffleMask().size();
  if (NumElts < 4)
    return false;

  // Check potential Factors.
  for (Factor = 2; Factor <= MaxFactor; Factor++) {
    if (SVI->isInterleave(Factor))
      return true;
  }

  return false;
}

static Value *getMaskOperand(IntrinsicInst *II) {
  switch (II->getIntrinsicID()) {
  default:
    llvm_unreachable("Unexpected intrinsic");
  case Intrinsic::vp_load:
  case Intrinsic::masked_load:
    return II->getOperand(1);
  case Intrinsic::vp_store:
  case Intrinsic::masked_store:
    return II->getOperand(2);
  }
}

// Return a pair of
//  (1) The corresponded deinterleaved mask, or nullptr if there is no valid
//  mask.
//  (2) Some mask effectively skips a certain field, and this element is a mask
//  in which inactive lanes represent fields that are skipped (i.e. "gaps").
static std::pair<Value *, APInt> getMask(Value *WideMask, unsigned Factor,
                                         ElementCount LeafValueEC);

static std::pair<Value *, APInt> getMask(Value *WideMask, unsigned Factor,
                                         VectorType *LeafValueTy) {
  return getMask(WideMask, Factor, LeafValueTy->getElementCount());
}

bool InterleavedAccessImpl::lowerInterleavedLoad(
    Instruction *Load, SmallSetVector<Instruction *, 32> &DeadInsts) {
  if (isa<ScalableVectorType>(Load->getType()))
    return false;

  auto *LI = dyn_cast<LoadInst>(Load);
  auto *II = dyn_cast<IntrinsicInst>(Load);
  if (!LI && !II)
    return false;

  if (LI && !LI->isSimple())
    return false;

  // Check if all users of this load are shufflevectors. If we encounter any
  // users that are extractelement instructions or binary operators, we save
  // them to later check if they can be modified to extract from one of the
  // shufflevectors instead of the load.

  SmallVector<ShuffleVectorInst *, 4> Shuffles;
  SmallVector<ExtractElementInst *, 4> Extracts;
  // BinOpShuffles need to be handled a single time in case both operands of the
  // binop are the same load.
  SmallSetVector<ShuffleVectorInst *, 4> BinOpShuffles;

  for (auto *User : Load->users()) {
    auto *Extract = dyn_cast<ExtractElementInst>(User);
    if (Extract && isa<ConstantInt>(Extract->getIndexOperand())) {
      Extracts.push_back(Extract);
      continue;
    }
    if (auto *BI = dyn_cast<BinaryOperator>(User)) {
      using namespace PatternMatch;
      if (!BI->user_empty() &&
          all_of(BI->users(), match_fn(m_Shuffle(m_Value(), m_Undef())))) {
        for (auto *SVI : BI->users())
          BinOpShuffles.insert(cast<ShuffleVectorInst>(SVI));
        continue;
      }
    }
    auto *SVI = dyn_cast<ShuffleVectorInst>(User);
    if (!SVI || !isa<UndefValue>(SVI->getOperand(1)))
      return false;

    Shuffles.push_back(SVI);
  }

  if (Shuffles.empty() && BinOpShuffles.empty())
    return false;

  unsigned Factor, Index;

  unsigned NumLoadElements =
      cast<FixedVectorType>(Load->getType())->getNumElements();
  auto *FirstSVI = Shuffles.size() > 0 ? Shuffles[0] : BinOpShuffles[0];
  // Check if the first shufflevector is DE-interleave shuffle.
  if (!isDeInterleaveMask(FirstSVI->getShuffleMask(), Factor, Index, MaxFactor,
                          NumLoadElements))
    return false;

  // Holds the corresponding index for each DE-interleave shuffle.
  SmallVector<unsigned, 4> Indices;

  VectorType *VecTy = cast<VectorType>(FirstSVI->getType());

  // Check if other shufflevectors are also DE-interleaved of the same type
  // and factor as the first shufflevector.
  for (auto *Shuffle : Shuffles) {
    if (Shuffle->getType() != VecTy)
      return false;
    if (!ShuffleVectorInst::isDeInterleaveMaskOfFactor(
            Shuffle->getShuffleMask(), Factor, Index))
      return false;

    assert(Shuffle->getShuffleMask().size() <= NumLoadElements);
    Indices.push_back(Index);
  }
  for (auto *Shuffle : BinOpShuffles) {
    if (Shuffle->getType() != VecTy)
      return false;
    if (!ShuffleVectorInst::isDeInterleaveMaskOfFactor(
            Shuffle->getShuffleMask(), Factor, Index))
      return false;

    assert(Shuffle->getShuffleMask().size() <= NumLoadElements);

    if (cast<Instruction>(Shuffle->getOperand(0))->getOperand(0) == Load)
      Indices.push_back(Index);
    if (cast<Instruction>(Shuffle->getOperand(0))->getOperand(1) == Load)
      Indices.push_back(Index);
  }

  // Try and modify users of the load that are extractelement instructions to
  // use the shufflevector instructions instead of the load.
  if (!tryReplaceExtracts(Extracts, Shuffles))
    return false;

  bool BinOpShuffleChanged =
      replaceBinOpShuffles(BinOpShuffles.getArrayRef(), Shuffles, Load);

  Value *Mask = nullptr;
  auto GapMask = APInt::getAllOnes(Factor);
  if (LI) {
    LLVM_DEBUG(dbgs() << "IA: Found an interleaved load: " << *Load << "\n");
  } else {
    // Check mask operand. Handle both all-true/false and interleaved mask.
    std::tie(Mask, GapMask) = getMask(getMaskOperand(II), Factor, VecTy);
    if (!Mask)
      return false;

    LLVM_DEBUG(dbgs() << "IA: Found an interleaved vp.load or masked.load: "
                      << *Load << "\n");
    LLVM_DEBUG(dbgs() << "IA: With nominal factor " << Factor
                      << " and actual factor " << GapMask.popcount() << "\n");
  }

  // Try to create target specific intrinsics to replace the load and
  // shuffles.
  if (!TLI->lowerInterleavedLoad(cast<Instruction>(Load), Mask, Shuffles,
                                 Indices, Factor, GapMask))
    // If Extracts is not empty, tryReplaceExtracts made changes earlier.
    return !Extracts.empty() || BinOpShuffleChanged;

  DeadInsts.insert_range(Shuffles);

  DeadInsts.insert(Load);
  return true;
}

bool InterleavedAccessImpl::replaceBinOpShuffles(
    ArrayRef<ShuffleVectorInst *> BinOpShuffles,
    SmallVectorImpl<ShuffleVectorInst *> &Shuffles, Instruction *Load) {
  for (auto *SVI : BinOpShuffles) {
    BinaryOperator *BI = cast<BinaryOperator>(SVI->getOperand(0));
    Type *BIOp0Ty = BI->getOperand(0)->getType();
    ArrayRef<int> Mask = SVI->getShuffleMask();
    assert(all_of(Mask, [&](int Idx) {
      return Idx < (int)cast<FixedVectorType>(BIOp0Ty)->getNumElements();
    }));

    BasicBlock::iterator insertPos = SVI->getIterator();
    auto *NewSVI1 =
        new ShuffleVectorInst(BI->getOperand(0), PoisonValue::get(BIOp0Ty),
                              Mask, SVI->getName(), insertPos);
    auto *NewSVI2 = new ShuffleVectorInst(
        BI->getOperand(1), PoisonValue::get(BI->getOperand(1)->getType()), Mask,
        SVI->getName(), insertPos);
    BinaryOperator *NewBI = BinaryOperator::CreateWithCopiedFlags(
        BI->getOpcode(), NewSVI1, NewSVI2, BI, BI->getName(), insertPos);
    SVI->replaceAllUsesWith(NewBI);
    LLVM_DEBUG(dbgs() << "  Replaced: " << *BI << "\n    And   : " << *SVI
                      << "\n  With    : " << *NewSVI1 << "\n    And   : "
                      << *NewSVI2 << "\n    And   : " << *NewBI << "\n");
    RecursivelyDeleteTriviallyDeadInstructions(SVI);
    if (NewSVI1->getOperand(0) == Load)
      Shuffles.push_back(NewSVI1);
    if (NewSVI2->getOperand(0) == Load)
      Shuffles.push_back(NewSVI2);
  }

  return !BinOpShuffles.empty();
}

bool InterleavedAccessImpl::tryReplaceExtracts(
    ArrayRef<ExtractElementInst *> Extracts,
    ArrayRef<ShuffleVectorInst *> Shuffles) {
  // If there aren't any extractelement instructions to modify, there's nothing
  // to do.
  if (Extracts.empty())
    return true;

  // Maps extractelement instructions to vector-index pairs. The extractlement
  // instructions will be modified to use the new vector and index operands.
  DenseMap<ExtractElementInst *, std::pair<Value *, int>> ReplacementMap;

  for (auto *Extract : Extracts) {
    // The vector index that is extracted.
    auto *IndexOperand = cast<ConstantInt>(Extract->getIndexOperand());
    auto Index = IndexOperand->getSExtValue();

    // Look for a suitable shufflevector instruction. The goal is to modify the
    // extractelement instruction (which uses an interleaved load) to use one
    // of the shufflevector instructions instead of the load.
    for (auto *Shuffle : Shuffles) {
      // If the shufflevector instruction doesn't dominate the extract, we
      // can't create a use of it.
      if (!DT->dominates(Shuffle, Extract))
        continue;

      // Inspect the indices of the shufflevector instruction. If the shuffle
      // selects the same index that is extracted, we can modify the
      // extractelement instruction.
      SmallVector<int, 4> Indices;
      Shuffle->getShuffleMask(Indices);
      for (unsigned I = 0; I < Indices.size(); ++I)
        if (Indices[I] == Index) {
          assert(Extract->getOperand(0) == Shuffle->getOperand(0) &&
                 "Vector operations do not match");
          ReplacementMap[Extract] = std::make_pair(Shuffle, I);
          break;
        }

      // If we found a suitable shufflevector instruction, stop looking.
      if (ReplacementMap.count(Extract))
        break;
    }

    // If we did not find a suitable shufflevector instruction, the
    // extractelement instruction cannot be modified, so we must give up.
    if (!ReplacementMap.count(Extract))
      return false;
  }

  // Finally, perform the replacements.
  IRBuilder<> Builder(Extracts[0]->getContext());
  for (auto &Replacement : ReplacementMap) {
    auto *Extract = Replacement.first;
    auto *Vector = Replacement.second.first;
    auto Index = Replacement.second.second;
    Builder.SetInsertPoint(Extract);
    Extract->replaceAllUsesWith(Builder.CreateExtractElement(Vector, Index));
    Extract->eraseFromParent();
  }

  return true;
}

bool InterleavedAccessImpl::lowerInterleavedStore(
    Instruction *Store, SmallSetVector<Instruction *, 32> &DeadInsts) {
  Value *StoredValue;
  auto *SI = dyn_cast<StoreInst>(Store);
  auto *II = dyn_cast<IntrinsicInst>(Store);
  if (SI) {
    if (!SI->isSimple())
      return false;
    StoredValue = SI->getValueOperand();
  } else {
    assert(II->getIntrinsicID() == Intrinsic::vp_store ||
           II->getIntrinsicID() == Intrinsic::masked_store);
    StoredValue = II->getArgOperand(0);
  }

  auto *SVI = dyn_cast<ShuffleVectorInst>(StoredValue);
  if (!SVI || !SVI->hasOneUse() || isa<ScalableVectorType>(SVI->getType()))
    return false;

  unsigned NumStoredElements =
      cast<FixedVectorType>(SVI->getType())->getNumElements();
  // Check if the shufflevector is RE-interleave shuffle.
  unsigned Factor;
  if (!isReInterleaveMask(SVI, Factor, MaxFactor))
    return false;
  assert(NumStoredElements % Factor == 0 &&
         "number of stored element should be a multiple of Factor");

  Value *Mask = nullptr;
  auto GapMask = APInt::getAllOnes(Factor);
  if (SI) {
    LLVM_DEBUG(dbgs() << "IA: Found an interleaved store: " << *Store << "\n");
  } else {
    // Check mask operand. Handle both all-true/false and interleaved mask.
    unsigned LaneMaskLen = NumStoredElements / Factor;
    std::tie(Mask, GapMask) = getMask(getMaskOperand(II), Factor,
                                      ElementCount::getFixed(LaneMaskLen));
    if (!Mask)
      return false;

    LLVM_DEBUG(dbgs() << "IA: Found an interleaved vp.store or masked.store: "
                      << *Store << "\n");
    LLVM_DEBUG(dbgs() << "IA: With nominal factor " << Factor
                      << " and actual factor " << GapMask.popcount() << "\n");
  }

  // Try to create target specific intrinsics to replace the store and
  // shuffle.
  if (!TLI->lowerInterleavedStore(Store, Mask, SVI, Factor, GapMask))
    return false;

  // Already have a new target specific interleaved store. Erase the old store.
  DeadInsts.insert(Store);
  DeadInsts.insert(SVI);
  return true;
}

// A wide mask <1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0> could be used to skip the
// last field in a factor-of-three interleaved store or deinterleaved load (in
// which case LeafMaskLen is 4). Such (wide) mask is also known as gap mask.
// This helper function tries to detect this pattern and return the actual
// factor we're accessing, which is 2 in this example.
static void getGapMask(const Constant &MaskConst, unsigned Factor,
                       unsigned LeafMaskLen, APInt &GapMask) {
  assert(GapMask.getBitWidth() == Factor);
  for (unsigned F = 0U; F < Factor; ++F) {
    bool AllZero = true;
    for (unsigned Idx = 0U; Idx < LeafMaskLen; ++Idx) {
      Constant *C = MaskConst.getAggregateElement(F + Idx * Factor);
      if (!C->isZeroValue()) {
        AllZero = false;
        break;
      }
    }
    // All mask bits on this field are zero, skipping it.
    if (AllZero)
      GapMask.clearBit(F);
  }
}

static std::pair<Value *, APInt> getMask(Value *WideMask, unsigned Factor,
                                         ElementCount LeafValueEC) {
  auto GapMask = APInt::getAllOnes(Factor);

  if (auto *IMI = dyn_cast<IntrinsicInst>(WideMask)) {
    if (unsigned F = getInterleaveIntrinsicFactor(IMI->getIntrinsicID());
        F && F == Factor) {
      Value *RefArg = nullptr;
      // Check if all the intrinsic arguments are the same, except those that
      // are zeros, which we mark as gaps in the gap mask.
      for (auto [Idx, Arg] : enumerate(IMI->args())) {
        if (auto *C = dyn_cast<Constant>(Arg); C && C->isZeroValue()) {
          GapMask.clearBit(Idx);
          continue;
        }

        if (!RefArg)
          RefArg = Arg;
        else if (RefArg != Arg)
          return {nullptr, GapMask};
      }

      // In a very rare occasion, all the intrinsic arguments might be zeros,
      // in which case we still want to return an all-zeros constant instead of
      // nullptr.
      return {RefArg ? RefArg : IMI->getArgOperand(0), GapMask};
    }
  }

  // Masks that are assembled from bitwise AND.
  if (auto *AndOp = dyn_cast<BinaryOperator>(WideMask);
      AndOp && AndOp->getOpcode() == Instruction::And) {
    auto [MaskLHS, GapMaskLHS] =
        getMask(AndOp->getOperand(0), Factor, LeafValueEC);
    auto [MaskRHS, GapMaskRHS] =
        getMask(AndOp->getOperand(1), Factor, LeafValueEC);
    if (!MaskLHS || !MaskRHS)
      return {nullptr, GapMask};
    // Using IRBuilder here so that any trivial constants could be folded right
    // away.
    return {IRBuilder<>(AndOp).CreateAnd(MaskLHS, MaskRHS),
            GapMaskLHS & GapMaskRHS};
  }

  if (auto *ConstMask = dyn_cast<Constant>(WideMask)) {
    if (auto *Splat = ConstMask->getSplatValue())
      // All-ones or all-zeros mask.
      return {ConstantVector::getSplat(LeafValueEC, Splat), GapMask};

    if (LeafValueEC.isFixed()) {
      unsigned LeafMaskLen = LeafValueEC.getFixedValue();
      // First, check if we use a gap mask to skip some of the factors / fields.
      getGapMask(*ConstMask, Factor, LeafMaskLen, GapMask);

      SmallVector<Constant *, 8> LeafMask(LeafMaskLen, nullptr);
      // If this is a fixed-length constant mask, each lane / leaf has to
      // use the same mask. This is done by checking if every group with Factor
      // number of elements in the interleaved mask has homogeneous values.
      for (unsigned Idx = 0U; Idx < LeafMaskLen * Factor; ++Idx) {
        if (!GapMask[Idx % Factor])
          continue;
        Constant *C = ConstMask->getAggregateElement(Idx);
        if (LeafMask[Idx / Factor] && LeafMask[Idx / Factor] != C)
          return {nullptr, GapMask};
        LeafMask[Idx / Factor] = C;
      }

      return {ConstantVector::get(LeafMask), GapMask};
    }
  }

  if (auto *SVI = dyn_cast<ShuffleVectorInst>(WideMask)) {
    Type *Op1Ty = SVI->getOperand(1)->getType();
    if (!isa<FixedVectorType>(Op1Ty))
      return {nullptr, GapMask};

    // Check that the shuffle mask is: a) an interleave, b) all of the same
    // set of the elements, and c) contained by the first source.  (c) could
    // be relaxed if desired.
    unsigned NumSrcElts =
        cast<FixedVectorType>(SVI->getOperand(1)->getType())->getNumElements();
    SmallVector<unsigned> StartIndexes;
    if (ShuffleVectorInst::isInterleaveMask(SVI->getShuffleMask(), Factor,
                                            NumSrcElts * 2, StartIndexes) &&
        llvm::all_of(StartIndexes, equal_to(0)) &&
        llvm::all_of(SVI->getShuffleMask(), [&NumSrcElts](int Idx) {
          return Idx < (int)NumSrcElts;
        })) {
      auto *LeafMaskTy =
          VectorType::get(Type::getInt1Ty(SVI->getContext()), LeafValueEC);
      IRBuilder<> Builder(SVI);
      return {Builder.CreateExtractVector(LeafMaskTy, SVI->getOperand(0),
                                          uint64_t(0)),
              GapMask};
    }
  }

  return {nullptr, GapMask};
}

bool InterleavedAccessImpl::lowerDeinterleaveIntrinsic(
    IntrinsicInst *DI, SmallSetVector<Instruction *, 32> &DeadInsts) {
  Instruction *LoadedVal = dyn_cast<Instruction>(DI->getOperand(0));
  if (!LoadedVal || !LoadedVal->hasOneUse())
    return false;

  auto *LI = dyn_cast<LoadInst>(LoadedVal);
  auto *II = dyn_cast<IntrinsicInst>(LoadedVal);
  if (!LI && !II)
    return false;

  const unsigned Factor = getDeinterleaveIntrinsicFactor(DI->getIntrinsicID());
  assert(Factor && "unexpected deinterleave intrinsic");

  Value *Mask = nullptr;
  if (LI) {
    if (!LI->isSimple())
      return false;

    LLVM_DEBUG(dbgs() << "IA: Found a load with deinterleave intrinsic " << *DI
                      << " and factor = " << Factor << "\n");
  } else {
    assert(II);
    if (II->getIntrinsicID() != Intrinsic::masked_load &&
        II->getIntrinsicID() != Intrinsic::vp_load)
      return false;

    // Check mask operand. Handle both all-true/false and interleaved mask.
    APInt GapMask(Factor, 0);
    std::tie(Mask, GapMask) =
        getMask(getMaskOperand(II), Factor, getDeinterleavedVectorType(DI));
    if (!Mask)
      return false;
    // We haven't supported gap mask if it's deinterleaving using intrinsics.
    // Yet it is possible that we already changed the IR, hence returning true
    // here.
    if (GapMask.popcount() != Factor)
      return true;

    LLVM_DEBUG(dbgs() << "IA: Found a vp.load or masked.load with deinterleave"
                      << " intrinsic " << *DI << " and factor = "
                      << Factor << "\n");
  }

  // Try and match this with target specific intrinsics.
  if (!TLI->lowerDeinterleaveIntrinsicToLoad(LoadedVal, Mask, DI))
    return false;

  DeadInsts.insert(DI);
  // We now have a target-specific load, so delete the old one.
  DeadInsts.insert(LoadedVal);
  return true;
}

bool InterleavedAccessImpl::lowerInterleaveIntrinsic(
    IntrinsicInst *IntII, SmallSetVector<Instruction *, 32> &DeadInsts) {
  if (!IntII->hasOneUse())
    return false;
  Instruction *StoredBy = dyn_cast<Instruction>(IntII->user_back());
  if (!StoredBy)
    return false;
  auto *SI = dyn_cast<StoreInst>(StoredBy);
  auto *II = dyn_cast<IntrinsicInst>(StoredBy);
  if (!SI && !II)
    return false;

  SmallVector<Value *, 8> InterleaveValues(IntII->args());
  const unsigned Factor = getInterleaveIntrinsicFactor(IntII->getIntrinsicID());
  assert(Factor && "unexpected interleave intrinsic");

  Value *Mask = nullptr;
  if (II) {
    if (II->getIntrinsicID() != Intrinsic::masked_store &&
        II->getIntrinsicID() != Intrinsic::vp_store)
      return false;
    // Check mask operand. Handle both all-true/false and interleaved mask.
    APInt GapMask(Factor, 0);
    std::tie(Mask, GapMask) =
        getMask(getMaskOperand(II), Factor,
                cast<VectorType>(InterleaveValues[0]->getType()));
    if (!Mask)
      return false;
    // We haven't supported gap mask if it's interleaving using intrinsics. Yet
    // it is possible that we already changed the IR, hence returning true here.
    if (GapMask.popcount() != Factor)
      return true;

    LLVM_DEBUG(dbgs() << "IA: Found a vp.store or masked.store with interleave"
                      << " intrinsic " << *IntII << " and factor = "
                      << Factor << "\n");
  } else {
    if (!SI->isSimple())
      return false;

    LLVM_DEBUG(dbgs() << "IA: Found a store with interleave intrinsic "
                      << *IntII << " and factor = " << Factor << "\n");
  }

  // Try and match this with target specific intrinsics.
  if (!TLI->lowerInterleaveIntrinsicToStore(StoredBy, Mask, InterleaveValues))
    return false;

  // We now have a target-specific store, so delete the old one.
  DeadInsts.insert(StoredBy);
  DeadInsts.insert(IntII);
  return true;
}

bool InterleavedAccessImpl::runOnFunction(Function &F) {
  // Holds dead instructions that will be erased later.
  SmallSetVector<Instruction *, 32> DeadInsts;
  bool Changed = false;

  using namespace PatternMatch;
  for (auto &I : instructions(F)) {
    if (match(&I, m_CombineOr(m_Load(m_Value()),
                              m_Intrinsic<Intrinsic::vp_load>())) ||
        match(&I, m_Intrinsic<Intrinsic::masked_load>()))
      Changed |= lowerInterleavedLoad(&I, DeadInsts);

    if (match(&I, m_CombineOr(m_Store(m_Value(), m_Value()),
                              m_Intrinsic<Intrinsic::vp_store>())) ||
        match(&I, m_Intrinsic<Intrinsic::masked_store>()))
      Changed |= lowerInterleavedStore(&I, DeadInsts);

    if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
      if (getDeinterleaveIntrinsicFactor(II->getIntrinsicID()))
        Changed |= lowerDeinterleaveIntrinsic(II, DeadInsts);
      else if (getInterleaveIntrinsicFactor(II->getIntrinsicID()))
        Changed |= lowerInterleaveIntrinsic(II, DeadInsts);
    }
  }

  for (auto *I : DeadInsts)
    I->eraseFromParent();

  return Changed;
}
