Skip to content

Commit 1483659

Browse files
authored
[GC] Use MapVector for GCStrategyMap (llvm#132729)
Use `MapVector` so `GCStrategyMap` can support forward and reverse iterator, which is required in `AsmPrinter`.
1 parent adabc83 commit 1483659

File tree

6 files changed

+127
-13
lines changed

6 files changed

+127
-13
lines changed

llvm/include/llvm/CodeGen/GCMetadata.h

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#define LLVM_CODEGEN_GCMETADATA_H
3434

3535
#include "llvm/ADT/DenseMap.h"
36+
#include "llvm/ADT/MapVector.h"
3637
#include "llvm/ADT/SmallVector.h"
3738
#include "llvm/ADT/StringMap.h"
3839
#include "llvm/ADT/StringRef.h"
@@ -151,15 +152,49 @@ class GCFunctionInfo {
151152
size_t live_size(const iterator &p) const { return roots_size(); }
152153
};
153154

154-
struct GCStrategyMap {
155-
StringMap<std::unique_ptr<GCStrategy>> StrategyMap;
155+
class GCStrategyMap {
156+
using MapT =
157+
MapVector<StringRef, std::unique_ptr<GCStrategy>, StringMap<unsigned>>;
158+
MapT Strategies;
156159

160+
public:
157161
GCStrategyMap() = default;
158162
GCStrategyMap(GCStrategyMap &&) = default;
159163

160164
/// Handle invalidation explicitly.
161165
bool invalidate(Module &M, const PreservedAnalyses &PA,
162166
ModuleAnalysisManager::Invalidator &Inv);
167+
168+
using iterator = MapT::iterator;
169+
using const_iterator = MapT::const_iterator;
170+
using reverse_iterator = MapT::reverse_iterator;
171+
using const_reverse_iterator = MapT::const_reverse_iterator;
172+
173+
iterator begin() { return Strategies.begin(); }
174+
const_iterator begin() const { return Strategies.begin(); }
175+
iterator end() { return Strategies.end(); }
176+
const_iterator end() const { return Strategies.end(); }
177+
178+
reverse_iterator rbegin() { return Strategies.rbegin(); }
179+
const_reverse_iterator rbegin() const { return Strategies.rbegin(); }
180+
reverse_iterator rend() { return Strategies.rend(); }
181+
const_reverse_iterator rend() const { return Strategies.rend(); }
182+
183+
bool empty() const { return Strategies.empty(); }
184+
185+
const GCStrategy &operator[](StringRef GCName) const {
186+
auto I = Strategies.find(GCName);
187+
assert(I != Strategies.end() && "Required strategy doesn't exist!");
188+
return *I->second;
189+
}
190+
191+
std::pair<iterator, bool> try_emplace(StringRef GCName) {
192+
return Strategies.try_emplace(GCName);
193+
}
194+
195+
bool contains(StringRef GCName) const {
196+
return Strategies.find(GCName) != Strategies.end();
197+
}
163198
};
164199

165200
/// An analysis pass which caches information about the entire Module.

llvm/include/llvm/IR/GCStrategy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class Type;
6363
class GCStrategy {
6464
private:
6565
friend class GCModuleInfo;
66+
friend class CollectorMetadataAnalysis;
6667

6768
std::string Name;
6869

llvm/lib/CodeGen/GCMetadata.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ bool GCStrategyMap::invalidate(Module &M, const PreservedAnalyses &PA,
2626
for (const auto &F : M) {
2727
if (F.isDeclaration() || !F.hasGC())
2828
continue;
29-
if (!StrategyMap.contains(F.getGC()))
29+
if (!contains(F.getGC()))
3030
return true;
3131
}
3232
return false;
@@ -36,17 +36,18 @@ AnalysisKey CollectorMetadataAnalysis::Key;
3636

3737
CollectorMetadataAnalysis::Result
3838
CollectorMetadataAnalysis::run(Module &M, ModuleAnalysisManager &MAM) {
39-
Result R;
40-
auto &Map = R.StrategyMap;
39+
Result StrategyMap;
4140
for (auto &F : M) {
4241
if (F.isDeclaration() || !F.hasGC())
4342
continue;
44-
auto GCName = F.getGC();
45-
auto [It, Inserted] = Map.try_emplace(GCName);
46-
if (Inserted)
43+
StringRef GCName = F.getGC();
44+
auto [It, Inserted] = StrategyMap.try_emplace(GCName);
45+
if (Inserted) {
4746
It->second = getGCStrategy(GCName);
47+
It->second->Name = GCName;
48+
}
4849
}
49-
return R;
50+
return StrategyMap;
5051
}
5152

5253
AnalysisKey GCFunctionAnalysis::Key;
@@ -61,9 +62,9 @@ GCFunctionAnalysis::run(Function &F, FunctionAnalysisManager &FAM) {
6162
MAMProxy.cachedResultExists<CollectorMetadataAnalysis>(*F.getParent()) &&
6263
"This pass need module analysis `collector-metadata`!");
6364
auto &Map =
64-
MAMProxy.getCachedResult<CollectorMetadataAnalysis>(*F.getParent())
65-
->StrategyMap;
66-
GCFunctionInfo Info(F, *Map[F.getGC()]);
65+
*MAMProxy.getCachedResult<CollectorMetadataAnalysis>(*F.getParent());
66+
GCStrategy &S = *Map.try_emplace(F.getGC()).first->second;
67+
GCFunctionInfo Info(F, S);
6768
return Info;
6869
}
6970

llvm/lib/CodeGen/ShadowStackGCLowering.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ class ShadowStackGCLowering : public FunctionPass {
109109
PreservedAnalyses ShadowStackGCLoweringPass::run(Module &M,
110110
ModuleAnalysisManager &MAM) {
111111
auto &Map = MAM.getResult<CollectorMetadataAnalysis>(M);
112-
if (Map.StrategyMap.contains("shadow-stack"))
112+
if (!Map.contains("shadow-stack"))
113113
return PreservedAnalyses::all();
114114

115115
ShadowStackGCLoweringImpl Impl;

llvm/unittests/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ add_llvm_unittest(CodeGenTests
2929
DIETest.cpp
3030
DroppedVariableStatsMIRTest.cpp
3131
DwarfStringPoolEntryRefTest.cpp
32+
GCMetadata.cpp
3233
InstrRefLDVTest.cpp
3334
LowLevelTypeTest.cpp
3435
LexicalScopesTest.cpp

llvm/unittests/CodeGen/GCMetadata.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//===- llvm/unittest/CodeGen/GCMetadata.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/CodeGen/GCMetadata.h"
10+
#include "llvm/Analysis/CGSCCPassManager.h"
11+
#include "llvm/Analysis/LoopAnalysisManager.h"
12+
#include "llvm/AsmParser/Parser.h"
13+
#include "llvm/IR/Analysis.h"
14+
#include "llvm/IR/LLVMContext.h"
15+
#include "llvm/IR/Module.h"
16+
#include "llvm/IR/PassManager.h"
17+
#include "llvm/Passes/PassBuilder.h"
18+
#include "llvm/Support/SourceMgr.h"
19+
#include "gtest/gtest.h"
20+
21+
using namespace llvm;
22+
23+
namespace {
24+
25+
std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) {
26+
SMDiagnostic Err;
27+
return parseAssemblyString(IR, Err, Context);
28+
}
29+
30+
class GCMetadataTest : public ::testing::Test {
31+
protected:
32+
LLVMContext Context;
33+
std::unique_ptr<Module> M;
34+
35+
public:
36+
GCMetadataTest()
37+
: M(parseIR(Context, R"(
38+
%Env = type ptr
39+
40+
define void @.main(%Env) gc "shadow-stack" {
41+
%Root = alloca %Env
42+
call void @llvm.gcroot( ptr %Root, %Env null )
43+
unreachable
44+
}
45+
46+
define void @g() gc "erlang" {
47+
entry:
48+
ret void
49+
}
50+
51+
declare void @llvm.gcroot(ptr, %Env)
52+
)")) {}
53+
};
54+
55+
TEST_F(GCMetadataTest, Basic) {
56+
LoopAnalysisManager LAM;
57+
FunctionAnalysisManager FAM;
58+
CGSCCAnalysisManager CGAM;
59+
ModuleAnalysisManager MAM;
60+
PassBuilder PB;
61+
PB.registerModuleAnalyses(MAM);
62+
PB.registerCGSCCAnalyses(CGAM);
63+
PB.registerFunctionAnalyses(FAM);
64+
PB.registerLoopAnalyses(LAM);
65+
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
66+
67+
ModulePassManager MPM;
68+
FunctionPassManager FPM;
69+
GCStrategyMap &StrategyMap = MAM.getResult<CollectorMetadataAnalysis>(*M);
70+
for (auto &[GCName, Strategy] : StrategyMap)
71+
EXPECT_EQ(GCName, Strategy->getName());
72+
for (auto &[GCName, Strategy] : llvm::reverse(StrategyMap))
73+
EXPECT_EQ(GCName, Strategy->getName());
74+
}
75+
76+
} // namespace

0 commit comments

Comments
 (0)