Skip to content

Commit a2b5fd7

Browse files
authored
[SandboxIR][Region] Auxiliary vector metadata now requires a region (#137443)
The auxiliary vector is represented by the !sandboxaux metadata. But until now adding an instruction to the aux vector would not automatically add it to the region (i.e., it would not mark it with !sandboxvec). This behavior was problematic when generating regions from metadata, because you wouldn't know which region owns the auxiliary vector. This patch fixes this issue: We now require that an instruction with !sandboxaux also defines its region with !sandboxvec.
1 parent d4d4a04 commit a2b5fd7

File tree

3 files changed

+80
-13
lines changed

3 files changed

+80
-13
lines changed

llvm/include/llvm/SandboxIR/Region.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,18 @@ class Region {
114114
/// ID (for later deregistration) of the "erase instruction" callback.
115115
Context::CallbackID EraseInstCB;
116116

117-
/// Adds I to the set.
118-
void add(Instruction *I);
117+
/// Adds \p I to the set but also don't track the instruction's score if \p
118+
/// IgnoreCost is true. Only to be used when adding an instruction to the
119+
/// auxiliary vector.
120+
/// NOTE: When an instruction is added to the region we track it cost in the
121+
/// scoreboard, which currently resides in the region class. However, when we
122+
/// add an instruction to the auxiliary vector it does get tagged as being a
123+
/// member of the region (for ownership reasons), but its cost does not get
124+
/// counted because the instruction hasn't been added in the "normal" way.
125+
void addImpl(Instruction *I, bool IgnoreCost);
126+
/// Adds I to the set. This is the main API for adding an instruction to the
127+
/// region.
128+
void add(Instruction *I) { addImpl(I, /*IgnoreCost=*/false); }
119129
/// Removes I from the set.
120130
void remove(Instruction *I);
121131
friend class Context; // The callbacks need to call add() and remove().

llvm/lib/SandboxIR/Region.cpp

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,13 @@ Region::~Region() {
5151
Ctx.unregisterEraseInstrCallback(EraseInstCB);
5252
}
5353

54-
void Region::add(Instruction *I) {
54+
void Region::addImpl(Instruction *I, bool IgnoreCost) {
5555
Insts.insert(I);
5656
// TODO: Consider tagging instructions lazily.
5757
cast<llvm::Instruction>(I->Val)->setMetadata(MDKind, RegionMDN);
58-
// Keep track of the instruction cost.
59-
Scoreboard.add(I);
58+
if (!IgnoreCost)
59+
// Keep track of the instruction cost.
60+
Scoreboard.add(I);
6061
}
6162

6263
void Region::setAux(ArrayRef<Instruction *> Aux) {
@@ -69,6 +70,8 @@ void Region::setAux(ArrayRef<Instruction *> Aux) {
6970
"Instruction already in Aux!");
7071
cast<llvm::Instruction>(I->Val)->setMetadata(
7172
AuxMDKind, MDNode::get(LLVMCtx, ConstantAsMetadata::get(IdxC)));
73+
// Aux instrs should always be in a region.
74+
addImpl(I, /*DontTrackCost=*/true);
7275
}
7376
}
7477

@@ -84,6 +87,8 @@ void Region::setAux(unsigned Idx, Instruction *I) {
8487
Aux[Idx] = nullptr;
8588
}
8689
Aux[Idx] = I;
90+
// Aux instrs should always be in a region.
91+
addImpl(I, /*DontTrackCost=*/true);
8792
}
8893

8994
void Region::dropAuxMetadata(Instruction *I) {
@@ -151,8 +156,8 @@ Region::createRegionsFromMD(Function &F, TargetTransformInfo &TTI) {
151156
for (BasicBlock &BB : F) {
152157
for (Instruction &Inst : BB) {
153158
auto *LLVMI = cast<llvm::Instruction>(Inst.Val);
159+
Region *R = nullptr;
154160
if (auto *MDN = LLVMI->getMetadata(MDKind)) {
155-
Region *R = nullptr;
156161
auto [It, Inserted] = MDNToRegion.try_emplace(MDN);
157162
if (Inserted) {
158163
Regions.push_back(std::make_unique<Region>(Ctx, TTI));
@@ -161,14 +166,17 @@ Region::createRegionsFromMD(Function &F, TargetTransformInfo &TTI) {
161166
} else {
162167
R = It->second;
163168
}
164-
R->add(&Inst);
165-
166-
if (auto *AuxMDN = LLVMI->getMetadata(AuxMDKind)) {
167-
llvm::Constant *IdxC =
168-
dyn_cast<ConstantAsMetadata>(AuxMDN->getOperand(0))->getValue();
169-
auto Idx = cast<llvm::ConstantInt>(IdxC)->getSExtValue();
170-
R->setAux(Idx, &Inst);
169+
R->addImpl(&Inst, /*IgnoreCost=*/true);
170+
}
171+
if (auto *AuxMDN = LLVMI->getMetadata(AuxMDKind)) {
172+
llvm::Constant *IdxC =
173+
dyn_cast<ConstantAsMetadata>(AuxMDN->getOperand(0))->getValue();
174+
auto Idx = cast<llvm::ConstantInt>(IdxC)->getSExtValue();
175+
if (R == nullptr) {
176+
errs() << "No region specified for Aux: '" << *LLVMI << "'\n";
177+
exit(1);
171178
}
179+
R->setAux(Idx, &Inst);
172180
}
173181
}
174182
}

llvm/unittests/SandboxIR/RegionTest.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,22 @@ define void @foo(i8 %v) {
429429
}
430430
}
431431

432+
TEST_F(RegionTest, AuxWithoutRegion) {
433+
parseIR(C, R"IR(
434+
define void @foo(i8 %v) {
435+
%Add0 = add i8 %v, 0, !sandboxaux !0
436+
ret void
437+
}
438+
!0 = !{i32 0}
439+
)IR");
440+
llvm::Function *LLVMF = &*M->getFunction("foo");
441+
sandboxir::Context Ctx(C);
442+
auto *F = Ctx.createFunction(LLVMF);
443+
#ifndef NDEBUG
444+
EXPECT_DEATH(sandboxir::Region::createRegionsFromMD(*F, *TTI), "No region.*");
445+
#endif
446+
}
447+
432448
TEST_F(RegionTest, AuxRoundTrip) {
433449
parseIR(C, R"IR(
434450
define i8 @foo(i8 %v0, i8 %v1) {
@@ -461,3 +477,36 @@ define i8 @foo(i8 %v0, i8 %v1) {
461477
#endif
462478
EXPECT_THAT(Rgn.getAux(), testing::ElementsAre(T1, T0));
463479
}
480+
481+
// Same as before but only add instructions to aux. They should get added too
482+
// the region too automatically.
483+
TEST_F(RegionTest, AuxOnlyRoundTrip) {
484+
parseIR(C, R"IR(
485+
define void @foo(i8 %v) {
486+
%add0 = add i8 %v, 0
487+
%add1 = add i8 %v, 1
488+
ret void
489+
}
490+
)IR");
491+
llvm::Function *LLVMF = &*M->getFunction("foo");
492+
sandboxir::Context Ctx(C);
493+
auto *F = Ctx.createFunction(LLVMF);
494+
auto *BB = &*F->begin();
495+
auto It = BB->begin();
496+
auto *Add0 = cast<sandboxir::Instruction>(&*It++);
497+
auto *Add1 = cast<sandboxir::Instruction>(&*It++);
498+
499+
sandboxir::Region Rgn(Ctx, *TTI);
500+
#ifndef NDEBUG
501+
EXPECT_DEATH(Rgn.setAux({Add0, Add0}), ".*already.*");
502+
#endif
503+
Rgn.setAux({Add1, Add0});
504+
505+
SmallVector<std::unique_ptr<sandboxir::Region>> Regions =
506+
sandboxir::Region::createRegionsFromMD(*F, *TTI);
507+
ASSERT_EQ(1U, Regions.size());
508+
#ifndef NDEBUG
509+
EXPECT_EQ(Rgn, *Regions[0].get());
510+
#endif
511+
EXPECT_THAT(Rgn.getAux(), testing::ElementsAre(Add1, Add0));
512+
}

0 commit comments

Comments
 (0)