Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/il/J9Node.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 "j9cfg.h"
24
#include "il/J9Node.hpp"
25
26
#include <algorithm>
27
#include "codegen/CodeGenerator.hpp"
28
#include "compile/Compilation.hpp"
29
#include "compile/Method.hpp"
30
#include "env/CompilerEnv.hpp"
31
#include "il/MethodSymbol.hpp"
32
#include "il/Node.hpp"
33
#include "il/Node_inlines.hpp"
34
#include "il/Symbol.hpp"
35
#include "runtime/RuntimeAssumptions.hpp"
36
#include "env/CHTable.hpp"
37
#include "env/PersistentCHTable.hpp"
38
#include "env/VMJ9.h"
39
40
#ifdef TR_TARGET_S390
41
#include "z/codegen/S390Register.hpp"
42
#endif
43
44
#if (HOST_COMPILER == COMPILER_MSVC)
45
#define MAX_PACKED_DECIMAL_SIZE 32
46
#define UNICODE_SIGN_SIZE 2
47
// On Windows, macros are used instead of TR::DataType:: static functions to size some temp arrays
48
// COMPILER_MSVC outputs 'error C2057: expected constant expression' when the static functions are used to determine the array's size
49
#endif
50
51
/**
52
* Constructors and destructors
53
*/
54
55
J9::Node::Node(TR::Node *originatingByteCodeNode, TR::ILOpCodes op, uint16_t numChildren)
56
: OMR::NodeConnector(originatingByteCodeNode, op, numChildren),
57
#ifdef TR_TARGET_S390
58
_storageReferenceHint(NULL),
59
#endif
60
_unionPropertyB()
61
{
62
// check that _unionPropertyA union is disjoint
63
TR_ASSERT(
64
self()->hasSymbolReference()
65
+ self()->hasRegLoadStoreSymbolReference()
66
+ self()->hasBranchDestinationNode()
67
+ self()->hasBlock()
68
+ self()->hasArrayStride()
69
+ self()->hasPinningArrayPointer()
70
+ self()->hasDataType() <= 1,
71
"_unionPropertyA union is not disjoint for this node %s (%p):\n"
72
" has({SymbolReference, ...}, ..., DataType) = ({%1d,%1d},%1d,%1d,%1d,%1d,%1d)\n",
73
self()->getOpCode().getName(), this,
74
self()->hasSymbolReference(),
75
self()->hasRegLoadStoreSymbolReference(),
76
self()->hasBranchDestinationNode(),
77
self()->hasBlock(),
78
self()->hasArrayStride(),
79
self()->hasPinningArrayPointer(),
80
self()->hasDataType());
81
82
// check that _unionPropertyB union is disjoint
83
TR_ASSERT(self()->hasDecimalInfo() + self()->hasBCDFlags() <= 1,
84
"_unionPropertyB union is not disjoint for this node %s (%p):\n"
85
" has(DecimalInfo, BCDFlags) = (%1d,%1d)\n",
86
self()->getOpCode().getName(), this,
87
self()->hasDecimalInfo(), self()->hasBCDFlags());
88
89
if (self()->hasDecimalInfo())
90
{
91
// Every node that has decimal info must set a valid precision but adjust/fraction and round can be 0
92
// NOTE: update isDecimalSizeAndShapeEquivalent() routine when adding fields that specify
93
// the shape/size of a decimal node (such as precision/adjust/fraction/setSign etc) to _decimalInfo.
94
// Flag type fields like clean/preferred signs do not need to be added to isDecimalSizeAndShapeEquivalent()
95
_unionPropertyB._decimalInfo._decimalPrecision = TR::DataType::getInvalidDecimalPrecision(); // valid range is 0->TR_MAX_DECIMAL_PRECISION (defined in OMRDataTypes.hpp)
96
_unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor = 0; // valid range is -31->31 for adjust/fraction and 0->62 for divisor precision
97
_unionPropertyB._decimalInfo._decimalSourcePrecisionOrDividend = 0; // valid range is 0->63 for source precision and 0->62 for dividend precision
98
_unionPropertyB._decimalInfo._setSign = raw_bcd_sign_unknown; // for isSetSignOnNode() opcodes such as TR::pdclearSetSign
99
_unionPropertyB._decimalInfo._hasNoSignStateOnLoad = 0; // 0 (false) is the conservative setting -- meaning do not clobber the sign code unless FE explicitly instructs
100
_unionPropertyB._decimalInfo._castedToBCD = 0; // 0 (false) originally was a BCD type, 1 (true) casted from a non-BCD type (e.g. aggr, int) to a BCD type during optimization
101
_unionPropertyB._decimalInfo._signStateIsKnown = 0;
102
_unionPropertyB._decimalInfo._hasCleanSign = 0;
103
_unionPropertyB._decimalInfo._hasPreferredSign = 0;
104
_unionPropertyB._decimalInfo._round = 0; // 0 means no rounding, 1 means rounding
105
_unionPropertyB._decimalInfo._signCode = raw_bcd_sign_unknown;
106
}
107
}
108
109
J9::Node::Node(TR::Node *from, uint16_t numChildren)
110
: OMR::NodeConnector(from, numChildren)
111
{
112
#ifdef TR_TARGET_S390
113
if (self()->getOpCode().canHaveStorageReferenceHint())
114
{
115
self()->setStorageReferenceHint(from->getStorageReferenceHint());
116
}
117
#endif
118
119
_unionPropertyB = from->_unionPropertyB; // TODO: use copyValidProperties
120
121
if (from->getOpCode().isConversionWithFraction())
122
{
123
self()->setDecimalFraction(from->getDecimalFraction());
124
}
125
}
126
127
J9::Node::~Node()
128
{
129
_unionPropertyB = UnionPropertyB();
130
}
131
132
bool
133
J9::Node::dontEliminateStores(bool isForLocalDeadStore)
134
{
135
// Disallow store sinking of BCD operations in Java because such operations may be under a BCDCHK node, implying that
136
// an exception path may be taken at runtime to evaluate the tree. Sinking such potentially exceptional operations
137
// violates the assumption that all such operations are to be anchored on a BCDCHK treetop, which the codegen expects
138
// to be able to generate the exception handling fallback code.
139
if (self()->getFirstChild()->getOpCode().isBinaryCodedDecimalOp())
140
return true;
141
else
142
return OMR::NodeConnector::dontEliminateStores(isForLocalDeadStore);
143
}
144
145
146
void
147
J9::Node::copyValidProperties(TR::Node *fromNode, TR::Node *toNode)
148
{
149
OMR::Node::copyValidProperties(fromNode, toNode);
150
151
#ifdef TR_TARGET_S390
152
if (fromNode->getOpCode().canHaveStorageReferenceHint())
153
{
154
toNode->setStorageReferenceHint(fromNode->getStorageReferenceHint());
155
}
156
#endif
157
158
// in order to determine the UnionPropertyB_type correctly, require children and symRef (from UnionPropertyA) to have been defined
159
// already as depends on getDataType which in term depends on these
160
UnionPropertyB_Type fromUnionPropertyB_Type = fromNode->getUnionPropertyB_Type();
161
UnionPropertyB_Type toUnionPropertyB_Type = toNode->getUnionPropertyB_Type();
162
163
if (fromUnionPropertyB_Type == toUnionPropertyB_Type)
164
{
165
switch (fromUnionPropertyB_Type)
166
{
167
case HasDecimalInfo:
168
#if !defined(ENABLE_RECREATE_WITH_COPY_VALID_PROPERTIES_COMPLETE)
169
// for now have to copy forward all decimalInfo properties
170
toNode->_unionPropertyB._decimalInfo = fromNode->_unionPropertyB._decimalInfo;
171
#else
172
// _decimalPrecision
173
if (toNode->hasDecimalPrecision() && fromNode->hasDecimalPrecision())
174
toNode->setDecimalPrecision(fromNode->getDecimalPrecision());
175
176
// _decimalSourcePrecisionOrDividend
177
if (toNode->canHaveSourcePrecision() && fromNode->canHaveSourcePrecision())
178
toNode->setSourcePrecision(fromNode->getSourcePrecision());
179
180
// _decimalAdjustOrFractionOrDivisor
181
if (toNode->hasDecimalAdjust() && fromNode->hasDecimalAdjust())
182
toNode->setDecimalAdjust(fromNode->getDecimalAdjust());
183
else if (toNode->hasDecimalFraction() && fromNode->hasDecimalFraction())
184
toNode->setDecimalFraction(fromNode->getDecimalFraction());
185
186
// _round
187
if (toNode->hasDecimalRound() && fromNode->hasDecimalRound())
188
toNode->setDecimalRound(fromNode->getDecimalRound());
189
190
// _setSign
191
if (toNode->hasSetSign() && fromNode->hasSetSign())
192
toNode->setSetSign(fromNode->getSetSign());
193
194
// _signStateIsKnown
195
// _hasCleanSign
196
// _hasPreferredSign
197
// _signCode
198
// _hasNoSignStateOnLoad
199
if (toNode->getType().isBCD() && fromNode->getType().isBCD())
200
{
201
toNode->_unionPropertyB._decimalInfo._signStateIsKnown = fromNode->signStateIsKnown();
202
toNode->_unionPropertyB._decimalInfo._hasCleanSign = fromNode->hasKnownOrAssumedCleanSign(); // '10 0d' might be truncated to negative zero '0 00d' -- so no longer clean
203
toNode->_unionPropertyB._decimalInfo._hasPreferredSign = fromNode->hasKnownOrAssumedPreferredSign();
204
toNode->_unionPropertyB._decimalInfo._signCode = fromNode->getKnownOrAssumedSignCode();
205
if (toNode->getOpCode().isBCDLoad() && fromNode->getOpCode().isBCDLoad())
206
toNode->setHasSignStateOnLoad(fromNode->hasSignStateOnLoad());
207
if (toNode->getOpCode().chkOpsCastedToBCD() && fromNode->getOpCode().chkOpsCastedToBCD())
208
toNode->setCastedToBCD(fromNode->castedToBCD());
209
}
210
#endif
211
break;
212
case HasBcdFlags:
213
// should never get here, as only one type of opcodevalue for this flag
214
TR_ASSERT(fromNode->getOpCodeValue() == toNode->getOpCodeValue(),
215
"Unexpected comparison. Nodes that have _bcdFlags property should always be BCDCHK nodes. These are %s %p and %s %p nodes",
216
fromNode->getOpCode().getName(), fromNode,
217
toNode->getOpCode().getName(), toNode);
218
TR_ASSERT(false, "This makes no sense as recreate does not change the opcodevalue when copying forward properties from node %s %p to node %s %p",
219
fromNode->getOpCode().getName(), fromNode,
220
toNode->getOpCode().getName(), toNode);
221
break;
222
default:
223
/* HasNoUnionPropertyB */
224
break;
225
}
226
}
227
228
}
229
230
/**
231
* Constructors and destructors end
232
*/
233
234
235
uint32_t
236
J9::Node::getSize()
237
{
238
if (self()->getType().isBCD())
239
{
240
// this is a temporary workaround for a compiler bug where too many bits are getting pulled out of the bit container
241
/*
242
TR_ASSERT(_unionPropertyB._decimalInfo._decimalPrecision >=0 && _unionPropertyB._decimalInfo._decimalPrecision <=TR_MAX_DECIMAL_PRECISION,
243
"unexpected decimal precision %d on node %p\n", _unionPropertyB._decimalInfo._decimalPrecision, this);
244
return TR::DataType::getSizeFromBCDPrecision(getDataType(), _unionPropertyB._decimalInfo._decimalPrecision);
245
*/
246
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalPrecision field for node %s %p that does not have it", self()->getOpCode().getName(), self());
247
int32_t newPrec = _unionPropertyB._decimalInfo._decimalPrecision & 0x3F;
248
return TR::DataType::getSizeFromBCDPrecision(self()->getDataType(), newPrec);
249
}
250
return OMR::NodeConnector::getSize();
251
}
252
253
/**
254
* Given a direct call to Object.clone node, return the class of the receiver.
255
*/
256
TR_OpaqueClassBlock *
257
J9::Node::getCloneClassInNode()
258
{
259
TR_ASSERT(!self()->hasNodeExtension(), "Node %p should not have node extension");
260
return (TR_OpaqueClassBlock *)_unionBase._children[1];
261
}
262
263
264
TR::Node *
265
J9::Node::processJNICall(TR::TreeTop * callNodeTreeTop, TR::ResolvedMethodSymbol * owningSymbol)
266
{
267
TR::Compilation * comp = TR::comp();
268
if (!comp->cg()->getSupportsDirectJNICalls() || comp->getOption(TR_DisableDirectToJNI) || (comp->compileRelocatableCode() && !comp->cg()->supportsDirectJNICallsForAOT()))
269
return self();
270
271
TR::ResolvedMethodSymbol * methodSymbol = self()->getSymbol()->castToResolvedMethodSymbol();
272
TR_ResolvedMethod * resolvedMethod = methodSymbol->getResolvedMethod();
273
274
// TR_DisableDirectToJNIInline means only convert calls in thunks
275
// also don't directly call any native method that has tracing enabled
276
//
277
if (!comp->getCurrentMethod()->isJNINative() &&
278
(comp->getOption(TR_DisableDirectToJNIInline) ||
279
comp->fej9()->isAnyMethodTracingEnabled(resolvedMethod->getPersistentIdentifier())))
280
return self();
281
282
if (!comp->getOption(TR_DisableUnsafe) && !TR::Compiler->om.canGenerateArraylets() &&
283
(methodSymbol->getRecognizedMethod() == TR::java_nio_Bits_copyToByteArray ||
284
methodSymbol->getRecognizedMethod() == TR::java_nio_Bits_copyFromByteArray))
285
return self();
286
287
#ifdef J9VM_OPT_JAVA_CRYPTO_ACCELERATION
288
if (self()->processJNICryptoMethodCall(methodSymbol, comp))
289
{
290
return self();
291
}
292
#endif
293
294
if (comp->canTransformUnsafeCopyToArrayCopy()
295
&& self()->isUnsafeCopyMemoryIntrinsic())
296
{
297
return self();
298
}
299
if (comp->canTransformUnsafeSetMemory() &&
300
(methodSymbol->getRecognizedMethod() == TR::sun_misc_Unsafe_setMemory))
301
{
302
return self();
303
}
304
305
if (methodSymbol->getRecognizedMethod() == TR::sun_misc_Unsafe_ensureClassInitialized)
306
{
307
return self();
308
}
309
310
if (methodSymbol->getRecognizedMethod() == TR::jdk_internal_loader_NativeLibraries_load)
311
{
312
return self();
313
}
314
315
if (methodSymbol->canReplaceWithHWInstr())
316
return self();
317
318
// don't convert synchronized jni calls to direct to jni calls unless we're compiling
319
// the jni thunk.
320
//
321
if (resolvedMethod->isSynchronized() && !comp->getCurrentMethod()->isJNINative())
322
{
323
// todo: consider adding monent/monexit trees so that it can inlined
324
return self();
325
}
326
327
if (self()->getOpCode().isCallIndirect())
328
{
329
// todo: handle nonoverridden indirect calls
330
// || (methodSymbol->isVirtualMethod() && !virtualMethodIsOverridden(resolvedMethod))))
331
return self();
332
}
333
334
#if defined(TR_TARGET_POWER)
335
// Recognizing these methods on Power allows us to take a shortcut
336
// in the JNI dispatch where we mangle the register dependencies and call
337
// optimized helpers in the JIT library using what amounts to system/C dispatch.
338
// The addresses of the optimized helpers in the server process will not necessarily
339
// match the client-side addresses, so we can't take this shortcut in JITServer mode.
340
if (((methodSymbol->getRecognizedMethod() == TR::java_util_zip_CRC32_update) ||
341
(methodSymbol->getRecognizedMethod() == TR::java_util_zip_CRC32_updateBytes) ||
342
(methodSymbol->getRecognizedMethod() == TR::java_util_zip_CRC32_updateByteBuffer)) &&
343
!comp->requiresSpineChecks()
344
#ifdef J9VM_OPT_JITSERVER
345
&& !comp->isOutOfProcessCompilation()
346
#endif
347
)
348
{
349
self()->setPreparedForDirectJNI();
350
return self();
351
}
352
#endif
353
354
// In the latest round of VM drops, we've lowered the maximum outgoing argument size on the C stack to 32
355
// (it used to be the maximum 255). This means that fixed frame platforms (those who pre-allocate space
356
// in the C stack for outgoing arguments, as opposed to buying new stack to pass arguments) who implement
357
// direct JNI can no longer depend on the VM allocating the full 255 slots of backing store.
358
//
359
// The simplest solution would be to simply not translate JNI methods which have more than 32 arguments,
360
// and fall back to the interpreter for those cases. The VM handles the >32 case by calling to another
361
// C function which does allocate space for the full 255 arguments, but this approach will of course not
362
// work for the JIT.
363
//
364
// The 32 limit is on the method argument count (which includes the receiver
365
// for virtual methods), but not the "fixed" parameters (the JNIEnv * and the
366
// class parameter for static methods), so we actually have 34 slots of space
367
// preallocated on fixed frame platforms.
368
//
369
uint32_t numChildren = self()->getNumChildren();
370
if (numChildren - self()->getFirstArgumentIndex() > 32 && comp->cg()->hasFixedFrameC_CallingConvention())
371
return self();
372
373
if (callNodeTreeTop->getNode()->getOpCode().isNullCheck())
374
{
375
//TR_ASSERT(!callNodeTreeTop->getNode()->getOpCode().isResolveCheck(), "Node::processJNICall, expected NULLCHK node");
376
TR::Node::recreate(callNodeTreeTop->getNode(), TR::NULLCHK);
377
callNodeTreeTop->getNode()->extractTheNullCheck(callNodeTreeTop->getPrevTreeTop());
378
}
379
380
bool wrapObjects = !comp->fej9()->jniDoNotWrapObjects(resolvedMethod);
381
382
// Add a level of indirection for each address argument to a JNI method
383
//
384
if (wrapObjects)
385
{
386
int32_t i;
387
for (i = 0; i < numChildren; ++i)
388
{
389
TR::Node * n = self()->getChild(i);
390
if (n->getDataType() == TR::Address)
391
{
392
if (n->getOpCode().hasSymbolReference() && n->getSymbol()->isAutoOrParm())
393
{
394
n->decReferenceCount();
395
self()->setAndIncChild(i, TR::Node::createWithSymRef(n, TR::loadaddr, 0, n->getSymbolReference()));
396
}
397
else
398
{
399
TR::SymbolReference * symRef = comp->getSymRefTab()->createTemporary(owningSymbol, TR::Address);
400
TR::TreeTop::create(comp, callNodeTreeTop->getPrevTreeTop(), TR::Node::createWithSymRef(TR::astore, 1, 1, n, symRef));
401
// create will have inc'ed the reference count, but there really aren't more
402
// parents, so need to dec it back.
403
n->decReferenceCount();
404
self()->setAndIncChild(i, TR::Node::createWithSymRef(n, TR::loadaddr, 0, symRef));
405
}
406
if (n->isNonNull())
407
{
408
self()->getChild(i)->setPointsToNonNull(true);
409
}
410
}
411
}
412
}
413
414
self()->setPreparedForDirectJNI();
415
416
if (methodSymbol->isStatic())
417
{
418
TR::Node * newNode = new (comp->getNodePool()) TR::Node(self(), numChildren + 1);
419
for (int32_t i = numChildren; i; --i)
420
newNode->setChild(i, self()->getChild(i - 1));
421
newNode->setNumChildren(numChildren + 1);
422
423
424
TR::ResolvedMethodSymbol * callerSymbol = self()->getSymbolReference()->getOwningMethodSymbol(comp);
425
int32_t callerCP = self()->getSymbolReference()->getCPIndex();
426
427
// For JNI thunks cp index is -1
428
// passing cpIndex = -1 to findOrCreateClassSymbol shouldn't be an issue as it will figure out the address from resolvedMethod->containingClass()
429
// we only need cpIndex for relocations in AOT and compiling JNI thunks is disable in AOT
430
int32_t classCP = (callerCP != -1) ? callerSymbol->getResolvedMethod()->classCPIndexOfMethod(callerCP) : -1;
431
432
TR_ASSERT ((callerCP != -1 || callerSymbol->isNative()), "Cannot have cp index -1 for JNI calls other than JNI thunks.\n");
433
434
TR::Node *addressOfJ9Class = TR::Node::aconst(newNode, (uintptr_t)resolvedMethod->containingClass());
435
addressOfJ9Class->setIsClassPointerConstant(true);
436
TR::Node *addressOfJavaLangClassReference;
437
438
TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());
439
if (comp->target().is64Bit())
440
{
441
addressOfJavaLangClassReference =
442
TR::Node::create(TR::aladd, 2,
443
addressOfJ9Class,
444
TR::Node::lconst(newNode, fej9->getOffsetOfJavaLangClassFromClassField()));
445
}
446
else
447
{
448
addressOfJavaLangClassReference =
449
TR::Node::create(TR::aiadd, 2,
450
addressOfJ9Class,
451
TR::Node::iconst(newNode, fej9->getOffsetOfJavaLangClassFromClassField()));
452
}
453
newNode->setAndIncChild(0, addressOfJavaLangClassReference);
454
455
if (callNodeTreeTop->getNode() == self())
456
{
457
callNodeTreeTop->setNode(newNode);
458
}
459
else
460
{
461
TR_ASSERT(callNodeTreeTop->getNode()->getChild(0) == self(), "call node " POINTER_PRINTF_FORMAT " is not the child of a treetop", self());
462
callNodeTreeTop->getNode()->setChild(0, newNode);
463
}
464
return newNode;
465
}
466
467
return self();
468
}
469
470
void
471
J9::Node::devirtualizeCall(TR::TreeTop *treeTop)
472
{
473
OMR::NodeConnector::devirtualizeCall(treeTop);
474
TR::ResolvedMethodSymbol *methodSymbol = self()->getSymbol()->castToResolvedMethodSymbol();
475
476
if (methodSymbol->isJNI())
477
self()->processJNICall(treeTop, TR::comp()->getMethodSymbol());
478
}
479
480
bool
481
J9::Node::isEvenPrecision()
482
{
483
return ((self()->getDecimalPrecision() & 0x1) == 0);
484
}
485
486
bool
487
J9::Node::isOddPrecision()
488
{
489
return ((self()->getDecimalPrecision() & 0x1) != 0);
490
}
491
492
/**
493
* A 'simple' widening or truncation is a pdshl node that changes the precision of its child but has a shift amount of 0
494
*/
495
bool
496
J9::Node::isSimpleTruncation()
497
{
498
if (self()->getOpCode().isModifyPrecision() &&
499
self()->getDecimalPrecision() < self()->getFirstChild()->getDecimalPrecision())
500
{
501
return true;
502
}
503
else if (self()->getOpCodeValue() == TR::pdshl &&
504
self()->getSecondChild()->getOpCode().isLoadConst() &&
505
self()->getSecondChild()->get64bitIntegralValue() == 0 &&
506
self()->getDecimalPrecision() < self()->getFirstChild()->getDecimalPrecision())
507
{
508
return true;
509
}
510
else
511
{
512
return false;
513
}
514
}
515
516
/**
517
* Example of an intermediate truncation (no shifts involved)
518
* zd2pd p=4 0034 this
519
* pd2zd p=2 34 child
520
* pdx p=4 1234 grandChild
521
* In this case it would be illegal to cancel out the zd2pd/pd2zd nodes because the child (pd2zd) has the
522
* side effect of truncating during the conversion operation.
523
*
524
* The shift case is more complicated as only some of the child digits may survive the shift
525
* Example of a truncating shift that is *not* an intermediate truncation:
526
* pdshl p=3 300 // survivingDigits = 1 <= child->prec (1) so not an intermediate truncation
527
* zd2pd p=1 3 // isTruncating=true
528
* zdx p=3 123
529
* shift=2
530
*
531
* so
532
* zdshl p=3 300
533
* zdx p=3 123
534
* shift=2
535
* gives an equivalent answer
536
*
537
* Example of a truncating shift that *is* an intermediate truncation:
538
* pdshl p=4 0300 // survivingDigits = 2 > child->prec (1) so is an intermediate truncation
539
* zd2pd p=1 3 // isTruncating=true
540
* zdx p=3 123
541
* shift=2
542
*
543
* so
544
* zdshl p=4 2300
545
* zdx p=3 123
546
* shift=2
547
* gives a different answer
548
*/
549
bool
550
J9::Node::hasIntermediateTruncation()
551
{
552
TR::Node *valueChild = self()->getValueChild();
553
TR_ASSERT(self()->getType().isBCD() && valueChild->getType().isBCD(), "hasIntermediateTruncation only valid for BCD parent (dt=%s) and child (dt=%s)\n",
554
self()->getDataType().toString(), valueChild->getDataType().toString());
555
if (valueChild->isTruncating() &&
556
self()->survivingDigits() > valueChild->getDecimalPrecision())
557
{
558
return true;
559
}
560
else
561
{
562
return false;
563
}
564
}
565
566
/**
567
* For non-shift operations the surviving digits is simply the precision.
568
*
569
* Left shift example:
570
* For a 3v0 conversion to a 2v2 result (left shift by 2) there are 2 surviving digits -- 123. -> 123.00 but result precision is 4 so only 23.00 survive.
571
* The shiftedPrecision is 3+2 = 5 and this is > than the nodePrec of 4.
572
* There is 1 truncated digit so reduce the shiftedPrecision by 1 to get the surviving digits value of 2.
573
*
574
* Right shift example:
575
* For a 3v2 conversion to 2v1 result (right shift by 1) there are 3 surviving digits -- 123.45 -> 123.4 but result precision is 3 so only 23.4 survive.
576
* The shiftedPrecision is 5-1 = 4 and this > than the nodePrec of 3.
577
* There is 1 truncated digit so reduce the shiftedPrecision by 1 to get the surviving digits value of 3.
578
*
579
* @note that the shift formula for surviving digits degenerates to just getDecimalPrecision() when adjust == 0
580
*/
581
int32_t
582
J9::Node::survivingDigits()
583
{
584
TR_ASSERT(self()->getType().isBCD(), "node %p (op %d) is not a BCD type (dt=%s)\n", self(), self()->getOpCodeValue(), self()->getDataType().toString());
585
int32_t survivingDigits = 0;
586
if (self()->getOpCode().isShift())
587
{
588
TR::Node *child = self()->getFirstChild(); // left shift 3v0 -> 2v2
589
int32_t adjust = self()->getDecimalAdjust(); // 2
590
int32_t shiftedPrecision = child->getDecimalPrecision() + adjust; // 5=3+2
591
int32_t truncatedDigits = shiftedPrecision - self()->getDecimalPrecision(); // 1=5-4
592
survivingDigits = child->getDecimalPrecision() - truncatedDigits; // 2=3-1
593
}
594
else
595
{
596
survivingDigits = self()->getDecimalPrecision();
597
}
598
return survivingDigits;
599
}
600
601
bool
602
J9::Node::isTruncating()
603
{
604
if (self()->getType().isBCD() && self()->getNumChildren() >= 1 && self()->getValueChild()->getType().isBCD())
605
{
606
if (self()->getOpCode().isShift())
607
return self()->isTruncatingBCDShift();
608
else if (self()->getDecimalPrecision() < self()->getValueChild()->getDecimalPrecision())
609
return true;
610
else
611
return false;
612
}
613
else if (self()->getType().isBCD() && self()->getOpCode().isConversion() && self()->getNumChildren() >= 1 && !self()->getValueChild()->getType().isBCD())
614
{
615
if (self()->hasSourcePrecision() && self()->getDecimalPrecision() < self()->getSourcePrecision())
616
return true;
617
else if (!self()->hasSourcePrecision()) // Conservative, but necessary for correctness in some opts; best to always set sourcePrecision
618
return true;
619
else
620
return false;
621
}
622
else
623
{
624
return false;
625
}
626
}
627
628
bool
629
J9::Node::isTruncatingBCDShift()
630
{
631
TR_ASSERT(self()->getType().isBCD() && (self()->getOpCode().isModifyPrecision() || self()->getOpCode().isShift()), "node %p (op %d) is not a BCD shift\n", this, self()->getOpCodeValue());
632
633
if (self()->getOpCode().isModifyPrecision() &&
634
self()->getDecimalPrecision() < self()->getFirstChild()->getDecimalPrecision())
635
{
636
return true;
637
}
638
else if (self()->getOpCode().isShift() &&
639
self()->getDecimalPrecision() < (self()->getFirstChild()->getDecimalPrecision() + self()->getDecimalAdjust()))
640
{
641
return true;
642
}
643
else
644
{
645
return false;
646
}
647
}
648
649
bool
650
J9::Node::isWideningBCDShift()
651
{
652
TR_ASSERT(self()->getType().isBCD() && (self()->getOpCode().isModifyPrecision() || self()->getOpCode().isShift()), "node %p (op %d) is not a BCD shift\n", self(), self()->getOpCodeValue());
653
654
if (self()->getOpCode().isModifyPrecision() &&
655
self()->getDecimalPrecision() > self()->getFirstChild()->getDecimalPrecision())
656
{
657
return true;
658
}
659
else if (self()->getOpCode().isShift() &&
660
self()->getDecimalPrecision() > (self()->getFirstChild()->getDecimalPrecision() + self()->getDecimalAdjust()))
661
{
662
return true;
663
}
664
else
665
{
666
return false;
667
}
668
}
669
670
bool
671
J9::Node::isSimpleWidening()
672
{
673
if (self()->getOpCode().isModifyPrecision() &&
674
self()->getDecimalPrecision() > self()->getFirstChild()->getDecimalPrecision())
675
{
676
return true;
677
}
678
else if (self()->getOpCodeValue() == TR::pdshl &&
679
self()->getSecondChild()->getOpCode().isLoadConst() &&
680
self()->getSecondChild()->get64bitIntegralValue() == 0 &&
681
self()->getDecimalPrecision() > self()->getFirstChild()->getDecimalPrecision())
682
{
683
return true;
684
}
685
else
686
{
687
return false;
688
}
689
}
690
691
bool
692
J9::Node::mustClean()
693
{
694
if (self()->getType().isAnyPacked() &&
695
(self()->getOpCodeValue() == TR::pdclean || (self()->getOpCode().isStore() && self()->mustCleanSignInPDStoreEvaluator())))
696
{
697
return true;
698
}
699
return false;
700
}
701
702
void
703
J9::Node::setKnownSignCodeFromRawSign(int32_t rawSignCode)
704
{
705
if (TR::Node::typeSupportedForSignCodeTracking(self()->getDataType()))
706
{
707
if (rawSignCode == 0xc)
708
self()->setKnownSignCode(raw_bcd_sign_0xc);
709
else if (rawSignCode == 0xd)
710
self()->setKnownSignCode(raw_bcd_sign_0xd);
711
else if (rawSignCode == 0xf)
712
self()->setKnownSignCode(raw_bcd_sign_0xf);
713
}
714
}
715
716
/**
717
* @todo Start tracking SeparateOneByte and SeparateTwoByte sign sizes too
718
*/
719
bool
720
J9::Node::typeSupportedForSignCodeTracking(TR::DataType dt)
721
{
722
return TR::DataType::getSignCodeSize(dt) == EmbeddedHalfByte;
723
}
724
725
bool
726
J9::Node::typeSupportedForTruncateOrWiden(TR::DataType dt)
727
{
728
return dt == TR::PackedDecimal
729
|| dt == TR::ZonedDecimalSignLeadingEmbedded
730
|| dt == TR::ZonedDecimal ;
731
}
732
733
void
734
J9::Node::truncateOrWidenBCDLiteral(TR::DataType dt, char *newLit, int32_t newPrecision, char *oldLit, int32_t oldPrecision)
735
{
736
TR_ASSERT(TR::Node::typeSupportedForTruncateOrWiden(dt),
737
"datatype %s not supported in truncateOrWidenBCDLiteral\n", dt.toString());
738
bool isLeadingSign = (dt == TR::ZonedDecimalSignLeadingEmbedded);
739
int32_t newSize = TR::DataType::getSizeFromBCDPrecision(dt, newPrecision);
740
int32_t oldSize = TR::DataType::getSizeFromBCDPrecision(dt, oldPrecision);
741
memset(newLit, TR::DataType::getOneByteBCDFill(dt), newSize);
742
char *shiftedNewLit = newLit;
743
char *shiftedLit = oldLit;
744
int32_t copySize = oldSize;
745
if (newSize > oldSize)
746
{
747
shiftedNewLit += (newSize - oldSize); // a widening into a right justified field so bump the destination
748
copySize = oldSize;
749
}
750
else if (newSize < oldSize)
751
{
752
shiftedLit += (oldSize - newSize); // a truncation from a right justified field so bump the source
753
copySize = newSize;
754
}
755
memcpy(shiftedNewLit, shiftedLit, copySize);
756
if (dt == TR::PackedDecimal && ((newPrecision&0x1)==0)) // zero top nibble for even precision results
757
newLit[0] &= 0x0F;
758
759
if (isLeadingSign)
760
{
761
TR_ASSERT(dt == TR::ZonedDecimalSignLeadingEmbedded, "only zdsle leading sign type supported in truncateOrWidenBCDLiteral (dt=%s)\n", dt.toString());
762
uint8_t sign = oldLit[0]&0xf0;
763
newLit[0] = (newLit[0]&0x0f) | sign;
764
}
765
}
766
767
void
768
J9::Node::setNewBCDSignOnLiteral(uint32_t newSignCode, TR::DataType dt, char *lit, int32_t litSize)
769
{
770
switch (dt)
771
{
772
case TR::PackedDecimal:
773
TR_ASSERT(newSignCode <= 0xF, "expecting packed embedded sign type %s signCode 0x%x to be <= 0xF\n", dt.toString(), newSignCode);
774
lit[litSize-1] = (newSignCode | (lit[litSize-1] & 0xf0));
775
break;
776
case TR::ZonedDecimal:
777
TR_ASSERT(newSignCode <= 0xF, "expecting zoned embedded sign type %s signCode 0x%x to be <= 0xF\n", dt.toString(), newSignCode);
778
lit[litSize-1] = ((newSignCode<<4) | (lit[litSize-1] & 0x0f));
779
break;
780
case TR::ZonedDecimalSignLeadingEmbedded:
781
TR_ASSERT(newSignCode <= 0xF, "expecting zoned leading embedded sign type %s signCode 0x%x to be <= 0xF\n", dt.toString(), newSignCode);
782
lit[0] = ((newSignCode<<4) | (lit[0] & 0x0f));
783
break;
784
case TR::ZonedDecimalSignLeadingSeparate:
785
TR_ASSERT(newSignCode <= 0xFF, "expecting separate sign type %s signCode 0x%x to be <= 0xFF\n", dt.toString(), newSignCode);
786
lit[0] = newSignCode;
787
break;
788
case TR::ZonedDecimalSignTrailingSeparate:
789
TR_ASSERT(newSignCode <= 0xFF, "expecting separate sign type %s signCode 0x%x to be <= 0xFF\n", dt.toString(), newSignCode);
790
lit[litSize-1] = newSignCode;
791
break;
792
case TR::UnicodeDecimalSignLeading:
793
TR_ASSERT(newSignCode <= 0xFF, "expecting separate sign type %s signCode 0x%x to be <= 0xFF\n", dt.toString(), newSignCode);
794
lit[0] = 0;
795
lit[1] = newSignCode;
796
break;
797
case TR::UnicodeDecimalSignTrailing:
798
TR_ASSERT(newSignCode <= 0xFF, "expecting separate sign type %s signCode 0x%x to be <= 0xFF\n", dt.toString(), newSignCode);
799
lit[litSize-2] = 0;
800
lit[litSize-1] = newSignCode;
801
break;
802
case TR::UnicodeDecimal:
803
TR_ASSERT(false, "TR::UnicodeDecimal type (%s) does not have a sign code\n", dt.toString());
804
break;
805
default:
806
TR_ASSERT(false, "unknown bcd type %s\n", dt.toString());
807
break;
808
}
809
}
810
811
TR::Node *
812
J9::Node::getSetSignValueNode()
813
{
814
TR::Node *setSignValueNode = NULL;
815
if (self()->getOpCode().isSetSign())
816
{
817
int32_t setSignValueIndex = TR::ILOpCode::getSetSignValueIndex(self()->getOpCodeValue());
818
if (setSignValueIndex > 0)
819
{
820
setSignValueNode = self()->getChild(setSignValueIndex);
821
}
822
else
823
{
824
TR_ASSERT(false, "setSignValueIndex should be > 0 and not %d\n", setSignValueIndex);
825
}
826
}
827
else
828
{
829
TR_ASSERT(false, "getSetSignValueNode only valid for setSign ops and not op %d\n", self()->getOpCodeValue());
830
}
831
return setSignValueNode;
832
}
833
834
bool
835
J9::Node::alwaysGeneratesAKnownCleanSign()
836
{
837
TR::Compilation *comp = TR::comp();
838
return comp->cg()->alwaysGeneratesAKnownCleanSign(self());
839
}
840
841
bool
842
J9::Node::alwaysGeneratesAKnownPositiveCleanSign()
843
{
844
TR::Compilation *comp = TR::comp();
845
return comp->cg()->alwaysGeneratesAKnownPositiveCleanSign(self());
846
}
847
848
#ifdef TR_TARGET_S390
849
int32_t
850
J9::Node::getStorageReferenceSize()
851
{
852
TR::Compilation *comp = TR::comp();
853
if (self()->getType().isAggregate())
854
{
855
return self()->getSize();
856
}
857
else if (self()->getOpCode().isBCDToNonBCDConversion())
858
{
859
return self()->getStorageReferenceSourceSize();
860
}
861
else
862
{
863
TR_ASSERT(self()->getType().isBCD(), "node result type should be a BCD type in getStorageReferenceSize and not type %s\n", self()->getDataType().toString());
864
int32_t size = 0;
865
switch (self()->getOpCodeValue())
866
{
867
case TR::l2pd:
868
size = comp->cg()->getLongToPackedFixedSize();
869
break;
870
case TR::i2pd:
871
size = comp->cg()->getIntegerToPackedFixedSize();
872
break;
873
case TR::pdadd:
874
case TR::pdsub:
875
size = comp->cg()->getPDAddSubEncodedSize(self());
876
break;
877
case TR::pdmul:
878
size = comp->cg()->getPDMulEncodedSize(self());
879
break;
880
case TR::pddiv:
881
case TR::pdrem:
882
size = comp->cg()->getPDDivEncodedSize(self());
883
break;
884
case TR::ud2pd:
885
case TR::udsl2pd:
886
case TR::udst2pd:
887
size = comp->cg()->getUnicodeToPackedFixedResultSize();
888
break;
889
default:
890
size = self()->getSize();
891
break;
892
}
893
894
if ((self()->getOpCode().isPackedRightShift() && self()->getDecimalRound() != 0) || self()->getOpCodeValue() == TR::pdshlOverflow)
895
size = std::max(self()->getSize(), self()->getFirstChild()->getSize());
896
897
return size;
898
}
899
}
900
901
int32_t
902
J9::Node::getStorageReferenceSourceSize()
903
{
904
TR::Compilation *comp = TR::comp();
905
int32_t size = 0;
906
switch (self()->getOpCodeValue())
907
{
908
case TR::pd2l:
909
case TR::pd2lu:
910
case TR::pd2lOverflow:
911
size = comp->cg()->getPackedToLongFixedSize();
912
break;
913
case TR::pd2i:
914
case TR::pd2iu:
915
case TR::pd2iOverflow:
916
size = comp->cg()->getPackedToIntegerFixedSize();
917
break;
918
default:
919
TR_ASSERT(false, "node %p and type %s not supported in getStorageReferenceSourceSize\n", self(), self()->getDataType().toString());
920
break;
921
}
922
return size;
923
}
924
925
TR_PseudoRegister*
926
J9::Node::getPseudoRegister()
927
{
928
TR_ASSERT(self()->getOpCodeValue() != TR::BBStart, "don't call getPseudoRegister for a BBStart");
929
TR::Register *reg = self()->getRegister();
930
return reg ? reg->getPseudoRegister() : 0;
931
}
932
933
TR_OpaquePseudoRegister*
934
J9::Node::getOpaquePseudoRegister()
935
{
936
TR_ASSERT(self()->getOpCodeValue() != TR::BBStart, "don't call getOpaquePseudoRegister for a BBStart");
937
TR::Register *reg = self()->getRegister();
938
return reg ? reg->getOpaquePseudoRegister() : 0;
939
}
940
941
#endif //S390
942
943
944
bool
945
J9::Node::pdshrRoundIsConstantZero()
946
{
947
if (self()->getOpCode().isPackedRightShift())
948
{
949
if (self()->getThirdChild()->getOpCode().isLoadConst() &&
950
self()->getThirdChild()->get64bitIntegralValue() == 0)
951
{
952
return true;
953
}
954
}
955
else
956
{
957
TR_ASSERT(false, "Only packed shift right operations have a round node (op %d)\n", self()->getOpCodeValue());
958
}
959
return false;
960
}
961
962
/*
963
* \brief
964
* Get the node type signature
965
*
966
* \parm len
967
*
968
* \parm allocKind
969
*
970
* \parm parmAsAuto
971
* For a node with parm symbol, the API is used in two different ways because the slot for dead
972
* parm symbol can be reused for variables of any type. When \parm parmAsAuto is true, parm is
973
* treated as other auto and the type signature is ignored. When \parm parmAsAuto is false, the
974
* type signature of the parm symbol is returned.
975
*/
976
const char *
977
J9::Node::getTypeSignature(int32_t & len, TR_AllocationKind allocKind, bool parmAsAuto)
978
{
979
TR::Compilation * c = TR::comp();
980
// todo: can do better for array element references
981
if (!self()->getOpCode().hasSymbolReference())
982
return 0;
983
984
TR::SymbolReference *symRef = self()->getSymbolReference();
985
TR::Symbol *sym = symRef->getSymbol();
986
if (parmAsAuto && sym->isParm())
987
return 0;
988
bool allowForAOT = c->getOption(TR_UseSymbolValidationManager);
989
TR_PersistentClassInfo * classInfo = c->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(c->getCurrentMethod()->containingClass(), c, allowForAOT);
990
TR::Node * node = self();
991
TR_PersistentFieldInfo * fieldInfo = classInfo && classInfo->getFieldInfo() ? classInfo->getFieldInfo()->findFieldInfo(c, node, false) : 0;
992
if (fieldInfo && fieldInfo->isTypeInfoValid() && fieldInfo->getNumChars() > 0)
993
{
994
len = fieldInfo->getNumChars();
995
return fieldInfo->getClassPointer();
996
}
997
998
if (self()->getOpCodeValue() == TR::multianewarray)
999
symRef = self()->getChild(self()->getNumChildren()-1)->getSymbolReference();
1000
const char * sig = symRef->getTypeSignature( len, allocKind);
1001
if (sig)
1002
return sig;
1003
1004
if (self()->getOpCodeValue() == TR::aloadi && symRef->getCPIndex() == -1)
1005
{
1006
// Look for an array element reference. If this is such a reference, look
1007
// down to get the signature of the base and strip off one layer of array
1008
// indirection.
1009
//
1010
TR::Node * child = self()->getFirstChild();
1011
if (child->isInternalPointer())
1012
{
1013
child = child->getFirstChild();
1014
sig = child->getTypeSignature(len, allocKind, parmAsAuto);
1015
if (sig != NULL && *sig == '[')
1016
{
1017
--len;
1018
return sig+1;
1019
}
1020
}
1021
}
1022
1023
// todo: could do more work to figure out types for 'new' nodes
1024
1025
return 0;
1026
}
1027
1028
1029
1030
bool
1031
J9::Node::isTruncatingOrWideningAggrOrBCD()
1032
{
1033
TR_ASSERT(self()->getType().isAggregate() || self()->getType().isBCD(),
1034
"truncatingOrWideningAggrOrBCD should only be called on BCD or aggr!");
1035
TR_ASSERT(self()->getValueChild() != NULL,
1036
"getValueChild should have a value!");
1037
1038
int32_t nodeSize = 0;
1039
int32_t valueSize = 0;
1040
1041
if (self()->getType().isAggregate())
1042
{
1043
nodeSize = self()->getSize();
1044
valueSize = self()->getValueChild()->getSize();
1045
}
1046
else if (self()->getType().isBCD())
1047
{
1048
nodeSize = self()->getDecimalPrecision();
1049
valueSize = self()->getValueChild()->getDecimalPrecision();
1050
}
1051
1052
return (nodeSize != valueSize);
1053
}
1054
1055
bool
1056
J9::Node::canRemoveArithmeticOperand()
1057
{
1058
TR::Compilation * comp = TR::comp();
1059
if (!comp->getOption(TR_KeepBCDWidening) && self()->getOpCodeValue() == TR::pdclean)
1060
{
1061
return true;
1062
}
1063
else if (self()->getOpCodeValue() == TR::pdSetSign)
1064
{
1065
// could also do for pdshxSetSign if pdshx is left in place but shift with setSign is usually cheaper than without
1066
if (self()->isNonNegative() && self()->getFirstChild()->isNonNegative())
1067
return true;
1068
else if (self()->isNonPositive() && self()->getFirstChild()->isNonPositive())
1069
return true;
1070
}
1071
return false;
1072
}
1073
1074
uint32_t
1075
J9::Node::hashOnBCDOrAggrLiteral(char *lit, size_t litSize)
1076
{
1077
uint32_t hash = 0;
1078
for (int32_t i = 0; i < litSize && i < TR_MAX_CHARS_FOR_HASH; i++)
1079
hash+=lit[i];
1080
hash+=(litSize*TR_DECIMAL_HASH); // avoid collisions for numbers like 10 and 100
1081
return hash;
1082
}
1083
1084
1085
1086
bool
1087
J9::Node::referencesSymbolInSubTree(TR::SymbolReference* symRef, vcount_t visitCount)
1088
{
1089
// The visit count in the node must be maintained by this method.
1090
//
1091
vcount_t oldVisitCount = self()->getVisitCount();
1092
if (oldVisitCount == visitCount)
1093
return false;
1094
self()->setVisitCount(visitCount);
1095
1096
if (self()->getOpCode().hasSymbolReference())
1097
{
1098
if (self()->getSymbolReference()->getReferenceNumber() == symRef->getReferenceNumber())
1099
{
1100
return true;
1101
}
1102
}
1103
1104
// For all other subtrees collect all symbols that could be killed between
1105
// here and the next reference.
1106
//
1107
for (int32_t i = self()->getNumChildren()-1; i >= 0; i--)
1108
{
1109
TR::Node * child = self()->getChild(i);
1110
if (child->referencesSymbolInSubTree(symRef, visitCount)) return true;
1111
}
1112
1113
return false;
1114
}
1115
1116
bool
1117
J9::Node::referencesMayKillAliasInSubTree(TR::Node * rootNode, vcount_t visitCount)
1118
{
1119
TR::Compilation * comp = TR::comp();
1120
TR::SparseBitVector references (comp->allocator());
1121
self()->getSubTreeReferences(references, visitCount);
1122
1123
return rootNode->mayKill().containsAny(references, comp);
1124
}
1125
1126
void
1127
J9::Node::getSubTreeReferences(TR::SparseBitVector &references, vcount_t visitCount) {
1128
// The visit count in the node must be maintained by this method.
1129
//
1130
vcount_t oldVisitCount = self()->getVisitCount();
1131
1132
if (oldVisitCount == visitCount) return;
1133
1134
self()->setVisitCount(visitCount);
1135
1136
if (self()->getOpCode().hasSymbolReference() &&
1137
self()->getSymbolReference() &&
1138
(self()->getOpCodeValue() != TR::loadaddr)) // a loadaddr is not really a reference
1139
{
1140
references[self()->getSymbolReference()->getReferenceNumber()]=true;
1141
}
1142
1143
for (int32_t i = self()->getNumChildren()-1; i >= 0; i--)
1144
self()->getChild(i)->getSubTreeReferences(references, visitCount);
1145
}
1146
1147
TR_ParentOfChildNode*
1148
J9::Node::referencesSymbolExactlyOnceInSubTree(
1149
TR::Node* parent, int32_t childNum, TR::SymbolReference* symRef, vcount_t visitCount)
1150
{
1151
// The visit count in the node must be maintained by this method.
1152
//
1153
TR::Compilation * comp = TR::comp();
1154
vcount_t oldVisitCount = self()->getVisitCount();
1155
if (oldVisitCount == visitCount)
1156
return NULL;
1157
self()->setVisitCount(visitCount);
1158
1159
if (self()->getOpCode().hasSymbolReference() && (self()->getSymbolReference()->getReferenceNumber() == symRef->getReferenceNumber()))
1160
{
1161
TR_ParentOfChildNode* pNode = new (comp->trStackMemory()) TR_ParentOfChildNode(parent, childNum);
1162
return pNode;
1163
}
1164
1165
// For all other subtrees, see if any has a ref. If exactly one does, return it
1166
TR_ParentOfChildNode* matchNode=NULL;
1167
for (int32_t i = self()->getNumChildren()-1; i >= 0; i--)
1168
{
1169
TR::Node * child = self()->getChild(i);
1170
TR_ParentOfChildNode* curr = child->referencesSymbolExactlyOnceInSubTree(self(), i, symRef, visitCount);
1171
if (curr)
1172
{
1173
if (matchNode)
1174
{
1175
return NULL;
1176
}
1177
matchNode = curr;
1178
}
1179
}
1180
1181
return matchNode;
1182
}
1183
1184
/**
1185
* Node field functions
1186
*/
1187
1188
#ifdef TR_TARGET_S390
1189
1190
TR_StorageReference *
1191
J9::Node::getStorageReferenceHint()
1192
{
1193
TR_ASSERT(self()->getOpCode().canHaveStorageReferenceHint(), "attempting to access _storageReferenceHint field for node %s %p that does not have it", self()->getOpCode().getName(), this);
1194
if (_storageReferenceHint && !_storageReferenceHint->hintHasBeenUsed())
1195
return _storageReferenceHint;
1196
else
1197
return NULL;
1198
}
1199
1200
TR_StorageReference *
1201
J9::Node::setStorageReferenceHint(TR_StorageReference *s)
1202
{
1203
TR_ASSERT(self()->getOpCode().canHaveStorageReferenceHint(), "attempting to access _storageReferenceHint field for node %s %p that does not have it", self()->getOpCode().getName(), this);
1204
return (_storageReferenceHint = s);
1205
}
1206
1207
#endif
1208
1209
/**
1210
* Node field functions end
1211
*/
1212
1213
1214
1215
1216
1217
/**
1218
* UnionPropertyB functions
1219
*/
1220
1221
bool
1222
J9::Node::hasDecimalInfo()
1223
{
1224
// _decimalInfo is only valid if opcode has datatype
1225
if (self()->getOpCode().hasNoDataType())
1226
return false;
1227
1228
// _decimalInfo is used for those languages that return true as determined by the code below
1229
return
1230
// Any node with a BCD type (pdloadi, pdadd, zd2pd, pdstorei etc)
1231
self()->getType().isBCD() ||
1232
// Conversions from a BCD type to a float to encode # of fractional digits (pd2f, pd2d, etc.)
1233
self()->getOpCode().isConversionWithFraction()
1234
// BCD types and also any BCD ifs and compares (e.g. ifpdcmpxx, pdcmpxx)
1235
|| self()->chkOpsCastedToBCD();
1236
}
1237
1238
bool
1239
J9::Node::hasBCDFlags()
1240
{
1241
// used for BCDCHK only
1242
return self()->getOpCodeValue() == TR::BCDCHK;
1243
}
1244
1245
J9::Node::UnionPropertyB_Type
1246
J9::Node::getUnionPropertyB_Type()
1247
{
1248
if (self()->hasDecimalInfo())
1249
// in order to determine this correctly, require children and symRef to be already defined
1250
// as depends on getDataType which in term depends on these
1251
return HasDecimalInfo;
1252
else if (self()->hasBCDFlags())
1253
return HasBcdFlags;
1254
else
1255
return HasNoUnionPropertyB;
1256
}
1257
1258
bool
1259
J9::Node::hasDecimalPrecision()
1260
{
1261
return self()->getType().isBCD();
1262
}
1263
1264
bool
1265
J9::Node::hasDecimalAdjust()
1266
{
1267
return !self()->getOpCode().isShift() && !self()->getOpCode().isConversionWithFraction() && self()->getType().isBCD();
1268
}
1269
1270
bool
1271
J9::Node::hasSetSign()
1272
{
1273
return self()->getType().isBCD() && self()->getOpCode().isSetSignOnNode();
1274
}
1275
1276
bool
1277
J9::Node::hasDecimalFraction()
1278
{
1279
return self()->getOpCode().isConversionWithFraction();
1280
}
1281
1282
bool
1283
J9::Node::hasDecimalRound()
1284
{
1285
return self()->getType().isBCD() && !self()->getOpCode().isRightShift();
1286
}
1287
1288
1289
1290
void
1291
J9::Node::setDecimalPrecision(int32_t p)
1292
{
1293
TR_ASSERT(self()->getType().isBCD(), "opcode not supported for setDecimalPrecision on node %p\n", self());
1294
TR_ASSERT(p > 0 && p <= TR_MAX_DECIMAL_PRECISION, "unexpected decimal precision %d on node %p\n", p, self());
1295
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalPrecision field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1296
if (_unionPropertyB._decimalInfo._decimalPrecision != TR::DataType::getInvalidDecimalPrecision() &&
1297
(uint32_t)p < _unionPropertyB._decimalInfo._decimalPrecision)
1298
{
1299
if (self()->getKnownOrAssumedSignCode() != raw_bcd_sign_0xc)
1300
{
1301
_unionPropertyB._decimalInfo._hasCleanSign = 0;
1302
}
1303
if (self()->chkSkipPadByteClearing())
1304
self()->setSkipPadByteClearing(false);
1305
}
1306
_unionPropertyB._decimalInfo._decimalPrecision = (uint32_t)p;
1307
}
1308
1309
uint8_t
1310
J9::Node::getDecimalPrecision()
1311
{
1312
TR_ASSERT(self()->getType().isBCD(), "opcode not supported for getDecimalPrecision on node %p\n", self());
1313
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalPrecision field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1314
TR_ASSERT(_unionPropertyB._decimalInfo._decimalPrecision > 0 && _unionPropertyB._decimalInfo._decimalPrecision <= TR_MAX_DECIMAL_PRECISION,
1315
"unexpected decimal precision %d on node %p\n", _unionPropertyB._decimalInfo._decimalPrecision, self());
1316
return _unionPropertyB._decimalInfo._decimalPrecision;
1317
}
1318
1319
1320
1321
// These precision setting routines set a precision big enough to hold the full computed result
1322
// A caller or codegen may choose to set a different value (bigger or smaller) to satisfy a specific
1323
// semantic or encoding requirement -- see getPDMulEncodedPrecision et al. in the platform code generators
1324
void
1325
J9::Node::setPDMulPrecision()
1326
{
1327
TR_ASSERT(self()->getOpCode().isPackedMultiply(), "setPDMulPrecision only valid for pdmul nodes\n");
1328
TR_ASSERT(self()->getNumChildren() >= 2, "expecting >= 2 children and not %d children on a packed multiply node\n", self()->getNumChildren());
1329
self()->setDecimalPrecision(self()->getFirstChild()->getDecimalPrecision() + self()->getSecondChild()->getDecimalPrecision());
1330
}
1331
1332
void
1333
J9::Node::setPDAddSubPrecision()
1334
{
1335
TR_ASSERT(self()->getOpCode().isPackedAdd() || self()->getOpCode().isPackedSubtract(), "setPDAddSubPrecision only valid for pdadd/pdsub nodes\n");
1336
TR_ASSERT(self()->getNumChildren() >= 2, "expecting >= 2 children and not %d children on a packed add/sub node\n", self()->getNumChildren());
1337
self()->setDecimalPrecision(std::max(self()->getFirstChild()->getDecimalPrecision(), self()->getSecondChild()->getDecimalPrecision())+1);
1338
}
1339
1340
void
1341
J9::Node::setDecimalAdjust(int32_t a)
1342
{
1343
TR_ASSERT(a >= TR::DataType::getMinDecimalAdjust() && a <= TR::DataType::getMaxDecimalAdjust(), "unexpected decimal adjust %d\n", a);
1344
// conversions should not have an adjust
1345
TR_ASSERT(!self()->getOpCode().isShift(), "decimalAdjust is the 2nd child on pdshr/pdshl nodes\n");
1346
TR_ASSERT(!self()->getOpCode().isConversionWithFraction(), "conversions nodes should not use setDecimalAdjust\n");
1347
TR_ASSERT(self()->getType().isBCD(), "type not supported for setDecimalAdjust\n");
1348
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalAdjustOrFractionOrDivisor field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1349
_unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor = a;
1350
}
1351
1352
int32_t
1353
J9::Node::getDecimalAdjust()
1354
{
1355
// conversions should not have an adjust
1356
TR_ASSERT(!self()->getOpCode().isConversionWithFraction(), "conversions nodes should not use getDecimalAdjust\n");
1357
TR_ASSERT(self()->getType().isBCD(), "type not supported for getDecimalAdjust\n");
1358
int64_t adjust = 0;
1359
if (self()->getOpCode().isShift() && self()->getSecondChild()->getOpCode().isLoadConst())
1360
adjust = self()->getOpCode().isRightShift() ? -self()->getSecondChild()->get64bitIntegralValue() : self()->getSecondChild()->get64bitIntegralValue();
1361
else
1362
{
1363
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalAdjustOrFractionOrDivisor field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1364
adjust = _unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor;
1365
}
1366
TR_ASSERT(adjust >= TR::DataType::getMinDecimalAdjust() && adjust <= TR::DataType::getMaxDecimalAdjust(),
1367
"unexpected decimal adjust %d\n", (int32_t)adjust);
1368
return (int32_t)adjust;
1369
}
1370
1371
1372
1373
void
1374
J9::Node::setDecimalFraction(int32_t f)
1375
{
1376
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalAdjustOrFractionOrDivisor field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1377
TR_ASSERT(f >= TR::DataType::getMinDecimalFraction() && f <= TR::DataType::getMaxDecimalFraction(), "unexpected decimal fraction %d\n", f);
1378
TR_ASSERT(self()->getOpCode().isConversionWithFraction(), "only valid for conversion nodes that have a fraction\n"); // such as f2pd or pd2f
1379
_unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor = f;
1380
}
1381
1382
int32_t
1383
J9::Node::getDecimalFraction()
1384
{
1385
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalAdjustOrFractionOrDivisor field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1386
TR_ASSERT(_unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor >= TR::DataType::getMinDecimalFraction() && _unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor <= TR::DataType::getMaxDecimalFraction(),
1387
"unexpected decimal fraction %d\n", _unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor);
1388
TR_ASSERT(self()->getOpCode().isConversionWithFraction(), "only valid for conversion nodes that have a fraction\n"); // such as f2pd or pd2f
1389
return _unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor;
1390
}
1391
1392
1393
1394
/**
1395
* Source precisions are valid for conversions from a non-BCD type to a BCD type
1396
*/
1397
bool
1398
J9::Node::canHaveSourcePrecision()
1399
{
1400
if (self()->getOpCode().isConversion() && self()->getType().isBCD() && !self()->getFirstChild()->getType().isBCD())
1401
return true;
1402
return false;
1403
}
1404
1405
bool
1406
J9::Node::hasSourcePrecision()
1407
{
1408
if (!self()->canHaveSourcePrecision())
1409
return false;
1410
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalSourcePrecisionOrDividend field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1411
return (_unionPropertyB._decimalInfo._decimalSourcePrecisionOrDividend > 0);
1412
}
1413
1414
void
1415
J9::Node::setSourcePrecision(int32_t prec)
1416
{
1417
TR_ASSERT(self()->canHaveSourcePrecision(), "setSourcePrecision can only be called on a non-BCD-to-BCD conversion node\n");
1418
TR_ASSERT(prec >= 1, "source precision must be >= 1\n");
1419
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalSourcePrecisionOrDividend field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1420
_unionPropertyB._decimalInfo._decimalSourcePrecisionOrDividend = prec;
1421
}
1422
1423
int32_t
1424
J9::Node::getSourcePrecision()
1425
{
1426
TR_ASSERT(self()->canHaveSourcePrecision(), "getSourcePrecision can only be called on a non-BCD-to-BCD conversion node\n");
1427
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalSourcePrecisionOrDividend field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1428
if (_unionPropertyB._decimalInfo._decimalSourcePrecisionOrDividend == 0)
1429
return TR_MAX_DECIMAL_PRECISION;
1430
else
1431
return _unionPropertyB._decimalInfo._decimalSourcePrecisionOrDividend;
1432
}
1433
1434
int32_t
1435
J9::Node::getDecimalAdjustOrFractionOrDivisor()
1436
{
1437
if (self()->getOpCode().isConversionWithFraction())
1438
return self()->getDecimalFraction();
1439
else
1440
return self()->getDecimalAdjust();
1441
}
1442
1443
int32_t
1444
J9::Node::getDecimalRoundOrDividend()
1445
{
1446
return self()->getDecimalRound();
1447
}
1448
1449
bool
1450
J9::Node::isSetSignValueOnNode()
1451
{
1452
if (self()->hasSetSign())
1453
{
1454
TR_ASSERT(self()->getSetSign() != raw_bcd_sign_unknown,"%s (%p) is a setSign node but does not have a value setSign value\n", self()->getOpCode().getName(), self());
1455
return true;
1456
}
1457
else
1458
{
1459
return false;
1460
}
1461
}
1462
1463
void
1464
J9::Node::setSetSign(TR_RawBCDSignCode setSign)
1465
{
1466
TR_ASSERT(self()->hasSetSign(), "setSetSign only supported for setsign nodes (%s %p)\n", self()->getOpCode().getName(), self());
1467
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._setSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1468
_unionPropertyB._decimalInfo._setSign = setSign;
1469
}
1470
1471
TR_RawBCDSignCode
1472
J9::Node::getSetSign()
1473
{
1474
TR_ASSERT(self()->hasSetSign(), "getSetSign only supported for setsign nodes (%s %p)\n", self()->getOpCode().getName(), self());
1475
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._setSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1476
return _unionPropertyB._decimalInfo._setSign;
1477
}
1478
1479
bool
1480
J9::Node::isDecimalSizeAndShapeEquivalent(TR::Node *other)
1481
{
1482
if (self()->getDecimalPrecision() == other->getDecimalPrecision() &&
1483
self()->getDecimalAdjustOrFractionOrDivisor() == other->getDecimalAdjustOrFractionOrDivisor() &&
1484
self()->getDecimalRoundOrDividend() == other->getDecimalRoundOrDividend())
1485
{
1486
if (self()->getOpCode().isSetSignOnNode() && other->getOpCode().isSetSignOnNode() &&
1487
self()->getSetSign() != other->getSetSign())
1488
{
1489
return false;
1490
}
1491
else
1492
{
1493
return true;
1494
}
1495
}
1496
else
1497
{
1498
return false;
1499
}
1500
}
1501
1502
1503
1504
void
1505
J9::Node::setDecimalRound(int32_t r)
1506
{
1507
TR_ASSERT(r >= 0 && r <= TR::DataType::getMaxDecimalRound(), "unexpected decimal round %d\n", r);
1508
TR_ASSERT(self()->getType().isBCD(), "type not supported for setDecimalRound\n");
1509
TR_ASSERT(!self()->getOpCode().isRightShift(), "decimalRound is the 3rd child on pdshr nodes\n");
1510
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._round field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1511
_unionPropertyB._decimalInfo._round = (r > 0 ? 1 : 0);
1512
}
1513
1514
uint8_t
1515
J9::Node::getDecimalRound()
1516
{
1517
TR_ASSERT(self()->getType().isBCD(), "type not supported for getDecimalRound\n");
1518
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._round field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1519
int64_t round = 0;
1520
if (self()->getOpCode().isPackedRightShift() && self()->getChild(2)->getOpCode().isLoadConst())
1521
round = self()->getChild(2)->get64bitIntegralValue();
1522
else
1523
round = (_unionPropertyB._decimalInfo._round == 1 ? 5 : 0);
1524
TR_ASSERT(round >= 0 && round <= TR::DataType::getMaxDecimalRound() && round <= TR::getMaxUnsigned<TR::Int8>(), "unexpected decimal round %d\n", (int32_t)round);
1525
return (uint8_t)round;
1526
}
1527
1528
1529
1530
bool
1531
J9::Node::signStateIsKnown()
1532
{
1533
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signStateIsKnown field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1534
return _unionPropertyB._decimalInfo._signStateIsKnown == 1;
1535
}
1536
1537
void
1538
J9::Node::setSignStateIsKnown()
1539
{
1540
if (self()->signStateIsAssumed())
1541
self()->resetDecimalSignFlags(); // ensure any lingering assumed sign state is cleared
1542
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signStateIsKnown field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1543
_unionPropertyB._decimalInfo._signStateIsKnown = 1;
1544
}
1545
1546
bool
1547
J9::Node::signStateIsAssumed()
1548
{
1549
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signStateIsKnown field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1550
return _unionPropertyB._decimalInfo._signStateIsKnown == 0;
1551
}
1552
1553
void
1554
J9::Node::setSignStateIsAssumed()
1555
{
1556
if (self()->signStateIsKnown())
1557
self()->resetDecimalSignFlags(); // ensure any lingering known sign state is cleared
1558
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signStateIsKnown field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1559
_unionPropertyB._decimalInfo._signStateIsKnown = 0;
1560
}
1561
1562
1563
1564
bool
1565
J9::Node::hasKnownCleanSign()
1566
{
1567
TR_ASSERT(self()->getType().isBCD(), "hasKnownCleanSign only supported for BCD type nodes\n");
1568
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasCleanSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1569
if (self()->alwaysGeneratesAKnownCleanSign())
1570
return true;
1571
else
1572
return self()->signStateIsKnown() && _unionPropertyB._decimalInfo._hasCleanSign == 1;
1573
}
1574
1575
void
1576
J9::Node::setHasKnownCleanSign(bool v)
1577
{
1578
TR::Compilation *c = TR::comp();
1579
TR_ASSERT(self()->getType().isBCD(), "setHasKnownCleanSign only supported for BCD type nodes\n");
1580
if (self()->getType().isBCD() &&
1581
performNodeTransformation2(c, "O^O NODE FLAGS: Setting hasKnownCleanSign flag on node %p to %d\n", self(), v))
1582
{
1583
self()->setSignStateIsKnown();
1584
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasCleanSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1585
_unionPropertyB._decimalInfo._hasCleanSign = v ? 1 : 0;
1586
}
1587
}
1588
1589
bool
1590
J9::Node::hasAssumedCleanSign()
1591
{
1592
TR_ASSERT(self()->getType().isBCD(), "hasAssumedCleanSign only supported for BCD type nodes\n");
1593
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasCleanSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1594
return self()->signStateIsAssumed() && _unionPropertyB._decimalInfo._hasCleanSign == 1;
1595
}
1596
1597
void
1598
J9::Node::setHasAssumedCleanSign(bool v)
1599
{
1600
TR::Compilation * c = TR::comp();
1601
TR_ASSERT(self()->getType().isBCD(), "setHasAssumedCleanSign only supported for BCD type nodes\n");
1602
if (self()->getType().isBCD() &&
1603
performNodeTransformation2(c, "O^O NODE FLAGS: Setting hasAssumedCleanSign flag on node %p to %d\n", self(), v))
1604
{
1605
self()->setSignStateIsAssumed();
1606
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasCleanSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1607
_unionPropertyB._decimalInfo._hasCleanSign = v ? 1 : 0;
1608
}
1609
}
1610
1611
bool
1612
J9::Node::hasKnownOrAssumedCleanSign()
1613
{
1614
TR_ASSERT(self()->getType().isBCD(), "hasKnownOrAssumedCleanSign only supported for BCD type nodes\n");
1615
return self()->hasKnownCleanSign() || self()->hasAssumedCleanSign();
1616
}
1617
1618
void
1619
J9::Node::setHasKnownAndAssumedCleanSign(bool v)
1620
{
1621
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasCleanSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1622
_unionPropertyB._decimalInfo._hasCleanSign = 0;
1623
}
1624
1625
void
1626
J9::Node::transferCleanSign(TR::Node *srcNode)
1627
{
1628
if (srcNode == NULL) return;
1629
1630
if (srcNode->hasKnownCleanSign())
1631
self()->setHasKnownCleanSign(true);
1632
else if (srcNode->hasAssumedCleanSign())
1633
self()->setHasAssumedCleanSign(true);
1634
}
1635
1636
1637
1638
bool
1639
J9::Node::hasKnownPreferredSign()
1640
{
1641
TR_ASSERT(self()->getType().isBCD(), "hasKnownPreferredSign only supported for BCD type nodes\n");
1642
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasPreferredSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1643
return self()->signStateIsKnown() && _unionPropertyB._decimalInfo._hasPreferredSign == 1;
1644
}
1645
1646
void
1647
J9::Node::setHasKnownPreferredSign(bool v)
1648
{
1649
TR::Compilation *c = TR::comp();
1650
TR_ASSERT(self()->getType().isBCD(), "setHasKnownPreferredSign only supported for BCD type nodes\n");
1651
if (self()->getType().isBCD() &&
1652
performNodeTransformation2(c, "O^O NODE FLAGS: Setting hasKnownPreferredSign flag on node %p to %d\n", self(), v))
1653
{
1654
self()->setSignStateIsKnown();
1655
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasPreferredSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1656
_unionPropertyB._decimalInfo._hasPreferredSign= v ? 1 : 0;
1657
}
1658
}
1659
1660
bool
1661
J9::Node::hasAssumedPreferredSign()
1662
{
1663
TR_ASSERT(self()->getType().isBCD(), "hasAssumedPreferredSign only supported for BCD type nodes\n");
1664
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasPreferredSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1665
return self()->signStateIsAssumed() && _unionPropertyB._decimalInfo._hasPreferredSign == 1;
1666
}
1667
1668
void
1669
J9::Node::setHasAssumedPreferredSign(bool v)
1670
{
1671
TR::Compilation *c = TR::comp();
1672
TR_ASSERT(self()->getType().isBCD(), "setHasAssumedPreferredSign only supported for BCD type nodes\n");
1673
if (self()->getType().isBCD() &&
1674
performNodeTransformation2(c, "O^O NODE FLAGS: Setting hasAssumedPreferredSign flag on node %p to %d\n", self(), v))
1675
{
1676
self()->setSignStateIsAssumed();
1677
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasPreferredSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1678
_unionPropertyB._decimalInfo._hasPreferredSign= v ? 1 : 0;
1679
}
1680
}
1681
1682
bool
1683
J9::Node::hasKnownOrAssumedPreferredSign()
1684
{
1685
TR_ASSERT(self()->getType().isBCD(), "hasKnownOrAssumedPreferredSign only supported for BCD type nodes\n");
1686
return self()->hasKnownPreferredSign() || self()->hasAssumedPreferredSign();
1687
}
1688
1689
bool
1690
J9::Node::hasKnownSignCode()
1691
{
1692
TR_ASSERT(self()->getType().isBCD(), "hasKnownSignCode only supported for BCD type nodes\n");
1693
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signCode field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1694
return self()->signStateIsKnown() && (_unionPropertyB._decimalInfo._signCode != raw_bcd_sign_unknown);
1695
}
1696
1697
TR_RawBCDSignCode
1698
J9::Node::getKnownSignCode()
1699
{
1700
TR_ASSERT(self()->getType().isBCD(), "getKnownSignCode only supported for BCD type nodes\n");
1701
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signCode field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1702
return self()->signStateIsKnown() ? _unionPropertyB._decimalInfo._signCode : raw_bcd_sign_unknown;
1703
}
1704
1705
bool
1706
J9::Node::hasAssumedSignCode()
1707
{
1708
TR_ASSERT(self()->getType().isBCD(), "hasAssumedSignCode only supported for BCD type nodes\n");
1709
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signCode field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1710
return self()->signStateIsAssumed() && (_unionPropertyB._decimalInfo._signCode != raw_bcd_sign_unknown);
1711
}
1712
1713
TR_RawBCDSignCode
1714
J9::Node::getAssumedSignCode()
1715
{
1716
TR_ASSERT(self()->getType().isBCD(), "getAssumedSignCode only supported for BCD type nodes\n");
1717
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signCode field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1718
return self()->signStateIsAssumed() ? _unionPropertyB._decimalInfo._signCode : raw_bcd_sign_unknown;
1719
}
1720
1721
bool
1722
J9::Node::hasKnownOrAssumedSignCode()
1723
{
1724
TR_ASSERT(self()->getType().isBCD(), "hasKnownOrAssumedSignCode only supported for BCD type nodes\n");
1725
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalPrecision field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1726
return self()->hasKnownSignCode() || self()->hasAssumedSignCode();
1727
}
1728
1729
TR_RawBCDSignCode
1730
J9::Node::getKnownOrAssumedSignCode()
1731
{
1732
TR_ASSERT(self()->getType().isBCD(), "getKnownSignCode only supported for BCD type nodes\n");
1733
if (self()->hasKnownSignCode())
1734
return self()->getKnownSignCode();
1735
else if (self()->hasAssumedSignCode())
1736
return self()->getAssumedSignCode();
1737
else
1738
return raw_bcd_sign_unknown;
1739
}
1740
1741
void
1742
J9::Node::setKnownOrAssumedSignCode(TR_RawBCDSignCode sign, bool isKnown)
1743
{
1744
TR::Compilation *c = TR::comp();
1745
TR_ASSERT(self()->getType().isBCD(), "setKnownSignCode only supported for BCD type nodes\n");
1746
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo fields for node %s %p that does not have it", self()->getOpCode().getName(), self());
1747
// TODO: start tracking SeparateOneByte and SeparateTwoByte sign sizes too
1748
if (self()->getType().isBCD() && TR::Node::typeSupportedForSignCodeTracking(self()->getDataType()))
1749
{
1750
if (performNodeTransformation2(c, "O^O NODE FLAGS: Setting knownSignCode on node %p to %s\n", self(), TR::DataType::getName(sign)))
1751
{
1752
if (isKnown)
1753
self()->setSignStateIsKnown();
1754
else
1755
self()->setSignStateIsAssumed();
1756
_unionPropertyB._decimalInfo._signCode = sign;
1757
if (TR::DataType::rawSignIsPositive(self()->getDataType(), TR::DataType::getValue(sign)))
1758
self()->setIsNonNegative(true); // >= 0
1759
else if (TR::DataType::rawSignIsNegative(self()->getDataType(), TR::DataType::getValue(sign)))
1760
self()->setIsNonPositive(true); // <= 0 negative zero is possible
1761
}
1762
if ((sign == raw_bcd_sign_0xc) && (0xc == TR::DataType::getPreferredPlusCode()))
1763
_unionPropertyB._decimalInfo._hasCleanSign = 1;
1764
if ((sign == raw_bcd_sign_0xc || sign == raw_bcd_sign_0xd) && (0xc == TR::DataType::getPreferredPlusCode() && 0xd == TR::DataType::getPreferredMinusCode()))
1765
_unionPropertyB._decimalInfo._hasPreferredSign = 1;
1766
}
1767
}
1768
1769
void
1770
J9::Node::setKnownSignCode(TR_RawBCDSignCode sign)
1771
{
1772
self()->setKnownOrAssumedSignCode(sign, true); // isKnown=true
1773
}
1774
1775
void
1776
J9::Node::transferSignCode(TR::Node *srcNode)
1777
{
1778
if (srcNode == NULL) return;
1779
1780
if (srcNode->hasKnownSignCode())
1781
self()->setKnownSignCode(srcNode->getKnownSignCode());
1782
else if (srcNode->hasAssumedSignCode())
1783
self()->setAssumedSignCode(srcNode->getAssumedSignCode());
1784
}
1785
1786
1787
1788
/**
1789
* The mapping to/from TR_BCDSignCode from/to the 0xc/0xd/0xf 'raw' encodings in setKnownSignCode/knownSignCodeIs below
1790
* is temporary until TR_BCDSignCode is tracked on the nodes instead of TR_RawBCDSignCode
1791
* Doing it this way allows new code (such as VP constrainBCDAggrLoad) to start using this new more general interface
1792
* The final code will be just calling setKnownOrAssumedSignCode(sign, true, c) but now the 'sign' parm will be TR_BCDSignCode of TR_RawBCDSignCode
1793
*/
1794
bool
1795
J9::Node::knownSignCodeIs(TR_BCDSignCode sign)
1796
{
1797
if (self()->hasKnownSignCode() &&
1798
TR::DataType::getBCDSignFromRawSign(self()->getKnownSignCode()) == sign)
1799
{
1800
return true;
1801
}
1802
else
1803
{
1804
return false;
1805
}
1806
}
1807
1808
void
1809
J9::Node::setKnownSignCode(TR_BCDSignCode sign)
1810
{
1811
if (TR::Node::typeSupportedForSignCodeTracking(self()->getDataType()))
1812
{
1813
TR_RawBCDSignCode rawBCDSign = TR::DataType::getRawSignFromBCDSign(sign);
1814
if (rawBCDSign != raw_bcd_sign_unknown)
1815
self()->setKnownSignCode(rawBCDSign);
1816
}
1817
}
1818
1819
bool
1820
J9::Node::assumedSignCodeIs(TR_BCDSignCode sign)
1821
{
1822
if (self()->hasAssumedSignCode() &&
1823
TR::DataType::getBCDSignFromRawSign(self()->getAssumedSignCode()) == sign)
1824
{
1825
return true;
1826
}
1827
else
1828
{
1829
return false;
1830
}
1831
}
1832
1833
void
1834
J9::Node::setAssumedSignCode(TR_RawBCDSignCode sign)
1835
{
1836
self()->setKnownOrAssumedSignCode(sign, false); // isKnown=false
1837
}
1838
1839
bool
1840
J9::Node::knownOrAssumedSignCodeIs(TR_BCDSignCode sign)
1841
{
1842
if (self()->knownSignCodeIs(sign) || self()->assumedSignCodeIs(sign))
1843
{
1844
return true;
1845
}
1846
else
1847
{
1848
return false;
1849
}
1850
}
1851
1852
1853
1854
/**
1855
* The hasSignState property is stored in the reverse sense to make the interface easier to use (at the expense of some confusion here)
1856
*/
1857
bool
1858
J9::Node::hasSignStateOnLoad()
1859
{
1860
if (!self()->getOpCode().isBCDLoad())
1861
return false;
1862
1863
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasNoSignStateOnLoad field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1864
if (_unionPropertyB._decimalInfo._hasNoSignStateOnLoad == 0) // !NoSign == HasSignState
1865
return true; // i.e. sign state of load must be preserved (no ZAP widening, for example, as this could change 0xf -> 0xc) -- this is the conservative setting
1866
else if (_unionPropertyB._decimalInfo._hasNoSignStateOnLoad == 1)
1867
return false; // i.e. no particular sign state had assumed on a load (so ZAP widening, for example, is allowed)
1868
else
1869
TR_ASSERT(false, "unexpected noSignState setting on %d on node %p\n", _unionPropertyB._decimalInfo._hasNoSignStateOnLoad, self());
1870
1871
return true; // conservative setting is that there is sign state to be preserved.
1872
}
1873
1874
void
1875
J9::Node::setHasSignStateOnLoad(bool v)
1876
{
1877
TR::Compilation *c = TR::comp();
1878
TR_ASSERT(self()->getOpCode().isBCDLoad(), "only BCDLoads can use setHasSignStateOnLoad (%s %p)\n", self()->getOpCode().getName(), self());
1879
1880
if (self()->getOpCode().isBCDLoad() &&
1881
performNodeTransformation2(c, "O^O NODE FLAGS: Setting _hasNoSignStateOnLoad flag on node %p to %d\n", self(), v?0:1))
1882
{
1883
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasNoSignStateOnLoad field for node %s %p that does not have it", self()->getOpCode().getName(), self());
1884
_unionPropertyB._decimalInfo._hasNoSignStateOnLoad = v ? 0 : 1; // v=true is the conservative setting, v=false will allow clobbering of the sign code
1885
}
1886
}
1887
1888
1889
1890
void
1891
J9::Node::transferSignState(TR::Node *srcNode, bool digitsLost)
1892
{
1893
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo fields for node %s %p that does not have it", self()->getOpCode().getName(), self());
1894
_unionPropertyB._decimalInfo._signStateIsKnown = srcNode->signStateIsKnown();
1895
_unionPropertyB._decimalInfo._hasCleanSign = digitsLost ? 0 : srcNode->hasKnownOrAssumedCleanSign(); // '10 0d' might be truncated to negative zero '0 00d' -- so no longer clean
1896
_unionPropertyB._decimalInfo._hasPreferredSign = srcNode->hasKnownOrAssumedPreferredSign();
1897
_unionPropertyB._decimalInfo._signCode = srcNode->getKnownOrAssumedSignCode();
1898
if (self()->getOpCode().isBCDLoad())
1899
self()->setHasSignStateOnLoad(srcNode->hasSignStateOnLoad());
1900
}
1901
1902
bool
1903
J9::Node::hasAnyKnownOrAssumedSignState()
1904
{
1905
if (self()->hasKnownOrAssumedCleanSign() ||
1906
self()->hasKnownOrAssumedPreferredSign() ||
1907
self()->hasKnownOrAssumedSignCode())
1908
{
1909
return true;
1910
}
1911
else
1912
{
1913
return false;
1914
}
1915
}
1916
1917
bool
1918
J9::Node::hasAnyDecimalSignState()
1919
{
1920
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo fields for node %s %p that does not have it", self()->getOpCode().getName(), self());
1921
if (_unionPropertyB._decimalInfo._hasCleanSign == 1 ||
1922
_unionPropertyB._decimalInfo._hasPreferredSign == 1 ||
1923
(self()->getOpCode().isLoadVar() && self()->hasSignStateOnLoad()) ||
1924
_unionPropertyB._decimalInfo._signCode != raw_bcd_sign_unknown)
1925
{
1926
return true;
1927
}
1928
else
1929
{
1930
return false;
1931
}
1932
}
1933
1934
void
1935
J9::Node::resetDecimalSignFlags()
1936
{
1937
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo fields for node %s %p that does not have it", self()->getOpCode().getName(), self());
1938
_unionPropertyB._decimalInfo._signStateIsKnown = 0;
1939
_unionPropertyB._decimalInfo._hasCleanSign = 0;
1940
_unionPropertyB._decimalInfo._hasPreferredSign = 0;
1941
_unionPropertyB._decimalInfo._hasNoSignStateOnLoad = 0;
1942
_unionPropertyB._decimalInfo._signCode=raw_bcd_sign_unknown;
1943
}
1944
1945
void
1946
J9::Node::resetSignState()
1947
{
1948
self()->resetDecimalSignFlags();
1949
self()->setIsZero(false);
1950
self()->setIsNonZero(false);
1951
self()->setIsNonPositive(false);
1952
self()->setIsNonNegative(false);
1953
}
1954
1955
1956
1957
bool
1958
J9::Node::isSignStateEquivalent(TR::Node *other)
1959
{
1960
if (self()->signStateIsKnown() == other->signStateIsKnown() &&
1961
self()->signStateIsAssumed() == other->signStateIsAssumed() &&
1962
self()->hasKnownCleanSign() == other->hasKnownCleanSign() &&
1963
self()->hasAssumedCleanSign() == other->hasAssumedCleanSign() &&
1964
self()->hasKnownPreferredSign() == other->hasKnownPreferredSign() &&
1965
self()->hasAssumedPreferredSign() == other->hasAssumedPreferredSign() &&
1966
self()->hasKnownSignCode() == other->hasKnownSignCode() &&
1967
self()->hasAssumedSignCode() == other->hasAssumedSignCode() &&
1968
self()->hasSignStateOnLoad() == other->hasSignStateOnLoad())
1969
{
1970
return true;
1971
}
1972
else
1973
{
1974
return false;
1975
}
1976
}
1977
1978
/**
1979
* if the 'other' node does not currently have any sign state then an improvement will be any sign state set on 'this' node
1980
*/
1981
bool
1982
J9::Node::isSignStateAnImprovementOver(TR::Node *other)
1983
{
1984
if (other->hasSignStateOnLoad() || other->hasAnyKnownOrAssumedSignState())
1985
return false;
1986
1987
bool thisHasAnyKnownOrAssumedSignState = self()->hasAnyKnownOrAssumedSignState();
1988
// having some (but undetermined) sign state for loads can prevent optimization or hinder codegen vs not having to assume anything
1989
// so return false in this case (but wouldn't be incorrect to return true in this case assuming other conditions below hold)
1990
if (self()->hasSignStateOnLoad() && !thisHasAnyKnownOrAssumedSignState)
1991
return false;
1992
1993
return thisHasAnyKnownOrAssumedSignState; // any sign state info is better than nothing
1994
}
1995
1996
1997
1998
bool
1999
J9::Node::chkOpsCastedToBCD()
2000
{
2001
if (self()->getType().isBCD())
2002
{
2003
return true;
2004
}
2005
else if (self()->getOpCode().isAnyBCDCompareOp())
2006
{
2007
// e.g. pdcmpxx
2008
return true;
2009
}
2010
else
2011
{
2012
return false;
2013
}
2014
}
2015
2016
bool
2017
J9::Node::castedToBCD()
2018
{
2019
if (self()->chkOpsCastedToBCD())
2020
{
2021
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._castedToBCD field for node %s %p that does not have it", self()->getOpCode().getName(), self());
2022
return _unionPropertyB._decimalInfo._castedToBCD==1;
2023
}
2024
else
2025
{
2026
return false;
2027
}
2028
}
2029
2030
void
2031
J9::Node::setCastedToBCD(bool v)
2032
{
2033
TR_ASSERT(self()->chkOpsCastedToBCD(), "node %s %p must be a BCD type or a BCD if or compare\n", self()->getOpCode().getName(), self());
2034
TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._castedToBCD field for node %s %p that does not have it", self()->getOpCode().getName(), self());
2035
_unionPropertyB._decimalInfo._castedToBCD = v ? 1 : 0;
2036
}
2037
2038
/**
2039
* UnionPropertyB functions end
2040
*/
2041
2042
2043
2044
2045
2046
/**
2047
* Node flag functions
2048
*/
2049
2050
bool
2051
J9::Node::isSpineCheckWithArrayElementChild()
2052
{
2053
TR_ASSERT(self()->getOpCode().isSpineCheck(), "assertion failure");
2054
return _flags.testAny(spineCHKWithArrayElementChild);
2055
}
2056
2057
void
2058
J9::Node::setSpineCheckWithArrayElementChild(bool v)
2059
{
2060
TR::Compilation * c = TR::comp();
2061
TR_ASSERT(self()->getOpCode().isSpineCheck(), "assertion failure");
2062
if (performNodeTransformation2(c, "O^O NODE FLAGS: Setting spineCHKWithArrayElementChild flag on node %p to %d\n", self(), v))
2063
_flags.set(spineCHKWithArrayElementChild, v);
2064
}
2065
2066
bool
2067
J9::Node::chkSpineCheckWithArrayElementChild()
2068
{
2069
return self()->getOpCode().isSpineCheck() && _flags.testAny(spineCHKWithArrayElementChild);
2070
}
2071
2072
const char *
2073
J9::Node::printSpineCheckWithArrayElementChild()
2074
{
2075
return self()->chkSpineCheckWithArrayElementChild() ? "spineCHKWithArrayElementChild " : "";
2076
}
2077
2078
2079
2080
bool
2081
J9::Node::isUnsafePutOrderedCall()
2082
{
2083
if (!self()->getOpCode().isCall())
2084
return false;
2085
2086
if (!self()->getSymbol()->isMethod())
2087
return false;
2088
2089
bool isPutOrdered = false;
2090
TR::MethodSymbol *symbol = self()->getSymbol()->getMethodSymbol();
2091
if (!symbol)
2092
return false;
2093
2094
if ((symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putBooleanOrdered_jlObjectJZ_V) ||
2095
(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putByteOrdered_jlObjectJB_V) ||
2096
(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putCharOrdered_jlObjectJC_V) ||
2097
(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putShortOrdered_jlObjectJS_V) ||
2098
(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putIntOrdered_jlObjectJI_V) ||
2099
(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putLongOrdered_jlObjectJJ_V) ||
2100
(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putFloatOrdered_jlObjectJF_V) ||
2101
(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putDoubleOrdered_jlObjectJD_V) ||
2102
(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putObjectOrdered_jlObjectJjlObject_V))
2103
isPutOrdered = true;
2104
2105
return isPutOrdered;
2106
}
2107
2108
bool
2109
J9::Node::isDontInlinePutOrderedCall()
2110
{
2111
TR_ASSERT(self()->getOpCode().isCall(), " Can only call this routine for a call node \n");
2112
bool isPutOrdered = self()->isUnsafePutOrderedCall();
2113
2114
TR_ASSERT(isPutOrdered, "attempt to set dontInlinePutOrderedCall flag and not a putOrdered call");
2115
if (isPutOrdered)
2116
return _flags.testAny(dontInlineUnsafePutOrderedCall);
2117
else
2118
return false;
2119
}
2120
2121
void
2122
J9::Node::setDontInlinePutOrderedCall()
2123
{
2124
TR::Compilation * c = TR::comp();
2125
TR_ASSERT(self()->getOpCode().isCall(), " Can only call this routine for a call node \n");
2126
bool isPutOrdered = self()->isUnsafePutOrderedCall();
2127
2128
TR_ASSERT(isPutOrdered, "attempt to set dontInlinePutOrderedCall flag and not a putOrdered call");
2129
if (isPutOrdered)
2130
{
2131
if (performNodeTransformation1(c, "O^O NODE FLAGS: Setting dontInlineUnsafePutOrderedCall flag on node %p\n", self()))
2132
_flags.set(dontInlineUnsafePutOrderedCall);
2133
}
2134
2135
}
2136
2137
bool
2138
J9::Node::isUnsafeCopyMemoryIntrinsic()
2139
{
2140
if (self()->getOpCode().isCall() && self()->getSymbol()->isMethod())
2141
{
2142
TR::MethodSymbol *symbol = self()->getSymbol()->getMethodSymbol();
2143
if (symbol && symbol->isNative())
2144
{
2145
switch (symbol->getRecognizedMethod())
2146
{
2147
case TR::sun_misc_Unsafe_copyMemory:
2148
case TR::jdk_internal_misc_Unsafe_copyMemory0:
2149
return true;
2150
default:
2151
break;
2152
}
2153
}
2154
}
2155
return false;
2156
}
2157
2158
bool
2159
J9::Node::chkDontInlineUnsafePutOrderedCall()
2160
{
2161
bool isPutOrdered = self()->isUnsafePutOrderedCall();
2162
return isPutOrdered && _flags.testAny(dontInlineUnsafePutOrderedCall);
2163
}
2164
2165
const char *
2166
J9::Node::printIsDontInlineUnsafePutOrderedCall()
2167
{
2168
return self()->chkDontInlineUnsafePutOrderedCall() ? "dontInlineUnsafePutOrderedCall " : "";
2169
}
2170
2171
2172
2173
bool
2174
J9::Node::isUnsafeGetPutCASCallOnNonArray()
2175
{
2176
if (!self()->getSymbol()->isMethod())
2177
return false;
2178
TR::MethodSymbol *symbol = self()->getSymbol()->getMethodSymbol();
2179
if (!symbol)
2180
return false;
2181
2182
//TR_ASSERT(symbol->castToResolvedMethodSymbol()->getResolvedMethod()->isUnsafeWithObjectArg(), "Attempt to check flag on a method that is not JNI Unsafe that needs special care for arraylets\n");
2183
TR_ASSERT(symbol->getMethod()->isUnsafeWithObjectArg() || symbol->getMethod()->isUnsafeCAS(),"Attempt to check flag on a method that is not JNI Unsafe that needs special care for arraylets\n");
2184
return _flags.testAny(unsafeGetPutOnNonArray);
2185
}
2186
2187
void
2188
J9::Node::setUnsafeGetPutCASCallOnNonArray()
2189
{
2190
TR::Compilation * c = TR::comp();
2191
TR_ASSERT(self()->getSymbol()->isMethod() && self()->getSymbol()->getMethodSymbol(), "setUnsafeGetPutCASCallOnNonArray called on node which is not a call");
2192
2193
//TR_ASSERT(getSymbol()->getMethodSymbol()->castToResolvedMethodSymbol()->getResolvedMethod()->isUnsafeWithObjectArg(),"Attempt to change flag on a method that is not JNI Unsafe that needs special care for arraylets\n");
2194
TR_ASSERT(self()->getSymbol()->getMethodSymbol()->getMethod()->isUnsafeWithObjectArg() || self()->getSymbol()->getMethodSymbol()->getMethod()->isUnsafeCAS(),"Attempt to check flag on a method that is not JNI Unsafe that needs special care for arraylets\n");
2195
if (performNodeTransformation1(c, "O^O NODE FLAGS: Setting unsafeGetPutOnNonArray flag on node %p\n", self()))
2196
_flags.set(unsafeGetPutOnNonArray);
2197
}
2198
2199
2200
2201
bool
2202
J9::Node::isProcessedByCallCloneConstrain()
2203
{
2204
return self()->getOpCode().isCall() && self()->getOpCodeValue() != TR::arraycopy && _flags.testAny(processedByCallCloneConstrain);
2205
}
2206
2207
void
2208
J9::Node::setProcessedByCallCloneConstrain()
2209
{
2210
_flags.set(processedByCallCloneConstrain, true);
2211
}
2212
2213
2214
2215
bool
2216
J9::Node::isDAAVariableSlowCall()
2217
{
2218
TR_ASSERT(self()->getOpCode().isCall(), "Opcode must be a call");
2219
return _flags.testAny(DAAVariableSlowCall);
2220
}
2221
2222
void
2223
J9::Node::setDAAVariableSlowCall(bool v)
2224
{
2225
TR_ASSERT(self()->getOpCode().isCall(), "Opcode must be a call");
2226
_flags.set(DAAVariableSlowCall);
2227
}
2228
2229
2230
2231
bool
2232
J9::Node::isBCDStoreTemporarilyALoad()
2233
{
2234
TR_ASSERT(self()->getOpCode().isBCDLoadVar(),
2235
"flag only valid for BCD load ops\n");
2236
if (self()->getOpCode().isBCDLoadVar())
2237
return _flags.testAny(IsBCDStoreTemporarilyALoad);
2238
else
2239
return false;
2240
2241
}
2242
2243
void
2244
J9::Node::setBCDStoreIsTemporarilyALoad(bool v)
2245
{
2246
TR::Compilation *c = TR::comp();
2247
TR_ASSERT(self()->getOpCode().isBCDLoadVar(),
2248
"flag only valid for BCD load ops\n");
2249
if (self()->getOpCode().isBCDLoadVar() &&
2250
performNodeTransformation2(c, "O^O NODE FLAGS: Setting IsBCDStoreTemporarilyALoad flag on node %p to %d\n", self(), v))
2251
_flags.set(IsBCDStoreTemporarilyALoad, v);
2252
}
2253
2254
2255
2256
bool
2257
J9::Node::cleanSignDuringPackedLeftShift()
2258
{
2259
TR_ASSERT(self()->getOpCode().isPackedLeftShift(), "flag only valid for isPackedLeftShift nodes\n");
2260
if (self()->getOpCode().isPackedLeftShift())
2261
return _flags.testAny(CleanSignDuringPackedLeftShift);
2262
else
2263
return false;
2264
}
2265
2266
void
2267
J9::Node::setCleanSignDuringPackedLeftShift(bool v)
2268
{
2269
TR::Compilation *c = TR::comp();
2270
TR_ASSERT(self()->getOpCode().isPackedLeftShift(), "flag only valid for isPackedLeftShift nodes\n");
2271
if (self()->getOpCode().isPackedLeftShift() && performNodeTransformation2(c, "O^O NODE FLAGS: Setting CleanSignDuringPackedLeftShift flag on node %p to %d\n", self(), v))
2272
_flags.set(CleanSignDuringPackedLeftShift, v);
2273
}
2274
2275
bool
2276
J9::Node::chkCleanSignDuringPackedLeftShift()
2277
{
2278
return self()->getOpCode().isPackedLeftShift() &&
2279
_flags.testAny(CleanSignDuringPackedLeftShift);
2280
}
2281
2282
const char *
2283
J9::Node::printCleanSignDuringPackedLeftShift()
2284
{
2285
return self()->chkCleanSignDuringPackedLeftShift() ? "cleanSignDuringPackedLeftShift " : "";
2286
}
2287
2288
bool
2289
J9::Node::chkOpsSkipCopyOnLoad()
2290
{
2291
return (self()->getType().isBCD() || self()->getType().isAggregate()) && !self()->getOpCode().isStore() && !self()->getOpCode().isCall();
2292
}
2293
2294
bool
2295
J9::Node::skipCopyOnLoad()
2296
{
2297
TR_ASSERT(self()->chkOpsSkipCopyOnLoad(), "flag only valid for BCD or aggregate non-store and non-call ops\n");
2298
if ((self()->getType().isBCD() || self()->getType().isAggregate()) && !self()->getOpCode().isStore() && !self()->getOpCode().isCall())
2299
return _flags.testAny(SkipCopyOnLoad);
2300
else
2301
return false;
2302
}
2303
2304
void
2305
J9::Node::setSkipCopyOnLoad(bool v)
2306
{
2307
TR::Compilation *c = TR::comp();
2308
TR_ASSERT(self()->chkOpsSkipCopyOnLoad(), "flag only valid for BCD or aggregate non-store and non-call ops\n");
2309
if ((self()->getType().isBCD() || self()->getType().isAggregate()) && !self()->getOpCode().isStore() && !self()->getOpCode().isCall() &&
2310
performNodeTransformation2(c, "O^O NODE FLAGS: Setting skipCopyOnLoad flag on node %p to %d\n", self(), v))
2311
_flags.set(SkipCopyOnLoad, v);
2312
}
2313
2314
bool
2315
J9::Node::chkSkipCopyOnLoad()
2316
{
2317
return self()->chkOpsSkipCopyOnLoad() && _flags.testAny(SkipCopyOnLoad);
2318
}
2319
2320
const char *
2321
J9::Node::printSkipCopyOnLoad()
2322
{
2323
return self()->chkSkipCopyOnLoad() ? "skipCopyOnLoad " : "";
2324
}
2325
2326
2327
2328
bool
2329
J9::Node::chkOpsSkipCopyOnStore()
2330
{
2331
return self()->getOpCode().isBCDStore();
2332
}
2333
2334
bool
2335
J9::Node::skipCopyOnStore()
2336
{
2337
TR_ASSERT(self()->chkOpsSkipCopyOnStore(), "flag only valid for BCD or aggregate store ops\n");
2338
if (self()->chkOpsSkipCopyOnStore())
2339
return _flags.testAny(SkipCopyOnStore);
2340
else
2341
return false;
2342
}
2343
2344
void
2345
J9::Node::setSkipCopyOnStore(bool v)
2346
{
2347
TR::Compilation *c = TR::comp();
2348
TR_ASSERT(self()->chkOpsSkipCopyOnStore(), "flag only valid for BCD or aggregate store ops\n");
2349
if (self()->chkOpsSkipCopyOnStore() &&
2350
performNodeTransformation2(c, "O^O NODE FLAGS: Setting skipCopyOnStore flag on node %p to %d\n", self(), v))
2351
{
2352
_flags.set(SkipCopyOnStore, v);
2353
}
2354
}
2355
2356
bool
2357
J9::Node::chkSkipCopyOnStore()
2358
{
2359
return self()->chkOpsSkipCopyOnStore() && _flags.testAny(SkipCopyOnStore);
2360
}
2361
2362
const char *
2363
J9::Node::printSkipCopyOnStore()
2364
{
2365
return self()->chkSkipCopyOnStore() ? "skipCopyOnStore " : "";
2366
}
2367
2368
2369
2370
bool
2371
J9::Node::chkOpsCleanSignInPDStoreEvaluator()
2372
{
2373
return self()->getDataType() == TR::PackedDecimal && self()->getOpCode().isStore();
2374
}
2375
2376
bool
2377
J9::Node::mustCleanSignInPDStoreEvaluator()
2378
{
2379
TR_ASSERT(self()->chkOpsCleanSignInPDStoreEvaluator(), "flag only valid for packed decimal store nodes\n");
2380
if (self()->chkOpsCleanSignInPDStoreEvaluator())
2381
return _flags.testAny(cleanSignInPDStoreEvaluator);
2382
else
2383
return false;
2384
}
2385
2386
void
2387
J9::Node::setCleanSignInPDStoreEvaluator(bool v)
2388
{
2389
TR::Compilation *c = TR::comp();
2390
TR_ASSERT(self()->chkOpsCleanSignInPDStoreEvaluator(), "flag only valid for packed decimal store nodes\n");
2391
if (self()->chkOpsCleanSignInPDStoreEvaluator() &&
2392
performNodeTransformation2(c, "O^O NODE FLAGS: Setting cleanSignInPDStoreEvaluator flag on node %p to %d\n", self(), v))
2393
_flags.set(cleanSignInPDStoreEvaluator, v);
2394
}
2395
2396
bool
2397
J9::Node::chkCleanSignInPDStoreEvaluator()
2398
{
2399
return self()->chkOpsCleanSignInPDStoreEvaluator() && _flags.testAny(cleanSignInPDStoreEvaluator);
2400
}
2401
2402
const char *
2403
J9::Node::printCleanSignInPDStoreEvaluator()
2404
{
2405
return self()->chkCleanSignInPDStoreEvaluator() ? "cleanSignInPDStoreEvaluator " : "";
2406
}
2407
2408
2409
2410
bool
2411
J9::Node::chkOpsUseStoreAsAnAccumulator()
2412
{
2413
return self()->getOpCode().canUseStoreAsAnAccumulator();
2414
}
2415
2416
bool
2417
J9::Node::useStoreAsAnAccumulator()
2418
{
2419
TR_ASSERT(self()->chkOpsUseStoreAsAnAccumulator(), "flag only valid for BCD or aggregate store ops\n");
2420
if (self()->chkOpsUseStoreAsAnAccumulator())
2421
return _flags.testAny(UseStoreAsAnAccumulator);
2422
else
2423
return false;
2424
}
2425
2426
void
2427
J9::Node::setUseStoreAsAnAccumulator(bool v)
2428
{
2429
TR::Compilation *c = TR::comp();
2430
TR_ASSERT(self()->chkOpsUseStoreAsAnAccumulator(), "flag only valid for BCD or aggregate store ops\n");
2431
if (self()->chkOpsUseStoreAsAnAccumulator() &&
2432
performNodeTransformation2(c, "O^O NODE FLAGS: Setting UseStoreAsAnAccumulator flag on node %p to %d\n", self(), v))
2433
{
2434
_flags.set(UseStoreAsAnAccumulator, v);
2435
}
2436
}
2437
2438
bool
2439
J9::Node::chkUseStoreAsAnAccumulator()
2440
{
2441
return self()->chkOpsUseStoreAsAnAccumulator() && _flags.testAny(UseStoreAsAnAccumulator);
2442
}
2443
2444
const char *
2445
J9::Node::printUseStoreAsAnAccumulator()
2446
{
2447
return self()->chkUseStoreAsAnAccumulator() ? "useStoreAsAnAccumulator " : "";
2448
}
2449
2450
2451
2452
bool
2453
J9::Node::canSkipPadByteClearing()
2454
{
2455
TR_ASSERT(self()->getType().isAnyPacked() && !self()->getOpCode().isStore(),
2456
"flag only valid for wcode non-store packed operations\n");
2457
if (self()->getType().isAnyPacked() && !self()->getOpCode().isStore())
2458
return _flags.testAny(skipPadByteClearing);
2459
else
2460
return false;
2461
}
2462
2463
void
2464
J9::Node::setSkipPadByteClearing(bool v)
2465
{
2466
TR::Compilation *c = TR::comp();
2467
TR_ASSERT(self()->getType().isAnyPacked() && !self()->getOpCode().isStore(),
2468
"flag only valid for wcode non-store packed operations\n");
2469
if (self()->getType().isAnyPacked() && !self()->getOpCode().isStore() &&
2470
(c==NULL || performNodeTransformation2(c, "O^O NODE FLAGS: Setting skipPadByteClearing flag on node %p to %d\n", self(), v)))
2471
_flags.set(skipPadByteClearing, v);
2472
}
2473
2474
bool
2475
J9::Node::chkSkipPadByteClearing()
2476
{
2477
return self()->getType().isAnyPacked() && !self()->getOpCode().isStore() &&
2478
_flags.testAny(skipPadByteClearing);
2479
}
2480
2481
const char *
2482
J9::Node::printSkipPadByteClearing()
2483
{
2484
return self()->chkSkipPadByteClearing() ? "skipPadByteClearing " : "";
2485
}
2486
2487
2488
2489
bool
2490
J9::Node::chkOpsIsInMemoryCopyProp()
2491
{
2492
TR::Compilation *c = TR::comp();
2493
return self()->getOpCode().isStore() && c->cg()->IsInMemoryType(self()->getType());
2494
}
2495
2496
bool
2497
J9::Node::isInMemoryCopyProp()
2498
{
2499
if (self()->chkOpsIsInMemoryCopyProp())
2500
return _flags.testAny(IsInMemoryCopyProp);
2501
else
2502
return false;
2503
}
2504
2505
void
2506
J9::Node::setIsInMemoryCopyProp(bool v)
2507
{
2508
if (self()->chkOpsIsInMemoryCopyProp())
2509
{
2510
_flags.set(IsInMemoryCopyProp, v);
2511
}
2512
}
2513
2514
bool
2515
J9::Node::chkIsInMemoryCopyProp()
2516
{
2517
return self()->chkOpsIsInMemoryCopyProp() && _flags.testAny(IsInMemoryCopyProp);
2518
}
2519
2520
const char *
2521
J9::Node::printIsInMemoryCopyProp()
2522
{
2523
return self()->chkIsInMemoryCopyProp() ? "IsInMemoryCopyProp " : "";
2524
}
2525
2526
2527
2528
bool
2529
J9::Node::chkSharedMemory()
2530
{
2531
TR_ASSERT(self()->getType().isAddress(), "flag only valid for addresses\n");
2532
return _flags.testAny(sharedMemory);
2533
}
2534
2535
void
2536
J9::Node::setSharedMemory(bool v)
2537
{
2538
TR_ASSERT(self()->getType().isAddress(), "flag only valid for addresses\n");
2539
_flags.set(sharedMemory, v);
2540
}
2541
2542
const char *
2543
J9::Node::printSharedMemory()
2544
{
2545
return self()->getType().isAddress() ? "sharedMemory " : "";
2546
}
2547
2548
/**
2549
* Node flag functions end
2550
*/
2551
2552
bool
2553
J9::Node::isArrayCopyCall()
2554
{
2555
if (self()->getOpCode().isCall() && self()->getSymbol()->isMethod())
2556
{
2557
TR::RecognizedMethod recognizedMethod = self()->getSymbol()->castToMethodSymbol()->getRecognizedMethod();
2558
2559
if (recognizedMethod == TR::java_lang_System_arraycopy ||
2560
recognizedMethod == TR::java_lang_String_compressedArrayCopy_BIBII ||
2561
recognizedMethod == TR::java_lang_String_compressedArrayCopy_BICII ||
2562
recognizedMethod == TR::java_lang_String_compressedArrayCopy_CIBII ||
2563
recognizedMethod == TR::java_lang_String_compressedArrayCopy_CICII ||
2564
recognizedMethod == TR::java_lang_String_decompressedArrayCopy_BIBII ||
2565
recognizedMethod == TR::java_lang_String_decompressedArrayCopy_BICII ||
2566
recognizedMethod == TR::java_lang_String_decompressedArrayCopy_CIBII ||
2567
recognizedMethod == TR::java_lang_String_decompressedArrayCopy_CICII)
2568
{
2569
return true;
2570
}
2571
else
2572
{
2573
TR::Method *method = self()->getSymbol()->castToMethodSymbol()->getMethod();
2574
2575
// Method may be unresolved but we would still like to transform arraycopy calls so pattern match the signature as well
2576
if (method != NULL &&
2577
(method->nameLength() == 9) &&
2578
(method->classNameLength() == 16) &&
2579
(strncmp(method->nameChars(), "arraycopy", 9) == 0) &&
2580
(strncmp(method->classNameChars(), "java/lang/System", 16) == 0))
2581
{
2582
return true;
2583
}
2584
}
2585
}
2586
2587
return OMR::Node::isArrayCopyCall();
2588
}
2589
2590
2591
bool
2592
J9::Node::requiresRegisterPair(TR::Compilation *comp)
2593
{
2594
return OMR::NodeConnector::requiresRegisterPair(comp);
2595
}
2596
2597
bool
2598
J9::Node::canGCandReturn()
2599
{
2600
TR::Compilation * comp = TR::comp();
2601
if (comp->getOption(TR_EnableFieldWatch))
2602
{
2603
if (self()->getOpCodeValue() == TR::treetop || self()->getOpCode().isNullCheck() || self()->getOpCode().isAnchor())
2604
{
2605
TR::Node * node = self()->getFirstChild();
2606
if (node->getOpCode().isReadBar() || node->getOpCode().isWrtBar())
2607
return true;
2608
}
2609
}
2610
return OMR::NodeConnector::canGCandReturn();
2611
}
2612
2613