Skip to content

Commit 9521704

Browse files
author
Krzysztof Parzyszek
committed
[RDF] Use hash-based containers, cache extra information
This improves performance.
1 parent 00602ee commit 9521704

File tree

3 files changed

+84
-11
lines changed

3 files changed

+84
-11
lines changed

llvm/include/llvm/CodeGen/RDFLiveness.h

+31-7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "llvm/MC/LaneBitmask.h"
1919
#include <map>
2020
#include <set>
21+
#include <unordered_map>
22+
#include <unordered_set>
2123
#include <utility>
2224

2325
namespace llvm {
@@ -28,6 +30,30 @@ class MachineDominatorTree;
2830
class MachineRegisterInfo;
2931
class TargetRegisterInfo;
3032

33+
} // namespace llvm
34+
35+
namespace llvm {
36+
namespace rdf {
37+
namespace detail {
38+
39+
using NodeRef = std::pair<NodeId, LaneBitmask>;
40+
41+
} // namespace detail
42+
} // namespace rdf
43+
} // namespace llvm
44+
45+
namespace std {
46+
47+
template <> struct hash<llvm::rdf::detail::NodeRef> {
48+
std::size_t operator()(llvm::rdf::detail::NodeRef R) const {
49+
return std::hash<llvm::rdf::NodeId>{}(R.first) ^
50+
std::hash<llvm::LaneBitmask::Type>{}(R.second.getAsInteger());
51+
}
52+
};
53+
54+
} // namespace std
55+
56+
namespace llvm {
3157
namespace rdf {
3258

3359
struct Liveness {
@@ -46,10 +72,9 @@ namespace rdf {
4672
std::map<MachineBasicBlock*,RegisterAggr> Map;
4773
};
4874

49-
using NodeRef = std::pair<NodeId, LaneBitmask>;
50-
using NodeRefSet = std::set<NodeRef>;
51-
// RegisterId in RefMap must be normalized.
52-
using RefMap = std::map<RegisterId, NodeRefSet>;
75+
using NodeRef = detail::NodeRef;
76+
using NodeRefSet = std::unordered_set<NodeRef>;
77+
using RefMap = std::unordered_map<RegisterId, NodeRefSet>;
5378

5479
Liveness(MachineRegisterInfo &mri, const DataFlowGraph &g)
5580
: DFG(g), TRI(g.getTRI()), PRI(g.getPRI()), MDT(g.getDT()),
@@ -110,15 +135,14 @@ namespace rdf {
110135
// Cache of mapping from node ids (for RefNodes) to the containing
111136
// basic blocks. Not computing it each time for each node reduces
112137
// the liveness calculation time by a large fraction.
113-
using NodeBlockMap = DenseMap<NodeId, MachineBasicBlock *>;
114-
NodeBlockMap NBMap;
138+
DenseMap<NodeId, MachineBasicBlock *> NBMap;
115139

116140
// Phi information:
117141
//
118142
// RealUseMap
119143
// map: NodeId -> (map: RegisterId -> NodeRefSet)
120144
// phi id -> (map: register -> set of reached non-phi uses)
121-
std::map<NodeId, RefMap> RealUseMap;
145+
DenseMap<NodeId, RefMap> RealUseMap;
122146

123147
// Inverse iterated dominance frontier.
124148
std::map<MachineBasicBlock*,std::set<MachineBasicBlock*>> IIDF;

llvm/include/llvm/CodeGen/RDFRegisters.h

+32-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ namespace rdf {
9191
bool operator< (const RegisterRef &RR) const {
9292
return Reg < RR.Reg || (Reg == RR.Reg && Mask < RR.Mask);
9393
}
94+
95+
size_t hash() const {
96+
return std::hash<RegisterId>{}(Reg) ^
97+
std::hash<LaneBitmask::Type>{}(Mask.getAsInteger());
98+
}
9499
};
95100

96101

@@ -171,10 +176,15 @@ namespace rdf {
171176
: Units(pri.getTRI().getNumRegUnits()), PRI(pri) {}
172177
RegisterAggr(const RegisterAggr &RG) = default;
173178

179+
unsigned count() const { return Units.count(); }
174180
bool empty() const { return Units.none(); }
175181
bool hasAliasOf(RegisterRef RR) const;
176182
bool hasCoverOf(RegisterRef RR) const;
177183

184+
bool operator==(const RegisterAggr &A) const {
185+
return DenseMapInfo<BitVector>::isEqual(Units, A.Units);
186+
}
187+
178188
static bool isCoverOf(RegisterRef RA, RegisterRef RB,
179189
const PhysicalRegisterInfo &PRI) {
180190
return RegisterAggr(PRI).insert(RA).hasCoverOf(RB);
@@ -191,6 +201,10 @@ namespace rdf {
191201
RegisterRef clearIn(RegisterRef RR) const;
192202
RegisterRef makeRegRef() const;
193203

204+
size_t hash() const {
205+
return DenseMapInfo<BitVector>::getHashValue(Units);
206+
}
207+
194208
void print(raw_ostream &OS) const;
195209

196210
struct rr_iterator {
@@ -244,9 +258,26 @@ namespace rdf {
244258
LaneBitmask Mask;
245259
};
246260
raw_ostream &operator<< (raw_ostream &OS, const PrintLaneMaskOpt &P);
247-
248261
} // end namespace rdf
249262

250263
} // end namespace llvm
251264

265+
namespace std {
266+
template <> struct hash<llvm::rdf::RegisterRef> {
267+
size_t operator()(llvm::rdf::RegisterRef A) const {
268+
return A.hash();
269+
}
270+
};
271+
template <> struct hash<llvm::rdf::RegisterAggr> {
272+
size_t operator()(const llvm::rdf::RegisterAggr &A) const {
273+
return A.hash();
274+
}
275+
};
276+
template <> struct equal_to<llvm::rdf::RegisterAggr> {
277+
bool operator()(const llvm::rdf::RegisterAggr &A,
278+
const llvm::rdf::RegisterAggr &B) const {
279+
return A == B;
280+
}
281+
};
282+
}
252283
#endif // LLVM_LIB_TARGET_HEXAGON_RDFREGISTERS_H

llvm/lib/CodeGen/RDFLiveness.cpp

+21-3
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include <cstdint>
4848
#include <iterator>
4949
#include <map>
50+
#include <unordered_map>
5051
#include <utility>
5152
#include <vector>
5253

@@ -476,7 +477,7 @@ void Liveness::computePhiInfo() {
476477
// phi use -> (map: reaching phi -> set of registers defined in between)
477478
std::map<NodeId,std::map<NodeId,RegisterAggr>> PhiUp;
478479
std::vector<NodeId> PhiUQ; // Work list of phis for upward propagation.
479-
std::map<NodeId,RegisterAggr> PhiDRs; // Phi -> registers defined by it.
480+
std::unordered_map<NodeId,RegisterAggr> PhiDRs; // Phi -> registers defined by it.
480481

481482
// Go over all phis.
482483
for (NodeAddr<PhiNode*> PhiA : Phis) {
@@ -652,6 +653,23 @@ void Liveness::computePhiInfo() {
652653
// is covered, or until reaching the final phi. Only assume that the
653654
// reference reaches the phi in the latter case.
654655

656+
// The operation "clearIn" can be expensive. For a given set of intervening
657+
// defs, cache the result of subtracting these defs from a given register
658+
// ref.
659+
using SubMap = std::unordered_map<RegisterRef, RegisterRef>;
660+
std::unordered_map<RegisterAggr, SubMap> Subs;
661+
auto ClearIn = [] (RegisterRef RR, const RegisterAggr &Mid, SubMap &SM) {
662+
if (Mid.empty())
663+
return RR;
664+
auto F = SM.find(RR);
665+
if (F != SM.end())
666+
return F->second;
667+
RegisterRef S = Mid.clearIn(RR);
668+
SM.insert({RR, S});
669+
return S;
670+
};
671+
672+
// Go over all phis.
655673
for (unsigned i = 0; i < PhiUQ.size(); ++i) {
656674
auto PA = DFG.addr<PhiNode*>(PhiUQ[i]);
657675
NodeList PUs = PA.Addr->members_if(DFG.IsRef<NodeAttrs::Use>, DFG);
@@ -663,13 +681,13 @@ void Liveness::computePhiInfo() {
663681
for (const std::pair<const NodeId, RegisterAggr> &P : PUM) {
664682
bool Changed = false;
665683
const RegisterAggr &MidDefs = P.second;
666-
667684
// Collect the set PropUp of uses that are reached by the current
668685
// phi PA, and are not covered by any intervening def between the
669686
// currently visited use UA and the upward phi P.
670687

671688
if (MidDefs.hasCoverOf(UR))
672689
continue;
690+
SubMap &SM = Subs[MidDefs];
673691

674692
// General algorithm:
675693
// for each (R,U) : U is use node of R, U is reached by PA
@@ -689,7 +707,7 @@ void Liveness::computePhiInfo() {
689707
LaneBitmask M = R.Mask & V.second;
690708
if (M.none())
691709
continue;
692-
if (RegisterRef SS = MidDefs.clearIn(RegisterRef(R.Reg, M))) {
710+
if (RegisterRef SS = ClearIn(RegisterRef(R.Reg, M), MidDefs, SM)) {
693711
NodeRefSet &RS = RealUseMap[P.first][SS.Reg];
694712
Changed |= RS.insert({V.first,SS.Mask}).second;
695713
}

0 commit comments

Comments
 (0)