Skip to content

Commit 54c93aa

Browse files
authored
[SandboxVec][Legality] Scaffolding for Legality (#112623)
This patch adds a LegalityResultWithReason class for describing the reason why legality decided not to vectorize the code.
1 parent 9e03920 commit 54c93aa

File tree

5 files changed

+149
-3
lines changed

5 files changed

+149
-3
lines changed

llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Legality.h

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,47 @@
1313
#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_LEGALITY_H
1414

1515
#include "llvm/ADT/ArrayRef.h"
16+
#include "llvm/Support/Casting.h"
17+
#include "llvm/Support/raw_ostream.h"
1618

1719
namespace llvm::sandboxir {
1820

1921
class LegalityAnalysis;
2022
class Value;
2123

2224
enum class LegalityResultID {
25+
Pack, ///> Collect scalar values.
2326
Widen, ///> Vectorize by combining scalars to a vector.
2427
};
2528

29+
/// The reason for vectorizing or not vectorizing.
30+
enum class ResultReason {
31+
DiffOpcodes,
32+
DiffTypes,
33+
};
34+
35+
#ifndef NDEBUG
36+
struct ToStr {
37+
static const char *getLegalityResultID(LegalityResultID ID) {
38+
switch (ID) {
39+
case LegalityResultID::Pack:
40+
return "Pack";
41+
case LegalityResultID::Widen:
42+
return "Widen";
43+
}
44+
}
45+
46+
static const char *getVecReason(ResultReason Reason) {
47+
switch (Reason) {
48+
case ResultReason::DiffOpcodes:
49+
return "DiffOpcodes";
50+
case ResultReason::DiffTypes:
51+
return "DiffTypes";
52+
}
53+
}
54+
};
55+
#endif // NDEBUG
56+
2657
/// The legality outcome is represented by a class rather than an enum class
2758
/// because in some cases the legality checks are expensive and look for a
2859
/// particular instruction that can be passed along to the vectorizer to avoid
@@ -35,7 +66,34 @@ class LegalityResult {
3566
friend class LegalityAnalysis;
3667

3768
public:
69+
virtual ~LegalityResult() {}
3870
LegalityResultID getSubclassID() const { return ID; }
71+
#ifndef NDEBUG
72+
virtual void print(raw_ostream &OS) const {
73+
OS << ToStr::getLegalityResultID(ID);
74+
}
75+
LLVM_DUMP_METHOD void dump() const;
76+
friend raw_ostream &operator<<(raw_ostream &OS, const LegalityResult &LR) {
77+
LR.print(OS);
78+
return OS;
79+
}
80+
#endif // NDEBUG
81+
};
82+
83+
/// Base class for results with reason.
84+
class LegalityResultWithReason : public LegalityResult {
85+
ResultReason Reason;
86+
LegalityResultWithReason(LegalityResultID ID, ResultReason Reason)
87+
: LegalityResult(ID), Reason(Reason) {}
88+
friend class Pack; // For constructor.
89+
90+
public:
91+
#ifndef NDEBUG
92+
void print(raw_ostream &OS) const override {
93+
LegalityResult::print(OS);
94+
OS << " Reason: " << ToStr::getVecReason(Reason);
95+
}
96+
#endif
3997
};
4098

4199
class Widen final : public LegalityResult {
@@ -48,14 +106,37 @@ class Widen final : public LegalityResult {
48106
}
49107
};
50108

109+
class Pack final : public LegalityResultWithReason {
110+
Pack(ResultReason Reason)
111+
: LegalityResultWithReason(LegalityResultID::Pack, Reason) {}
112+
friend class LegalityAnalysis; // For constructor.
113+
114+
public:
115+
static bool classof(const LegalityResult *From) {
116+
return From->getSubclassID() == LegalityResultID::Pack;
117+
}
118+
};
119+
51120
/// Performs the legality analysis and returns a LegalityResult object.
52121
class LegalityAnalysis {
122+
/// Owns the legality result objects created by createLegalityResult().
123+
SmallVector<std::unique_ptr<LegalityResult>> ResultPool;
124+
/// Checks opcodes, types and other IR-specifics and returns a ResultReason
125+
/// object if not vectorizable, or nullptr otherwise.
126+
std::optional<ResultReason>
127+
notVectorizableBasedOnOpcodesAndTypes(ArrayRef<Value *> Bndl);
128+
53129
public:
54130
LegalityAnalysis() = default;
55-
LegalityResult canVectorize(ArrayRef<Value *> Bndl) {
56-
// TODO: For now everything is legal.
57-
return Widen();
131+
/// A LegalityResult factory.
132+
template <typename ResultT, typename... ArgsT>
133+
ResultT &createLegalityResult(ArgsT... Args) {
134+
ResultPool.push_back(std::unique_ptr<ResultT>(new ResultT(Args...)));
135+
return cast<ResultT>(*ResultPool.back());
58136
}
137+
/// Checks if it's legal to vectorize the instructions in \p Bndl.
138+
/// \Returns a LegalityResult object owned by LegalityAnalysis.
139+
LegalityResult &canVectorize(ArrayRef<Value *> Bndl);
59140
};
60141

61142
} // namespace llvm::sandboxir

llvm/lib/Transforms/Vectorize/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ add_llvm_component_library(LLVMVectorize
55
LoopVectorize.cpp
66
SandboxVectorizer/DependencyGraph.cpp
77
SandboxVectorizer/Interval.cpp
8+
SandboxVectorizer/Legality.cpp
89
SandboxVectorizer/Passes/BottomUpVec.cpp
910
SandboxVectorizer/Passes/RegionsFromMetadata.cpp
1011
SandboxVectorizer/SandboxVectorizer.cpp
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===- Legality.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/SandboxIR/Value.h"
11+
#include "llvm/Support/Debug.h"
12+
13+
namespace llvm::sandboxir {
14+
15+
#ifndef NDEBUG
16+
void LegalityResult::dump() const {
17+
print(dbgs());
18+
dbgs() << "\n";
19+
}
20+
#endif // NDEBUG
21+
22+
std::optional<ResultReason>
23+
LegalityAnalysis::notVectorizableBasedOnOpcodesAndTypes(
24+
ArrayRef<Value *> Bndl) {
25+
// TODO: Unimplemented.
26+
return std::nullopt;
27+
}
28+
29+
LegalityResult &LegalityAnalysis::canVectorize(ArrayRef<Value *> Bndl) {
30+
if (auto ReasonOpt = notVectorizableBasedOnOpcodesAndTypes(Bndl))
31+
return createLegalityResult<Pack>(*ReasonOpt);
32+
33+
// TODO: Check for existing vectors containing values in Bndl.
34+
35+
// TODO: Check with scheduler.
36+
37+
return createLegalityResult<Widen>();
38+
}
39+
} // namespace llvm::sandboxir

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ void BottomUpVec::vectorizeRec(ArrayRef<Value *> Bndl) {
5050
}
5151
break;
5252
}
53+
case LegalityResultID::Pack: {
54+
// TODO: Unimplemented
55+
llvm_unreachable("Unimplemented");
56+
}
5357
}
5458
}
5559

