using namespace llvm;
namespace {
-typedef DenseMap<const Value *, std::pair<unsigned, bool>> OrderMap;
+struct OrderMap {
+ DenseMap<const Value *, std::pair<unsigned, bool>> IDs;
+ unsigned LastGlobalConstantID;
+ unsigned LastGlobalValueID;
+
+ OrderMap() : LastGlobalConstantID(0), LastGlobalValueID(0) {}
+
+ bool isGlobalConstant(unsigned ID) const {
+ return ID <= LastGlobalConstantID;
+ }
+ bool isGlobalValue(unsigned ID) const {
+ return ID <= LastGlobalValueID && !isGlobalConstant(ID);
+ }
+
+ unsigned size() const { return IDs.size(); }
+ std::pair<unsigned, bool> &operator[](const Value *V) { return IDs[V]; }
+ std::pair<unsigned, bool> lookup(const Value *V) const {
+ return IDs.lookup(V);
+ }
+ void index(const Value *V) {
+ // Explicitly sequence get-size and insert-value operations to avoid UB.
+ unsigned ID = IDs.size() + 1;
+ IDs[V].first = ID;
+ }
+};
}
static void orderValue(const Value *V, OrderMap &OM) {
if (const Constant *C = dyn_cast<Constant>(V))
if (C->getNumOperands() && !isa<GlobalValue>(C))
for (const Value *Op : C->operands())
- if (!isa<BasicBlock>(Op))
+ if (!isa<BasicBlock>(Op) && !isa<GlobalValue>(Op))
orderValue(Op, OM);
// Note: we cannot cache this lookup above, since inserting into the map
- // changes the map's size, and thus affects the ID.
- OM[V].first = OM.size() + 1;
+ // changes the map's size, and thus affects the other IDs.
+ OM.index(V);
}
static OrderMap orderModule(const Module *M) {
// and ValueEnumerator::incorporateFunction().
OrderMap OM;
+ // In the reader, initializers of GlobalValues are set *after* all the
+ // globals have been read. Rather than awkwardly modeling this behaviour
+ // directly in predictValueUseListOrderImpl(), just assign IDs to
+ // initializers of GlobalValues before GlobalValues themselves to model this
+ // implicitly.
for (const GlobalVariable &G : M->globals())
- orderValue(&G, OM);
+ if (G.hasInitializer())
+ if (!isa<GlobalValue>(G.getInitializer()))
+ orderValue(G.getInitializer(), OM);
+ for (const GlobalAlias &A : M->aliases())
+ if (!isa<GlobalValue>(A.getAliasee()))
+ orderValue(A.getAliasee(), OM);
+ for (const Function &F : *M)
+ if (F.hasPrefixData())
+ if (!isa<GlobalValue>(F.getPrefixData()))
+ orderValue(F.getPrefixData(), OM);
+ OM.LastGlobalConstantID = OM.size();
+
+ // Initializers of GlobalValues are processed in
+ // BitcodeReader::ResolveGlobalAndAliasInits(). Match the order there rather
+ // than ValueEnumerator, and match the code in predictValueUseListOrderImpl()
+ // by giving IDs in reverse order.
+ //
+ // Since GlobalValues never reference each other directly (just through
+ // initializers), their relative IDs only matter for determining order of
+ // uses in their initializers.
for (const Function &F : *M)
orderValue(&F, OM);
for (const GlobalAlias &A : M->aliases())
orderValue(&A, OM);
for (const GlobalVariable &G : M->globals())
- if (G.hasInitializer())
- orderValue(G.getInitializer(), OM);
- for (const GlobalAlias &A : M->aliases())
- orderValue(A.getAliasee(), OM);
- for (const Function &F : *M)
- if (F.hasPrefixData())
- orderValue(F.getPrefixData(), OM);
+ orderValue(&G, OM);
+ OM.LastGlobalValueID = OM.size();
for (const Function &F : *M) {
if (F.isDeclaration())
// We may have lost some users.
return;
- std::sort(List.begin(), List.end(),
- [&OM, ID](const Entry &L, const Entry &R) {
+ bool IsGlobalValue = OM.isGlobalValue(ID);
+ std::sort(List.begin(), List.end(), [&](const Entry &L, const Entry &R) {
const Use *LU = L.first;
const Use *RU = R.first;
+ if (LU == RU)
+ return false;
+
auto LID = OM.lookup(LU->getUser()).first;
auto RID = OM.lookup(RU->getUser()).first;
+
+ // Global values are processed in reverse order.
+ //
+ // Moreover, initializers of GlobalValues are set *after* all the globals
+ // have been read (despite having earlier IDs). Rather than awkwardly
+ // modeling this behaviour here, orderModule() has assigned IDs to
+ // initializers of GlobalValues before GlobalValues themselves.
+ if (OM.isGlobalValue(LID) && OM.isGlobalValue(RID))
+ return LID < RID;
+
// If ID is 4, then expect: 7 6 5 1 2 3.
if (LID < RID) {
- if (RID < ID)
- return true;
+ if (RID <= ID)
+ if (!IsGlobalValue) // GlobalValue uses don't get reversed.
+ return true;
return false;
}
if (RID < LID) {
- if (LID < ID)
- return false;
+ if (LID <= ID)
+ if (!IsGlobalValue) // GlobalValue uses don't get reversed.
+ return false;
return true;
}
+
// LID and RID are equal, so we have different operands of the same user.
// Assume operands are added in order for all instructions.
- if (LU->getOperandNo() < RU->getOperandNo())
- return LID < ID;
- return ID < LID;
+ if (LID <= ID)
+ if (!IsGlobalValue) // GlobalValue uses don't get reversed.
+ return LU->getOperandNo() < RU->getOperandNo();
+ return LU->getOperandNo() > RU->getOperandNo();
});
if (std::is_sorted(
return;
// Store the shuffle.
- UseListOrder O;
- O.V = V;
- O.F = F;
- for (auto &I : List)
- O.Shuffle.push_back(I.second);
- Stack.push_back(O);
+ Stack.emplace_back(V, F, List.size());
+ assert(List.size() == Stack.back().Shuffle.size() && "Wrong size");
+ for (size_t I = 0, E = List.size(); I != E; ++I)
+ Stack.back().Shuffle[I] = List[I].second;
}
static void predictValueUseListOrder(const Value *V, const Function *F,
// Recursive descent into constants.
if (const Constant *C = dyn_cast<Constant>(V))
- if (C->getNumOperands() && !isa<GlobalValue>(C))
+ if (C->getNumOperands()) // Visit GlobalValues.
for (const Value *Op : C->operands())
- if (isa<Constant>(Op) && !isa<GlobalValue>(Op))
+ if (isa<Constant>(Op)) // Visit GlobalValues.
predictValueUseListOrder(Op, F, OM, Stack);
}
for (const BasicBlock &BB : F)
for (const Instruction &I : BB)
for (const Value *Op : I.operands())
- if ((isa<Constant>(*Op) && !isa<GlobalValue>(*Op)) ||
- isa<InlineAsm>(*Op))
+ if (isa<Constant>(*Op) || isa<InlineAsm>(*Op)) // Visit GlobalValues.
predictValueUseListOrder(Op, &F, OM, Stack);
for (const BasicBlock &BB : F)
for (const Instruction &I : BB)
void ValueEnumerator::EnumerateMetadata(const Value *MD) {
assert((isa<MDNode>(MD) || isa<MDString>(MD)) && "Invalid metadata kind");
- // Enumerate the type of this value.
- EnumerateType(MD->getType());
-
+ // Skip function-local nodes themselves, but walk their operands.
const MDNode *N = dyn_cast<MDNode>(MD);
-
- // In the module-level pass, skip function-local nodes themselves, but
- // do walk their operands.
if (N && N->isFunctionLocal() && N->getFunction()) {
EnumerateMDNodeOperands(N);
return;
}
- // Check to see if it's already in!
- unsigned &MDValueID = MDValueMap[MD];
- if (MDValueID) {
- // Increment use count.
- MDValues[MDValueID-1].second++;
+ // Insert a dummy ID to block the co-recursive call to
+ // EnumerateMDNodeOperands() from re-visiting MD in a cyclic graph.
+ //
+ // Return early if there's already an ID.
+ if (!MDValueMap.insert(std::make_pair(MD, 0)).second)
return;
- }
- MDValues.push_back(std::make_pair(MD, 1U));
- MDValueID = MDValues.size();
- // Enumerate all non-function-local operands.
+ // Enumerate the type of this value.
+ EnumerateType(MD->getType());
+
+ // Visit operands first to minimize RAUW.
if (N)
EnumerateMDNodeOperands(N);
+
+ // Replace the dummy ID inserted above with the correct one. MDValueMap may
+ // have changed by inserting operands, so we need a fresh lookup here.
+ MDValues.push_back(MD);
+ MDValueMap[MD] = MDValues.size();
}
/// EnumerateFunctionLocalMetadataa - Incorporate function-local metadata
// Check to see if it's already in!
unsigned &MDValueID = MDValueMap[N];
- if (MDValueID) {
- // Increment use count.
- MDValues[MDValueID-1].second++;
+ if (MDValueID)
return;
- }
- MDValues.push_back(std::make_pair(N, 1U));
+
+ MDValues.push_back(N);
MDValueID = MDValues.size();
// To incoroporate function-local information visit all function-local
for (unsigned i = NumModuleValues, e = Values.size(); i != e; ++i)
ValueMap.erase(Values[i].first);
for (unsigned i = NumModuleMDValues, e = MDValues.size(); i != e; ++i)
- MDValueMap.erase(MDValues[i].first);
+ MDValueMap.erase(MDValues[i]);
for (unsigned i = 0, e = BasicBlocks.size(); i != e; ++i)
ValueMap.erase(BasicBlocks[i]);