@@ -28,6 +28,17 @@ using namespace llvm;
28
28
namespace {
29
29
struct OrderMap {
30
30
DenseMap<const Value *, std::pair<unsigned , bool >> IDs;
31
+ unsigned LastGlobalConstantID;
32
+ unsigned LastGlobalValueID;
33
+
34
+ OrderMap () : LastGlobalConstantID(0 ), LastGlobalValueID(0 ) {}
35
+
36
+ bool isGlobalConstant (unsigned ID) const {
37
+ return ID <= LastGlobalConstantID;
38
+ }
39
+ bool isGlobalValue (unsigned ID) const {
40
+ return ID <= LastGlobalValueID && !isGlobalConstant (ID);
41
+ }
31
42
32
43
unsigned size () const { return IDs.size (); }
33
44
std::pair<unsigned , bool > &operator [](const Value *V) { return IDs[V]; }
@@ -49,7 +60,7 @@ static void orderValue(const Value *V, OrderMap &OM) {
49
60
if (const Constant *C = dyn_cast<Constant>(V))
50
61
if (C->getNumOperands () && !isa<GlobalValue>(C))
51
62
for (const Value *Op : C->operands ())
52
- if (!isa<BasicBlock>(Op))
63
+ if (!isa<BasicBlock>(Op) && !isa<GlobalValue>(Op) )
53
64
orderValue (Op, OM);
54
65
55
66
// Note: we cannot cache this lookup above, since inserting into the map
@@ -62,12 +73,11 @@ static OrderMap orderModule(const Module *M) {
62
73
// and ValueEnumerator::incorporateFunction().
63
74
OrderMap OM;
64
75
65
- for (const GlobalVariable &G : M->globals ())
66
- orderValue (&G, OM);
67
- for (const Function &F : *M)
68
- orderValue (&F, OM);
69
- for (const GlobalAlias &A : M->aliases ())
70
- orderValue (&A, OM);
76
+ // In the reader, initializers of GlobalValues are set *after* all the
77
+ // globals have been read. Rather than awkwardly modeling this behaviour
78
+ // directly in predictValueUseListOrderImpl(), just assign IDs to
79
+ // initializers of GlobalValues before GlobalValues themselves to model this
80
+ // implicitly.
71
81
for (const GlobalVariable &G : M->globals ())
72
82
if (G.hasInitializer ())
73
83
orderValue (G.getInitializer (), OM);
@@ -76,6 +86,23 @@ static OrderMap orderModule(const Module *M) {
76
86
for (const Function &F : *M)
77
87
if (F.hasPrefixData ())
78
88
orderValue (F.getPrefixData (), OM);
89
+ OM.LastGlobalConstantID = OM.size ();
90
+
91
+ // Initializers of GlobalValues are processed in
92
+ // BitcodeReader::ResolveGlobalAndAliasInits(). Match the order there rather
93
+ // than ValueEnumerator, and match the code in predictValueUseListOrderImpl()
94
+ // by giving IDs in reverse order.
95
+ //
96
+ // Since GlobalValues never reference each other directly (just through
97
+ // initializers), their relative IDs only matter for determining order of
98
+ // uses in their initializers.
99
+ for (const Function &F : *M)
100
+ orderValue (&F, OM);
101
+ for (const GlobalAlias &A : M->aliases ())
102
+ orderValue (&A, OM);
103
+ for (const GlobalVariable &G : M->globals ())
104
+ orderValue (&G, OM);
105
+ OM.LastGlobalValueID = OM.size ();
79
106
80
107
for (const Function &F : *M) {
81
108
if (F.isDeclaration ())
@@ -115,31 +142,45 @@ static void predictValueUseListOrderImpl(const Value *V, const Function *F,
115
142
// We may have lost some users.
116
143
return ;
117
144
118
- std::sort (List. begin (), List. end (),
119
- [&OM, ID ](const Entry &L, const Entry &R) {
145
+ bool IsGlobalValue = OM. isGlobalValue (ID);
146
+ std::sort (List. begin (), List. end (), [& ](const Entry &L, const Entry &R) {
120
147
const Use *LU = L.first ;
121
148
const Use *RU = R.first ;
122
149
if (LU == RU)
123
150
return false ;
124
151
125
152
auto LID = OM.lookup (LU->getUser ()).first ;
126
153
auto RID = OM.lookup (RU->getUser ()).first ;
154
+
155
+ // Global values are processed in reverse order.
156
+ //
157
+ // Moreover, initializers of GlobalValues are set *after* all the globals
158
+ // have been read (despite having earlier IDs). Rather than awkwardly
159
+ // modeling this behaviour here, orderModule() has assigned IDs to
160
+ // initializers of GlobalValues before GlobalValues themselves.
161
+ if (OM.isGlobalValue (LID) && OM.isGlobalValue (RID))
162
+ return LID < RID;
163
+
127
164
// If ID is 4, then expect: 7 6 5 1 2 3.
128
165
if (LID < RID) {
129
166
if (RID < ID)
130
- return true ;
167
+ if (!IsGlobalValue) // GlobalValue uses don't get reversed.
168
+ return true ;
131
169
return false ;
132
170
}
133
171
if (RID < LID) {
134
172
if (LID < ID)
135
- return false ;
173
+ if (!IsGlobalValue) // GlobalValue uses don't get reversed.
174
+ return false ;
136
175
return true ;
137
176
}
177
+
138
178
// LID and RID are equal, so we have different operands of the same user.
139
179
// Assume operands are added in order for all instructions.
140
- if (LU->getOperandNo () < RU->getOperandNo ())
141
- return LID < ID;
142
- return ID < LID;
180
+ if (LID < ID)
181
+ if (!IsGlobalValue) // GlobalValue uses don't get reversed.
182
+ return LU->getOperandNo () < RU->getOperandNo ();
183
+ return LU->getOperandNo () > RU->getOperandNo ();
143
184
});
144
185
145
186
if (std::is_sorted (
0 commit comments