Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/z/codegen/InMemoryLoadStoreMarking.cpp
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 2021 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#include "codegen/InMemoryLoadStoreMarking.hpp"
24
25
#include <stddef.h>
26
#include <stdint.h>
27
#include <string.h>
28
#include "env/FrontEnd.hpp"
29
#include "compile/Compilation.hpp"
30
#include "control/Options.hpp"
31
#include "control/Options_inlines.hpp"
32
#include "env/VMJ9.h"
33
#include "il/AliasSetInterface.hpp"
34
#include "il/Block.hpp"
35
#include "il/DataTypes.hpp"
36
#include "il/ILOpCodes.hpp"
37
#include "il/ILOps.hpp"
38
#include "il/MethodSymbol.hpp"
39
#include "il/Node.hpp"
40
#include "il/Node_inlines.hpp"
41
#include "il/Symbol.hpp"
42
#include "il/SymbolReference.hpp"
43
#include "il/TreeTop.hpp"
44
#include "il/TreeTop_inlines.hpp"
45
#include "infra/Assert.hpp"
46
#include "infra/Bit.hpp"
47
48
49
#define OPT_DETAILS "O^O IN MEMORY LOAD/STORE MARKING: "
50
51
void InMemoryLoadStoreMarking::perform()
52
{
53
54
LexicalTimer pt1("InMemoryLoadStoreMarking", comp()->phaseTimer());
55
56
vcount_t visitCount = comp()->incOrResetVisitCount();
57
58
clearAllLists();
59
60
TR::Block *block = NULL;
61
for (TR::TreeTop *tt = comp()->getStartTree(); tt; tt = tt->getNextTreeTop())
62
{
63
TR::Node* node = tt->getNode();
64
65
TR_ASSERT(node->getVisitCount() != visitCount, "Code Gen: error in lowering trees");
66
TR_ASSERT(node->getReferenceCount() == 0, "Code Gen: error in lowering trees");
67
68
if (node->getOpCodeValue() == TR::BBStart)
69
{
70
block = node->getBlock();
71
if (!block->isExtensionOfPreviousBlock())
72
{
73
if (cg->traceBCDCodeGen())
74
traceMsg(comp(),"block_%d is a new extension so clear all load and store lists\n",block->getNumber());
75
clearAllLists();
76
}
77
}
78
79
// depth first search on children to populate the commoned nodes lists
80
visitChildren(node, tt, visitCount);
81
82
// after descending to look at the children (and add to the lists) now see if the current treetop
83
// is a possible def and any nodes have to be removed from the lists
84
handleDef(node, tt);
85
}
86
}
87
88
void InMemoryLoadStoreMarking::visitChildren(TR::Node *parent, TR::TreeTop *tt, vcount_t visitCount)
89
{
90
parent->setVisitCount(visitCount);
91
92
if (parent->getOpCode().isBinaryCodedDecimalOp())
93
cg->setMethodContainsBinaryCodedDecimal();
94
95
if (parent->getOpCode().isBinaryCodedDecimalOp())
96
{
97
cg->setAddStorageReferenceHints();
98
}
99
100
for (int32_t childCount = 0; childCount < parent->getNumChildren(); childCount++)
101
{
102
TR::Node *child = parent->getChild(childCount);
103
refineConditionalCleanLoadList(child, parent);
104
if (child->getVisitCount() != visitCount)
105
{
106
visitChildren(child, tt, visitCount);
107
examineFirstReference(child, tt);
108
}
109
else
110
{
111
examineCommonedReference(child, parent, tt);
112
}
113
}
114
}
115
116
void InMemoryLoadStoreMarking::refineConditionalCleanLoadList(TR::Node *child, TR::Node *parent)
117
{
118
if (!child->getOpCode().isBCDLoadVar())
119
return;
120
if (_BCDConditionalCleanLoadList.find(child))
121
{
122
if (cg->traceBCDCodeGen())
123
traceMsg(comp(),"found %s (%p) in condCleanLoadList : examine parent %s (%p) to see if it relies on clean sign\n",
124
child->getOpCode().getName(),child,parent->getOpCode().getName(),parent);
125
if (cg->reliesOnAParticularSignEncoding(parent))
126
{
127
if (cg->traceBCDCodeGen())
128
traceMsg(comp(),"\tz^z : parent %s (%p) does rely on a clean sign so remove child %s (%p) from condCleanLoadList\n",
129
parent->getOpCode().getName(),parent,child->getOpCode().getName(),child);
130
_BCDConditionalCleanLoadList.remove(child);
131
}
132
else
133
{
134
if (cg->traceBCDCodeGen())
135
traceMsg(comp(),"\tparent %s (%p) does not rely on a clean sign so do not remove child %s (%p) from condCleanLoadList\n",
136
parent->getOpCode().getName(),parent,child->getOpCode().getName(),child);
137
}
138
}
139
}
140
141
void InMemoryLoadStoreMarking::examineFirstReference(TR::Node *node, TR::TreeTop* tt) // called the first time 'node' is encountered
142
{
143
if ((node->getType().isAggregate() || node->getType().isBCD()) &&
144
node->getReferenceCount() > 1)
145
{
146
if (tt->getNode()->getOpCode().isBCDStore() &&
147
tt->getNode()->getValueChild() == node)
148
{
149
if (cg->traceBCDCodeGen())
150
traceMsg(comp(),"store first encounter: %s (%p) under %s (%p), add store to list and set node futureUseCount %d\n",
151
node->getOpCode().getName(),node,tt->getNode()->getOpCode().getName(),tt->getNode(),node->getReferenceCount()-1);
152
node->setFutureUseCount(node->getReferenceCount()-1);
153
_BCDAggrStoreList.add(tt->getNode());
154
}
155
// in cases like:
156
// pdstore <- tt->getNode()
157
// pdload <- node
158
// the pdstore is added the _BCDAggrStoreList and the node is added to the _BCDAggrLoadList and the node futureUseCount is set twice but to the same value
159
if (node->getOpCode().isBCDLoadVar())
160
{
161
if (cg->traceBCDCodeGen())
162
traceMsg(comp(),"load var first encounter: %s (%p), add load to list and set node futureUseCount %d\n",node->getOpCode().getName(),node,node->getReferenceCount()-1);
163
node->setFutureUseCount(node->getReferenceCount()-1);
164
_BCDAggrLoadList.add(node);
165
}
166
}
167
}
168
169
void InMemoryLoadStoreMarking::handleLoadLastReference(TR::Node *node, List<TR::Node> &nodeList, TR_NodeListTypes listType)
170
{
171
bool isLastReferenceInList = node->getOpCode().isBCDLoadVar() && nodeList.find(node);
172
173
if (isLastReferenceInList &&
174
performTransformation(comp(),"%ssetSkipCopyOnLoad to true on %s (0x%p) and remove from %s\n",OPT_DETAILS,node->getOpCode().getName(),node,getName(listType)))
175
{
176
node->setSkipCopyOnLoad(true);
177
nodeList.remove(node);
178
}
179
180
if (isLastReferenceInList &&
181
listType == ConditionalCleanLoadList &&
182
node->hasSignStateOnLoad() &&
183
performTransformation(comp(),"%ssetHasSignStateOnLoad to false on %s (0x%p) for node in %s\n",OPT_DETAILS,node->getOpCode().getName(),node,getName(listType)))
184
{
185
// if every reference does not rely on the sign state then it is safe to consider that the load has no sign state on the load (as all parent will not care about a particular sign)
186
node->setHasSignStateOnLoad(false);
187
}
188
}
189
190
void InMemoryLoadStoreMarking::examineCommonedReference(TR::Node *child, TR::Node *parent, TR::TreeTop *tt)
191
{
192
if (!child->getType().isBCD())
193
return;
194
int32_t isLastReference = child->decFutureUseCount() == 0;
195
if (cg->traceBCDCodeGen())
196
traceMsg(comp(),"looking at commoned reference to %s (%p) with parent %s (%p) and tt %s (%p) (isLastReference %s)\n",
197
child->getOpCode().getName(),child,
198
parent?parent->getOpCode().getName():"NULL",parent,
199
tt?tt->getNode()->getOpCode().getName():"NULL",tt?tt->getNode():0,
200
isLastReference?"yes":"no");
201
202
if (!isLastReference)
203
return;
204
205
if (child->getType().isBCD() && !_BCDAggrStoreList.isEmpty())
206
{
207
ListIterator<TR::Node> listIt(&_BCDAggrStoreList);
208
for (TR::Node *store=listIt.getFirst(); store; store = listIt.getNext())
209
{
210
if (isLastReference &&
211
store->getValueChild() == child &&
212
performTransformation(comp(),"%ssetSkipCopyOnStore to true on %s (0x%p) and remove from list for last commoned ref to valueChild %s (0x%p)\n",
213
OPT_DETAILS,store->getOpCode().getName(),store,child->getOpCode().getName(),child))
214
{
215
store->setSkipCopyOnStore(true);
216
_BCDAggrStoreList.remove(store);
217
}
218
}
219
}
220
221
if (isLastReference)
222
{
223
handleLoadLastReference(child, _BCDAggrLoadList, LoadList);
224
handleLoadLastReference(child, _BCDConditionalCleanLoadList, ConditionalCleanLoadList);
225
}
226
}
227
228
bool InMemoryLoadStoreMarking::allListsAreEmpty()
229
{
230
if (_BCDAggrLoadList.isEmpty() &&
231
_BCDAggrStoreList.isEmpty() &&
232
_BCDConditionalCleanLoadList.isEmpty())
233
{
234
return true;
235
}
236
else
237
{
238
return false;
239
}
240
}
241
242
void InMemoryLoadStoreMarking::handleDef(TR::Node* node, TR::TreeTop* tt)
243
{
244
if (!allListsAreEmpty())
245
{
246
if (tt->isPossibleDef())
247
{
248
TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg->fe());
249
TR::Node *defNode = tt->getNode()->getOpCodeValue() == TR::treetop ? tt->getNode()->getFirstChild() : tt->getNode();
250
processBCDAggrNodeList(_BCDAggrLoadList, defNode, LoadList);
251
processBCDAggrNodeList(_BCDConditionalCleanLoadList, defNode, ConditionalCleanLoadList);
252
processBCDAggrNodeList(_BCDAggrStoreList, defNode, StoreList);
253
}
254
}
255
}
256
257
bool InMemoryLoadStoreMarking::isConditionalCleanLoad(TR::Node *listNode, TR::Node *defNode)
258
{
259
if (defNode->getOpCode().isBCDStore() &&
260
defNode->chkCleanSignInPDStoreEvaluator() &&
261
listNode->getOpCode().isBCDLoadVar() &&
262
defNode->getValueChild() == listNode &&
263
defNode->getDecimalPrecision() == listNode->getDecimalPrecision() &&
264
cg->loadOrStoreAddressesMatch(defNode, listNode))
265
{
266
//
267
// pdstore "a" clean
268
// pdload "a"
269
//
270
// =>pdload "a"
271
//
272
// In this case, if all the parents of pdload "a" do not rely on the sign being clean then this exact store from "a" to "a" does not
273
// have to be considered a kill and the skipCopyOnLoad flag can still be set.
274
// The listNode will be added to the _BCDConditionalCleanLoadList so all subsequent references have their parents checked (for not relying on the clean sign).
275
//
276
// The _BCDConditionalCleanLoadList also must be checked for other possible kills as with the regular _BCDAggrLoadList
277
// The caller is removing listNode from _BCDAggrLoadList so a particular listNode will only be in one of (or neither of) _BCDConditionalCleanLoadList and _BCDAggrLoadList
278
if (cg->traceBCDCodeGen())
279
traceMsg(comp(),"\t\tfound conditional clean listNode %s (%p) under %s (%p) : do not consider a def but add to condCleanLoadList if not already present\n",
280
listNode->getOpCode().getName(),listNode,defNode->getOpCode().getName(),defNode);
281
return true;
282
}
283
return false;
284
}
285
286
void InMemoryLoadStoreMarking::addToConditionalCleanLoadList(TR::Node *listNode)
287
{
288
if (_BCDConditionalCleanLoadList.find(listNode))
289
{
290
// This condition may be hit if the commoned load is present under two or more different stores to the same location that also clean:
291
// pdstore "a" clean
292
// pdload "a"
293
//
294
// pdstore "a" clean
295
// =>pdload "a" <-- will already be in list at this point
296
//
297
if (cg->traceBCDCodeGen())
298
traceMsg(comp(),"\t\tlistNode %s (%p) already present in condCleanLoadList : do not add again\n",
299
listNode->getOpCode().getName(),listNode);
300
}
301
else
302
{
303
if (cg->traceBCDCodeGen())
304
traceMsg(comp(),"\t\tlistNode %s (%p) not already present in condCleanLoadList : add to list\n",
305
listNode->getOpCode().getName(),listNode);
306
_BCDConditionalCleanLoadList.add(listNode);
307
}
308
}
309
310
void InMemoryLoadStoreMarking::processBCDAggrNodeList(List<TR::Node> &nodeList, TR::Node *defNode, TR_NodeListTypes listType)
311
{
312
if (!nodeList.isEmpty())
313
{
314
if (cg->traceBCDCodeGen())
315
traceMsg(comp(),"\titerate through non-empty %s\n",getName(listType));
316
bool isRegularLoadList = (listType == LoadList);
317
bool isConditionalCleanLoadList = (listType == ConditionalCleanLoadList);
318
bool isAnyTypeOfLoadList = (isRegularLoadList || isConditionalCleanLoadList);
319
ListIterator<TR::Node> listIt(&nodeList);
320
for (TR::Node *listNode=listIt.getFirst(); listNode; listNode = listIt.getNext())
321
{
322
TR_ASSERT((isAnyTypeOfLoadList && listNode->getOpCode().isBCDLoadVar()) || listNode->getOpCode().isBCDStore(),
323
"only bcd/aggr loadVars or stores should be in the list (%s (%p))\n",listNode->getOpCode().getName(),listNode);
324
if (isAnyTypeOfLoadList ||
325
listNode != defNode) // skip the current store treetop node
326
{
327
bool defNodeHasSymRef = defNode->getOpCode().hasSymbolReference() && defNode->getSymbolReference();
328
if (cg->traceBCDCodeGen())
329
traceMsg(comp(),"\t\tintersect defNode %s (%p) #%d aliases with listNode %s (%p) #%d\n",
330
defNode->getOpCode().getName(),defNode,defNodeHasSymRef ? defNode->getSymbolReference()->getReferenceNumber() : -1,
331
listNode->getOpCode().getName(),listNode,listNode->getSymbolReference()->getReferenceNumber());
332
333
if (!defNodeHasSymRef || defNode->getSymbolReference()->getUseDefAliases().contains(listNode->getSymbolReference(), comp()))
334
{
335
if (isAnyTypeOfLoadList)
336
{
337
// There are two possible list types (condClean and regular load list) that can reach here and two conditions (clean or not clean) so expressing 4 states as a table
338
//
339
// | _BCDConditionalCleanLoadList (cleanList) | _BCDAggrLoadList (regList)
340
//---------------------------|---------------------------------------------|---------------------------------
341
// isConditionalCleanLoad | 1) add listNode to cleanList | 1) add listNode to cleanList
342
// | | 2) remove listNode from regList
343
// --------------------------|---------------------------------------------|----------------------------------
344
// !isConditionalCleanLoad | 1) remove listNode from cleanList | 1) remove listNode from regList
345
//
346
347
// first check if we are able to place listNode in the conditional load list vs more conservatively just marking setSkipCopyOnLoad to false
348
if (isConditionalCleanLoad(listNode, defNode))
349
{
350
addToConditionalCleanLoadList(listNode);
351
if (isRegularLoadList)
352
{
353
if (cg->traceBCDCodeGen())
354
traceMsg(comp(),"\t\t\tremove listNode %s (%p) from regular load list\n",listNode->getOpCode().getName(),listNode);
355
nodeList.remove(listNode);
356
}
357
}
358
else
359
{
360
// this path may either be removing a load from the regular or conditional load list (in the latter case when some other type of def is possibly seen)
361
if (cg->traceBCDCodeGen())
362
traceMsg(comp(),"\t\t\tfound an intersection so remove listNode %s (%p) from %s and set setSkipCopyOnLoad flag to false (defNodeHasSymRef=%s)\n",
363
listNode->getOpCode().getName(),listNode,getName(listType),defNodeHasSymRef?"yes":"no");
364
listNode->setSkipCopyOnLoad(false);
365
nodeList.remove(listNode);
366
}
367
}
368
else
369
{
370
if (cg->traceBCDCodeGen())
371
traceMsg(comp(),"\t\t\tfound an intersection so remove listNode %s (%p) from %s and set setSkipCopyOnStore flag to false (defNodeHasSymRef=%s)\n",
372
listNode->getOpCode().getName(),listNode,getName(listType),defNodeHasSymRef?"yes":"no");
373
TR_ASSERT(listType == StoreList,"expecting StoreList for listNode %s (%p)\n",listNode->getOpCode().getName(),listNode);
374
listNode->setSkipCopyOnStore(false);
375
nodeList.remove(listNode);
376
}
377
}
378
}
379
else if (cg->traceBCDCodeGen())
380
{
381
traceMsg(comp(),"\t\tskipping current store treetop listNode %s (%p)\n",listNode->getOpCode().getName(),listNode);
382
}
383
}
384
}
385
}
386
387
void InMemoryLoadStoreMarking::clearAllLists()
388
{
389
clearLoadLists();
390
_BCDAggrStoreList.deleteAll();
391
}
392
393
void InMemoryLoadStoreMarking::clearLoadLists()
394
{
395
_BCDAggrLoadList.deleteAll();
396
_BCDConditionalCleanLoadList.deleteAll();
397
}
398
399
char *InMemoryLoadStoreMarking::_TR_NodeListTypeNames[NodeList_NumTypes] =
400
{
401
"LoadList",
402
"ConditionalCleanLoadList",
403
"StoreList"
404
};
405
406