-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[SandboxVec] Move seed collection into its own separate pass #127132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
//===- SeedCollection.h -----------------------------------------*- C++ -*-===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// The seed-collection pass of the bottom-up vectorizer. | ||
// | ||
|
||
#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_SEEDCOLLECTION_H | ||
#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_SEEDCOLLECTION_H | ||
|
||
#include "llvm/SandboxIR/Pass.h" | ||
#include "llvm/SandboxIR/PassManager.h" | ||
|
||
namespace llvm::sandboxir { | ||
|
||
/// This pass collects the instructions that can become vectorization "seeds", | ||
/// like stores to consecutive memory addresses. It then goes over the collected | ||
/// seeds, slicing them into appropriately sized chunks, creating a Region with | ||
/// the seed slice as the Auxiliary vector and runs the region pass pipeline. | ||
class SeedCollection final : public FunctionPass { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, this should probably explain that it runs a pipeline of region passes, passing the collected seeds in the aux vector to the first pass in the pipeline. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see anything new. Did you forget to push a commit? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops I pushed it to the wrong branch... |
||
|
||
/// The PM containing the pipeline of region passes. | ||
RegionPassManager RPM; | ||
|
||
public: | ||
SeedCollection(StringRef Pipeline); | ||
bool runOnFunction(Function &F, const Analyses &A) final; | ||
void printPipeline(raw_ostream &OS) const final { | ||
OS << getName() << "\n"; | ||
RPM.printPipeline(OS); | ||
} | ||
}; | ||
|
||
} // namespace llvm::sandboxir | ||
|
||
#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_SEEDCOLLECTION_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
//===- 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()); | ||
// TODO: Replace save() with a save pass in the pass pipeline. | ||
Ctx.save(); | ||
Rgn.setAux(SeedSlice); | ||
// Run the region pass pipeline. | ||
Change |= RPM.runOnRegion(Rgn, A); | ||
Rgn.clearAux(); | ||
} | ||
} | ||
} | ||
} | ||
return Change; | ||
} | ||
} // namespace sandboxir | ||
} // namespace llvm |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that we have, in the aux vector, an extra way in which information can flow from one pass to the next, we should document very carefully what each pass expects to get there. This class should have a documentation comment anyway, so please add that and describe what needs to be passed in the aux vector.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's a great point. Even though it is safe to run the pass without having set the Aux vector, it really expects it to be populated. I am wondering if there is a more structured way of expressing this, perhaps using a different subclass of the RegionPass?