Skip to content

Commit 553520b

Browse files
committed
Revert "[SandboxVec][DAG] MemDGNode for memory-dependency candidate nodes (llvm#109684)"
This reverts commit fd5e220.
1 parent 4c0d805 commit 553520b

File tree

3 files changed

+29
-226
lines changed

3 files changed

+29
-226
lines changed

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

Lines changed: 17 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -29,61 +29,35 @@
2929

3030
namespace llvm::sandboxir {
3131

32-
class DependencyGraph;
33-
class MemDGNode;
34-
35-
/// SubclassIDs for isa/dyn_cast etc.
36-
enum class DGNodeID {
37-
DGNode,
38-
MemDGNode,
39-
};
40-
4132
/// A DependencyGraph Node that points to an Instruction and contains memory
4233
/// dependency edges.
4334
class DGNode {
44-
protected:
4535
Instruction *I;
46-
// TODO: Use a PointerIntPair for SubclassID and I.
47-
/// For isa/dyn_cast etc.
48-
DGNodeID SubclassID;
4936
/// Memory predecessors.
50-
DenseSet<MemDGNode *> MemPreds;
51-
52-
DGNode(Instruction *I, DGNodeID ID) : I(I), SubclassID(ID) {}
53-
friend class MemDGNode; // For constructor.
37+
DenseSet<DGNode *> MemPreds;
38+
/// This is true if this may read/write memory, or if it has some ordering
39+
/// constraints, like with stacksave/stackrestore and alloca/inalloca.
40+
bool IsMem;
5441

5542
public:
56-
DGNode(Instruction *I) : I(I), SubclassID(DGNodeID::DGNode) {
57-
assert(!isMemDepCandidate(I) && "Expected Non-Mem instruction, ");
58-
}
59-
DGNode(const DGNode &Other) = delete;
60-
virtual ~DGNode() = default;
61-
/// \Returns true if this is before \p Other in program order.
62-
bool comesBefore(const DGNode *Other) { return I->comesBefore(Other->I); }
63-
/// \Returns true if \p I is a memory dependency candidate instruction.
64-
static bool isMemDepCandidate(Instruction *I) {
65-
AllocaInst *Alloca;
66-
return I->isMemDepCandidate() ||
67-
((Alloca = dyn_cast<AllocaInst>(I)) &&
68-
Alloca->isUsedWithInAlloca()) ||
69-
I->isStackSaveOrRestoreIntrinsic();
43+
DGNode(Instruction *I) : I(I) {
44+
IsMem = I->isMemDepCandidate() ||
45+
(isa<AllocaInst>(I) && cast<AllocaInst>(I)->isUsedWithInAlloca()) ||
46+
I->isStackSaveOrRestoreIntrinsic();
7047
}
71-
7248
Instruction *getInstruction() const { return I; }
73-
void addMemPred(MemDGNode *PredN) { MemPreds.insert(PredN); }
49+
void addMemPred(DGNode *PredN) { MemPreds.insert(PredN); }
7450
/// \Returns all memory dependency predecessors.
75-
iterator_range<DenseSet<MemDGNode *>::const_iterator> memPreds() const {
51+
iterator_range<DenseSet<DGNode *>::const_iterator> memPreds() const {
7652
return make_range(MemPreds.begin(), MemPreds.end());
7753
}
7854
/// \Returns true if there is a memory dependency N->this.
79-
bool hasMemPred(DGNode *N) const {
80-
if (auto *MN = dyn_cast<MemDGNode>(N))
81-
return MemPreds.count(MN);
82-
return false;
83-
}
84-
55+
bool hasMemPred(DGNode *N) const { return MemPreds.count(N); }
56+
/// \Returns true if this may read/write memory, or if it has some ordering
57+
/// constraints, like with stacksave/stackrestore and alloca/inalloca.
58+
bool isMem() const { return IsMem; }
8559
#ifndef NDEBUG
86-
virtual void print(raw_ostream &OS, bool PrintDeps = true) const;
60+
void print(raw_ostream &OS, bool PrintDeps = true) const;
8761
friend raw_ostream &operator<<(DGNode &N, raw_ostream &OS) {
8862
N.print(OS);
8963
return OS;
@@ -92,46 +66,9 @@ class DGNode {
9266
#endif // NDEBUG
9367
};
9468

95-
/// A DependencyGraph Node for instructions that may read/write memory, or have
96-
/// some ordering constraints, like with stacksave/stackrestore and
97-
/// alloca/inalloca.
98-
class MemDGNode final : public DGNode {
99-
MemDGNode *PrevMemN = nullptr;
100-
MemDGNode *NextMemN = nullptr;
101-
102-
void setNextNode(MemDGNode *N) { NextMemN = N; }
103-
void setPrevNode(MemDGNode *N) { PrevMemN = N; }
104-
friend class DependencyGraph; // For setNextNode(), setPrevNode().
105-
106-
public:
107-
MemDGNode(Instruction *I) : DGNode(I, DGNodeID::MemDGNode) {
108-
assert(isMemDepCandidate(I) && "Expected Mem instruction!");
109-
}
110-
static bool classof(const DGNode *Other) {
111-
return Other->SubclassID == DGNodeID::MemDGNode;
112-
}
113-
/// \Returns the previous Mem DGNode in instruction order.
114-
MemDGNode *getPrevNode() const { return PrevMemN; }
115-
/// \Returns the next Mem DGNode in instruction order.
116-
MemDGNode *getNextNode() const { return NextMemN; }
117-
};
118-
119-
/// Convenience builders for a MemDGNode interval.
120-
class MemDGNodeIntervalBuilder {
121-
public:
122-
/// Given \p Instrs it finds their closest mem nodes in the interval and
123-
/// returns the corresponding mem range. Note: BotN (or its neighboring mem
124-
/// node) is included in the range.
125-
static Interval<MemDGNode> make(const Interval<Instruction> &Instrs,
126-
DependencyGraph &DAG);
127-
static Interval<MemDGNode> makeEmpty() { return {}; }
128-
};
129-
13069
class DependencyGraph {
13170
private:
13271
DenseMap<Instruction *, std::unique_ptr<DGNode>> InstrToNodeMap;
133-
/// The DAG spans across all instructions in this interval.
134-
Interval<Instruction> DAGInterval;
13572

13673
public:
13774
DependencyGraph() {}
@@ -140,20 +77,10 @@ class DependencyGraph {
14077
auto It = InstrToNodeMap.find(I);
14178
return It != InstrToNodeMap.end() ? It->second.get() : nullptr;
14279
}
143-
/// Like getNode() but returns nullptr if \p I is nullptr.
144-
DGNode *getNodeOrNull(Instruction *I) const {
145-
if (I == nullptr)
146-
return nullptr;
147-
return getNode(I);
148-
}
14980
DGNode *getOrCreateNode(Instruction *I) {
15081
auto [It, NotInMap] = InstrToNodeMap.try_emplace(I);
151-
if (NotInMap) {
152-
if (DGNode::isMemDepCandidate(I))
153-
It->second = std::make_unique<MemDGNode>(I);
154-
else
155-
It->second = std::make_unique<DGNode>(I);
156-
}
82+
if (NotInMap)
83+
It->second = std::make_unique<DGNode>(I);
15784
return It->second.get();
15885
}
15986
/// Build/extend the dependency graph such that it includes \p Instrs. Returns

llvm/lib/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.cpp

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,6 @@ void DGNode::dump() const {
3131
}
3232
#endif // NDEBUG
3333

34-
Interval<MemDGNode>
35-
MemDGNodeIntervalBuilder::make(const Interval<Instruction> &Instrs,
36-
DependencyGraph &DAG) {
37-
// If top or bottom instructions are not mem-dep candidate nodes we need to
38-
// walk down/up the chain and find the mem-dep ones.
39-
Instruction *MemTopI = Instrs.top();
40-
Instruction *MemBotI = Instrs.bottom();
41-
while (!DGNode::isMemDepCandidate(MemTopI) && MemTopI != MemBotI)
42-
MemTopI = MemTopI->getNextNode();
43-
while (!DGNode::isMemDepCandidate(MemBotI) && MemBotI != MemTopI)
44-
MemBotI = MemBotI->getPrevNode();
45-
// If we couldn't find a mem node in range TopN - BotN then it's empty.
46-
if (!DGNode::isMemDepCandidate(MemTopI))
47-
return {};
48-
// Now that we have the mem-dep nodes, create and return the range.
49-
return Interval<MemDGNode>(cast<MemDGNode>(DAG.getNode(MemTopI)),
50-
cast<MemDGNode>(DAG.getNode(MemBotI)));
51-
}
52-
5334
Interval<Instruction> DependencyGraph::extend(ArrayRef<Instruction *> Instrs) {
5435
if (Instrs.empty())
5536
return {};
@@ -58,18 +39,10 @@ Interval<Instruction> DependencyGraph::extend(ArrayRef<Instruction *> Instrs) {
5839
auto *TopI = Interval.top();
5940
auto *BotI = Interval.bottom();
6041
DGNode *LastN = getOrCreateNode(TopI);
61-
MemDGNode *LastMemN = dyn_cast<MemDGNode>(LastN);
6242
for (Instruction *I = TopI->getNextNode(), *E = BotI->getNextNode(); I != E;
6343
I = I->getNextNode()) {
6444
auto *N = getOrCreateNode(I);
65-
N->addMemPred(LastMemN);
66-
// Build the Mem node chain.
67-
if (auto *MemN = dyn_cast<MemDGNode>(N)) {
68-
MemN->setPrevNode(LastMemN);
69-
if (LastMemN != nullptr)
70-
LastMemN->setNextNode(MemN);
71-
LastMemN = MemN;
72-
}
45+
N->addMemPred(LastN);
7346
LastN = N;
7447
}
7548
return Interval;

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

Lines changed: 11 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ struct DependencyGraphTest : public testing::Test {
2929
}
3030
};
3131

32-
TEST_F(DependencyGraphTest, MemDGNode) {
32+
TEST_F(DependencyGraphTest, DGNode_IsMem) {
3333
parseIR(C, R"IR(
3434
declare void @llvm.sideeffect()
3535
declare void @llvm.pseudoprobe(i64, i64, i32, i64)
@@ -66,16 +66,16 @@ define void @foo(i8 %v1, ptr %ptr) {
6666

6767
sandboxir::DependencyGraph DAG;
6868
DAG.extend({&*BB->begin(), BB->getTerminator()});
69-
EXPECT_TRUE(isa<llvm::sandboxir::MemDGNode>(DAG.getNode(Store)));
70-
EXPECT_TRUE(isa<llvm::sandboxir::MemDGNode>(DAG.getNode(Load)));
71-
EXPECT_FALSE(isa<llvm::sandboxir::MemDGNode>(DAG.getNode(Add)));
72-
EXPECT_TRUE(isa<llvm::sandboxir::MemDGNode>(DAG.getNode(StackSave)));
73-
EXPECT_TRUE(isa<llvm::sandboxir::MemDGNode>(DAG.getNode(StackRestore)));
74-
EXPECT_FALSE(isa<llvm::sandboxir::MemDGNode>(DAG.getNode(SideEffect)));
75-
EXPECT_FALSE(isa<llvm::sandboxir::MemDGNode>(DAG.getNode(PseudoProbe)));
76-
EXPECT_TRUE(isa<llvm::sandboxir::MemDGNode>(DAG.getNode(FakeUse)));
77-
EXPECT_TRUE(isa<llvm::sandboxir::MemDGNode>(DAG.getNode(Call)));
78-
EXPECT_FALSE(isa<llvm::sandboxir::MemDGNode>(DAG.getNode(Ret)));
69+
EXPECT_TRUE(DAG.getNode(Store)->isMem());
70+
EXPECT_TRUE(DAG.getNode(Load)->isMem());
71+
EXPECT_FALSE(DAG.getNode(Add)->isMem());
72+
EXPECT_TRUE(DAG.getNode(StackSave)->isMem());
73+
EXPECT_TRUE(DAG.getNode(StackRestore)->isMem());
74+
EXPECT_FALSE(DAG.getNode(SideEffect)->isMem());
75+
EXPECT_FALSE(DAG.getNode(PseudoProbe)->isMem());
76+
EXPECT_TRUE(DAG.getNode(FakeUse)->isMem());
77+
EXPECT_TRUE(DAG.getNode(Call)->isMem());
78+
EXPECT_FALSE(DAG.getNode(Ret)->isMem());
7979
}
8080

8181
TEST_F(DependencyGraphTest, Basic) {
@@ -115,100 +115,3 @@ define void @foo(ptr %ptr, i8 %v0, i8 %v1) {
115115
EXPECT_THAT(N1->memPreds(), testing::ElementsAre(N0));
116116
EXPECT_THAT(N2->memPreds(), testing::ElementsAre(N1));
117117
}
118-
119-
TEST_F(DependencyGraphTest, MemDGNode_getPrevNode_getNextNode) {
120-
parseIR(C, R"IR(
121-
define void @foo(ptr %ptr, i8 %v0, i8 %v1) {
122-
store i8 %v0, ptr %ptr
123-
add i8 %v0, %v0
124-
store i8 %v1, ptr %ptr
125-
ret void
126-
}
127-
)IR");
128-
llvm::Function *LLVMF = &*M->getFunction("foo");
129-
sandboxir::Context Ctx(C);
130-
auto *F = Ctx.createFunction(LLVMF);
131-
auto *BB = &*F->begin();
132-
auto It = BB->begin();
133-
auto *S0 = cast<sandboxir::StoreInst>(&*It++);
134-
[[maybe_unused]] auto *Add = cast<sandboxir::BinaryOperator>(&*It++);
135-
auto *S1 = cast<sandboxir::StoreInst>(&*It++);
136-
[[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++);
137-
138-
sandboxir::DependencyGraph DAG;
139-
DAG.extend({&*BB->begin(), BB->getTerminator()});
140-
141-
auto *S0N = cast<sandboxir::MemDGNode>(DAG.getNode(S0));
142-
auto *S1N = cast<sandboxir::MemDGNode>(DAG.getNode(S1));
143-
144-
EXPECT_EQ(S0N->getPrevNode(), nullptr);
145-
EXPECT_EQ(S0N->getNextNode(), S1N);
146-
147-
EXPECT_EQ(S1N->getPrevNode(), S0N);
148-
EXPECT_EQ(S1N->getNextNode(), nullptr);
149-
}
150-
151-
TEST_F(DependencyGraphTest, DGNodeRange) {
152-
parseIR(C, R"IR(
153-
define void @foo(ptr %ptr, i8 %v0, i8 %v1) {
154-
add i8 %v0, %v0
155-
store i8 %v0, ptr %ptr
156-
add i8 %v0, %v0
157-
store i8 %v1, ptr %ptr
158-
ret void
159-
}
160-
)IR");
161-
llvm::Function *LLVMF = &*M->getFunction("foo");
162-
sandboxir::Context Ctx(C);
163-
auto *F = Ctx.createFunction(LLVMF);
164-
auto *BB = &*F->begin();
165-
auto It = BB->begin();
166-
auto *Add0 = cast<sandboxir::BinaryOperator>(&*It++);
167-
auto *S0 = cast<sandboxir::StoreInst>(&*It++);
168-
auto *Add1 = cast<sandboxir::BinaryOperator>(&*It++);
169-
auto *S1 = cast<sandboxir::StoreInst>(&*It++);
170-
auto *Ret = cast<sandboxir::ReturnInst>(&*It++);
171-
172-
sandboxir::DependencyGraph DAG;
173-
DAG.extend({&*BB->begin(), BB->getTerminator()});
174-
175-
auto *S0N = cast<sandboxir::MemDGNode>(DAG.getNode(S0));
176-
auto *S1N = cast<sandboxir::MemDGNode>(DAG.getNode(S1));
177-
178-
// Check empty range.
179-
EXPECT_THAT(sandboxir::MemDGNodeIntervalBuilder::makeEmpty(),
180-
testing::ElementsAre());
181-
182-
// Returns the pointers in Range.
183-
auto getPtrVec = [](const auto &Range) {
184-
SmallVector<const sandboxir::DGNode *> Vec;
185-
for (const sandboxir::DGNode &N : Range)
186-
Vec.push_back(&N);
187-
return Vec;
188-
};
189-
// Both TopN and BotN are memory.
190-
EXPECT_THAT(
191-
getPtrVec(sandboxir::MemDGNodeIntervalBuilder::make({S0, S1}, DAG)),
192-
testing::ElementsAre(S0N, S1N));
193-
// Only TopN is memory.
194-
EXPECT_THAT(
195-
getPtrVec(sandboxir::MemDGNodeIntervalBuilder::make({S0, Ret}, DAG)),
196-
testing::ElementsAre(S0N, S1N));
197-
EXPECT_THAT(
198-
getPtrVec(sandboxir::MemDGNodeIntervalBuilder::make({S0, Add1}, DAG)),
199-
testing::ElementsAre(S0N));
200-
// Only BotN is memory.
201-
EXPECT_THAT(
202-
getPtrVec(sandboxir::MemDGNodeIntervalBuilder::make({Add0, S1}, DAG)),
203-
testing::ElementsAre(S0N, S1N));
204-
EXPECT_THAT(
205-
getPtrVec(sandboxir::MemDGNodeIntervalBuilder::make({Add0, S0}, DAG)),
206-
testing::ElementsAre(S0N));
207-
// Neither TopN or BotN is memory.
208-
EXPECT_THAT(
209-
getPtrVec(sandboxir::MemDGNodeIntervalBuilder::make({Add0, Ret}, DAG)),
210-
testing::ElementsAre(S0N, S1N));
211-
EXPECT_THAT(
212-
getPtrVec(sandboxir::MemDGNodeIntervalBuilder::make({Add0, Add0}, DAG)),
213-
testing::ElementsAre());
214-
}

0 commit comments

Comments
 (0)