llvm/unittests/Transforms/Vectorize/SandboxVectorizer/LegalityTest.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,24 @@ define void @foo(ptr %ptr) {
5555
auto Result = Legality.canVectorize({St0, St1});
5656
EXPECT_TRUE(isa<sandboxir::Widen>(Result));
5757
}
58+
59+
#ifndef NDEBUG
60+
TEST_F(LegalityTest, LegalityResultDump) {
61+
auto Matches = [](const sandboxir::LegalityResult &Result,
62+
const std::string &ExpectedStr) -> bool {
63+
std::string Buff;
64+
raw_string_ostream OS(Buff);
65+
Result.print(OS);
66+
return Buff == ExpectedStr;
67+
};
68+
sandboxir::LegalityAnalysis Legality;
69+
EXPECT_TRUE(
70+
Matches(Legality.createLegalityResult<sandboxir::Widen>(), "Widen"));
71+
EXPECT_TRUE(Matches(Legality.createLegalityResult<sandboxir::Pack>(
72+
sandboxir::ResultReason::DiffOpcodes),
73+
"Pack Reason: DiffOpcodes"));
74+
EXPECT_TRUE(Matches(Legality.createLegalityResult<sandboxir::Pack>(
75+
sandboxir::ResultReason::DiffTypes),
76+
"Pack Reason: DiffTypes"));
77+
}
78+
#endif // NDEBUG

0 commit comments

Comments
 (0)