[llvm] [CodeGen] Speed up ReachingDefAnalysis (NFC) (PR #100913)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 13 12:43:43 PDT 2024
================
@@ -33,35 +32,156 @@ namespace llvm {
class MachineBasicBlock;
class MachineInstr;
-/// Thin wrapper around "int" used to store reaching definitions,
-/// using an encoding that makes it compatible with TinyPtrVector.
-/// The 0th LSB is forced zero (and will be used for pointer union tagging),
-/// The 1st LSB is forced one (to make sure the value is non-zero).
-class ReachingDef {
- uintptr_t Encoded;
- friend struct PointerLikeTypeTraits<ReachingDef>;
- explicit ReachingDef(uintptr_t Encoded) : Encoded(Encoded) {}
-
+// An implementation of multimap from (MBBNumber, Unit) to reaching definitions.
+//
+// This implementation only supports modification operations just enough
+// to serve our needs:
+//
+// - addDef
+// - prependDef
+// - replaceFront
+//
+// Internally, the multimap is implemented as a collection of singly linked
+// lists represented on top of a single array. Each singly-linked list
+// contains reaching definitions for a given pair of MBBNumber and Unit.
+//
+// This design has the following highlights:
+//
+// - Unlike SparseMultiset or other maps, we do not store keys as part of values
+// or anywhere else in the data structure.
+//
+// - The single array design minimizes malloc traffic.
+//
+// - Reaching definitions share one array. This means that if one pair of
+// (MBBNumber, Unit) has multiple reaching definitions while another pair of
+// (MBBNumber, Unit) has none, they cancel each other to some extent.
+class MBBReachingDefsInfo {
public:
- ReachingDef(std::nullptr_t) : Encoded(0) {}
- ReachingDef(int Instr) : Encoded(((uintptr_t) Instr << 2) | 2) {}
- operator int() const { return ((int) Encoded) >> 2; }
-};
+ MBBReachingDefsInfo() = default;
+ MBBReachingDefsInfo(const MBBReachingDefsInfo &) = delete;
+ MBBReachingDefsInfo &operator=(const MBBReachingDefsInfo &) = delete;
+
+ // Initialize the multimap with the number of basic blocks and the number of
+ // register units.
+ void init(unsigned BBs, unsigned Regs) {
+ assert(NumBlockIDs == 0 && "can initialize only once");
+ assert(NumRegUnits == 0 && "can initialize only once");
+ assert(Storage.empty() && "can initialize only once");
+ NumBlockIDs = BBs;
+ NumRegUnits = Regs;
+ unsigned NumIndexes = NumBlockIDs * NumRegUnits;
+ // Reserve space for reaching definitions. Note that the first NumIndexes
+ // elements are used for indexes to various chains. The second half
+ // accommodates up to one reaching def per (MBBNumber, Unit) pair on
+ // average.
+ Storage.reserve(NumIndexes * 2);
+ Storage.assign(NumIndexes, std::make_pair(0, 0));
+ }
-template<>
-struct PointerLikeTypeTraits<ReachingDef> {
- static constexpr int NumLowBitsAvailable = 1;
+ // Clear the entire data structure.
+ void clear() {
+ NumBlockIDs = 0;
+ NumRegUnits = 0;
+ Storage.clear();
+ }
+
+ // Add a reaching definition Def to the end of the singly-linked list of
+ // definitions for (MBBNumber, Unit).
+ void addDef(unsigned MBBNumber, unsigned Unit, int Def) {
+ unsigned Key = computeKey(MBBNumber, Unit);
+ unsigned NewIndex = Storage.size();
+ Storage.emplace_back(Def, 0);
+ if (Storage[Key].first == 0) {
+ // Update the index of the first element.
+ Storage[Key].first = NewIndex;
+ // Update the index of the last element.
+ Storage[Key].second = NewIndex;
+ } else {
+ unsigned OldLastPos = Storage[Key].second;
+ // The old last element now points to the new element.
+ Storage[OldLastPos].second = NewIndex;
+ // Update the index of the last element.
+ Storage[Key].second = NewIndex;
+ }
+ }
+
+ // Add a reaching definition Def to the beginning of the singly-linked list of
+ // definitions for (MBBNumber, Unit).
+ void prependDef(unsigned MBBNumber, unsigned Unit, int Def) {
+ unsigned Key = computeKey(MBBNumber, Unit);
+ unsigned NewIndex = Storage.size();
+ Storage.emplace_back(Def, 0);
+ if (Storage[Key].first == 0) {
+ // Update the index of the first element.
+ Storage[Key].first = NewIndex;
+ // Update the index of the last element.
+ Storage[Key].second = NewIndex;
----------------
arsenm wrote:
Looking up twice?
https://github.com/llvm/llvm-project/pull/100913
More information about the llvm-commits
mailing list