Path: blob/master/runtime/compiler/il/J9Node.cpp
6000 views
/*******************************************************************************1* Copyright (c) 2000, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/2122#include "j9cfg.h"23#include "il/J9Node.hpp"2425#include <algorithm>26#include "codegen/CodeGenerator.hpp"27#include "compile/Compilation.hpp"28#include "compile/Method.hpp"29#include "env/CompilerEnv.hpp"30#include "il/MethodSymbol.hpp"31#include "il/Node.hpp"32#include "il/Node_inlines.hpp"33#include "il/Symbol.hpp"34#include "runtime/RuntimeAssumptions.hpp"35#include "env/CHTable.hpp"36#include "env/PersistentCHTable.hpp"37#include "env/VMJ9.h"3839#ifdef TR_TARGET_S39040#include "z/codegen/S390Register.hpp"41#endif4243#if (HOST_COMPILER == COMPILER_MSVC)44#define MAX_PACKED_DECIMAL_SIZE 3245#define UNICODE_SIGN_SIZE 246// On Windows, macros are used instead of TR::DataType:: static functions to size some temp arrays47// COMPILER_MSVC outputs 'error C2057: expected constant expression' when the static functions are used to determine the array's size48#endif4950/**51* Constructors and destructors52*/5354J9::Node::Node(TR::Node *originatingByteCodeNode, TR::ILOpCodes op, uint16_t numChildren)55: OMR::NodeConnector(originatingByteCodeNode, op, numChildren),56#ifdef TR_TARGET_S39057_storageReferenceHint(NULL),58#endif59_unionPropertyB()60{61// check that _unionPropertyA union is disjoint62TR_ASSERT(63self()->hasSymbolReference()64+ self()->hasRegLoadStoreSymbolReference()65+ self()->hasBranchDestinationNode()66+ self()->hasBlock()67+ self()->hasArrayStride()68+ self()->hasPinningArrayPointer()69+ self()->hasDataType() <= 1,70"_unionPropertyA union is not disjoint for this node %s (%p):\n"71" has({SymbolReference, ...}, ..., DataType) = ({%1d,%1d},%1d,%1d,%1d,%1d,%1d)\n",72self()->getOpCode().getName(), this,73self()->hasSymbolReference(),74self()->hasRegLoadStoreSymbolReference(),75self()->hasBranchDestinationNode(),76self()->hasBlock(),77self()->hasArrayStride(),78self()->hasPinningArrayPointer(),79self()->hasDataType());8081// check that _unionPropertyB union is disjoint82TR_ASSERT(self()->hasDecimalInfo() + self()->hasBCDFlags() <= 1,83"_unionPropertyB union is not disjoint for this node %s (%p):\n"84" has(DecimalInfo, BCDFlags) = (%1d,%1d)\n",85self()->getOpCode().getName(), this,86self()->hasDecimalInfo(), self()->hasBCDFlags());8788if (self()->hasDecimalInfo())89{90// Every node that has decimal info must set a valid precision but adjust/fraction and round can be 091// NOTE: update isDecimalSizeAndShapeEquivalent() routine when adding fields that specify92// the shape/size of a decimal node (such as precision/adjust/fraction/setSign etc) to _decimalInfo.93// Flag type fields like clean/preferred signs do not need to be added to isDecimalSizeAndShapeEquivalent()94_unionPropertyB._decimalInfo._decimalPrecision = TR::DataType::getInvalidDecimalPrecision(); // valid range is 0->TR_MAX_DECIMAL_PRECISION (defined in OMRDataTypes.hpp)95_unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor = 0; // valid range is -31->31 for adjust/fraction and 0->62 for divisor precision96_unionPropertyB._decimalInfo._decimalSourcePrecisionOrDividend = 0; // valid range is 0->63 for source precision and 0->62 for dividend precision97_unionPropertyB._decimalInfo._setSign = raw_bcd_sign_unknown; // for isSetSignOnNode() opcodes such as TR::pdclearSetSign98_unionPropertyB._decimalInfo._hasNoSignStateOnLoad = 0; // 0 (false) is the conservative setting -- meaning do not clobber the sign code unless FE explicitly instructs99_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 optimization100_unionPropertyB._decimalInfo._signStateIsKnown = 0;101_unionPropertyB._decimalInfo._hasCleanSign = 0;102_unionPropertyB._decimalInfo._hasPreferredSign = 0;103_unionPropertyB._decimalInfo._round = 0; // 0 means no rounding, 1 means rounding104_unionPropertyB._decimalInfo._signCode = raw_bcd_sign_unknown;105}106}107108J9::Node::Node(TR::Node *from, uint16_t numChildren)109: OMR::NodeConnector(from, numChildren)110{111#ifdef TR_TARGET_S390112if (self()->getOpCode().canHaveStorageReferenceHint())113{114self()->setStorageReferenceHint(from->getStorageReferenceHint());115}116#endif117118_unionPropertyB = from->_unionPropertyB; // TODO: use copyValidProperties119120if (from->getOpCode().isConversionWithFraction())121{122self()->setDecimalFraction(from->getDecimalFraction());123}124}125126J9::Node::~Node()127{128_unionPropertyB = UnionPropertyB();129}130131bool132J9::Node::dontEliminateStores(bool isForLocalDeadStore)133{134// Disallow store sinking of BCD operations in Java because such operations may be under a BCDCHK node, implying that135// an exception path may be taken at runtime to evaluate the tree. Sinking such potentially exceptional operations136// violates the assumption that all such operations are to be anchored on a BCDCHK treetop, which the codegen expects137// to be able to generate the exception handling fallback code.138if (self()->getFirstChild()->getOpCode().isBinaryCodedDecimalOp())139return true;140else141return OMR::NodeConnector::dontEliminateStores(isForLocalDeadStore);142}143144145void146J9::Node::copyValidProperties(TR::Node *fromNode, TR::Node *toNode)147{148OMR::Node::copyValidProperties(fromNode, toNode);149150#ifdef TR_TARGET_S390151if (fromNode->getOpCode().canHaveStorageReferenceHint())152{153toNode->setStorageReferenceHint(fromNode->getStorageReferenceHint());154}155#endif156157// in order to determine the UnionPropertyB_type correctly, require children and symRef (from UnionPropertyA) to have been defined158// already as depends on getDataType which in term depends on these159UnionPropertyB_Type fromUnionPropertyB_Type = fromNode->getUnionPropertyB_Type();160UnionPropertyB_Type toUnionPropertyB_Type = toNode->getUnionPropertyB_Type();161162if (fromUnionPropertyB_Type == toUnionPropertyB_Type)163{164switch (fromUnionPropertyB_Type)165{166case HasDecimalInfo:167#if !defined(ENABLE_RECREATE_WITH_COPY_VALID_PROPERTIES_COMPLETE)168// for now have to copy forward all decimalInfo properties169toNode->_unionPropertyB._decimalInfo = fromNode->_unionPropertyB._decimalInfo;170#else171// _decimalPrecision172if (toNode->hasDecimalPrecision() && fromNode->hasDecimalPrecision())173toNode->setDecimalPrecision(fromNode->getDecimalPrecision());174175// _decimalSourcePrecisionOrDividend176if (toNode->canHaveSourcePrecision() && fromNode->canHaveSourcePrecision())177toNode->setSourcePrecision(fromNode->getSourcePrecision());178179// _decimalAdjustOrFractionOrDivisor180if (toNode->hasDecimalAdjust() && fromNode->hasDecimalAdjust())181toNode->setDecimalAdjust(fromNode->getDecimalAdjust());182else if (toNode->hasDecimalFraction() && fromNode->hasDecimalFraction())183toNode->setDecimalFraction(fromNode->getDecimalFraction());184185// _round186if (toNode->hasDecimalRound() && fromNode->hasDecimalRound())187toNode->setDecimalRound(fromNode->getDecimalRound());188189// _setSign190if (toNode->hasSetSign() && fromNode->hasSetSign())191toNode->setSetSign(fromNode->getSetSign());192193// _signStateIsKnown194// _hasCleanSign195// _hasPreferredSign196// _signCode197// _hasNoSignStateOnLoad198if (toNode->getType().isBCD() && fromNode->getType().isBCD())199{200toNode->_unionPropertyB._decimalInfo._signStateIsKnown = fromNode->signStateIsKnown();201toNode->_unionPropertyB._decimalInfo._hasCleanSign = fromNode->hasKnownOrAssumedCleanSign(); // '10 0d' might be truncated to negative zero '0 00d' -- so no longer clean202toNode->_unionPropertyB._decimalInfo._hasPreferredSign = fromNode->hasKnownOrAssumedPreferredSign();203toNode->_unionPropertyB._decimalInfo._signCode = fromNode->getKnownOrAssumedSignCode();204if (toNode->getOpCode().isBCDLoad() && fromNode->getOpCode().isBCDLoad())205toNode->setHasSignStateOnLoad(fromNode->hasSignStateOnLoad());206if (toNode->getOpCode().chkOpsCastedToBCD() && fromNode->getOpCode().chkOpsCastedToBCD())207toNode->setCastedToBCD(fromNode->castedToBCD());208}209#endif210break;211case HasBcdFlags:212// should never get here, as only one type of opcodevalue for this flag213TR_ASSERT(fromNode->getOpCodeValue() == toNode->getOpCodeValue(),214"Unexpected comparison. Nodes that have _bcdFlags property should always be BCDCHK nodes. These are %s %p and %s %p nodes",215fromNode->getOpCode().getName(), fromNode,216toNode->getOpCode().getName(), toNode);217TR_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",218fromNode->getOpCode().getName(), fromNode,219toNode->getOpCode().getName(), toNode);220break;221default:222/* HasNoUnionPropertyB */223break;224}225}226227}228229/**230* Constructors and destructors end231*/232233234uint32_t235J9::Node::getSize()236{237if (self()->getType().isBCD())238{239// this is a temporary workaround for a compiler bug where too many bits are getting pulled out of the bit container240/*241TR_ASSERT(_unionPropertyB._decimalInfo._decimalPrecision >=0 && _unionPropertyB._decimalInfo._decimalPrecision <=TR_MAX_DECIMAL_PRECISION,242"unexpected decimal precision %d on node %p\n", _unionPropertyB._decimalInfo._decimalPrecision, this);243return TR::DataType::getSizeFromBCDPrecision(getDataType(), _unionPropertyB._decimalInfo._decimalPrecision);244*/245TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalPrecision field for node %s %p that does not have it", self()->getOpCode().getName(), self());246int32_t newPrec = _unionPropertyB._decimalInfo._decimalPrecision & 0x3F;247return TR::DataType::getSizeFromBCDPrecision(self()->getDataType(), newPrec);248}249return OMR::NodeConnector::getSize();250}251252/**253* Given a direct call to Object.clone node, return the class of the receiver.254*/255TR_OpaqueClassBlock *256J9::Node::getCloneClassInNode()257{258TR_ASSERT(!self()->hasNodeExtension(), "Node %p should not have node extension");259return (TR_OpaqueClassBlock *)_unionBase._children[1];260}261262263TR::Node *264J9::Node::processJNICall(TR::TreeTop * callNodeTreeTop, TR::ResolvedMethodSymbol * owningSymbol)265{266TR::Compilation * comp = TR::comp();267if (!comp->cg()->getSupportsDirectJNICalls() || comp->getOption(TR_DisableDirectToJNI) || (comp->compileRelocatableCode() && !comp->cg()->supportsDirectJNICallsForAOT()))268return self();269270TR::ResolvedMethodSymbol * methodSymbol = self()->getSymbol()->castToResolvedMethodSymbol();271TR_ResolvedMethod * resolvedMethod = methodSymbol->getResolvedMethod();272273// TR_DisableDirectToJNIInline means only convert calls in thunks274// also don't directly call any native method that has tracing enabled275//276if (!comp->getCurrentMethod()->isJNINative() &&277(comp->getOption(TR_DisableDirectToJNIInline) ||278comp->fej9()->isAnyMethodTracingEnabled(resolvedMethod->getPersistentIdentifier())))279return self();280281if (!comp->getOption(TR_DisableUnsafe) && !TR::Compiler->om.canGenerateArraylets() &&282(methodSymbol->getRecognizedMethod() == TR::java_nio_Bits_copyToByteArray ||283methodSymbol->getRecognizedMethod() == TR::java_nio_Bits_copyFromByteArray))284return self();285286#ifdef J9VM_OPT_JAVA_CRYPTO_ACCELERATION287if (self()->processJNICryptoMethodCall(methodSymbol, comp))288{289return self();290}291#endif292293if (comp->canTransformUnsafeCopyToArrayCopy()294&& self()->isUnsafeCopyMemoryIntrinsic())295{296return self();297}298if (comp->canTransformUnsafeSetMemory() &&299(methodSymbol->getRecognizedMethod() == TR::sun_misc_Unsafe_setMemory))300{301return self();302}303304if (methodSymbol->getRecognizedMethod() == TR::sun_misc_Unsafe_ensureClassInitialized)305{306return self();307}308309if (methodSymbol->getRecognizedMethod() == TR::jdk_internal_loader_NativeLibraries_load)310{311return self();312}313314if (methodSymbol->canReplaceWithHWInstr())315return self();316317// don't convert synchronized jni calls to direct to jni calls unless we're compiling318// the jni thunk.319//320if (resolvedMethod->isSynchronized() && !comp->getCurrentMethod()->isJNINative())321{322// todo: consider adding monent/monexit trees so that it can inlined323return self();324}325326if (self()->getOpCode().isCallIndirect())327{328// todo: handle nonoverridden indirect calls329// || (methodSymbol->isVirtualMethod() && !virtualMethodIsOverridden(resolvedMethod))))330return self();331}332333#if defined(TR_TARGET_POWER)334// Recognizing these methods on Power allows us to take a shortcut335// in the JNI dispatch where we mangle the register dependencies and call336// optimized helpers in the JIT library using what amounts to system/C dispatch.337// The addresses of the optimized helpers in the server process will not necessarily338// match the client-side addresses, so we can't take this shortcut in JITServer mode.339if (((methodSymbol->getRecognizedMethod() == TR::java_util_zip_CRC32_update) ||340(methodSymbol->getRecognizedMethod() == TR::java_util_zip_CRC32_updateBytes) ||341(methodSymbol->getRecognizedMethod() == TR::java_util_zip_CRC32_updateByteBuffer)) &&342!comp->requiresSpineChecks()343#ifdef J9VM_OPT_JITSERVER344&& !comp->isOutOfProcessCompilation()345#endif346)347{348self()->setPreparedForDirectJNI();349return self();350}351#endif352353// In the latest round of VM drops, we've lowered the maximum outgoing argument size on the C stack to 32354// (it used to be the maximum 255). This means that fixed frame platforms (those who pre-allocate space355// in the C stack for outgoing arguments, as opposed to buying new stack to pass arguments) who implement356// direct JNI can no longer depend on the VM allocating the full 255 slots of backing store.357//358// The simplest solution would be to simply not translate JNI methods which have more than 32 arguments,359// and fall back to the interpreter for those cases. The VM handles the >32 case by calling to another360// C function which does allocate space for the full 255 arguments, but this approach will of course not361// work for the JIT.362//363// The 32 limit is on the method argument count (which includes the receiver364// for virtual methods), but not the "fixed" parameters (the JNIEnv * and the365// class parameter for static methods), so we actually have 34 slots of space366// preallocated on fixed frame platforms.367//368uint32_t numChildren = self()->getNumChildren();369if (numChildren - self()->getFirstArgumentIndex() > 32 && comp->cg()->hasFixedFrameC_CallingConvention())370return self();371372if (callNodeTreeTop->getNode()->getOpCode().isNullCheck())373{374//TR_ASSERT(!callNodeTreeTop->getNode()->getOpCode().isResolveCheck(), "Node::processJNICall, expected NULLCHK node");375TR::Node::recreate(callNodeTreeTop->getNode(), TR::NULLCHK);376callNodeTreeTop->getNode()->extractTheNullCheck(callNodeTreeTop->getPrevTreeTop());377}378379bool wrapObjects = !comp->fej9()->jniDoNotWrapObjects(resolvedMethod);380381// Add a level of indirection for each address argument to a JNI method382//383if (wrapObjects)384{385int32_t i;386for (i = 0; i < numChildren; ++i)387{388TR::Node * n = self()->getChild(i);389if (n->getDataType() == TR::Address)390{391if (n->getOpCode().hasSymbolReference() && n->getSymbol()->isAutoOrParm())392{393n->decReferenceCount();394self()->setAndIncChild(i, TR::Node::createWithSymRef(n, TR::loadaddr, 0, n->getSymbolReference()));395}396else397{398TR::SymbolReference * symRef = comp->getSymRefTab()->createTemporary(owningSymbol, TR::Address);399TR::TreeTop::create(comp, callNodeTreeTop->getPrevTreeTop(), TR::Node::createWithSymRef(TR::astore, 1, 1, n, symRef));400// create will have inc'ed the reference count, but there really aren't more401// parents, so need to dec it back.402n->decReferenceCount();403self()->setAndIncChild(i, TR::Node::createWithSymRef(n, TR::loadaddr, 0, symRef));404}405if (n->isNonNull())406{407self()->getChild(i)->setPointsToNonNull(true);408}409}410}411}412413self()->setPreparedForDirectJNI();414415if (methodSymbol->isStatic())416{417TR::Node * newNode = new (comp->getNodePool()) TR::Node(self(), numChildren + 1);418for (int32_t i = numChildren; i; --i)419newNode->setChild(i, self()->getChild(i - 1));420newNode->setNumChildren(numChildren + 1);421422423TR::ResolvedMethodSymbol * callerSymbol = self()->getSymbolReference()->getOwningMethodSymbol(comp);424int32_t callerCP = self()->getSymbolReference()->getCPIndex();425426// For JNI thunks cp index is -1427// passing cpIndex = -1 to findOrCreateClassSymbol shouldn't be an issue as it will figure out the address from resolvedMethod->containingClass()428// we only need cpIndex for relocations in AOT and compiling JNI thunks is disable in AOT429int32_t classCP = (callerCP != -1) ? callerSymbol->getResolvedMethod()->classCPIndexOfMethod(callerCP) : -1;430431TR_ASSERT ((callerCP != -1 || callerSymbol->isNative()), "Cannot have cp index -1 for JNI calls other than JNI thunks.\n");432433TR::Node *addressOfJ9Class = TR::Node::aconst(newNode, (uintptr_t)resolvedMethod->containingClass());434addressOfJ9Class->setIsClassPointerConstant(true);435TR::Node *addressOfJavaLangClassReference;436437TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());438if (comp->target().is64Bit())439{440addressOfJavaLangClassReference =441TR::Node::create(TR::aladd, 2,442addressOfJ9Class,443TR::Node::lconst(newNode, fej9->getOffsetOfJavaLangClassFromClassField()));444}445else446{447addressOfJavaLangClassReference =448TR::Node::create(TR::aiadd, 2,449addressOfJ9Class,450TR::Node::iconst(newNode, fej9->getOffsetOfJavaLangClassFromClassField()));451}452newNode->setAndIncChild(0, addressOfJavaLangClassReference);453454if (callNodeTreeTop->getNode() == self())455{456callNodeTreeTop->setNode(newNode);457}458else459{460TR_ASSERT(callNodeTreeTop->getNode()->getChild(0) == self(), "call node " POINTER_PRINTF_FORMAT " is not the child of a treetop", self());461callNodeTreeTop->getNode()->setChild(0, newNode);462}463return newNode;464}465466return self();467}468469void470J9::Node::devirtualizeCall(TR::TreeTop *treeTop)471{472OMR::NodeConnector::devirtualizeCall(treeTop);473TR::ResolvedMethodSymbol *methodSymbol = self()->getSymbol()->castToResolvedMethodSymbol();474475if (methodSymbol->isJNI())476self()->processJNICall(treeTop, TR::comp()->getMethodSymbol());477}478479bool480J9::Node::isEvenPrecision()481{482return ((self()->getDecimalPrecision() & 0x1) == 0);483}484485bool486J9::Node::isOddPrecision()487{488return ((self()->getDecimalPrecision() & 0x1) != 0);489}490491/**492* A 'simple' widening or truncation is a pdshl node that changes the precision of its child but has a shift amount of 0493*/494bool495J9::Node::isSimpleTruncation()496{497if (self()->getOpCode().isModifyPrecision() &&498self()->getDecimalPrecision() < self()->getFirstChild()->getDecimalPrecision())499{500return true;501}502else if (self()->getOpCodeValue() == TR::pdshl &&503self()->getSecondChild()->getOpCode().isLoadConst() &&504self()->getSecondChild()->get64bitIntegralValue() == 0 &&505self()->getDecimalPrecision() < self()->getFirstChild()->getDecimalPrecision())506{507return true;508}509else510{511return false;512}513}514515/**516* Example of an intermediate truncation (no shifts involved)517* zd2pd p=4 0034 this518* pd2zd p=2 34 child519* pdx p=4 1234 grandChild520* In this case it would be illegal to cancel out the zd2pd/pd2zd nodes because the child (pd2zd) has the521* side effect of truncating during the conversion operation.522*523* The shift case is more complicated as only some of the child digits may survive the shift524* Example of a truncating shift that is *not* an intermediate truncation:525* pdshl p=3 300 // survivingDigits = 1 <= child->prec (1) so not an intermediate truncation526* zd2pd p=1 3 // isTruncating=true527* zdx p=3 123528* shift=2529*530* so531* zdshl p=3 300532* zdx p=3 123533* shift=2534* gives an equivalent answer535*536* Example of a truncating shift that *is* an intermediate truncation:537* pdshl p=4 0300 // survivingDigits = 2 > child->prec (1) so is an intermediate truncation538* zd2pd p=1 3 // isTruncating=true539* zdx p=3 123540* shift=2541*542* so543* zdshl p=4 2300544* zdx p=3 123545* shift=2546* gives a different answer547*/548bool549J9::Node::hasIntermediateTruncation()550{551TR::Node *valueChild = self()->getValueChild();552TR_ASSERT(self()->getType().isBCD() && valueChild->getType().isBCD(), "hasIntermediateTruncation only valid for BCD parent (dt=%s) and child (dt=%s)\n",553self()->getDataType().toString(), valueChild->getDataType().toString());554if (valueChild->isTruncating() &&555self()->survivingDigits() > valueChild->getDecimalPrecision())556{557return true;558}559else560{561return false;562}563}564565/**566* For non-shift operations the surviving digits is simply the precision.567*568* Left shift example:569* 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.570* The shiftedPrecision is 3+2 = 5 and this is > than the nodePrec of 4.571* There is 1 truncated digit so reduce the shiftedPrecision by 1 to get the surviving digits value of 2.572*573* Right shift example:574* 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.575* The shiftedPrecision is 5-1 = 4 and this > than the nodePrec of 3.576* There is 1 truncated digit so reduce the shiftedPrecision by 1 to get the surviving digits value of 3.577*578* @note that the shift formula for surviving digits degenerates to just getDecimalPrecision() when adjust == 0579*/580int32_t581J9::Node::survivingDigits()582{583TR_ASSERT(self()->getType().isBCD(), "node %p (op %d) is not a BCD type (dt=%s)\n", self(), self()->getOpCodeValue(), self()->getDataType().toString());584int32_t survivingDigits = 0;585if (self()->getOpCode().isShift())586{587TR::Node *child = self()->getFirstChild(); // left shift 3v0 -> 2v2588int32_t adjust = self()->getDecimalAdjust(); // 2589int32_t shiftedPrecision = child->getDecimalPrecision() + adjust; // 5=3+2590int32_t truncatedDigits = shiftedPrecision - self()->getDecimalPrecision(); // 1=5-4591survivingDigits = child->getDecimalPrecision() - truncatedDigits; // 2=3-1592}593else594{595survivingDigits = self()->getDecimalPrecision();596}597return survivingDigits;598}599600bool601J9::Node::isTruncating()602{603if (self()->getType().isBCD() && self()->getNumChildren() >= 1 && self()->getValueChild()->getType().isBCD())604{605if (self()->getOpCode().isShift())606return self()->isTruncatingBCDShift();607else if (self()->getDecimalPrecision() < self()->getValueChild()->getDecimalPrecision())608return true;609else610return false;611}612else if (self()->getType().isBCD() && self()->getOpCode().isConversion() && self()->getNumChildren() >= 1 && !self()->getValueChild()->getType().isBCD())613{614if (self()->hasSourcePrecision() && self()->getDecimalPrecision() < self()->getSourcePrecision())615return true;616else if (!self()->hasSourcePrecision()) // Conservative, but necessary for correctness in some opts; best to always set sourcePrecision617return true;618else619return false;620}621else622{623return false;624}625}626627bool628J9::Node::isTruncatingBCDShift()629{630TR_ASSERT(self()->getType().isBCD() && (self()->getOpCode().isModifyPrecision() || self()->getOpCode().isShift()), "node %p (op %d) is not a BCD shift\n", this, self()->getOpCodeValue());631632if (self()->getOpCode().isModifyPrecision() &&633self()->getDecimalPrecision() < self()->getFirstChild()->getDecimalPrecision())634{635return true;636}637else if (self()->getOpCode().isShift() &&638self()->getDecimalPrecision() < (self()->getFirstChild()->getDecimalPrecision() + self()->getDecimalAdjust()))639{640return true;641}642else643{644return false;645}646}647648bool649J9::Node::isWideningBCDShift()650{651TR_ASSERT(self()->getType().isBCD() && (self()->getOpCode().isModifyPrecision() || self()->getOpCode().isShift()), "node %p (op %d) is not a BCD shift\n", self(), self()->getOpCodeValue());652653if (self()->getOpCode().isModifyPrecision() &&654self()->getDecimalPrecision() > self()->getFirstChild()->getDecimalPrecision())655{656return true;657}658else if (self()->getOpCode().isShift() &&659self()->getDecimalPrecision() > (self()->getFirstChild()->getDecimalPrecision() + self()->getDecimalAdjust()))660{661return true;662}663else664{665return false;666}667}668669bool670J9::Node::isSimpleWidening()671{672if (self()->getOpCode().isModifyPrecision() &&673self()->getDecimalPrecision() > self()->getFirstChild()->getDecimalPrecision())674{675return true;676}677else if (self()->getOpCodeValue() == TR::pdshl &&678self()->getSecondChild()->getOpCode().isLoadConst() &&679self()->getSecondChild()->get64bitIntegralValue() == 0 &&680self()->getDecimalPrecision() > self()->getFirstChild()->getDecimalPrecision())681{682return true;683}684else685{686return false;687}688}689690bool691J9::Node::mustClean()692{693if (self()->getType().isAnyPacked() &&694(self()->getOpCodeValue() == TR::pdclean || (self()->getOpCode().isStore() && self()->mustCleanSignInPDStoreEvaluator())))695{696return true;697}698return false;699}700701void702J9::Node::setKnownSignCodeFromRawSign(int32_t rawSignCode)703{704if (TR::Node::typeSupportedForSignCodeTracking(self()->getDataType()))705{706if (rawSignCode == 0xc)707self()->setKnownSignCode(raw_bcd_sign_0xc);708else if (rawSignCode == 0xd)709self()->setKnownSignCode(raw_bcd_sign_0xd);710else if (rawSignCode == 0xf)711self()->setKnownSignCode(raw_bcd_sign_0xf);712}713}714715/**716* @todo Start tracking SeparateOneByte and SeparateTwoByte sign sizes too717*/718bool719J9::Node::typeSupportedForSignCodeTracking(TR::DataType dt)720{721return TR::DataType::getSignCodeSize(dt) == EmbeddedHalfByte;722}723724bool725J9::Node::typeSupportedForTruncateOrWiden(TR::DataType dt)726{727return dt == TR::PackedDecimal728|| dt == TR::ZonedDecimalSignLeadingEmbedded729|| dt == TR::ZonedDecimal ;730}731732void733J9::Node::truncateOrWidenBCDLiteral(TR::DataType dt, char *newLit, int32_t newPrecision, char *oldLit, int32_t oldPrecision)734{735TR_ASSERT(TR::Node::typeSupportedForTruncateOrWiden(dt),736"datatype %s not supported in truncateOrWidenBCDLiteral\n", dt.toString());737bool isLeadingSign = (dt == TR::ZonedDecimalSignLeadingEmbedded);738int32_t newSize = TR::DataType::getSizeFromBCDPrecision(dt, newPrecision);739int32_t oldSize = TR::DataType::getSizeFromBCDPrecision(dt, oldPrecision);740memset(newLit, TR::DataType::getOneByteBCDFill(dt), newSize);741char *shiftedNewLit = newLit;742char *shiftedLit = oldLit;743int32_t copySize = oldSize;744if (newSize > oldSize)745{746shiftedNewLit += (newSize - oldSize); // a widening into a right justified field so bump the destination747copySize = oldSize;748}749else if (newSize < oldSize)750{751shiftedLit += (oldSize - newSize); // a truncation from a right justified field so bump the source752copySize = newSize;753}754memcpy(shiftedNewLit, shiftedLit, copySize);755if (dt == TR::PackedDecimal && ((newPrecision&0x1)==0)) // zero top nibble for even precision results756newLit[0] &= 0x0F;757758if (isLeadingSign)759{760TR_ASSERT(dt == TR::ZonedDecimalSignLeadingEmbedded, "only zdsle leading sign type supported in truncateOrWidenBCDLiteral (dt=%s)\n", dt.toString());761uint8_t sign = oldLit[0]&0xf0;762newLit[0] = (newLit[0]&0x0f) | sign;763}764}765766void767J9::Node::setNewBCDSignOnLiteral(uint32_t newSignCode, TR::DataType dt, char *lit, int32_t litSize)768{769switch (dt)770{771case TR::PackedDecimal:772TR_ASSERT(newSignCode <= 0xF, "expecting packed embedded sign type %s signCode 0x%x to be <= 0xF\n", dt.toString(), newSignCode);773lit[litSize-1] = (newSignCode | (lit[litSize-1] & 0xf0));774break;775case TR::ZonedDecimal:776TR_ASSERT(newSignCode <= 0xF, "expecting zoned embedded sign type %s signCode 0x%x to be <= 0xF\n", dt.toString(), newSignCode);777lit[litSize-1] = ((newSignCode<<4) | (lit[litSize-1] & 0x0f));778break;779case TR::ZonedDecimalSignLeadingEmbedded:780TR_ASSERT(newSignCode <= 0xF, "expecting zoned leading embedded sign type %s signCode 0x%x to be <= 0xF\n", dt.toString(), newSignCode);781lit[0] = ((newSignCode<<4) | (lit[0] & 0x0f));782break;783case TR::ZonedDecimalSignLeadingSeparate:784TR_ASSERT(newSignCode <= 0xFF, "expecting separate sign type %s signCode 0x%x to be <= 0xFF\n", dt.toString(), newSignCode);785lit[0] = newSignCode;786break;787case TR::ZonedDecimalSignTrailingSeparate:788TR_ASSERT(newSignCode <= 0xFF, "expecting separate sign type %s signCode 0x%x to be <= 0xFF\n", dt.toString(), newSignCode);789lit[litSize-1] = newSignCode;790break;791case TR::UnicodeDecimalSignLeading:792TR_ASSERT(newSignCode <= 0xFF, "expecting separate sign type %s signCode 0x%x to be <= 0xFF\n", dt.toString(), newSignCode);793lit[0] = 0;794lit[1] = newSignCode;795break;796case TR::UnicodeDecimalSignTrailing:797TR_ASSERT(newSignCode <= 0xFF, "expecting separate sign type %s signCode 0x%x to be <= 0xFF\n", dt.toString(), newSignCode);798lit[litSize-2] = 0;799lit[litSize-1] = newSignCode;800break;801case TR::UnicodeDecimal:802TR_ASSERT(false, "TR::UnicodeDecimal type (%s) does not have a sign code\n", dt.toString());803break;804default:805TR_ASSERT(false, "unknown bcd type %s\n", dt.toString());806break;807}808}809810TR::Node *811J9::Node::getSetSignValueNode()812{813TR::Node *setSignValueNode = NULL;814if (self()->getOpCode().isSetSign())815{816int32_t setSignValueIndex = TR::ILOpCode::getSetSignValueIndex(self()->getOpCodeValue());817if (setSignValueIndex > 0)818{819setSignValueNode = self()->getChild(setSignValueIndex);820}821else822{823TR_ASSERT(false, "setSignValueIndex should be > 0 and not %d\n", setSignValueIndex);824}825}826else827{828TR_ASSERT(false, "getSetSignValueNode only valid for setSign ops and not op %d\n", self()->getOpCodeValue());829}830return setSignValueNode;831}832833bool834J9::Node::alwaysGeneratesAKnownCleanSign()835{836TR::Compilation *comp = TR::comp();837return comp->cg()->alwaysGeneratesAKnownCleanSign(self());838}839840bool841J9::Node::alwaysGeneratesAKnownPositiveCleanSign()842{843TR::Compilation *comp = TR::comp();844return comp->cg()->alwaysGeneratesAKnownPositiveCleanSign(self());845}846847#ifdef TR_TARGET_S390848int32_t849J9::Node::getStorageReferenceSize()850{851TR::Compilation *comp = TR::comp();852if (self()->getType().isAggregate())853{854return self()->getSize();855}856else if (self()->getOpCode().isBCDToNonBCDConversion())857{858return self()->getStorageReferenceSourceSize();859}860else861{862TR_ASSERT(self()->getType().isBCD(), "node result type should be a BCD type in getStorageReferenceSize and not type %s\n", self()->getDataType().toString());863int32_t size = 0;864switch (self()->getOpCodeValue())865{866case TR::l2pd:867size = comp->cg()->getLongToPackedFixedSize();868break;869case TR::i2pd:870size = comp->cg()->getIntegerToPackedFixedSize();871break;872case TR::pdadd:873case TR::pdsub:874size = comp->cg()->getPDAddSubEncodedSize(self());875break;876case TR::pdmul:877size = comp->cg()->getPDMulEncodedSize(self());878break;879case TR::pddiv:880case TR::pdrem:881size = comp->cg()->getPDDivEncodedSize(self());882break;883case TR::ud2pd:884case TR::udsl2pd:885case TR::udst2pd:886size = comp->cg()->getUnicodeToPackedFixedResultSize();887break;888default:889size = self()->getSize();890break;891}892893if ((self()->getOpCode().isPackedRightShift() && self()->getDecimalRound() != 0) || self()->getOpCodeValue() == TR::pdshlOverflow)894size = std::max(self()->getSize(), self()->getFirstChild()->getSize());895896return size;897}898}899900int32_t901J9::Node::getStorageReferenceSourceSize()902{903TR::Compilation *comp = TR::comp();904int32_t size = 0;905switch (self()->getOpCodeValue())906{907case TR::pd2l:908case TR::pd2lu:909case TR::pd2lOverflow:910size = comp->cg()->getPackedToLongFixedSize();911break;912case TR::pd2i:913case TR::pd2iu:914case TR::pd2iOverflow:915size = comp->cg()->getPackedToIntegerFixedSize();916break;917default:918TR_ASSERT(false, "node %p and type %s not supported in getStorageReferenceSourceSize\n", self(), self()->getDataType().toString());919break;920}921return size;922}923924TR_PseudoRegister*925J9::Node::getPseudoRegister()926{927TR_ASSERT(self()->getOpCodeValue() != TR::BBStart, "don't call getPseudoRegister for a BBStart");928TR::Register *reg = self()->getRegister();929return reg ? reg->getPseudoRegister() : 0;930}931932TR_OpaquePseudoRegister*933J9::Node::getOpaquePseudoRegister()934{935TR_ASSERT(self()->getOpCodeValue() != TR::BBStart, "don't call getOpaquePseudoRegister for a BBStart");936TR::Register *reg = self()->getRegister();937return reg ? reg->getOpaquePseudoRegister() : 0;938}939940#endif //S390941942943bool944J9::Node::pdshrRoundIsConstantZero()945{946if (self()->getOpCode().isPackedRightShift())947{948if (self()->getThirdChild()->getOpCode().isLoadConst() &&949self()->getThirdChild()->get64bitIntegralValue() == 0)950{951return true;952}953}954else955{956TR_ASSERT(false, "Only packed shift right operations have a round node (op %d)\n", self()->getOpCodeValue());957}958return false;959}960961/*962* \brief963* Get the node type signature964*965* \parm len966*967* \parm allocKind968*969* \parm parmAsAuto970* For a node with parm symbol, the API is used in two different ways because the slot for dead971* parm symbol can be reused for variables of any type. When \parm parmAsAuto is true, parm is972* treated as other auto and the type signature is ignored. When \parm parmAsAuto is false, the973* type signature of the parm symbol is returned.974*/975const char *976J9::Node::getTypeSignature(int32_t & len, TR_AllocationKind allocKind, bool parmAsAuto)977{978TR::Compilation * c = TR::comp();979// todo: can do better for array element references980if (!self()->getOpCode().hasSymbolReference())981return 0;982983TR::SymbolReference *symRef = self()->getSymbolReference();984TR::Symbol *sym = symRef->getSymbol();985if (parmAsAuto && sym->isParm())986return 0;987bool allowForAOT = c->getOption(TR_UseSymbolValidationManager);988TR_PersistentClassInfo * classInfo = c->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(c->getCurrentMethod()->containingClass(), c, allowForAOT);989TR::Node * node = self();990TR_PersistentFieldInfo * fieldInfo = classInfo && classInfo->getFieldInfo() ? classInfo->getFieldInfo()->findFieldInfo(c, node, false) : 0;991if (fieldInfo && fieldInfo->isTypeInfoValid() && fieldInfo->getNumChars() > 0)992{993len = fieldInfo->getNumChars();994return fieldInfo->getClassPointer();995}996997if (self()->getOpCodeValue() == TR::multianewarray)998symRef = self()->getChild(self()->getNumChildren()-1)->getSymbolReference();999const char * sig = symRef->getTypeSignature( len, allocKind);1000if (sig)1001return sig;10021003if (self()->getOpCodeValue() == TR::aloadi && symRef->getCPIndex() == -1)1004{1005// Look for an array element reference. If this is such a reference, look1006// down to get the signature of the base and strip off one layer of array1007// indirection.1008//1009TR::Node * child = self()->getFirstChild();1010if (child->isInternalPointer())1011{1012child = child->getFirstChild();1013sig = child->getTypeSignature(len, allocKind, parmAsAuto);1014if (sig != NULL && *sig == '[')1015{1016--len;1017return sig+1;1018}1019}1020}10211022// todo: could do more work to figure out types for 'new' nodes10231024return 0;1025}1026102710281029bool1030J9::Node::isTruncatingOrWideningAggrOrBCD()1031{1032TR_ASSERT(self()->getType().isAggregate() || self()->getType().isBCD(),1033"truncatingOrWideningAggrOrBCD should only be called on BCD or aggr!");1034TR_ASSERT(self()->getValueChild() != NULL,1035"getValueChild should have a value!");10361037int32_t nodeSize = 0;1038int32_t valueSize = 0;10391040if (self()->getType().isAggregate())1041{1042nodeSize = self()->getSize();1043valueSize = self()->getValueChild()->getSize();1044}1045else if (self()->getType().isBCD())1046{1047nodeSize = self()->getDecimalPrecision();1048valueSize = self()->getValueChild()->getDecimalPrecision();1049}10501051return (nodeSize != valueSize);1052}10531054bool1055J9::Node::canRemoveArithmeticOperand()1056{1057TR::Compilation * comp = TR::comp();1058if (!comp->getOption(TR_KeepBCDWidening) && self()->getOpCodeValue() == TR::pdclean)1059{1060return true;1061}1062else if (self()->getOpCodeValue() == TR::pdSetSign)1063{1064// could also do for pdshxSetSign if pdshx is left in place but shift with setSign is usually cheaper than without1065if (self()->isNonNegative() && self()->getFirstChild()->isNonNegative())1066return true;1067else if (self()->isNonPositive() && self()->getFirstChild()->isNonPositive())1068return true;1069}1070return false;1071}10721073uint32_t1074J9::Node::hashOnBCDOrAggrLiteral(char *lit, size_t litSize)1075{1076uint32_t hash = 0;1077for (int32_t i = 0; i < litSize && i < TR_MAX_CHARS_FOR_HASH; i++)1078hash+=lit[i];1079hash+=(litSize*TR_DECIMAL_HASH); // avoid collisions for numbers like 10 and 1001080return hash;1081}1082108310841085bool1086J9::Node::referencesSymbolInSubTree(TR::SymbolReference* symRef, vcount_t visitCount)1087{1088// The visit count in the node must be maintained by this method.1089//1090vcount_t oldVisitCount = self()->getVisitCount();1091if (oldVisitCount == visitCount)1092return false;1093self()->setVisitCount(visitCount);10941095if (self()->getOpCode().hasSymbolReference())1096{1097if (self()->getSymbolReference()->getReferenceNumber() == symRef->getReferenceNumber())1098{1099return true;1100}1101}11021103// For all other subtrees collect all symbols that could be killed between1104// here and the next reference.1105//1106for (int32_t i = self()->getNumChildren()-1; i >= 0; i--)1107{1108TR::Node * child = self()->getChild(i);1109if (child->referencesSymbolInSubTree(symRef, visitCount)) return true;1110}11111112return false;1113}11141115bool1116J9::Node::referencesMayKillAliasInSubTree(TR::Node * rootNode, vcount_t visitCount)1117{1118TR::Compilation * comp = TR::comp();1119TR::SparseBitVector references (comp->allocator());1120self()->getSubTreeReferences(references, visitCount);11211122return rootNode->mayKill().containsAny(references, comp);1123}11241125void1126J9::Node::getSubTreeReferences(TR::SparseBitVector &references, vcount_t visitCount) {1127// The visit count in the node must be maintained by this method.1128//1129vcount_t oldVisitCount = self()->getVisitCount();11301131if (oldVisitCount == visitCount) return;11321133self()->setVisitCount(visitCount);11341135if (self()->getOpCode().hasSymbolReference() &&1136self()->getSymbolReference() &&1137(self()->getOpCodeValue() != TR::loadaddr)) // a loadaddr is not really a reference1138{1139references[self()->getSymbolReference()->getReferenceNumber()]=true;1140}11411142for (int32_t i = self()->getNumChildren()-1; i >= 0; i--)1143self()->getChild(i)->getSubTreeReferences(references, visitCount);1144}11451146TR_ParentOfChildNode*1147J9::Node::referencesSymbolExactlyOnceInSubTree(1148TR::Node* parent, int32_t childNum, TR::SymbolReference* symRef, vcount_t visitCount)1149{1150// The visit count in the node must be maintained by this method.1151//1152TR::Compilation * comp = TR::comp();1153vcount_t oldVisitCount = self()->getVisitCount();1154if (oldVisitCount == visitCount)1155return NULL;1156self()->setVisitCount(visitCount);11571158if (self()->getOpCode().hasSymbolReference() && (self()->getSymbolReference()->getReferenceNumber() == symRef->getReferenceNumber()))1159{1160TR_ParentOfChildNode* pNode = new (comp->trStackMemory()) TR_ParentOfChildNode(parent, childNum);1161return pNode;1162}11631164// For all other subtrees, see if any has a ref. If exactly one does, return it1165TR_ParentOfChildNode* matchNode=NULL;1166for (int32_t i = self()->getNumChildren()-1; i >= 0; i--)1167{1168TR::Node * child = self()->getChild(i);1169TR_ParentOfChildNode* curr = child->referencesSymbolExactlyOnceInSubTree(self(), i, symRef, visitCount);1170if (curr)1171{1172if (matchNode)1173{1174return NULL;1175}1176matchNode = curr;1177}1178}11791180return matchNode;1181}11821183/**1184* Node field functions1185*/11861187#ifdef TR_TARGET_S39011881189TR_StorageReference *1190J9::Node::getStorageReferenceHint()1191{1192TR_ASSERT(self()->getOpCode().canHaveStorageReferenceHint(), "attempting to access _storageReferenceHint field for node %s %p that does not have it", self()->getOpCode().getName(), this);1193if (_storageReferenceHint && !_storageReferenceHint->hintHasBeenUsed())1194return _storageReferenceHint;1195else1196return NULL;1197}11981199TR_StorageReference *1200J9::Node::setStorageReferenceHint(TR_StorageReference *s)1201{1202TR_ASSERT(self()->getOpCode().canHaveStorageReferenceHint(), "attempting to access _storageReferenceHint field for node %s %p that does not have it", self()->getOpCode().getName(), this);1203return (_storageReferenceHint = s);1204}12051206#endif12071208/**1209* Node field functions end1210*/121112121213121412151216/**1217* UnionPropertyB functions1218*/12191220bool1221J9::Node::hasDecimalInfo()1222{1223// _decimalInfo is only valid if opcode has datatype1224if (self()->getOpCode().hasNoDataType())1225return false;12261227// _decimalInfo is used for those languages that return true as determined by the code below1228return1229// Any node with a BCD type (pdloadi, pdadd, zd2pd, pdstorei etc)1230self()->getType().isBCD() ||1231// Conversions from a BCD type to a float to encode # of fractional digits (pd2f, pd2d, etc.)1232self()->getOpCode().isConversionWithFraction()1233// BCD types and also any BCD ifs and compares (e.g. ifpdcmpxx, pdcmpxx)1234|| self()->chkOpsCastedToBCD();1235}12361237bool1238J9::Node::hasBCDFlags()1239{1240// used for BCDCHK only1241return self()->getOpCodeValue() == TR::BCDCHK;1242}12431244J9::Node::UnionPropertyB_Type1245J9::Node::getUnionPropertyB_Type()1246{1247if (self()->hasDecimalInfo())1248// in order to determine this correctly, require children and symRef to be already defined1249// as depends on getDataType which in term depends on these1250return HasDecimalInfo;1251else if (self()->hasBCDFlags())1252return HasBcdFlags;1253else1254return HasNoUnionPropertyB;1255}12561257bool1258J9::Node::hasDecimalPrecision()1259{1260return self()->getType().isBCD();1261}12621263bool1264J9::Node::hasDecimalAdjust()1265{1266return !self()->getOpCode().isShift() && !self()->getOpCode().isConversionWithFraction() && self()->getType().isBCD();1267}12681269bool1270J9::Node::hasSetSign()1271{1272return self()->getType().isBCD() && self()->getOpCode().isSetSignOnNode();1273}12741275bool1276J9::Node::hasDecimalFraction()1277{1278return self()->getOpCode().isConversionWithFraction();1279}12801281bool1282J9::Node::hasDecimalRound()1283{1284return self()->getType().isBCD() && !self()->getOpCode().isRightShift();1285}1286128712881289void1290J9::Node::setDecimalPrecision(int32_t p)1291{1292TR_ASSERT(self()->getType().isBCD(), "opcode not supported for setDecimalPrecision on node %p\n", self());1293TR_ASSERT(p > 0 && p <= TR_MAX_DECIMAL_PRECISION, "unexpected decimal precision %d on node %p\n", p, self());1294TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalPrecision field for node %s %p that does not have it", self()->getOpCode().getName(), self());1295if (_unionPropertyB._decimalInfo._decimalPrecision != TR::DataType::getInvalidDecimalPrecision() &&1296(uint32_t)p < _unionPropertyB._decimalInfo._decimalPrecision)1297{1298if (self()->getKnownOrAssumedSignCode() != raw_bcd_sign_0xc)1299{1300_unionPropertyB._decimalInfo._hasCleanSign = 0;1301}1302if (self()->chkSkipPadByteClearing())1303self()->setSkipPadByteClearing(false);1304}1305_unionPropertyB._decimalInfo._decimalPrecision = (uint32_t)p;1306}13071308uint8_t1309J9::Node::getDecimalPrecision()1310{1311TR_ASSERT(self()->getType().isBCD(), "opcode not supported for getDecimalPrecision on node %p\n", self());1312TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalPrecision field for node %s %p that does not have it", self()->getOpCode().getName(), self());1313TR_ASSERT(_unionPropertyB._decimalInfo._decimalPrecision > 0 && _unionPropertyB._decimalInfo._decimalPrecision <= TR_MAX_DECIMAL_PRECISION,1314"unexpected decimal precision %d on node %p\n", _unionPropertyB._decimalInfo._decimalPrecision, self());1315return _unionPropertyB._decimalInfo._decimalPrecision;1316}1317131813191320// These precision setting routines set a precision big enough to hold the full computed result1321// A caller or codegen may choose to set a different value (bigger or smaller) to satisfy a specific1322// semantic or encoding requirement -- see getPDMulEncodedPrecision et al. in the platform code generators1323void1324J9::Node::setPDMulPrecision()1325{1326TR_ASSERT(self()->getOpCode().isPackedMultiply(), "setPDMulPrecision only valid for pdmul nodes\n");1327TR_ASSERT(self()->getNumChildren() >= 2, "expecting >= 2 children and not %d children on a packed multiply node\n", self()->getNumChildren());1328self()->setDecimalPrecision(self()->getFirstChild()->getDecimalPrecision() + self()->getSecondChild()->getDecimalPrecision());1329}13301331void1332J9::Node::setPDAddSubPrecision()1333{1334TR_ASSERT(self()->getOpCode().isPackedAdd() || self()->getOpCode().isPackedSubtract(), "setPDAddSubPrecision only valid for pdadd/pdsub nodes\n");1335TR_ASSERT(self()->getNumChildren() >= 2, "expecting >= 2 children and not %d children on a packed add/sub node\n", self()->getNumChildren());1336self()->setDecimalPrecision(std::max(self()->getFirstChild()->getDecimalPrecision(), self()->getSecondChild()->getDecimalPrecision())+1);1337}13381339void1340J9::Node::setDecimalAdjust(int32_t a)1341{1342TR_ASSERT(a >= TR::DataType::getMinDecimalAdjust() && a <= TR::DataType::getMaxDecimalAdjust(), "unexpected decimal adjust %d\n", a);1343// conversions should not have an adjust1344TR_ASSERT(!self()->getOpCode().isShift(), "decimalAdjust is the 2nd child on pdshr/pdshl nodes\n");1345TR_ASSERT(!self()->getOpCode().isConversionWithFraction(), "conversions nodes should not use setDecimalAdjust\n");1346TR_ASSERT(self()->getType().isBCD(), "type not supported for setDecimalAdjust\n");1347TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalAdjustOrFractionOrDivisor field for node %s %p that does not have it", self()->getOpCode().getName(), self());1348_unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor = a;1349}13501351int32_t1352J9::Node::getDecimalAdjust()1353{1354// conversions should not have an adjust1355TR_ASSERT(!self()->getOpCode().isConversionWithFraction(), "conversions nodes should not use getDecimalAdjust\n");1356TR_ASSERT(self()->getType().isBCD(), "type not supported for getDecimalAdjust\n");1357int64_t adjust = 0;1358if (self()->getOpCode().isShift() && self()->getSecondChild()->getOpCode().isLoadConst())1359adjust = self()->getOpCode().isRightShift() ? -self()->getSecondChild()->get64bitIntegralValue() : self()->getSecondChild()->get64bitIntegralValue();1360else1361{1362TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalAdjustOrFractionOrDivisor field for node %s %p that does not have it", self()->getOpCode().getName(), self());1363adjust = _unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor;1364}1365TR_ASSERT(adjust >= TR::DataType::getMinDecimalAdjust() && adjust <= TR::DataType::getMaxDecimalAdjust(),1366"unexpected decimal adjust %d\n", (int32_t)adjust);1367return (int32_t)adjust;1368}1369137013711372void1373J9::Node::setDecimalFraction(int32_t f)1374{1375TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalAdjustOrFractionOrDivisor field for node %s %p that does not have it", self()->getOpCode().getName(), self());1376TR_ASSERT(f >= TR::DataType::getMinDecimalFraction() && f <= TR::DataType::getMaxDecimalFraction(), "unexpected decimal fraction %d\n", f);1377TR_ASSERT(self()->getOpCode().isConversionWithFraction(), "only valid for conversion nodes that have a fraction\n"); // such as f2pd or pd2f1378_unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor = f;1379}13801381int32_t1382J9::Node::getDecimalFraction()1383{1384TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalAdjustOrFractionOrDivisor field for node %s %p that does not have it", self()->getOpCode().getName(), self());1385TR_ASSERT(_unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor >= TR::DataType::getMinDecimalFraction() && _unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor <= TR::DataType::getMaxDecimalFraction(),1386"unexpected decimal fraction %d\n", _unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor);1387TR_ASSERT(self()->getOpCode().isConversionWithFraction(), "only valid for conversion nodes that have a fraction\n"); // such as f2pd or pd2f1388return _unionPropertyB._decimalInfo._decimalAdjustOrFractionOrDivisor;1389}1390139113921393/**1394* Source precisions are valid for conversions from a non-BCD type to a BCD type1395*/1396bool1397J9::Node::canHaveSourcePrecision()1398{1399if (self()->getOpCode().isConversion() && self()->getType().isBCD() && !self()->getFirstChild()->getType().isBCD())1400return true;1401return false;1402}14031404bool1405J9::Node::hasSourcePrecision()1406{1407if (!self()->canHaveSourcePrecision())1408return false;1409TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalSourcePrecisionOrDividend field for node %s %p that does not have it", self()->getOpCode().getName(), self());1410return (_unionPropertyB._decimalInfo._decimalSourcePrecisionOrDividend > 0);1411}14121413void1414J9::Node::setSourcePrecision(int32_t prec)1415{1416TR_ASSERT(self()->canHaveSourcePrecision(), "setSourcePrecision can only be called on a non-BCD-to-BCD conversion node\n");1417TR_ASSERT(prec >= 1, "source precision must be >= 1\n");1418TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalSourcePrecisionOrDividend field for node %s %p that does not have it", self()->getOpCode().getName(), self());1419_unionPropertyB._decimalInfo._decimalSourcePrecisionOrDividend = prec;1420}14211422int32_t1423J9::Node::getSourcePrecision()1424{1425TR_ASSERT(self()->canHaveSourcePrecision(), "getSourcePrecision can only be called on a non-BCD-to-BCD conversion node\n");1426TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalSourcePrecisionOrDividend field for node %s %p that does not have it", self()->getOpCode().getName(), self());1427if (_unionPropertyB._decimalInfo._decimalSourcePrecisionOrDividend == 0)1428return TR_MAX_DECIMAL_PRECISION;1429else1430return _unionPropertyB._decimalInfo._decimalSourcePrecisionOrDividend;1431}14321433int32_t1434J9::Node::getDecimalAdjustOrFractionOrDivisor()1435{1436if (self()->getOpCode().isConversionWithFraction())1437return self()->getDecimalFraction();1438else1439return self()->getDecimalAdjust();1440}14411442int32_t1443J9::Node::getDecimalRoundOrDividend()1444{1445return self()->getDecimalRound();1446}14471448bool1449J9::Node::isSetSignValueOnNode()1450{1451if (self()->hasSetSign())1452{1453TR_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());1454return true;1455}1456else1457{1458return false;1459}1460}14611462void1463J9::Node::setSetSign(TR_RawBCDSignCode setSign)1464{1465TR_ASSERT(self()->hasSetSign(), "setSetSign only supported for setsign nodes (%s %p)\n", self()->getOpCode().getName(), self());1466TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._setSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());1467_unionPropertyB._decimalInfo._setSign = setSign;1468}14691470TR_RawBCDSignCode1471J9::Node::getSetSign()1472{1473TR_ASSERT(self()->hasSetSign(), "getSetSign only supported for setsign nodes (%s %p)\n", self()->getOpCode().getName(), self());1474TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._setSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());1475return _unionPropertyB._decimalInfo._setSign;1476}14771478bool1479J9::Node::isDecimalSizeAndShapeEquivalent(TR::Node *other)1480{1481if (self()->getDecimalPrecision() == other->getDecimalPrecision() &&1482self()->getDecimalAdjustOrFractionOrDivisor() == other->getDecimalAdjustOrFractionOrDivisor() &&1483self()->getDecimalRoundOrDividend() == other->getDecimalRoundOrDividend())1484{1485if (self()->getOpCode().isSetSignOnNode() && other->getOpCode().isSetSignOnNode() &&1486self()->getSetSign() != other->getSetSign())1487{1488return false;1489}1490else1491{1492return true;1493}1494}1495else1496{1497return false;1498}1499}1500150115021503void1504J9::Node::setDecimalRound(int32_t r)1505{1506TR_ASSERT(r >= 0 && r <= TR::DataType::getMaxDecimalRound(), "unexpected decimal round %d\n", r);1507TR_ASSERT(self()->getType().isBCD(), "type not supported for setDecimalRound\n");1508TR_ASSERT(!self()->getOpCode().isRightShift(), "decimalRound is the 3rd child on pdshr nodes\n");1509TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._round field for node %s %p that does not have it", self()->getOpCode().getName(), self());1510_unionPropertyB._decimalInfo._round = (r > 0 ? 1 : 0);1511}15121513uint8_t1514J9::Node::getDecimalRound()1515{1516TR_ASSERT(self()->getType().isBCD(), "type not supported for getDecimalRound\n");1517TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._round field for node %s %p that does not have it", self()->getOpCode().getName(), self());1518int64_t round = 0;1519if (self()->getOpCode().isPackedRightShift() && self()->getChild(2)->getOpCode().isLoadConst())1520round = self()->getChild(2)->get64bitIntegralValue();1521else1522round = (_unionPropertyB._decimalInfo._round == 1 ? 5 : 0);1523TR_ASSERT(round >= 0 && round <= TR::DataType::getMaxDecimalRound() && round <= TR::getMaxUnsigned<TR::Int8>(), "unexpected decimal round %d\n", (int32_t)round);1524return (uint8_t)round;1525}1526152715281529bool1530J9::Node::signStateIsKnown()1531{1532TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signStateIsKnown field for node %s %p that does not have it", self()->getOpCode().getName(), self());1533return _unionPropertyB._decimalInfo._signStateIsKnown == 1;1534}15351536void1537J9::Node::setSignStateIsKnown()1538{1539if (self()->signStateIsAssumed())1540self()->resetDecimalSignFlags(); // ensure any lingering assumed sign state is cleared1541TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signStateIsKnown field for node %s %p that does not have it", self()->getOpCode().getName(), self());1542_unionPropertyB._decimalInfo._signStateIsKnown = 1;1543}15441545bool1546J9::Node::signStateIsAssumed()1547{1548TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signStateIsKnown field for node %s %p that does not have it", self()->getOpCode().getName(), self());1549return _unionPropertyB._decimalInfo._signStateIsKnown == 0;1550}15511552void1553J9::Node::setSignStateIsAssumed()1554{1555if (self()->signStateIsKnown())1556self()->resetDecimalSignFlags(); // ensure any lingering known sign state is cleared1557TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signStateIsKnown field for node %s %p that does not have it", self()->getOpCode().getName(), self());1558_unionPropertyB._decimalInfo._signStateIsKnown = 0;1559}1560156115621563bool1564J9::Node::hasKnownCleanSign()1565{1566TR_ASSERT(self()->getType().isBCD(), "hasKnownCleanSign only supported for BCD type nodes\n");1567TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasCleanSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());1568if (self()->alwaysGeneratesAKnownCleanSign())1569return true;1570else1571return self()->signStateIsKnown() && _unionPropertyB._decimalInfo._hasCleanSign == 1;1572}15731574void1575J9::Node::setHasKnownCleanSign(bool v)1576{1577TR::Compilation *c = TR::comp();1578TR_ASSERT(self()->getType().isBCD(), "setHasKnownCleanSign only supported for BCD type nodes\n");1579if (self()->getType().isBCD() &&1580performNodeTransformation2(c, "O^O NODE FLAGS: Setting hasKnownCleanSign flag on node %p to %d\n", self(), v))1581{1582self()->setSignStateIsKnown();1583TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasCleanSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());1584_unionPropertyB._decimalInfo._hasCleanSign = v ? 1 : 0;1585}1586}15871588bool1589J9::Node::hasAssumedCleanSign()1590{1591TR_ASSERT(self()->getType().isBCD(), "hasAssumedCleanSign only supported for BCD type nodes\n");1592TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasCleanSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());1593return self()->signStateIsAssumed() && _unionPropertyB._decimalInfo._hasCleanSign == 1;1594}15951596void1597J9::Node::setHasAssumedCleanSign(bool v)1598{1599TR::Compilation * c = TR::comp();1600TR_ASSERT(self()->getType().isBCD(), "setHasAssumedCleanSign only supported for BCD type nodes\n");1601if (self()->getType().isBCD() &&1602performNodeTransformation2(c, "O^O NODE FLAGS: Setting hasAssumedCleanSign flag on node %p to %d\n", self(), v))1603{1604self()->setSignStateIsAssumed();1605TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasCleanSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());1606_unionPropertyB._decimalInfo._hasCleanSign = v ? 1 : 0;1607}1608}16091610bool1611J9::Node::hasKnownOrAssumedCleanSign()1612{1613TR_ASSERT(self()->getType().isBCD(), "hasKnownOrAssumedCleanSign only supported for BCD type nodes\n");1614return self()->hasKnownCleanSign() || self()->hasAssumedCleanSign();1615}16161617void1618J9::Node::setHasKnownAndAssumedCleanSign(bool v)1619{1620TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasCleanSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());1621_unionPropertyB._decimalInfo._hasCleanSign = 0;1622}16231624void1625J9::Node::transferCleanSign(TR::Node *srcNode)1626{1627if (srcNode == NULL) return;16281629if (srcNode->hasKnownCleanSign())1630self()->setHasKnownCleanSign(true);1631else if (srcNode->hasAssumedCleanSign())1632self()->setHasAssumedCleanSign(true);1633}1634163516361637bool1638J9::Node::hasKnownPreferredSign()1639{1640TR_ASSERT(self()->getType().isBCD(), "hasKnownPreferredSign only supported for BCD type nodes\n");1641TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasPreferredSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());1642return self()->signStateIsKnown() && _unionPropertyB._decimalInfo._hasPreferredSign == 1;1643}16441645void1646J9::Node::setHasKnownPreferredSign(bool v)1647{1648TR::Compilation *c = TR::comp();1649TR_ASSERT(self()->getType().isBCD(), "setHasKnownPreferredSign only supported for BCD type nodes\n");1650if (self()->getType().isBCD() &&1651performNodeTransformation2(c, "O^O NODE FLAGS: Setting hasKnownPreferredSign flag on node %p to %d\n", self(), v))1652{1653self()->setSignStateIsKnown();1654TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasPreferredSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());1655_unionPropertyB._decimalInfo._hasPreferredSign= v ? 1 : 0;1656}1657}16581659bool1660J9::Node::hasAssumedPreferredSign()1661{1662TR_ASSERT(self()->getType().isBCD(), "hasAssumedPreferredSign only supported for BCD type nodes\n");1663TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasPreferredSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());1664return self()->signStateIsAssumed() && _unionPropertyB._decimalInfo._hasPreferredSign == 1;1665}16661667void1668J9::Node::setHasAssumedPreferredSign(bool v)1669{1670TR::Compilation *c = TR::comp();1671TR_ASSERT(self()->getType().isBCD(), "setHasAssumedPreferredSign only supported for BCD type nodes\n");1672if (self()->getType().isBCD() &&1673performNodeTransformation2(c, "O^O NODE FLAGS: Setting hasAssumedPreferredSign flag on node %p to %d\n", self(), v))1674{1675self()->setSignStateIsAssumed();1676TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasPreferredSign field for node %s %p that does not have it", self()->getOpCode().getName(), self());1677_unionPropertyB._decimalInfo._hasPreferredSign= v ? 1 : 0;1678}1679}16801681bool1682J9::Node::hasKnownOrAssumedPreferredSign()1683{1684TR_ASSERT(self()->getType().isBCD(), "hasKnownOrAssumedPreferredSign only supported for BCD type nodes\n");1685return self()->hasKnownPreferredSign() || self()->hasAssumedPreferredSign();1686}16871688bool1689J9::Node::hasKnownSignCode()1690{1691TR_ASSERT(self()->getType().isBCD(), "hasKnownSignCode only supported for BCD type nodes\n");1692TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signCode field for node %s %p that does not have it", self()->getOpCode().getName(), self());1693return self()->signStateIsKnown() && (_unionPropertyB._decimalInfo._signCode != raw_bcd_sign_unknown);1694}16951696TR_RawBCDSignCode1697J9::Node::getKnownSignCode()1698{1699TR_ASSERT(self()->getType().isBCD(), "getKnownSignCode only supported for BCD type nodes\n");1700TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signCode field for node %s %p that does not have it", self()->getOpCode().getName(), self());1701return self()->signStateIsKnown() ? _unionPropertyB._decimalInfo._signCode : raw_bcd_sign_unknown;1702}17031704bool1705J9::Node::hasAssumedSignCode()1706{1707TR_ASSERT(self()->getType().isBCD(), "hasAssumedSignCode only supported for BCD type nodes\n");1708TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signCode field for node %s %p that does not have it", self()->getOpCode().getName(), self());1709return self()->signStateIsAssumed() && (_unionPropertyB._decimalInfo._signCode != raw_bcd_sign_unknown);1710}17111712TR_RawBCDSignCode1713J9::Node::getAssumedSignCode()1714{1715TR_ASSERT(self()->getType().isBCD(), "getAssumedSignCode only supported for BCD type nodes\n");1716TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._signCode field for node %s %p that does not have it", self()->getOpCode().getName(), self());1717return self()->signStateIsAssumed() ? _unionPropertyB._decimalInfo._signCode : raw_bcd_sign_unknown;1718}17191720bool1721J9::Node::hasKnownOrAssumedSignCode()1722{1723TR_ASSERT(self()->getType().isBCD(), "hasKnownOrAssumedSignCode only supported for BCD type nodes\n");1724TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalPrecision field for node %s %p that does not have it", self()->getOpCode().getName(), self());1725return self()->hasKnownSignCode() || self()->hasAssumedSignCode();1726}17271728TR_RawBCDSignCode1729J9::Node::getKnownOrAssumedSignCode()1730{1731TR_ASSERT(self()->getType().isBCD(), "getKnownSignCode only supported for BCD type nodes\n");1732if (self()->hasKnownSignCode())1733return self()->getKnownSignCode();1734else if (self()->hasAssumedSignCode())1735return self()->getAssumedSignCode();1736else1737return raw_bcd_sign_unknown;1738}17391740void1741J9::Node::setKnownOrAssumedSignCode(TR_RawBCDSignCode sign, bool isKnown)1742{1743TR::Compilation *c = TR::comp();1744TR_ASSERT(self()->getType().isBCD(), "setKnownSignCode only supported for BCD type nodes\n");1745TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo fields for node %s %p that does not have it", self()->getOpCode().getName(), self());1746// TODO: start tracking SeparateOneByte and SeparateTwoByte sign sizes too1747if (self()->getType().isBCD() && TR::Node::typeSupportedForSignCodeTracking(self()->getDataType()))1748{1749if (performNodeTransformation2(c, "O^O NODE FLAGS: Setting knownSignCode on node %p to %s\n", self(), TR::DataType::getName(sign)))1750{1751if (isKnown)1752self()->setSignStateIsKnown();1753else1754self()->setSignStateIsAssumed();1755_unionPropertyB._decimalInfo._signCode = sign;1756if (TR::DataType::rawSignIsPositive(self()->getDataType(), TR::DataType::getValue(sign)))1757self()->setIsNonNegative(true); // >= 01758else if (TR::DataType::rawSignIsNegative(self()->getDataType(), TR::DataType::getValue(sign)))1759self()->setIsNonPositive(true); // <= 0 negative zero is possible1760}1761if ((sign == raw_bcd_sign_0xc) && (0xc == TR::DataType::getPreferredPlusCode()))1762_unionPropertyB._decimalInfo._hasCleanSign = 1;1763if ((sign == raw_bcd_sign_0xc || sign == raw_bcd_sign_0xd) && (0xc == TR::DataType::getPreferredPlusCode() && 0xd == TR::DataType::getPreferredMinusCode()))1764_unionPropertyB._decimalInfo._hasPreferredSign = 1;1765}1766}17671768void1769J9::Node::setKnownSignCode(TR_RawBCDSignCode sign)1770{1771self()->setKnownOrAssumedSignCode(sign, true); // isKnown=true1772}17731774void1775J9::Node::transferSignCode(TR::Node *srcNode)1776{1777if (srcNode == NULL) return;17781779if (srcNode->hasKnownSignCode())1780self()->setKnownSignCode(srcNode->getKnownSignCode());1781else if (srcNode->hasAssumedSignCode())1782self()->setAssumedSignCode(srcNode->getAssumedSignCode());1783}1784178517861787/**1788* The mapping to/from TR_BCDSignCode from/to the 0xc/0xd/0xf 'raw' encodings in setKnownSignCode/knownSignCodeIs below1789* is temporary until TR_BCDSignCode is tracked on the nodes instead of TR_RawBCDSignCode1790* Doing it this way allows new code (such as VP constrainBCDAggrLoad) to start using this new more general interface1791* The final code will be just calling setKnownOrAssumedSignCode(sign, true, c) but now the 'sign' parm will be TR_BCDSignCode of TR_RawBCDSignCode1792*/1793bool1794J9::Node::knownSignCodeIs(TR_BCDSignCode sign)1795{1796if (self()->hasKnownSignCode() &&1797TR::DataType::getBCDSignFromRawSign(self()->getKnownSignCode()) == sign)1798{1799return true;1800}1801else1802{1803return false;1804}1805}18061807void1808J9::Node::setKnownSignCode(TR_BCDSignCode sign)1809{1810if (TR::Node::typeSupportedForSignCodeTracking(self()->getDataType()))1811{1812TR_RawBCDSignCode rawBCDSign = TR::DataType::getRawSignFromBCDSign(sign);1813if (rawBCDSign != raw_bcd_sign_unknown)1814self()->setKnownSignCode(rawBCDSign);1815}1816}18171818bool1819J9::Node::assumedSignCodeIs(TR_BCDSignCode sign)1820{1821if (self()->hasAssumedSignCode() &&1822TR::DataType::getBCDSignFromRawSign(self()->getAssumedSignCode()) == sign)1823{1824return true;1825}1826else1827{1828return false;1829}1830}18311832void1833J9::Node::setAssumedSignCode(TR_RawBCDSignCode sign)1834{1835self()->setKnownOrAssumedSignCode(sign, false); // isKnown=false1836}18371838bool1839J9::Node::knownOrAssumedSignCodeIs(TR_BCDSignCode sign)1840{1841if (self()->knownSignCodeIs(sign) || self()->assumedSignCodeIs(sign))1842{1843return true;1844}1845else1846{1847return false;1848}1849}1850185118521853/**1854* The hasSignState property is stored in the reverse sense to make the interface easier to use (at the expense of some confusion here)1855*/1856bool1857J9::Node::hasSignStateOnLoad()1858{1859if (!self()->getOpCode().isBCDLoad())1860return false;18611862TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasNoSignStateOnLoad field for node %s %p that does not have it", self()->getOpCode().getName(), self());1863if (_unionPropertyB._decimalInfo._hasNoSignStateOnLoad == 0) // !NoSign == HasSignState1864return 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 setting1865else if (_unionPropertyB._decimalInfo._hasNoSignStateOnLoad == 1)1866return false; // i.e. no particular sign state had assumed on a load (so ZAP widening, for example, is allowed)1867else1868TR_ASSERT(false, "unexpected noSignState setting on %d on node %p\n", _unionPropertyB._decimalInfo._hasNoSignStateOnLoad, self());18691870return true; // conservative setting is that there is sign state to be preserved.1871}18721873void1874J9::Node::setHasSignStateOnLoad(bool v)1875{1876TR::Compilation *c = TR::comp();1877TR_ASSERT(self()->getOpCode().isBCDLoad(), "only BCDLoads can use setHasSignStateOnLoad (%s %p)\n", self()->getOpCode().getName(), self());18781879if (self()->getOpCode().isBCDLoad() &&1880performNodeTransformation2(c, "O^O NODE FLAGS: Setting _hasNoSignStateOnLoad flag on node %p to %d\n", self(), v?0:1))1881{1882TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._hasNoSignStateOnLoad field for node %s %p that does not have it", self()->getOpCode().getName(), self());1883_unionPropertyB._decimalInfo._hasNoSignStateOnLoad = v ? 0 : 1; // v=true is the conservative setting, v=false will allow clobbering of the sign code1884}1885}1886188718881889void1890J9::Node::transferSignState(TR::Node *srcNode, bool digitsLost)1891{1892TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo fields for node %s %p that does not have it", self()->getOpCode().getName(), self());1893_unionPropertyB._decimalInfo._signStateIsKnown = srcNode->signStateIsKnown();1894_unionPropertyB._decimalInfo._hasCleanSign = digitsLost ? 0 : srcNode->hasKnownOrAssumedCleanSign(); // '10 0d' might be truncated to negative zero '0 00d' -- so no longer clean1895_unionPropertyB._decimalInfo._hasPreferredSign = srcNode->hasKnownOrAssumedPreferredSign();1896_unionPropertyB._decimalInfo._signCode = srcNode->getKnownOrAssumedSignCode();1897if (self()->getOpCode().isBCDLoad())1898self()->setHasSignStateOnLoad(srcNode->hasSignStateOnLoad());1899}19001901bool1902J9::Node::hasAnyKnownOrAssumedSignState()1903{1904if (self()->hasKnownOrAssumedCleanSign() ||1905self()->hasKnownOrAssumedPreferredSign() ||1906self()->hasKnownOrAssumedSignCode())1907{1908return true;1909}1910else1911{1912return false;1913}1914}19151916bool1917J9::Node::hasAnyDecimalSignState()1918{1919TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo fields for node %s %p that does not have it", self()->getOpCode().getName(), self());1920if (_unionPropertyB._decimalInfo._hasCleanSign == 1 ||1921_unionPropertyB._decimalInfo._hasPreferredSign == 1 ||1922(self()->getOpCode().isLoadVar() && self()->hasSignStateOnLoad()) ||1923_unionPropertyB._decimalInfo._signCode != raw_bcd_sign_unknown)1924{1925return true;1926}1927else1928{1929return false;1930}1931}19321933void1934J9::Node::resetDecimalSignFlags()1935{1936TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo fields for node %s %p that does not have it", self()->getOpCode().getName(), self());1937_unionPropertyB._decimalInfo._signStateIsKnown = 0;1938_unionPropertyB._decimalInfo._hasCleanSign = 0;1939_unionPropertyB._decimalInfo._hasPreferredSign = 0;1940_unionPropertyB._decimalInfo._hasNoSignStateOnLoad = 0;1941_unionPropertyB._decimalInfo._signCode=raw_bcd_sign_unknown;1942}19431944void1945J9::Node::resetSignState()1946{1947self()->resetDecimalSignFlags();1948self()->setIsZero(false);1949self()->setIsNonZero(false);1950self()->setIsNonPositive(false);1951self()->setIsNonNegative(false);1952}1953195419551956bool1957J9::Node::isSignStateEquivalent(TR::Node *other)1958{1959if (self()->signStateIsKnown() == other->signStateIsKnown() &&1960self()->signStateIsAssumed() == other->signStateIsAssumed() &&1961self()->hasKnownCleanSign() == other->hasKnownCleanSign() &&1962self()->hasAssumedCleanSign() == other->hasAssumedCleanSign() &&1963self()->hasKnownPreferredSign() == other->hasKnownPreferredSign() &&1964self()->hasAssumedPreferredSign() == other->hasAssumedPreferredSign() &&1965self()->hasKnownSignCode() == other->hasKnownSignCode() &&1966self()->hasAssumedSignCode() == other->hasAssumedSignCode() &&1967self()->hasSignStateOnLoad() == other->hasSignStateOnLoad())1968{1969return true;1970}1971else1972{1973return false;1974}1975}19761977/**1978* if the 'other' node does not currently have any sign state then an improvement will be any sign state set on 'this' node1979*/1980bool1981J9::Node::isSignStateAnImprovementOver(TR::Node *other)1982{1983if (other->hasSignStateOnLoad() || other->hasAnyKnownOrAssumedSignState())1984return false;19851986bool thisHasAnyKnownOrAssumedSignState = self()->hasAnyKnownOrAssumedSignState();1987// having some (but undetermined) sign state for loads can prevent optimization or hinder codegen vs not having to assume anything1988// so return false in this case (but wouldn't be incorrect to return true in this case assuming other conditions below hold)1989if (self()->hasSignStateOnLoad() && !thisHasAnyKnownOrAssumedSignState)1990return false;19911992return thisHasAnyKnownOrAssumedSignState; // any sign state info is better than nothing1993}1994199519961997bool1998J9::Node::chkOpsCastedToBCD()1999{2000if (self()->getType().isBCD())2001{2002return true;2003}2004else if (self()->getOpCode().isAnyBCDCompareOp())2005{2006// e.g. pdcmpxx2007return true;2008}2009else2010{2011return false;2012}2013}20142015bool2016J9::Node::castedToBCD()2017{2018if (self()->chkOpsCastedToBCD())2019{2020TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._castedToBCD field for node %s %p that does not have it", self()->getOpCode().getName(), self());2021return _unionPropertyB._decimalInfo._castedToBCD==1;2022}2023else2024{2025return false;2026}2027}20282029void2030J9::Node::setCastedToBCD(bool v)2031{2032TR_ASSERT(self()->chkOpsCastedToBCD(), "node %s %p must be a BCD type or a BCD if or compare\n", self()->getOpCode().getName(), self());2033TR_ASSERT(self()->hasDecimalInfo(), "attempting to access _decimalInfo._castedToBCD field for node %s %p that does not have it", self()->getOpCode().getName(), self());2034_unionPropertyB._decimalInfo._castedToBCD = v ? 1 : 0;2035}20362037/**2038* UnionPropertyB functions end2039*/204020412042204320442045/**2046* Node flag functions2047*/20482049bool2050J9::Node::isSpineCheckWithArrayElementChild()2051{2052TR_ASSERT(self()->getOpCode().isSpineCheck(), "assertion failure");2053return _flags.testAny(spineCHKWithArrayElementChild);2054}20552056void2057J9::Node::setSpineCheckWithArrayElementChild(bool v)2058{2059TR::Compilation * c = TR::comp();2060TR_ASSERT(self()->getOpCode().isSpineCheck(), "assertion failure");2061if (performNodeTransformation2(c, "O^O NODE FLAGS: Setting spineCHKWithArrayElementChild flag on node %p to %d\n", self(), v))2062_flags.set(spineCHKWithArrayElementChild, v);2063}20642065bool2066J9::Node::chkSpineCheckWithArrayElementChild()2067{2068return self()->getOpCode().isSpineCheck() && _flags.testAny(spineCHKWithArrayElementChild);2069}20702071const char *2072J9::Node::printSpineCheckWithArrayElementChild()2073{2074return self()->chkSpineCheckWithArrayElementChild() ? "spineCHKWithArrayElementChild " : "";2075}2076207720782079bool2080J9::Node::isUnsafePutOrderedCall()2081{2082if (!self()->getOpCode().isCall())2083return false;20842085if (!self()->getSymbol()->isMethod())2086return false;20872088bool isPutOrdered = false;2089TR::MethodSymbol *symbol = self()->getSymbol()->getMethodSymbol();2090if (!symbol)2091return false;20922093if ((symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putBooleanOrdered_jlObjectJZ_V) ||2094(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putByteOrdered_jlObjectJB_V) ||2095(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putCharOrdered_jlObjectJC_V) ||2096(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putShortOrdered_jlObjectJS_V) ||2097(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putIntOrdered_jlObjectJI_V) ||2098(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putLongOrdered_jlObjectJJ_V) ||2099(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putFloatOrdered_jlObjectJF_V) ||2100(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putDoubleOrdered_jlObjectJD_V) ||2101(symbol->getRecognizedMethod() == TR::sun_misc_Unsafe_putObjectOrdered_jlObjectJjlObject_V))2102isPutOrdered = true;21032104return isPutOrdered;2105}21062107bool2108J9::Node::isDontInlinePutOrderedCall()2109{2110TR_ASSERT(self()->getOpCode().isCall(), " Can only call this routine for a call node \n");2111bool isPutOrdered = self()->isUnsafePutOrderedCall();21122113TR_ASSERT(isPutOrdered, "attempt to set dontInlinePutOrderedCall flag and not a putOrdered call");2114if (isPutOrdered)2115return _flags.testAny(dontInlineUnsafePutOrderedCall);2116else2117return false;2118}21192120void2121J9::Node::setDontInlinePutOrderedCall()2122{2123TR::Compilation * c = TR::comp();2124TR_ASSERT(self()->getOpCode().isCall(), " Can only call this routine for a call node \n");2125bool isPutOrdered = self()->isUnsafePutOrderedCall();21262127TR_ASSERT(isPutOrdered, "attempt to set dontInlinePutOrderedCall flag and not a putOrdered call");2128if (isPutOrdered)2129{2130if (performNodeTransformation1(c, "O^O NODE FLAGS: Setting dontInlineUnsafePutOrderedCall flag on node %p\n", self()))2131_flags.set(dontInlineUnsafePutOrderedCall);2132}21332134}21352136bool2137J9::Node::isUnsafeCopyMemoryIntrinsic()2138{2139if (self()->getOpCode().isCall() && self()->getSymbol()->isMethod())2140{2141TR::MethodSymbol *symbol = self()->getSymbol()->getMethodSymbol();2142if (symbol && symbol->isNative())2143{2144switch (symbol->getRecognizedMethod())2145{2146case TR::sun_misc_Unsafe_copyMemory:2147case TR::jdk_internal_misc_Unsafe_copyMemory0:2148return true;2149default:2150break;2151}2152}2153}2154return false;2155}21562157bool2158J9::Node::chkDontInlineUnsafePutOrderedCall()2159{2160bool isPutOrdered = self()->isUnsafePutOrderedCall();2161return isPutOrdered && _flags.testAny(dontInlineUnsafePutOrderedCall);2162}21632164const char *2165J9::Node::printIsDontInlineUnsafePutOrderedCall()2166{2167return self()->chkDontInlineUnsafePutOrderedCall() ? "dontInlineUnsafePutOrderedCall " : "";2168}2169217021712172bool2173J9::Node::isUnsafeGetPutCASCallOnNonArray()2174{2175if (!self()->getSymbol()->isMethod())2176return false;2177TR::MethodSymbol *symbol = self()->getSymbol()->getMethodSymbol();2178if (!symbol)2179return false;21802181//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");2182TR_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");2183return _flags.testAny(unsafeGetPutOnNonArray);2184}21852186void2187J9::Node::setUnsafeGetPutCASCallOnNonArray()2188{2189TR::Compilation * c = TR::comp();2190TR_ASSERT(self()->getSymbol()->isMethod() && self()->getSymbol()->getMethodSymbol(), "setUnsafeGetPutCASCallOnNonArray called on node which is not a call");21912192//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");2193TR_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");2194if (performNodeTransformation1(c, "O^O NODE FLAGS: Setting unsafeGetPutOnNonArray flag on node %p\n", self()))2195_flags.set(unsafeGetPutOnNonArray);2196}2197219821992200bool2201J9::Node::isProcessedByCallCloneConstrain()2202{2203return self()->getOpCode().isCall() && self()->getOpCodeValue() != TR::arraycopy && _flags.testAny(processedByCallCloneConstrain);2204}22052206void2207J9::Node::setProcessedByCallCloneConstrain()2208{2209_flags.set(processedByCallCloneConstrain, true);2210}2211221222132214bool2215J9::Node::isDAAVariableSlowCall()2216{2217TR_ASSERT(self()->getOpCode().isCall(), "Opcode must be a call");2218return _flags.testAny(DAAVariableSlowCall);2219}22202221void2222J9::Node::setDAAVariableSlowCall(bool v)2223{2224TR_ASSERT(self()->getOpCode().isCall(), "Opcode must be a call");2225_flags.set(DAAVariableSlowCall);2226}2227222822292230bool2231J9::Node::isBCDStoreTemporarilyALoad()2232{2233TR_ASSERT(self()->getOpCode().isBCDLoadVar(),2234"flag only valid for BCD load ops\n");2235if (self()->getOpCode().isBCDLoadVar())2236return _flags.testAny(IsBCDStoreTemporarilyALoad);2237else2238return false;22392240}22412242void2243J9::Node::setBCDStoreIsTemporarilyALoad(bool v)2244{2245TR::Compilation *c = TR::comp();2246TR_ASSERT(self()->getOpCode().isBCDLoadVar(),2247"flag only valid for BCD load ops\n");2248if (self()->getOpCode().isBCDLoadVar() &&2249performNodeTransformation2(c, "O^O NODE FLAGS: Setting IsBCDStoreTemporarilyALoad flag on node %p to %d\n", self(), v))2250_flags.set(IsBCDStoreTemporarilyALoad, v);2251}2252225322542255bool2256J9::Node::cleanSignDuringPackedLeftShift()2257{2258TR_ASSERT(self()->getOpCode().isPackedLeftShift(), "flag only valid for isPackedLeftShift nodes\n");2259if (self()->getOpCode().isPackedLeftShift())2260return _flags.testAny(CleanSignDuringPackedLeftShift);2261else2262return false;2263}22642265void2266J9::Node::setCleanSignDuringPackedLeftShift(bool v)2267{2268TR::Compilation *c = TR::comp();2269TR_ASSERT(self()->getOpCode().isPackedLeftShift(), "flag only valid for isPackedLeftShift nodes\n");2270if (self()->getOpCode().isPackedLeftShift() && performNodeTransformation2(c, "O^O NODE FLAGS: Setting CleanSignDuringPackedLeftShift flag on node %p to %d\n", self(), v))2271_flags.set(CleanSignDuringPackedLeftShift, v);2272}22732274bool2275J9::Node::chkCleanSignDuringPackedLeftShift()2276{2277return self()->getOpCode().isPackedLeftShift() &&2278_flags.testAny(CleanSignDuringPackedLeftShift);2279}22802281const char *2282J9::Node::printCleanSignDuringPackedLeftShift()2283{2284return self()->chkCleanSignDuringPackedLeftShift() ? "cleanSignDuringPackedLeftShift " : "";2285}22862287bool2288J9::Node::chkOpsSkipCopyOnLoad()2289{2290return (self()->getType().isBCD() || self()->getType().isAggregate()) && !self()->getOpCode().isStore() && !self()->getOpCode().isCall();2291}22922293bool2294J9::Node::skipCopyOnLoad()2295{2296TR_ASSERT(self()->chkOpsSkipCopyOnLoad(), "flag only valid for BCD or aggregate non-store and non-call ops\n");2297if ((self()->getType().isBCD() || self()->getType().isAggregate()) && !self()->getOpCode().isStore() && !self()->getOpCode().isCall())2298return _flags.testAny(SkipCopyOnLoad);2299else2300return false;2301}23022303void2304J9::Node::setSkipCopyOnLoad(bool v)2305{2306TR::Compilation *c = TR::comp();2307TR_ASSERT(self()->chkOpsSkipCopyOnLoad(), "flag only valid for BCD or aggregate non-store and non-call ops\n");2308if ((self()->getType().isBCD() || self()->getType().isAggregate()) && !self()->getOpCode().isStore() && !self()->getOpCode().isCall() &&2309performNodeTransformation2(c, "O^O NODE FLAGS: Setting skipCopyOnLoad flag on node %p to %d\n", self(), v))2310_flags.set(SkipCopyOnLoad, v);2311}23122313bool2314J9::Node::chkSkipCopyOnLoad()2315{2316return self()->chkOpsSkipCopyOnLoad() && _flags.testAny(SkipCopyOnLoad);2317}23182319const char *2320J9::Node::printSkipCopyOnLoad()2321{2322return self()->chkSkipCopyOnLoad() ? "skipCopyOnLoad " : "";2323}2324232523262327bool2328J9::Node::chkOpsSkipCopyOnStore()2329{2330return self()->getOpCode().isBCDStore();2331}23322333bool2334J9::Node::skipCopyOnStore()2335{2336TR_ASSERT(self()->chkOpsSkipCopyOnStore(), "flag only valid for BCD or aggregate store ops\n");2337if (self()->chkOpsSkipCopyOnStore())2338return _flags.testAny(SkipCopyOnStore);2339else2340return false;2341}23422343void2344J9::Node::setSkipCopyOnStore(bool v)2345{2346TR::Compilation *c = TR::comp();2347TR_ASSERT(self()->chkOpsSkipCopyOnStore(), "flag only valid for BCD or aggregate store ops\n");2348if (self()->chkOpsSkipCopyOnStore() &&2349performNodeTransformation2(c, "O^O NODE FLAGS: Setting skipCopyOnStore flag on node %p to %d\n", self(), v))2350{2351_flags.set(SkipCopyOnStore, v);2352}2353}23542355bool2356J9::Node::chkSkipCopyOnStore()2357{2358return self()->chkOpsSkipCopyOnStore() && _flags.testAny(SkipCopyOnStore);2359}23602361const char *2362J9::Node::printSkipCopyOnStore()2363{2364return self()->chkSkipCopyOnStore() ? "skipCopyOnStore " : "";2365}2366236723682369bool2370J9::Node::chkOpsCleanSignInPDStoreEvaluator()2371{2372return self()->getDataType() == TR::PackedDecimal && self()->getOpCode().isStore();2373}23742375bool2376J9::Node::mustCleanSignInPDStoreEvaluator()2377{2378TR_ASSERT(self()->chkOpsCleanSignInPDStoreEvaluator(), "flag only valid for packed decimal store nodes\n");2379if (self()->chkOpsCleanSignInPDStoreEvaluator())2380return _flags.testAny(cleanSignInPDStoreEvaluator);2381else2382return false;2383}23842385void2386J9::Node::setCleanSignInPDStoreEvaluator(bool v)2387{2388TR::Compilation *c = TR::comp();2389TR_ASSERT(self()->chkOpsCleanSignInPDStoreEvaluator(), "flag only valid for packed decimal store nodes\n");2390if (self()->chkOpsCleanSignInPDStoreEvaluator() &&2391performNodeTransformation2(c, "O^O NODE FLAGS: Setting cleanSignInPDStoreEvaluator flag on node %p to %d\n", self(), v))2392_flags.set(cleanSignInPDStoreEvaluator, v);2393}23942395bool2396J9::Node::chkCleanSignInPDStoreEvaluator()2397{2398return self()->chkOpsCleanSignInPDStoreEvaluator() && _flags.testAny(cleanSignInPDStoreEvaluator);2399}24002401const char *2402J9::Node::printCleanSignInPDStoreEvaluator()2403{2404return self()->chkCleanSignInPDStoreEvaluator() ? "cleanSignInPDStoreEvaluator " : "";2405}2406240724082409bool2410J9::Node::chkOpsUseStoreAsAnAccumulator()2411{2412return self()->getOpCode().canUseStoreAsAnAccumulator();2413}24142415bool2416J9::Node::useStoreAsAnAccumulator()2417{2418TR_ASSERT(self()->chkOpsUseStoreAsAnAccumulator(), "flag only valid for BCD or aggregate store ops\n");2419if (self()->chkOpsUseStoreAsAnAccumulator())2420return _flags.testAny(UseStoreAsAnAccumulator);2421else2422return false;2423}24242425void2426J9::Node::setUseStoreAsAnAccumulator(bool v)2427{2428TR::Compilation *c = TR::comp();2429TR_ASSERT(self()->chkOpsUseStoreAsAnAccumulator(), "flag only valid for BCD or aggregate store ops\n");2430if (self()->chkOpsUseStoreAsAnAccumulator() &&2431performNodeTransformation2(c, "O^O NODE FLAGS: Setting UseStoreAsAnAccumulator flag on node %p to %d\n", self(), v))2432{2433_flags.set(UseStoreAsAnAccumulator, v);2434}2435}24362437bool2438J9::Node::chkUseStoreAsAnAccumulator()2439{2440return self()->chkOpsUseStoreAsAnAccumulator() && _flags.testAny(UseStoreAsAnAccumulator);2441}24422443const char *2444J9::Node::printUseStoreAsAnAccumulator()2445{2446return self()->chkUseStoreAsAnAccumulator() ? "useStoreAsAnAccumulator " : "";2447}2448244924502451bool2452J9::Node::canSkipPadByteClearing()2453{2454TR_ASSERT(self()->getType().isAnyPacked() && !self()->getOpCode().isStore(),2455"flag only valid for wcode non-store packed operations\n");2456if (self()->getType().isAnyPacked() && !self()->getOpCode().isStore())2457return _flags.testAny(skipPadByteClearing);2458else2459return false;2460}24612462void2463J9::Node::setSkipPadByteClearing(bool v)2464{2465TR::Compilation *c = TR::comp();2466TR_ASSERT(self()->getType().isAnyPacked() && !self()->getOpCode().isStore(),2467"flag only valid for wcode non-store packed operations\n");2468if (self()->getType().isAnyPacked() && !self()->getOpCode().isStore() &&2469(c==NULL || performNodeTransformation2(c, "O^O NODE FLAGS: Setting skipPadByteClearing flag on node %p to %d\n", self(), v)))2470_flags.set(skipPadByteClearing, v);2471}24722473bool2474J9::Node::chkSkipPadByteClearing()2475{2476return self()->getType().isAnyPacked() && !self()->getOpCode().isStore() &&2477_flags.testAny(skipPadByteClearing);2478}24792480const char *2481J9::Node::printSkipPadByteClearing()2482{2483return self()->chkSkipPadByteClearing() ? "skipPadByteClearing " : "";2484}2485248624872488bool2489J9::Node::chkOpsIsInMemoryCopyProp()2490{2491TR::Compilation *c = TR::comp();2492return self()->getOpCode().isStore() && c->cg()->IsInMemoryType(self()->getType());2493}24942495bool2496J9::Node::isInMemoryCopyProp()2497{2498if (self()->chkOpsIsInMemoryCopyProp())2499return _flags.testAny(IsInMemoryCopyProp);2500else2501return false;2502}25032504void2505J9::Node::setIsInMemoryCopyProp(bool v)2506{2507if (self()->chkOpsIsInMemoryCopyProp())2508{2509_flags.set(IsInMemoryCopyProp, v);2510}2511}25122513bool2514J9::Node::chkIsInMemoryCopyProp()2515{2516return self()->chkOpsIsInMemoryCopyProp() && _flags.testAny(IsInMemoryCopyProp);2517}25182519const char *2520J9::Node::printIsInMemoryCopyProp()2521{2522return self()->chkIsInMemoryCopyProp() ? "IsInMemoryCopyProp " : "";2523}2524252525262527bool2528J9::Node::chkSharedMemory()2529{2530TR_ASSERT(self()->getType().isAddress(), "flag only valid for addresses\n");2531return _flags.testAny(sharedMemory);2532}25332534void2535J9::Node::setSharedMemory(bool v)2536{2537TR_ASSERT(self()->getType().isAddress(), "flag only valid for addresses\n");2538_flags.set(sharedMemory, v);2539}25402541const char *2542J9::Node::printSharedMemory()2543{2544return self()->getType().isAddress() ? "sharedMemory " : "";2545}25462547/**2548* Node flag functions end2549*/25502551bool2552J9::Node::isArrayCopyCall()2553{2554if (self()->getOpCode().isCall() && self()->getSymbol()->isMethod())2555{2556TR::RecognizedMethod recognizedMethod = self()->getSymbol()->castToMethodSymbol()->getRecognizedMethod();25572558if (recognizedMethod == TR::java_lang_System_arraycopy ||2559recognizedMethod == TR::java_lang_String_compressedArrayCopy_BIBII ||2560recognizedMethod == TR::java_lang_String_compressedArrayCopy_BICII ||2561recognizedMethod == TR::java_lang_String_compressedArrayCopy_CIBII ||2562recognizedMethod == TR::java_lang_String_compressedArrayCopy_CICII ||2563recognizedMethod == TR::java_lang_String_decompressedArrayCopy_BIBII ||2564recognizedMethod == TR::java_lang_String_decompressedArrayCopy_BICII ||2565recognizedMethod == TR::java_lang_String_decompressedArrayCopy_CIBII ||2566recognizedMethod == TR::java_lang_String_decompressedArrayCopy_CICII)2567{2568return true;2569}2570else2571{2572TR::Method *method = self()->getSymbol()->castToMethodSymbol()->getMethod();25732574// Method may be unresolved but we would still like to transform arraycopy calls so pattern match the signature as well2575if (method != NULL &&2576(method->nameLength() == 9) &&2577(method->classNameLength() == 16) &&2578(strncmp(method->nameChars(), "arraycopy", 9) == 0) &&2579(strncmp(method->classNameChars(), "java/lang/System", 16) == 0))2580{2581return true;2582}2583}2584}25852586return OMR::Node::isArrayCopyCall();2587}258825892590bool2591J9::Node::requiresRegisterPair(TR::Compilation *comp)2592{2593return OMR::NodeConnector::requiresRegisterPair(comp);2594}25952596bool2597J9::Node::canGCandReturn()2598{2599TR::Compilation * comp = TR::comp();2600if (comp->getOption(TR_EnableFieldWatch))2601{2602if (self()->getOpCodeValue() == TR::treetop || self()->getOpCode().isNullCheck() || self()->getOpCode().isAnchor())2603{2604TR::Node * node = self()->getFirstChild();2605if (node->getOpCode().isReadBar() || node->getOpCode().isWrtBar())2606return true;2607}2608}2609return OMR::NodeConnector::canGCandReturn();2610}261126122613