Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/optimizer/IdiomRecognitionUtils.cpp
6000 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 "optimizer/IdiomRecognitionUtils.hpp"
24
25
#include <algorithm>
26
#include <stddef.h>
27
#include <stdint.h>
28
#include "codegen/CodeGenerator.hpp"
29
#include "env/FrontEnd.hpp"
30
#include "compile/Compilation.hpp"
31
#include "env/CompilerEnv.hpp"
32
#include "env/TRMemory.hpp"
33
#include "il/Block.hpp"
34
#include "il/DataTypes.hpp"
35
#include "il/ILOpCodes.hpp"
36
#include "il/ILOps.hpp"
37
#include "il/Node.hpp"
38
#include "il/Node_inlines.hpp"
39
#include "il/Symbol.hpp"
40
#include "il/SymbolReference.hpp"
41
#include "il/TreeTop.hpp"
42
#include "il/TreeTop_inlines.hpp"
43
#include "infra/Assert.hpp"
44
#include "infra/BitVector.hpp"
45
#include "infra/List.hpp"
46
#include "infra/TRCfgEdge.hpp"
47
#include "optimizer/IdiomRecognition.hpp"
48
#include "optimizer/Structure.hpp"
49
#include "optimizer/TranslateTable.hpp"
50
51
/************************************/
52
/************ Utilities *************/
53
/************************************/
54
void
55
dump256Bytes(uint8_t *t, TR::Compilation * comp)
56
{
57
int i;
58
traceMsg(comp, " | 0 1 2 3 4 5 6 7 8 9 A B C D E F\n");
59
traceMsg(comp, "--+--------------------------------");
60
for (i = 0; i < 256; i++)
61
{
62
if ((i % 16) == 0)
63
{
64
traceMsg(comp, "\n%02X|",i);
65
}
66
traceMsg(comp, "%2x",t[i]);
67
}
68
traceMsg(comp, "\n");
69
}
70
71
72
/******************************************************/
73
/************ Utilities for making idioms *************/
74
/******************************************************/
75
76
//*****************************************************************************************
77
// create the idiom for "v = src1 op val"
78
//*****************************************************************************************
79
TR_PCISCNode *
80
createIdiomIOP2VarInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, int opcode, TR_PCISCNode *v, TR_PCISCNode *src1, TR_PCISCNode *val)
81
{
82
TR_PCISCNode *n0, *n1;
83
TR_ASSERT(v->getOpcode() == TR_variable || v->getOpcode() == TR::iload, "Error!");
84
n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), opcode, v->getOpcode() == TR_variable ? TR::NoType : TR::Int32, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(n0);
85
n1 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::istore, TR::Int32, tgt->incNumNodes(), dagId, 1, 2, n0); tgt->addNode(n1);
86
n0->setChildren(src1, val);
87
n1->setChildren(n0, v->getOpcode() == TR::iload ? v->getChild(0) : v);
88
n0->setIsChildDirectlyConnected();
89
n1->setIsChildDirectlyConnected();
90
n0->setIsSuccDirectlyConnected();
91
return n1;
92
}
93
94
//*****************************************************************************************
95
// create the idiom for "v = v op val"
96
//*****************************************************************************************
97
TR_PCISCNode *
98
createIdiomIOP2VarInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, int opcode, TR_PCISCNode *v, TR_PCISCNode *val)
99
{
100
return createIdiomIOP2VarInLoop(tgt, ctrl, dagId, pred, opcode, v, v, val);
101
}
102
103
//*****************************************************************************************
104
// create the idiom for "v = src1 - val"
105
//*****************************************************************************************
106
TR_PCISCNode *
107
createIdiomDecVarInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *v, TR_PCISCNode *src1, TR_PCISCNode *subval)
108
{
109
return createIdiomIOP2VarInLoop(tgt, ctrl, dagId, pred, TR::isub, v, src1, subval);
110
}
111
112
//*****************************************************************************************
113
// create the idiom for "v = src1 + val"
114
//*****************************************************************************************
115
TR_PCISCNode *
116
createIdiomIncVarInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *v, TR_PCISCNode *src1, TR_PCISCNode *addval)
117
{
118
return createIdiomIOP2VarInLoop(tgt, ctrl, dagId, pred, TR::iadd, v, src1, addval);
119
}
120
121
//*****************************************************************************************
122
// create the idiom for "v = v - val"
123
//*****************************************************************************************
124
TR_PCISCNode *
125
createIdiomDecVarInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *v, TR_PCISCNode *subval)
126
{
127
return createIdiomDecVarInLoop(tgt, ctrl, dagId, pred, v, v, subval);
128
}
129
130
//*****************************************************************************************
131
// create the idiom for "v = v + val"
132
//*****************************************************************************************
133
TR_PCISCNode *
134
createIdiomIncVarInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *v, TR_PCISCNode *addval)
135
{
136
return createIdiomIncVarInLoop(tgt, ctrl, dagId, pred, v, v, addval);
137
}
138
139
//*****************************************************************************************
140
// create "iconst val" or "lconst val". Use lconst for a 64-bit environment
141
//*****************************************************************************************
142
TR_PCISCNode *
143
createIdiomArrayRelatedConst(TR_PCISCGraph *tgt, int32_t ctrl, uint16_t id, int dagId, int32_t val)
144
{
145
TR_PCISCNode *ret;
146
uint32_t opcode = (ctrl & CISCUtilCtl_64Bit) ? TR::lconst : TR::iconst;
147
ret = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), opcode, opcode == TR::lconst ? TR::Int64 : TR::Int32, id, dagId, 0, 0, val);
148
tgt->addNode(ret);
149
return ret;
150
}
151
152
153
//*****************************************************************************************
154
// create "iconst -sizeof(array header)" or "lconst -sizeof(array header)".
155
// Use lconst for a 64-bit environment.
156
//*****************************************************************************************
157
TR_PCISCNode *
158
createIdiomArrayHeaderConst(TR_PCISCGraph *tgt, int32_t ctrl, uint16_t id, int dagId, TR::Compilation *c)
159
{
160
return createIdiomArrayRelatedConst(tgt, ctrl, id, dagId, -(int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());
161
}
162
163
//*****************************************************************************************
164
// when the environment is under 64-bit, it'll insert "i2l" to the node.
165
//*****************************************************************************************
166
TR_PCISCNode *
167
createIdiomI2LIfNecessary(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode **pred, TR_PCISCNode *node)
168
{
169
TR_PCISCNode *ret = node;
170
if ((ctrl & (CISCUtilCtl_64Bit|CISCUtilCtl_NoI2L)) == (CISCUtilCtl_64Bit|0))
171
{
172
ret = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::i2l, TR::Int64, tgt->incNumNodes(), dagId, 1, 1, *pred, node); tgt->addNode(ret);
173
*pred = ret;
174
}
175
return ret;
176
}
177
178
#if 0
179
//*****************************************************************************************
180
// It creates an address tree of "index part" for a byte array. (e.g. index-header)
181
// It may insert I2L depending on the given flag.
182
//
183
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
184
//*****************************************************************************************
185
TR_PCISCNode *
186
createIdiomByteArrayAddressIndexTreeInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *index, TR_PCISCNode *cmah)
187
{
188
TR_PCISCNode *n0;
189
TR_PCISCNode *parentIndex;
190
if (ctrl & CISCUtilCtl_64Bit)
191
{
192
if (ctrl & CISCUtilCtl_NoI2L)
193
{
194
n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::lsub, TR::Int64, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(n0);
195
parentIndex = n0;
196
}
197
else
198
{
199
parentIndex = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::i2l, TR::Int64, tgt->incNumNodes(), dagId, 1, 1, pred); tgt->addNode(parentIndex);
200
n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::lsub, TR::Int64, tgt->incNumNodes(), dagId, 1, 2, parentIndex); tgt->addNode(n0);
201
n0->setChild(parentIndex);
202
n0->setIsChildDirectlyConnected();
203
}
204
}
205
else
206
{
207
n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::isub, TR::Int32, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(n0);
208
parentIndex = n0;
209
}
210
parentIndex->setChild(index);
211
if ((ctrl & CISCUtilCtl_ChildDirectConnected) || index->getOpcode() == TR_variable || index->getOpcode() == TR_arrayindex)
212
parentIndex->setIsChildDirectlyConnected();
213
n0->setChild(1, cmah);
214
return n0;
215
}
216
217
//*****************************************************************************************
218
// It creates an effective address tree for a byte array. (e.g. base+(index-header))
219
// It may insert I2L depending on the given flag.
220
//
221
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
222
//*****************************************************************************************
223
TR_PCISCNode *
224
createIdiomByteArrayAddressInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah)
225
{
226
TR_PCISCNode *n0, *n1;
227
228
n0 = createIdiomByteArrayAddressIndexTreeInLoop(tgt, ctrl, dagId, pred, index, cmah);
229
n1 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), (ctrl & CISCUtilCtl_64Bit) ? TR::aladd : TR::aiadd, TR::Address, tgt->incNumNodes(), dagId, 1, 2, n0); tgt->addNode(n1);
230
n1->setChildren(base, n0);
231
if (base->getOpcode() == TR_variable || base->getOpcode() == TR_arraybase)
232
n1->setIsChildDirectlyConnected();
233
return n1;
234
}
235
#endif
236
237
//*****************************************************************************************
238
// It creates an address tree of "index part" for a non-byte array. (e.g. index*4-header)
239
// It may insert I2L depending on the given flag.
240
//
241
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
242
//*****************************************************************************************
243
TR_PCISCNode *
244
createIdiomArrayAddressIndexTreeInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *index, TR_PCISCNode *cmah, TR_PCISCNode *constForMul)
245
{
246
TR_PCISCNode *n0, *mul;
247
if (ctrl & CISCUtilCtl_64Bit)
248
{
249
TR_PCISCNode *i2l;
250
if (ctrl & CISCUtilCtl_NoI2L)
251
{
252
mul = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::lmul, TR::Int64, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(mul);
253
i2l = mul;
254
}
255
else
256
{
257
i2l = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::i2l, TR::Int64, tgt->incNumNodes(), dagId, 1, 1, pred); tgt->addNode(i2l);
258
mul = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::lmul, TR::Int64, tgt->incNumNodes(), dagId, 1, 2, i2l); tgt->addNode(mul);
259
mul->setIsChildDirectlyConnected();
260
mul->setChild(i2l);
261
}
262
n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::lsub, TR::Int64, tgt->incNumNodes(), dagId, 1, 2, mul); tgt->addNode(n0);
263
i2l->setChild(index);
264
switch(index->getOpcode())
265
{
266
case TR_variable:
267
case TR_arrayindex:
268
i2l->setIsChildDirectlyConnected();
269
break;
270
}
271
n0->setIsChildDirectlyConnected();
272
}
273
else
274
{
275
mul = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::imul, TR::Int32, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(mul);
276
n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::isub, TR::Int32, tgt->incNumNodes(), dagId, 1, 2, mul); tgt->addNode(n0);
277
mul->setChild(index);
278
n0->setIsChildDirectlyConnected();
279
switch(index->getOpcode())
280
{
281
case TR_variable:
282
case TR_arrayindex:
283
mul->setIsChildDirectlyConnected();
284
break;
285
}
286
}
287
mul->setChild(1, constForMul);
288
n0->setChildren(mul, cmah);
289
return n0;
290
}
291
292
//*****************************************************************************************
293
// It creates an effective address tree for a non-byte array. (e.g. base+(index*4-header))
294
// It may insert I2L depending on the given flag.
295
//
296
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
297
//*****************************************************************************************
298
TR_PCISCNode *
299
createIdiomArrayAddressInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah, TR_PCISCNode *constForMul)
300
{
301
TR_PCISCNode *n0, *n1;
302
n0 = createIdiomArrayAddressIndexTreeInLoop(tgt, ctrl, dagId, pred, index, cmah, constForMul);
303
n1 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), (ctrl & CISCUtilCtl_64Bit) ? TR::aladd : TR::aiadd, TR::Address, tgt->incNumNodes(), dagId, 1, 2, n0); tgt->addNode(n1);
304
n1->setChildren(base, n0);
305
if (base->getOpcode() == TR_variable || base->getOpcode() == TR_arraybase)
306
n1->setIsChildDirectlyConnected();
307
return n1;
308
}
309
310
//*****************************************************************************************
311
// It creates an effective address tree for an array using the given index tree. (e.g. base+indexTree)
312
//
313
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
314
//*****************************************************************************************
315
TR_PCISCNode *
316
createIdiomArrayAddressInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *indexTree)
317
{
318
TR_PCISCNode *n1;
319
320
n1 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), (ctrl & CISCUtilCtl_64Bit) ? TR::aladd : TR::aiadd, TR::Address, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(n1);
321
n1->setChildren(base, indexTree);
322
return n1;
323
}
324
325
#if 0
326
//*****************************************************************************************
327
// It creates a byte array load.
328
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
329
//*****************************************************************************************
330
TR_PCISCNode *
331
createIdiomByteArrayLoadInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah)
332
{
333
TR_PCISCNode *n1, *n2;
334
n1 = createIdiomByteArrayAddressInLoop(tgt, ctrl, dagId, pred, base, index, cmah);
335
n2 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::bloadi, TR::Int8, tgt->incNumNodes(), dagId, 1, 1, n1); tgt->addNode(n2);
336
337
n2->setChild(n1);
338
n2->setIsChildDirectlyConnected();
339
return n2;
340
}
341
342
//*****************************************************************************************
343
// It creates a byte array store from the given address and storeval trees.
344
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
345
//*****************************************************************************************
346
TR_PCISCNode *
347
createIdiomByteArrayStoreBodyInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *addr, TR_PCISCNode *storeval)
348
{
349
TR_PCISCNode *n2, *i2b;
350
if (ctrl & CISCUtilCtl_NoConversion)
351
{
352
i2b = storeval;
353
}
354
else
355
{
356
i2b = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), (ctrl & CISCUtilCtl_AllConversion) ? TR_conversion : (TR_CISCOps)TR::i2b,
357
TR::Int8,
358
tgt->incNumNodes(), dagId, 1, 1, pred); tgt->addNode(i2b);
359
pred = i2b;
360
i2b->setChild(storeval);
361
}
362
363
n2 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::bstorei, TR::Int8, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(n2);
364
n2->setChildren(addr, i2b);
365
return n2;
366
}
367
368
//*****************************************************************************************
369
// It creates a byte array store from the given base, index, cmah, and storeval trees.
370
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
371
//*****************************************************************************************
372
TR_PCISCNode *
373
createIdiomByteArrayStoreInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah, TR_PCISCNode *storeval)
374
{
375
TR_PCISCNode *n1, *n2;
376
n1 = createIdiomByteArrayAddressInLoop(tgt, ctrl, dagId, pred, base, index, cmah);
377
n2 = createIdiomByteArrayStoreBodyInLoop(tgt, ctrl, dagId, n1, n1, storeval);
378
n2->setIsChildDirectlyConnected();
379
return n2;
380
}
381
#endif
382
383
//*****************************************************************************************
384
// It creates a char array load.
385
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
386
//*****************************************************************************************
387
TR_PCISCNode *
388
createIdiomCharArrayLoadInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah, TR_PCISCNode *const2)
389
{
390
return createIdiomArrayLoadInLoop(tgt, ctrl, dagId, pred, TR::sloadi, TR::Int16, base, index, cmah, const2);
391
}
392
393
//*****************************************************************************************
394
// It creates a non-byte array load.
395
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
396
//*****************************************************************************************
397
TR_PCISCNode *
398
createIdiomArrayLoadInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, int opcode, TR::DataType dataType, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah, TR_PCISCNode *mulconst)
399
{
400
TR_PCISCNode *n1, *n2;
401
n1 = createIdiomArrayAddressInLoop(tgt, ctrl, dagId, pred, base, index, cmah, mulconst);
402
n2 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), opcode, dataType, tgt->incNumNodes(), dagId, 1, 1, n1); tgt->addNode(n2);
403
404
n2->setChild(n1);
405
n2->setIsChildDirectlyConnected();
406
return n2;
407
}
408
409
//*****************************************************************************************
410
// It creates a non-byte array store from the given address and storeval trees.
411
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
412
//*****************************************************************************************
413
TR_PCISCNode *
414
createIdiomArrayStoreBodyInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, int opcode, TR::DataType dataType, TR_PCISCNode *addr, TR_PCISCNode *storeval)
415
{
416
TR_PCISCNode *n2, *i2c;
417
if (ctrl & CISCUtilCtl_NoConversion)
418
{
419
i2c = storeval;
420
}
421
else
422
{
423
i2c = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(),
424
(opcode == TR::sstorei) ? (TR_CISCOps)TR::i2s : TR_conversion,
425
(opcode == TR::sstorei) ? TR::Int16 : TR::NoType,
426
tgt->incNumNodes(), dagId, 1, 1, pred); tgt->addNode(i2c);
427
i2c->setIsOptionalNode();
428
pred = i2c;
429
i2c->setChild(storeval);
430
}
431
n2 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), opcode, dataType, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(n2);
432
n2->setChildren(addr, i2c);
433
return n2;
434
}
435
436
//*****************************************************************************************
437
// It creates a char array store from the given address and storeval trees.
438
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
439
//*****************************************************************************************
440
TR_PCISCNode *
441
createIdiomCharArrayStoreBodyInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *addr, TR_PCISCNode *storeval)
442
{
443
return createIdiomArrayStoreBodyInLoop(tgt, ctrl, dagId, pred, TR::sstorei, TR::Int16, addr, storeval);
444
}
445
446
//*****************************************************************************************
447
// It creates a char array store from the given base, index, cmah, and storeval trees.
448
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
449
//*****************************************************************************************
450
TR_PCISCNode *
451
createIdiomArrayStoreInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, int opcode, TR::DataType dataType, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah, TR_PCISCNode *const2, TR_PCISCNode *storeval)
452
{
453
TR_PCISCNode *n1, *n2;
454
n1 = createIdiomArrayAddressInLoop(tgt, ctrl, dagId, pred, base, index, cmah, const2);
455
n2 = createIdiomArrayStoreBodyInLoop(tgt, ctrl, dagId, n1, opcode, dataType, n1, storeval);
456
n2->setIsChildDirectlyConnected();
457
return n2;
458
}
459
460
//*****************************************************************************************
461
// It creates a char array store from the given base, index, cmah, and storeval trees.
462
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
463
//*****************************************************************************************
464
TR_PCISCNode *
465
createIdiomCharArrayStoreInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah, TR_PCISCNode *const2, TR_PCISCNode *storeval)
466
{
467
return createIdiomArrayStoreInLoop(tgt, ctrl, dagId, pred, TR::sstorei, TR::Int16, base, index, cmah, const2, storeval);
468
}
469
470
//*****************************************************************************************
471
// It creates a byte array load particularly for "sun/io/CharToByteSingleByte.JITintrinsicConvert".
472
// The base address is given via java.nio.DirectByteBuffer.
473
//
474
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
475
//*****************************************************************************************
476
TR_PCISCNode *
477
createIdiomByteDirectArrayLoadInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *index)
478
{
479
TR_PCISCNode *n2;
480
TR_PCISCNode *n0;
481
TR_PCISCNode *parentIndex;
482
if (ctrl & CISCUtilCtl_64Bit)
483
{
484
if (ctrl & CISCUtilCtl_NoI2L)
485
{
486
n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::ladd, TR::Int64, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(n0);
487
parentIndex = n0;
488
}
489
else
490
{
491
parentIndex = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::i2l, TR::Int64, tgt->incNumNodes(), dagId, 1, 1, pred); tgt->addNode(parentIndex);
492
n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::ladd, TR::Int64, tgt->incNumNodes(), dagId, 1, 2, parentIndex); tgt->addNode(n0);
493
n0->setChild(parentIndex);
494
n0->setIsChildDirectlyConnected();
495
}
496
parentIndex->setChild(index);
497
if ((ctrl & CISCUtilCtl_ChildDirectConnected) || index->getOpcode() == TR_variable || index->getOpcode() == TR_arrayindex)
498
parentIndex->setIsChildDirectlyConnected();
499
}
500
else
501
{
502
parentIndex = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::l2i, TR::Int32, tgt->incNumNodes(), dagId, 1, 1, pred); tgt->addNode(parentIndex);
503
parentIndex->setChild(base);
504
parentIndex->setIsChildDirectlyConnected();
505
base = parentIndex;
506
n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::iadd, TR::Int32, tgt->incNumNodes(), dagId, 1, 2, parentIndex); tgt->addNode(n0);
507
n0->setChild(index);
508
if ((ctrl & CISCUtilCtl_ChildDirectConnected) || index->getOpcode() == TR_variable || index->getOpcode() == TR_arrayindex)
509
n0->setIsChildDirectlyConnected();
510
}
511
n0->setChild(1, base);
512
n2 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::bloadi, TR::Int8, tgt->incNumNodes(), dagId, 1, 1, n0); tgt->addNode(n2);
513
514
n2->setChild(n0);
515
n2->setIsChildDirectlyConnected();
516
return n2;
517
}
518
519
//*****************************************************************************************
520
// It creates the idiom for "divide by 10" or the corresponding multiplication idiom
521
// based on the given flag.
522
//
523
// "InLoop" means that it sets the given dagId to all nodes in this subroutine.
524
//*****************************************************************************************
525
TR_PCISCNode *
526
createIdiomIDiv10InLoop(TR_PCISCGraph *tgt, int32_t ctrl, bool isDiv2Mul, int dagId, TR_PCISCNode *pred, TR_PCISCNode *src1, TR_PCISCNode *src2, TR_PCISCNode *c2, TR_PCISCNode *c31)
527
{
528
TR_PCISCNode *ret;
529
if (isDiv2Mul)
530
{
531
TR_PCISCNode *nmul= new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::imulh, TR::Int32 ,tgt->incNumNodes(), 1, 1, 2, pred, src1, src2); tgt->addNode(nmul);
532
TR_PCISCNode *nshr= new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::ishr, TR::Int32 ,tgt->incNumNodes(), 1, 1, 2, nmul, nmul, c2); tgt->addNode(nshr);
533
TR_PCISCNode *ushr= new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::iushr, TR::Int32 ,tgt->incNumNodes(), 1, 1, 2, nshr, src1, c31); tgt->addNode(ushr); // optional
534
ret = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::iadd, TR::Int32 ,tgt->incNumNodes(), 1, 1, 2, ushr, nshr, ushr); tgt->addNode(ret); // optional
535
ushr->setIsOptionalNode();
536
ushr->setSkipParentsCheck();
537
ret->setIsOptionalNode();
538
}
539
else
540
{
541
ret = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::idiv, TR::Int32 ,tgt->incNumNodes(), 1, 1, 2, pred, src1, src2); tgt->addNode(ret);
542
}
543
return ret;
544
}
545
546
547
//*****************************************************************************************
548
// Search the node "target" starting from "start" within this basic block
549
//*****************************************************************************************
550
bool
551
searchNodeInBlock(TR_CISCNode *start,
552
TR_CISCNode *target)
553
{
554
TR_CISCNode *t = start;
555
556
while (t->getNumSuccs() == 1 && t->getPreds()->isSingleton())
557
{
558
if (t == target) return true;
559
t = t->getSucc(0);
560
if (t == start) break; // maybe, this condition never happen.
561
}
562
563
return false;
564
}
565
566
567
//*****************************************************************************************
568
// Check if all successors of t will reach any node included in pBV.
569
//*****************************************************************************************
570
bool
571
checkSuccsSet(TR_CISCTransformer *const trans,
572
TR_CISCNode *t,
573
TR_BitVector *const pBV)
574
{
575
List<TR_CISCNode> *T2P = trans->getT2P();
576
TR_CISCNode *p;
577
578
while (t->getNumSuccs() == 1)
579
{
580
t = t->getSucc(0);
581
if (!t->isNegligible())
582
{
583
ListIterator<TR_CISCNode> li(T2P + t->getID());
584
for (p = li.getFirst(); p; p = li.getNext()) if (pBV->isSet(p->getID())) return true; // found the pattern node in pBV
585
return false; // cannot find the pattern node.
586
}
587
}
588
589
for (int i = t->getNumSuccs(); --i >= 0; )
590
{
591
TR_CISCNode *tn = t->getSucc(i);
592
if (!tn->isNegligible())
593
{
594
ListIterator<TR_CISCNode> li(T2P + tn->getID());
595
for (p = li.getFirst(); p; p = li.getNext()) if (pBV->isSet(p->getID())) break; // found the pattern node in pBV
596
if (!p) return false; // cannot find the pattern node.
597
}
598
else
599
{
600
if (!checkSuccsSet(trans, tn, pBV)) return false;
601
}
602
}
603
return true;
604
}
605
606
607
//*****************************************************************************************
608
// It searches an iload in the tree "q", and it returns the iload
609
//*****************************************************************************************
610
static TR_CISCNode *
611
searchIload(TR_CISCNode *q, bool allowArrayIndex)
612
{
613
while(true)
614
{
615
bool fail = false;
616
if (q->getOpcode() == TR::i2l)
617
{
618
q = q->getChild(0); // allow only TR::iload or TR_variable
619
fail = true;
620
}
621
if (q->getOpcode() == TR::iload || q->getOpcode() == TR_variable) return q;
622
if (allowArrayIndex && q->getOpcode() == TR_arrayindex) return q;
623
if (fail || q->getOpcode() == TR::lload || q->getNumChildren() < 1) return 0;
624
q = q->getChild(0);
625
}
626
return 0;
627
}
628
629
630
//*****************************************************************************************
631
// It searches an array load in the tree "top", and it returns the type of an array load,
632
// a base variable, and an index variable.
633
//*****************************************************************************************
634
bool
635
getThreeNodesForArray(TR_CISCNode *top, TR_CISCNode **ixloadORstore, TR_CISCNode **aload, TR_CISCNode **iload, bool allowArrayIndex)
636
{
637
TR_CISCNode *p;
638
639
// search ixloadORstore
640
p = top;
641
while(true)
642
{
643
if (p->getNumChildren() == 0) return false;
644
if (p->getIlOpCode().isLoadIndirect() || p->getIlOpCode().isStoreIndirect() ||
645
p->getOpcode() == TR_inbload || p->getOpcode() == TR_inbstore ||
646
p->getOpcode() == TR_indload || p->getOpcode() == TR_indstore ||
647
p->getOpcode() == TR_ibcload || p->getOpcode() == TR_ibcstore)
648
{
649
*ixloadORstore = p;
650
break;
651
}
652
p = p->getChild(0);
653
}
654
655
p = p->getChild(0);
656
657
TR_CISCNode *q;
658
switch(p->getOpcode())
659
{
660
case TR::aladd:
661
case TR::aiadd:
662
// search aload
663
q = p->getChild(0);
664
while(true)
665
{
666
if (q->getOpcode() == TR::aload || q->getOpcode() == TR_variable || q->getOpcode() == TR_arraybase)
667
{
668
*aload = q;
669
break;
670
}
671
if (q->getNumChildren() != 1) return false;
672
q = q->getChild(0);
673
}
674
675
// search iload
676
if ((q = searchIload(p->getChild(1), allowArrayIndex)) == 0) return false;
677
*iload = q;
678
break;
679
680
case TR::ladd:
681
case TR::iadd:
682
// search iload
683
if ((q = searchIload(p->getChild(1), allowArrayIndex)))
684
{
685
*iload = q;
686
q = p->getChild(0);
687
}
688
else if ((q = searchIload(p->getChild(0), allowArrayIndex)))
689
{
690
*iload = q;
691
q = p->getChild(1);
692
}
693
else
694
{
695
return false;
696
}
697
698
// search aload
699
while(true)
700
{
701
if (q->getOpcode() == TR::lload || q->getOpcode() == TR_variable)
702
{
703
*aload = q;
704
break;
705
}
706
if (q->getOpcode() == TR::iload || q->getNumChildren() != 1) return false;
707
q = q->getChild(0);
708
}
709
break;
710
711
default:
712
return false;
713
}
714
return true;
715
}
716
717
718
//*****************************************************************************************
719
// It returns isDcrement and modification length by analyzing if-opcode
720
//*****************************************************************************************
721
bool
722
testExitIF(int opcode, bool *isDecrement, int32_t *modLength, int32_t *modStartIdx)
723
{
724
switch(opcode)
725
{
726
case TR::ificmplt:
727
if (isDecrement) *isDecrement = true;
728
if (modLength) *modLength = 1;
729
if (modStartIdx) *modStartIdx = 0;
730
return true;
731
case TR::ificmple:
732
if (isDecrement) *isDecrement = true;
733
if (modLength) *modLength = 0;
734
if (modStartIdx) *modStartIdx = 1;
735
return true;
736
case TR::ificmpgt:
737
if (isDecrement) *isDecrement = false;
738
if (modLength) *modLength = 1;
739
if (modStartIdx) *modStartIdx = 0;
740
return true;
741
case TR::ificmpge:
742
if (isDecrement) *isDecrement = false;
743
if (modLength) *modLength = 0;
744
if (modStartIdx) *modStartIdx = 0;
745
return true;
746
}
747
return false;
748
}
749
750
751
/********************************************************************/
752
/************ Utilities for analyzing or making TR::Node *************/
753
/********************************************************************/
754
755
//*****************************************************************************************
756
// It returns the n'th child is "iconst value".
757
//*****************************************************************************************
758
bool
759
testIConst(TR_CISCNode *n, int idx, int32_t value)
760
{
761
TR_CISCNode *ch = n->getChild(idx);
762
return (ch->getOpcode() == TR::iconst && ch->getOtherInfo() == value);
763
}
764
765
766
//*****************************************************************************************
767
// It inserts i2l based on the given flag.
768
//*****************************************************************************************
769
TR::Node*
770
createI2LIfNecessary(TR::Compilation *comp, bool is64bit, TR::Node *child)
771
{
772
return is64bit ? TR::Node::create(TR::i2l, 1, child) : child;
773
}
774
775
776
//*****************************************************************************************
777
// It converts from store to load.
778
//*****************************************************************************************
779
TR::Node*
780
createLoad(TR::Node *baseNode)
781
{
782
return baseNode->getOpCode().isStoreDirect() ? TR::Node::createLoad(baseNode, baseNode->getSymbolReference()) :
783
baseNode->duplicateTree();
784
}
785
786
787
//*****************************************************************************************
788
// It creates a load instruction, and it inserts i2l based on the given flag.
789
//*****************************************************************************************
790
TR::Node*
791
createLoadWithI2LIfNecessary(TR::Compilation *comp, bool is64bit, TR::Node *indexNode)
792
{
793
TR_ASSERT(indexNode->getOpCode().hasSymbolReference(), "parameter error");
794
TR::Node *iload = createLoad(indexNode);
795
return createI2LIfNecessary(comp, is64bit, iload);
796
}
797
798
799
//*****************************************************************************************
800
// It creates a node of the constant value of the array header size.
801
//*****************************************************************************************
802
TR::Node*
803
createArrayHeaderConst(TR::Compilation *comp, bool is64bit, TR::Node *baseNode)
804
{
805
TR::Node *c2;
806
if (is64bit)
807
{
808
c2 = TR::Node::create(baseNode, TR::lconst, 0);
809
c2->setLongInt(-(int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());
810
}
811
else
812
{
813
c2 = TR::Node::create(baseNode, TR::iconst, 0, -(int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());
814
}
815
return c2;
816
}
817
818
819
//*****************************************************************************************
820
// It creates an effective address tree for the top of the given array.
821
//*****************************************************************************************
822
TR::Node*
823
createArrayTopAddressTree(TR::Compilation *comp, bool is64bit, TR::Node *baseNode)
824
{
825
TR::Node *top, *c2;
826
TR::Node *aload = createLoad(baseNode);
827
if (is64bit)
828
{
829
top = TR::Node::create(baseNode, TR::aladd, 2);
830
c2 = TR::Node::create(baseNode, TR::lconst, 0);
831
c2->setLongInt((int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());
832
}
833
else
834
{
835
top = TR::Node::create(baseNode, TR::aiadd, 2);
836
c2 = TR::Node::create(baseNode, TR::iconst, 0, (int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());
837
}
838
top->setAndIncChild(0, aload);
839
top->setAndIncChild(1, c2);
840
return top;
841
}
842
843
844
//*****************************************************************************************
845
// It converts from store to load, and it inserts i2l based on the given flag.
846
//*****************************************************************************************
847
TR::Node*
848
convertStoreToLoadWithI2LIfNecessary(TR::Compilation *comp, bool is64bit, TR::Node *indexNode)
849
{
850
return (indexNode->getOpCode().isStoreDirect()) ?
851
createLoadWithI2LIfNecessary(comp, is64bit, indexNode) :
852
createI2LIfNecessary(comp, is64bit, indexNode->getReferenceCount() ?
853
indexNode->duplicateTree() : indexNode);
854
}
855
856
857
//*****************************************************************************************
858
// It converts from store to load.
859
//*****************************************************************************************
860
TR::Node*
861
convertStoreToLoad(TR::Compilation *comp, TR::Node *indexNode)
862
{
863
return (indexNode->getOpCode().isStoreDirect()) ?
864
TR::Node::createLoad(indexNode, indexNode->getSymbolReference()) :
865
indexNode->getReferenceCount() ? indexNode->duplicateTree() : indexNode;
866
}
867
868
869
//*****************************************************************************************
870
// It creates the byte size from an element size. (i.e. ret = index * multiply)
871
//*****************************************************************************************
872
TR::Node*
873
createBytesFromElement(TR::Compilation *comp, bool is64bit, TR::Node *indexNode, int multiply)
874
{
875
TR::Node *top, *c2;
876
top = convertStoreToLoadWithI2LIfNecessary(comp, is64bit, indexNode);
877
878
if (is64bit)
879
{
880
if (multiply > 1)
881
{
882
c2 = TR::Node::create(indexNode, TR::lconst, 0); // c2 is used temporary
883
c2->setLongInt(multiply);
884
top = TR::Node::create(TR::lmul, 2, top, c2);
885
}
886
}
887
else
888
{
889
if (multiply > 1)
890
{
891
c2 = TR::Node::create(indexNode, TR::iconst, 0, multiply); // c2 is used temporary
892
top = TR::Node::create(TR::imul, 2, top, c2);
893
}
894
}
895
return top;
896
}
897
898
899
//*****************************************************************************************
900
// It creates an index address tree for the given indexNode and size.
901
//*****************************************************************************************
902
TR::Node*
903
createIndexOffsetTree(TR::Compilation *comp, bool is64bit, TR::Node *indexNode, int multiply)
904
{
905
TR::Node *top, *c1, *c2;
906
c1 = createBytesFromElement(comp, is64bit, indexNode, multiply);
907
908
if (is64bit)
909
{
910
c2 = TR::Node::create(indexNode, TR::lconst, 0);
911
c2->setLongInt(-(int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());
912
top = TR::Node::create(indexNode, TR::lsub, 2);
913
}
914
else
915
{
916
c2 = TR::Node::create(indexNode, TR::iconst, 0, -(int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());
917
top = TR::Node::create(indexNode, TR::isub, 2);
918
}
919
top->setAndIncChild(0, c1);
920
top->setAndIncChild(1, c2);
921
return top;
922
}
923
924
925
//*****************************************************************************************
926
// It creates an effective address tree for the given baseNode, indexNode and size.
927
//*****************************************************************************************
928
TR::Node*
929
createArrayAddressTree(TR::Compilation *comp, bool is64bit, TR::Node *baseNode, TR::Node *indexNode, int multiply)
930
{
931
if (indexNode->getOpCodeValue() == TR::iconst && indexNode->getInt() == 0)
932
{
933
return createArrayTopAddressTree(comp, is64bit, baseNode);
934
}
935
else
936
{
937
TR::Node *top, *c2;
938
TR::Node *aload = createLoad(baseNode);
939
c2 = createIndexOffsetTree(comp, is64bit, indexNode, multiply);
940
top = TR::Node::create(baseNode, is64bit ? TR::aladd : TR::aiadd, 2);
941
top->setAndIncChild(0, aload);
942
top->setAndIncChild(1, c2);
943
return top;
944
}
945
}
946
947
948
//*****************************************************************************************
949
// It creates an array load tree for the given load type, baseNode, indexNode and size.
950
//*****************************************************************************************
951
TR::Node*
952
createArrayLoad(TR::Compilation *comp, bool is64bit, TR::Node *ixload, TR::Node *baseNode, TR::Node *indexNode, int multiply)
953
{
954
TR::Node *top, *c1;
955
956
if (comp->useCompressedPointers() &&
957
(ixload->getDataType() == TR::Address))
958
multiply = multiply >> 1;
959
960
c1 = createArrayAddressTree(comp, is64bit, baseNode, indexNode, multiply);
961
TR::SymbolReference *symref=ixload->getSymbolReference();
962
top = TR::Node::createWithSymRef(ixload, ixload->getOpCodeValue(), 1, symref);
963
top->setAndIncChild(0, c1);
964
return top;
965
}
966
967
968
//*****************************************************************************************
969
// It replaces the array index in the address tree.
970
//*****************************************************************************************
971
TR::Node *
972
replaceIndexInAddressTree(TR::Compilation *comp, TR::Node *tree, TR::SymbolReference *symRef, TR::Node *newNode)
973
{
974
TR::Node *orgTree = tree;
975
if (tree->getOpCode().isIndirect()) tree = tree->getChild(0);
976
if (tree->getOpCode().isAdd())
977
{
978
tree = tree->getChild(1);
979
while(true)
980
{
981
TR::Node *parent = tree;
982
if (tree->getOpCodeValue() == TR::iadd)
983
{
984
TR::Node *ch1 = tree->getChild(1);
985
if (ch1->getOpCodeValue() == TR::iload)
986
{
987
if (ch1->getSymbolReference() == symRef)
988
{
989
parent->getAndDecChild(1);
990
parent->setAndIncChild(1, newNode);
991
return orgTree;
992
}
993
}
994
}
995
996
tree = tree->getChild(0);
997
if (!tree) break;
998
if (tree->getOpCodeValue() == TR::iload)
999
{
1000
if (tree->getSymbolReference() == symRef)
1001
{
1002
parent->getAndDecChild(0);
1003
parent->setAndIncChild(0, newNode);
1004
return orgTree;
1005
}
1006
else
1007
{
1008
return NULL;
1009
}
1010
}
1011
}
1012
}
1013
return NULL;
1014
}
1015
1016
//*****************************************************************************************
1017
// It modifies the array header constant in the given tree
1018
//*****************************************************************************************
1019
TR::Node *
1020
modifyArrayHeaderConst(TR::Compilation *comp, TR::Node *tree, int32_t offset)
1021
{
1022
if (offset == 0) return tree;
1023
if (!tree->getOpCode().isAdd()) tree = tree->getFirstChild();
1024
if (tree->getOpCodeValue() == TR::aiadd || tree->getOpCodeValue() == TR::aladd)
1025
{
1026
TR::Node *addOrSubNode = tree->getSecondChild();
1027
TR::Node *constLoad = addOrSubNode->getSecondChild();
1028
if (addOrSubNode->getOpCode().isSub())
1029
{
1030
offset = -offset;
1031
}
1032
else if (!addOrSubNode->getOpCode().isAdd())
1033
{
1034
return NULL; // failed
1035
}
1036
switch(constLoad->getOpCodeValue())
1037
{
1038
case TR::iconst:
1039
constLoad->setInt(constLoad->getInt() + offset);
1040
return constLoad;
1041
break;
1042
case TR::lconst:
1043
constLoad->setLongInt(constLoad->getLongInt() + offset);
1044
return constLoad;
1045
break;
1046
default:
1047
return NULL;
1048
}
1049
}
1050
return NULL;
1051
}
1052
1053
//*****************************************************************************************
1054
// It creates a table load node especially for function tables for TRT or TRxx
1055
//*****************************************************************************************
1056
TR::Node*
1057
createTableLoad(TR::Compilation *comp, TR::Node* repNode, uint8_t inputSize, uint8_t outputSize, void *array, bool dispTrace)
1058
{
1059
TR_SetTranslateTable setTable(comp, inputSize, outputSize, array,
1060
TR_TranslateTable::tableSize(inputSize, outputSize));
1061
TR::SymbolReference *tableSymRef = setTable.createSymbolRef();
1062
if (dispTrace)
1063
setTable.dumpTable();
1064
return TR::Node::createWithSymRef(repNode, TR::loadaddr, 0, tableSymRef);
1065
}
1066
1067
//*****************************************************************************************
1068
// It basically creates "ch1 op2 ch2", but it performs a simple constant folding.
1069
//*****************************************************************************************
1070
TR::Node*
1071
createOP2(TR::Compilation *comp, TR::ILOpCodes op2, TR::Node* ch1, TR::Node* ch2)
1072
{
1073
TR::Node* op2Node;
1074
bool done = false;
1075
if (ch2->getOpCodeValue() == TR::iconst)
1076
{
1077
int value = ch2->getInt();
1078
int32_t newVal;
1079
switch(op2)
1080
{
1081
case TR::iadd:
1082
case TR::isub:
1083
if (value == 0)
1084
{
1085
op2Node = ch1;
1086
done = true;
1087
}
1088
else if (ch1->getOpCodeValue() == TR::iconst)
1089
{
1090
newVal = (op2 == TR::iadd) ? (ch1->getInt() + ch2->getInt()) :
1091
(ch1->getInt() - ch2->getInt());
1092
op2Node = TR::Node::create(ch1, TR::iconst, 0, newVal);
1093
done = true;
1094
}
1095
break;
1096
case TR::imul:
1097
case TR::idiv:
1098
if (value == 1)
1099
{
1100
op2Node = ch1;
1101
done = true;
1102
}
1103
else if (ch1->getOpCodeValue() == TR::iconst)
1104
{
1105
if (ch2->getInt() == 0 && op2 == TR::idiv)
1106
break; // divide by 0
1107
newVal = (op2 == TR::imul) ? (ch1->getInt() * ch2->getInt()) :
1108
(ch1->getInt() / ch2->getInt());
1109
op2Node = TR::Node::create(ch1, TR::iconst, 0, newVal);
1110
done = true;
1111
}
1112
break;
1113
default:
1114
break;
1115
}
1116
}
1117
if (!done) op2Node = TR::Node::create(op2, 2, ch1, ch2);
1118
return op2Node;
1119
}
1120
1121
//*****************************************************************************************
1122
// It creates like the following tree "storeNode = ch1 op2 ch2"
1123
//*****************************************************************************************
1124
TR::Node*
1125
createStoreOP2(TR::Compilation *comp, TR::Node* storeNode, TR::ILOpCodes op2, TR::Node* ch1, TR::Node* ch2)
1126
{
1127
TR::Node* op2Node = createOP2(comp, op2, ch1, ch2);
1128
storeNode->setAndIncChild(0, op2Node);
1129
return storeNode;
1130
}
1131
1132
//*****************************************************************************************
1133
// It creates like the following tree "storeNode = ch1 op2 ch2" from the given symbol references.
1134
//*****************************************************************************************
1135
TR::Node*
1136
createStoreOP2(TR::Compilation *comp, TR::SymbolReference* store, TR::ILOpCodes op2, TR::SymbolReference* ch1, TR::Node* ch2, TR::Node *rep)
1137
{
1138
return createStoreOP2(comp,
1139
TR::Node::createWithSymRef(rep, comp->il.opCodeForDirectStore(store->getSymbol()->getDataType()), 1, store),
1140
op2,
1141
TR::Node::createWithSymRef(rep, comp->il.opCodeForDirectLoad(ch1->getSymbol()->getDataType()), 0, ch1),
1142
ch2);
1143
}
1144
1145
//*****************************************************************************************
1146
// It creates like the following tree "storeNode = ch1 op2 ch2" from the given symbol references.
1147
//*****************************************************************************************
1148
TR::Node*
1149
createStoreOP2(TR::Compilation *comp, TR::SymbolReference* store, TR::ILOpCodes op2, TR::SymbolReference* ch1, TR::SymbolReference* ch2, TR::Node *rep)
1150
{
1151
return createStoreOP2(comp, store, op2, ch1,
1152
TR::Node::createWithSymRef(rep, comp->il.opCodeForDirectLoad(ch2->getSymbol()->getDataType()), 0, ch2),
1153
rep);
1154
}
1155
1156
//*****************************************************************************************
1157
// It creates like the following tree "storeNode = ch1 op2 ch2" from the given symbol
1158
// references and constant value.
1159
//*****************************************************************************************
1160
TR::Node*
1161
createStoreOP2(TR::Compilation *comp, TR::SymbolReference* store, TR::ILOpCodes op2, TR::SymbolReference* ch1, int ch2Const, TR::Node *rep)
1162
{
1163
return createStoreOP2(comp, store, op2, ch1,
1164
TR::Node::create( rep, TR::iconst, 0, ch2Const),
1165
rep);
1166
}
1167
1168
1169
//*****************************************************************************************
1170
// It creates "min(x, y)", whose tree is x+(((y-x)>>31)&(y-x)).
1171
//*****************************************************************************************
1172
TR::Node*
1173
createMin(TR::Compilation *comp, TR::Node* x, TR::Node* y)
1174
{
1175
if (x->getOpCodeValue() == TR::iconst &&
1176
y->getOpCodeValue() == TR::iconst)
1177
{
1178
return TR::Node::create(x, TR::iconst, 0, std::min(x->getInt(), y->getInt()));
1179
}
1180
else
1181
{
1182
TR::Node *y_x = TR::Node::create(TR::isub, 2, y, x); // y-x
1183
TR::Node *shift = TR::Node::create(TR::ishr, 2, y_x,
1184
TR::Node::create(y_x, TR::iconst, 0, 31)); // y_x >> 31
1185
TR::Node *andop = TR::Node::create(TR::iand, 2, shift, y_x); // shift & y_x
1186
TR::Node *ret = TR::Node::create(TR::iadd, 2, x, andop); // x + andop
1187
return ret;
1188
}
1189
}
1190
1191
1192
//*****************************************************************************************
1193
// It creates "max(x, y)", whose tree is x-(((x-y)>>31)&(x-y)).
1194
//*****************************************************************************************
1195
TR::Node*
1196
createMax(TR::Compilation *comp, TR::Node* x, TR::Node* y)
1197
{
1198
if (x->getOpCodeValue() == TR::iconst &&
1199
y->getOpCodeValue() == TR::iconst)
1200
{
1201
return TR::Node::create(x, TR::iconst, 0, std::max(x->getInt(), y->getInt()));
1202
}
1203
else
1204
{
1205
TR::Node *x_y = TR::Node::create(TR::isub, 2, x, y); // x-y
1206
TR::Node *shift = TR::Node::create(TR::ishr, 2, x_y,
1207
TR::Node::create(x_y, TR::iconst, 0, 31)); // x_y >> 31
1208
TR::Node *andop = TR::Node::create(TR::iand, 2, shift, x_y); // shift & x_y
1209
TR::Node *ret = TR::Node::create(TR::isub, 2, x, andop); // x - andop
1210
return ret;
1211
}
1212
}
1213
1214
1215
//*****************************************************************************************
1216
// It will return a constant load in the target graph corresponding to the pattern node mulConst.
1217
// If mulConst is NULL, *elementSize will be set to 1.
1218
// Otherwise, *elementSize will be set to the value of the constant, and *multiplier will be set
1219
// to that TR::Node.
1220
//*****************************************************************************************
1221
bool
1222
getMultiplier(TR_CISCTransformer *trans, TR_CISCNode *mulConst, TR::Node **multiplier, int *elementSize, TR::DataType srcNodeType)
1223
{
1224
TR::Node *mulFactorNode = 0;
1225
if (mulConst)
1226
{
1227
TR_CISCNode *mulConstT = trans->getP2TRep(mulConst);
1228
if (!mulConstT->isNewCISCNode())
1229
mulFactorNode = mulConstT->getHeadOfTrNodeInfo()->_node;
1230
}
1231
if (mulFactorNode)
1232
{
1233
TR_ASSERT(mulFactorNode->getOpCode().isLoadConst(), "error!");
1234
switch(mulFactorNode->getOpCodeValue())
1235
{
1236
case TR::iconst:
1237
*elementSize = mulFactorNode->getInt();
1238
*multiplier = mulFactorNode;
1239
return true;
1240
case TR::lconst:
1241
*elementSize = (int)mulFactorNode->getLongInt();
1242
*multiplier = mulFactorNode;
1243
return true;
1244
default:
1245
TR_ASSERT(false, "error!");
1246
return false;
1247
}
1248
}
1249
else
1250
{
1251
*multiplier = NULL;
1252
*elementSize = 1;
1253
}
1254
return true;
1255
}
1256
1257
1258
//*****************************************************************************************
1259
// It will get each representative target node using P2T table for each pattern node.
1260
// The number of pattern nodes is given by "count".
1261
// The result (several TR::Nodes) is set to "array".
1262
//*****************************************************************************************
1263
void
1264
getP2TTrRepNodes(TR_CISCTransformer *trans, TR::Node** array, int count)
1265
{
1266
TR_CISCGraph *P = trans->getP();
1267
ListIterator<TR_CISCNode> pi(P->getOrderByData());
1268
TR_CISCNode *pn;
1269
int index = 0;
1270
for (pn = pi.getFirst(); pn && index < count; pn = pi.getNext(), index++)
1271
{
1272
TR_CISCNode *tn = trans->getP2TRepInLoop(pn);
1273
if (!tn) tn = trans->getP2TRep(pn);
1274
TR::Node *candidate = NULL;
1275
if (tn)
1276
{
1277
ListIterator<TrNodeInfo> li(tn->getTrNodeInfo());
1278
candidate = tn->getHeadOfTrNodeInfo()->_node;
1279
TrNodeInfo *p;
1280
for (p = li.getFirst(); p; p = li.getNext())
1281
{
1282
if (!p->_node->getOpCode().isStoreDirect())
1283
{
1284
candidate = p->_node;
1285
break;
1286
}
1287
}
1288
if (candidate->getOpCode().isStoreDirect())
1289
{
1290
ListIterator<TR_CISCNode> pi(tn->getParents());
1291
TR_CISCNode *p;
1292
bool noLoad = true;
1293
for (p = pi.getFirst(); p; p = pi.getNext())
1294
{
1295
if (p->isLoadVarDirect()) noLoad = false;
1296
}
1297
if (noLoad)
1298
{
1299
for (p = pi.getFirst(); p; p = pi.getNext())
1300
{
1301
if (!p->isOutsideOfLoop() &&
1302
p->isStoreDirect() &&
1303
p->isNegligible())
1304
{
1305
trans->getBeforeInsertionList()->add(candidate->duplicateTree());
1306
break;
1307
}
1308
}
1309
}
1310
}
1311
}
1312
array[index] = candidate;
1313
}
1314
}
1315
1316
//*****************************************************************************************
1317
// Get first two representative target nodes.
1318
//*****************************************************************************************
1319
void
1320
getP2TTrRepNodes(TR_CISCTransformer *trans, TR::Node** n1, TR::Node** n2)
1321
{
1322
TR::Node* array[2];
1323
getP2TTrRepNodes(trans, array, 2);
1324
if (n1) *n1 = array[0];
1325
if (n2) *n2 = array[1];
1326
}
1327
1328
//*****************************************************************************************
1329
// Get first three representative target nodes.
1330
//*****************************************************************************************
1331
void
1332
getP2TTrRepNodes(TR_CISCTransformer *trans, TR::Node** n1, TR::Node** n2, TR::Node** n3)
1333
{
1334
TR::Node* array[3];
1335
getP2TTrRepNodes(trans, array, 3);
1336
if (n1) *n1 = array[0];
1337
if (n2) *n2 = array[1];
1338
if (n3) *n3 = array[2];
1339
}
1340
1341
//*****************************************************************************************
1342
// Get first four representative target nodes.
1343
//*****************************************************************************************
1344
void
1345
getP2TTrRepNodes(TR_CISCTransformer *trans, TR::Node** n1, TR::Node** n2, TR::Node** n3, TR::Node** n4)
1346
{
1347
TR::Node* array[4];
1348
getP2TTrRepNodes(trans, array, 4);
1349
if (n1) *n1 = array[0];
1350
if (n2) *n2 = array[1];
1351
if (n3) *n3 = array[2];
1352
if (n4) *n4 = array[3];
1353
}
1354
1355
//*****************************************************************************************
1356
// Get first five representative target nodes.
1357
//*****************************************************************************************
1358
void
1359
getP2TTrRepNodes(TR_CISCTransformer *trans, TR::Node** n1, TR::Node** n2, TR::Node** n3, TR::Node** n4, TR::Node** n5)
1360
{
1361
TR::Node* array[5];
1362
getP2TTrRepNodes(trans, array, 5);
1363
if (n1) *n1 = array[0];
1364
if (n2) *n2 = array[1];
1365
if (n3) *n3 = array[2];
1366
if (n4) *n4 = array[3];
1367
if (n5) *n5 = array[4];
1368
}
1369
1370
//*****************************************************************************************
1371
// Get first six representative target nodes.
1372
//*****************************************************************************************
1373
void
1374
getP2TTrRepNodes(TR_CISCTransformer *trans, TR::Node** n1, TR::Node** n2, TR::Node** n3, TR::Node** n4, TR::Node** n5, TR::Node** n6)
1375
{
1376
TR::Node* array[6];
1377
getP2TTrRepNodes(trans, array, 6);
1378
if (n1) *n1 = array[0];
1379
if (n2) *n2 = array[1];
1380
if (n3) *n3 = array[2];
1381
if (n4) *n4 = array[3];
1382
if (n5) *n5 = array[4];
1383
if (n6) *n6 = array[5];
1384
}
1385
1386
//*****************************************************************************************
1387
// Get first seven representative target nodes.
1388
//*****************************************************************************************
1389
void
1390
getP2TTrRepNodes(TR_CISCTransformer *trans, TR::Node** n1, TR::Node** n2, TR::Node** n3, TR::Node** n4, TR::Node** n5, TR::Node** n6, TR::Node** n7)
1391
{
1392
TR::Node* array[7];
1393
getP2TTrRepNodes(trans, array, 7);
1394
if (n1) *n1 = array[0];
1395
if (n2) *n2 = array[1];
1396
if (n3) *n3 = array[2];
1397
if (n4) *n4 = array[3];
1398
if (n5) *n5 = array[4];
1399
if (n6) *n6 = array[5];
1400
if (n7) *n7 = array[6];
1401
}
1402
1403
//*****************************************************************************************
1404
// Confirm whether only the table[0] is zero and other entries (table[1 to 256]) are non-zero
1405
//*****************************************************************************************
1406
bool
1407
isFitTRTFunctionTable(uint8_t *table)
1408
{
1409
if (*table) return false;
1410
for (int i = 1; i < 256; i++)
1411
if (table[i] == 0) return false;
1412
return true;
1413
}
1414
1415
1416
//*****************************************************************************************
1417
// create table alignment check node for arraytranslate
1418
//*****************************************************************************************
1419
TR::Node*
1420
createTableAlignmentCheck(TR::Compilation *comp, TR::Node *tableNode, bool isByteSource, bool isByteTarget, bool tableBackedByRawStorage)
1421
{
1422
int32_t mask = comp->cg()->arrayTranslateTableRequiresAlignment(isByteSource, isByteTarget);
1423
TR::Node * compareNode = NULL;
1424
if (mask != 0 && mask != 7)
1425
{
1426
if (comp->target().is64Bit())
1427
{
1428
TR::Node * zeroNode = TR::Node::create(tableNode, TR::lconst);
1429
zeroNode->setLongInt(0);
1430
TR::Node * pageNode = TR::Node::create(tableNode, TR::lconst);
1431
pageNode->setLongInt(mask);
1432
TR::Node * dupTableNode = tableNode->duplicateTree();
1433
if (!tableBackedByRawStorage)
1434
{
1435
TR::Node * hdrSizeNode = TR::Node::create(tableNode, TR::lconst, 0);
1436
hdrSizeNode->setLongInt((int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());
1437
dupTableNode = TR::Node::create(TR::ladd, 2, dupTableNode, hdrSizeNode);
1438
}
1439
TR::Node * andNode = TR::Node::create(TR::land, 2, dupTableNode, pageNode);
1440
1441
compareNode = TR::Node::createif(TR::iflcmpne, zeroNode, andNode);
1442
}
1443
else
1444
{
1445
TR::Node * zeroNode = TR::Node::create(tableNode, TR::iconst, 0, 0);
1446
TR::Node * pageNode = TR::Node::create(tableNode, TR::iconst, 0, mask);
1447
TR::Node * dupTableNode = tableNode->duplicateTree();
1448
if (!tableBackedByRawStorage)
1449
{
1450
TR::Node * hdrSizeNode = TR::Node::create(tableNode, TR::iconst, 0, TR::Compiler->om.contiguousArrayHeaderSizeInBytes());
1451
dupTableNode = TR::Node::create(TR::iadd, 2, dupTableNode, hdrSizeNode);
1452
}
1453
TR::Node * andNode = TR::Node::create(TR::iand, 2, dupTableNode, pageNode);
1454
1455
compareNode = TR::Node::createif(TR::ificmpne, zeroNode, andNode);
1456
}
1457
}
1458
return compareNode;
1459
}
1460
1461
1462
//*****************************************************************************************
1463
// Sort each entry of the given list
1464
//*****************************************************************************************
1465
List<TR_CISCNode>*
1466
sortList(List<TR_CISCNode>* input, List<TR_CISCNode>* output, List<TR_CISCNode>* order, bool reverse)
1467
{
1468
if (input->isSingleton())
1469
{
1470
TR_CISCNode *n = input->getListHead()->getData();
1471
if (order->find(n))
1472
output->add(n);
1473
}
1474
else
1475
{
1476
ListIterator<TR_CISCNode> li(order);
1477
TR_CISCNode *n = li.getFirst();
1478
if (!reverse)
1479
{
1480
ListAppender<TR_CISCNode> appender(output);
1481
for (; n; n = li.getNext())
1482
{
1483
if (input->find(n)) appender.add(n);
1484
}
1485
}
1486
else
1487
{
1488
for (; n; n = li.getNext())
1489
{
1490
if (input->find(n)) output->add(n);
1491
}
1492
}
1493
}
1494
return output;
1495
}
1496
1497
//*****************************************************************************************
1498
// Checks if loop preheader block is last block in method.
1499
//*****************************************************************************************
1500
bool isLoopPreheaderLastBlockInMethod(TR::Compilation *comp, TR::Block *block, TR::Block **predBlock)
1501
{
1502
1503
// If already a loop invariant block, we likely have the preheader.
1504
if (block->getStructureOf() && block->getStructureOf()->isLoopInvariantBlock())
1505
{
1506
if (predBlock)
1507
*predBlock = block;
1508
if (block->getExit()->getNextTreeTop() == NULL)
1509
{
1510
traceMsg(comp, "Preheader block_%d [%p] is last block in method.\n", block->getNumber(), block);
1511
return true;
1512
}
1513
}
1514
else
1515
{
1516
// Find the loop preheader block and check its next treetop.
1517
for (auto edge = block->getPredecessors().begin(); edge != block->getPredecessors().end(); ++edge)
1518
{
1519
TR::Block *source = toBlock ((*edge)->getFrom());
1520
1521
if (source->getStructureOf() &&
1522
source->getStructureOf()->isLoopInvariantBlock())
1523
{
1524
if (predBlock)
1525
*predBlock = source;
1526
if (source->getExit()->getNextTreeTop() == NULL)
1527
{
1528
traceMsg(comp, "Preheader block_%d [%p] to block_%d [%p] is last block in method.\n", source->getNumber(), source, block->getNumber(), block);
1529
return true;
1530
}
1531
}
1532
}
1533
}
1534
return false;
1535
}
1536
1537
1538
//*****************************************************************************************
1539
// Search for specific symref within a given subtree. If targetNode is specified, the node with the matching symref
1540
// will be replaced with the targetNode.
1541
// @param curNode The parent node to recursively search
1542
// @param symRefNumberToBeMatched The symbol reference number to be matched
1543
// @return The load TR::Node* with the matching symbol reference number. NULL if not found.
1544
//*****************************************************************************************
1545
TR::Node*
1546
findLoadWithMatchingSymRefNumber(TR::Node *curNode, int32_t symRefNumberToBeMatched)
1547
{
1548
TR::Node *node = NULL;
1549
// Recursively iterate through each children node and look for nodes with the matching symref to replace.
1550
for (int32_t i = 0; i < curNode->getNumChildren(); i++)
1551
{
1552
TR::Node *childNode = curNode->getChild(i);
1553
1554
if (childNode->getOpCode().isLoad() && childNode->getOpCode().hasSymbolReference() && (childNode->getSymbolReference()->getReferenceNumber() == symRefNumberToBeMatched))
1555
{
1556
node = childNode;
1557
break;
1558
}
1559
else
1560
{
1561
node = findLoadWithMatchingSymRefNumber(childNode, symRefNumberToBeMatched);
1562
if (node != NULL)
1563
break;
1564
}
1565
}
1566
return node;
1567
}
1568
1569
1570
//*****************************************************************************************
1571
// Search for specific symref within a given subtree. If targetNode is specified, the node with the matching symref
1572
// will be replaced with the targetNode.
1573
//*****************************************************************************************
1574
bool
1575
findAndOrReplaceNodesWithMatchingSymRefNumber(TR::Node *curNode, TR::Node *targetNode, int32_t symRefNumberToBeMatched)
1576
{
1577
bool isFound = false;
1578
1579
// Recursively iterate through each children node and look for nodes with the matching symref to replace.
1580
for (int32_t i = 0; i < curNode->getNumChildren(); i++)
1581
{
1582
TR::Node *childNode = curNode->getChild(i);
1583
1584
if (childNode->getOpCode().hasSymbolReference() && (childNode->getSymbolReference()->getReferenceNumber() == symRefNumberToBeMatched))
1585
{
1586
if (targetNode != NULL)
1587
curNode->setAndIncChild(i,targetNode);
1588
isFound = true;
1589
}
1590
else
1591
{
1592
isFound = findAndOrReplaceNodesWithMatchingSymRefNumber(childNode, targetNode, symRefNumberToBeMatched) || isFound;
1593
}
1594
}
1595
return isFound;
1596
}
1597
1598
1599