blob: f3b62e36e51150607e33f5cffee329969a089fb4 [file] [log] [blame]
//===- SeedCollection.cpp - Seed collection pass --------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/SeedCollection.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/SandboxIR/Module.h"
#include "llvm/SandboxIR/Region.h"
#include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerPassBuilder.h"
#include "llvm/Transforms/Vectorize/SandboxVectorizer/SeedCollector.h"
#include "llvm/Transforms/Vectorize/SandboxVectorizer/VecUtils.h"
namespace llvm {
static cl::opt<unsigned>
OverrideVecRegBits("sbvec-vec-reg-bits", cl::init(0), cl::Hidden,
cl::desc("Override the vector register size in bits, "
"which is otherwise found by querying TTI."));
static cl::opt<bool>
AllowNonPow2("sbvec-allow-non-pow2", cl::init(false), cl::Hidden,
cl::desc("Allow non-power-of-2 vectorization."));
namespace sandboxir {
SeedCollection::SeedCollection(StringRef Pipeline)
: FunctionPass("seed-collection"),
RPM("rpm", Pipeline, SandboxVectorizerPassBuilder::createRegionPass) {}
bool SeedCollection::runOnFunction(Function &F, const Analyses &A) {
bool Change = false;
const auto &DL = F.getParent()->getDataLayout();
unsigned VecRegBits =
OverrideVecRegBits != 0
? OverrideVecRegBits
: A.getTTI()
.getRegisterBitWidth(TargetTransformInfo::RGK_FixedWidthVector)
.getFixedValue();
// TODO: Start from innermost BBs first
for (auto &BB : F) {
SeedCollector SC(&BB, A.getScalarEvolution());
for (SeedBundle &Seeds : SC.getStoreSeeds()) {
unsigned ElmBits =
Utils::getNumBits(VecUtils::getElementType(Utils::getExpectedType(
Seeds[Seeds.getFirstUnusedElementIdx()])),
DL);
auto DivideBy2 = [](unsigned Num) {
auto Floor = VecUtils::getFloorPowerOf2(Num);
if (Floor == Num)
return Floor / 2;
return Floor;
};
// Try to create the largest vector supported by the target. If it fails
// reduce the vector size by half.
for (unsigned SliceElms = std::min(VecRegBits / ElmBits,
Seeds.getNumUnusedBits() / ElmBits);
SliceElms >= 2u; SliceElms = DivideBy2(SliceElms)) {
if (Seeds.allUsed())
break;
// Keep trying offsets after FirstUnusedElementIdx, until we vectorize
// the slice. This could be quite expensive, so we enforce a limit.
for (unsigned Offset = Seeds.getFirstUnusedElementIdx(),
OE = Seeds.size();
Offset + 1 < OE; Offset += 1) {
// Seeds are getting used as we vectorize, so skip them.
if (Seeds.isUsed(Offset))
continue;
if (Seeds.allUsed())
break;
auto SeedSlice =
Seeds.getSlice(Offset, SliceElms * ElmBits, !AllowNonPow2);
if (SeedSlice.empty())
continue;
assert(SeedSlice.size() >= 2 && "Should have been rejected!");
// Create a region containing the seed slice.
auto &Ctx = F.getContext();
Region Rgn(Ctx, A.getTTI());
Rgn.setAux(SeedSlice);
// Run the region pass pipeline.
Change |= RPM.runOnRegion(Rgn, A);
Rgn.clearAux();
}
}
}
}
return Change;
}
} // namespace sandboxir
} // namespace llvm