Skip to content

Commit 42c5a30

Browse files
authored
[SandboxVec] Legality boilerplate (#108650)
This patch adds the basic API for the Legality component of the vectorizer. It also adds some very basic code in the bottom-up vectorizer that uses the API.
1 parent 785624b commit 42c5a30

File tree

5 files changed

+178
-1
lines changed

5 files changed

+178
-1
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//===- Legality.h -----------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Legality checks for the Sandbox Vectorizer.
10+
//
11+
12+
#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_LEGALITY_H
13+
#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_LEGALITY_H
14+
15+
#include "llvm/SandboxIR/SandboxIR.h"
16+
17+
namespace llvm::sandboxir {
18+
19+
class LegalityAnalysis;
20+
21+
enum class LegalityResultID {
22+
Widen, ///> Vectorize by combining scalars to a vector.
23+
};
24+
25+
/// The legality outcome is represented by a class rather than an enum class
26+
/// because in some cases the legality checks are expensive and look for a
27+
/// particular instruction that can be passed along to the vectorizer to avoid
28+
/// repeating the same expensive computation.
29+
class LegalityResult {
30+
protected:
31+
LegalityResultID ID;
32+
/// Only Legality can create LegalityResults.
33+
LegalityResult(LegalityResultID ID) : ID(ID) {}
34+
friend class LegalityAnalysis;
35+
36+
public:
37+
LegalityResultID getSubclassID() const { return ID; }
38+
};
39+
40+
class Widen final : public LegalityResult {
41+
friend class LegalityAnalysis;
42+
Widen() : LegalityResult(LegalityResultID::Widen) {}
43+
44+
public:
45+
static bool classof(const LegalityResult *From) {
46+
return From->getSubclassID() == LegalityResultID::Widen;
47+
}
48+
};
49+
50+
/// Performs the legality analysis and returns a LegalityResult object.
51+
class LegalityAnalysis {
52+
public:
53+
LegalityAnalysis() = default;
54+
LegalityResult canVectorize(ArrayRef<Value *> Bndl) {
55+
// TODO: For now everything is legal.
56+
return Widen();
57+
}
58+
};
59+
60+
} // namespace llvm::sandboxir
61+
62+
#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_LEGALITY_H

llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,18 @@
1212
#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_BOTTOMUPVEC_H
1313
#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_BOTTOMUPVEC_H
1414

15+
#include "llvm/ADT/ArrayRef.h"
1516
#include "llvm/SandboxIR/Pass.h"
17+
#include "llvm/SandboxIR/SandboxIR.h"
18+
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Legality.h"
1619

1720
namespace llvm::sandboxir {
1821

1922
class BottomUpVec final : public FunctionPass {
23+
bool Change = false;
24+
LegalityAnalysis Legality;
25+
void vectorizeRec(ArrayRef<Value *> Bndl);
26+
void tryVectorize(ArrayRef<Value *> Seeds);
2027

2128
public:
2229
BottomUpVec() : FunctionPass("bottom-up-vec") {}

llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,58 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h"
10+
#include "llvm/ADT/SmallVector.h"
1011

1112
using namespace llvm::sandboxir;
1213

13-
bool BottomUpVec::runOnFunction(Function &F) { return false; }
14+
namespace llvm::sandboxir {
15+
// TODO: This is a temporary function that returns some seeds.
16+
// Replace this with SeedCollector's function when it lands.
17+
static llvm::SmallVector<Value *, 4> collectSeeds(BasicBlock &BB) {
18+
llvm::SmallVector<Value *, 4> Seeds;
19+
for (auto &I : BB)
20+
if (auto *SI = llvm::dyn_cast<StoreInst>(&I))
21+
Seeds.push_back(SI);
22+
return Seeds;
23+
}
24+
25+
static SmallVector<Value *, 4> getOperand(ArrayRef<Value *> Bndl,
26+
unsigned OpIdx) {
27+
SmallVector<Value *, 4> Operands;
28+
for (Value *BndlV : Bndl) {
29+
auto *BndlI = cast<Instruction>(BndlV);
30+
Operands.push_back(BndlI->getOperand(OpIdx));
31+
}
32+
return Operands;
33+
}
34+
35+
} // namespace llvm::sandboxir
36+
37+
void BottomUpVec::vectorizeRec(ArrayRef<Value *> Bndl) {
38+
auto LegalityRes = Legality.canVectorize(Bndl);
39+
switch (LegalityRes.getSubclassID()) {
40+
case LegalityResultID::Widen: {
41+
auto *I = cast<Instruction>(Bndl[0]);
42+
for (auto OpIdx : seq<unsigned>(I->getNumOperands())) {
43+
auto OperandBndl = getOperand(Bndl, OpIdx);
44+
vectorizeRec(OperandBndl);
45+
}
46+
break;
47+
}
48+
}
49+
}
50+
51+
void BottomUpVec::tryVectorize(ArrayRef<Value *> Bndl) { vectorizeRec(Bndl); }
52+
53+
bool BottomUpVec::runOnFunction(Function &F) {
54+
Change = false;
55+
// TODO: Start from innermost BBs first
56+
for (auto &BB : F) {
57+
// TODO: Replace with proper SeedCollector function.
58+
auto Seeds = collectSeeds(BB);
59+
// TODO: Slice Seeds into smaller chunks.
60+
if (Seeds.size() >= 2)
61+
tryVectorize(Seeds);
62+
}
63+
return Change;
64+
}

llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ set(LLVM_LINK_COMPONENTS
99

1010
add_llvm_unittest(SandboxVectorizerTests
1111
DependencyGraphTest.cpp
12+
LegalityTest.cpp
1213
)
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//===- LegalityTest.cpp ---------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Legality.h"
10+
#include "llvm/AsmParser/Parser.h"
11+
#include "llvm/SandboxIR/SandboxIR.h"
12+
#include "llvm/Support/SourceMgr.h"
13+
#include "gtest/gtest.h"
14+
15+
using namespace llvm;
16+
17+
struct LegalityTest : public testing::Test {
18+
LLVMContext C;
19+
std::unique_ptr<Module> M;
20+
21+
void parseIR(LLVMContext &C, const char *IR) {
22+
SMDiagnostic Err;
23+
M = parseAssemblyString(IR, Err, C);
24+
if (!M)
25+
Err.print("LegalityTest", errs());
26+
}
27+
};
28+
29+
TEST_F(LegalityTest, Legality) {
30+
parseIR(C, R"IR(
31+
define void @foo(ptr %ptr) {
32+
%gep0 = getelementptr float, ptr %ptr, i32 0
33+
%gep1 = getelementptr float, ptr %ptr, i32 1
34+
%ld0 = load float, ptr %gep0
35+
%ld1 = load float, ptr %gep0
36+
store float %ld0, ptr %gep0
37+
store float %ld1, ptr %gep1
38+
ret void
39+
}
40+
)IR");
41+
llvm::Function *LLVMF = &*M->getFunction("foo");
42+
sandboxir::Context Ctx(C);
43+
auto *F = Ctx.createFunction(LLVMF);
44+
auto *BB = &*F->begin();
45+
auto It = BB->begin();
46+
[[maybe_unused]] auto *Gep0 = cast<sandboxir::GetElementPtrInst>(&*It++);
47+
[[maybe_unused]] auto *Gep1 = cast<sandboxir::GetElementPtrInst>(&*It++);
48+
[[maybe_unused]] auto *Ld0 = cast<sandboxir::LoadInst>(&*It++);
49+
[[maybe_unused]] auto *Ld1 = cast<sandboxir::LoadInst>(&*It++);
50+
auto *St0 = cast<sandboxir::StoreInst>(&*It++);
51+
auto *St1 = cast<sandboxir::StoreInst>(&*It++);
52+
53+
sandboxir::LegalityAnalysis Legality;
54+
auto Result = Legality.canVectorize({St0, St1});
55+
EXPECT_TRUE(isa<sandboxir::Widen>(Result));
56+
}

0 commit comments

Comments
 (0)