Path: blob/master/runtime/compiler/optimizer/J9LocalCSE.cpp
6000 views
/*******************************************************************************1* Copyright (c) 2000, 2019 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 "env/VMJ9.h"23#include "codegen/InstOpCode.hpp"24#include "codegen/CodeGenerator.hpp"25#include "il/Block.hpp"26#include "il/Node.hpp"27#include "il/Node_inlines.hpp"28#include "il/StaticSymbol.hpp"29#include "optimizer/LocalCSE.hpp"30#include "optimizer/Optimization_inlines.hpp"3132bool33J9::LocalCSE::shouldTransformBlock(TR::Block *block)34{35if (!OMR::LocalCSE::shouldTransformBlock(block))36return false;3738if (self()->comp()->getMethodHotness() < warm &&39block->getFrequency() < TR::Options::_localCSEFrequencyThreshold &&40!self()->comp()->compileRelocatableCode())41return false;4243return true;44}4546bool47J9::LocalCSE::shouldCommonNode(TR::Node *parent, TR::Node *node)48{49if (!OMR::LocalCSE::shouldCommonNode(parent, node))50return false;5152if (parent != NULL)53{54// Commoning NULL pointers under a guard might result in dereferencing a NULL pointer55if (parent->isNopableInlineGuard() && node->getOpCode().hasSymbolReference())56{57TR::Symbol* symbol = node->getSymbolReference()->getSymbol();5859if (symbol->isStatic() && symbol->getStaticSymbol()->getStaticAddress() == NULL)60{61return false;62}63}6465// Prevent commoning of the first child of BCDCHK if the recognized DAA API checkOverflow argument is true.66//67// The BCDCHK node is well structured. Its first child represents a BCD operation that may raise a hardware68// interrupt if malformed input is provided. The evaluation of BCDCHK creates an OOL path to which we branch to69// from the signal handler if a hardware interrupt was caught. This OOL path simply reconstructs the original70// Java call to the DAA API and delegates the respective computation.71//72// Some DAA APIs have a conditional parameter called checkOverflow which lets the user control whether the73// respective API will raise a Java exception if overflow is detected. Thus if the checkOverflow argument is74// true then the evaluation of BCDCHK may or may not raise a Java exception. The issue with this is the following75// example scenario:76//77// n1n BCDCHK78// n2n pdshl79// ...80// ...81// n3n iconst 082// ...83// n4n BCDCHK84// n5n pdshl85// ...86// ...87// n6n iconst 188//89// Assuming n2n and n5n represent the same operation local CSE will attempt to common n2n with n5n. However given90// the above this can result in unwanted behavior. Commoning n5n with n2n is incorrect because the BCDCHK at n4n91// had checkOverflow argument as true (n6n) and thus the original DAA Java calls were in fact different. Assuming92// the BCDCHKs at n1n and n4n both raised hardware interrupts the fallback OOL path in case of n1n would have not93// raised a Java exception and the execution would resume as normal. However in case on n6n the fallback OOL path94// may or may not raise a Java exception so execution could in fact diverge to a different path. Hence it is not95// correct to common n5n and n2n in such cases.96//97// The following block of code checks for the above case and prevents commoning of n5n with n2n.98//99// NOTE: if n4n came before n1n in the treetop order then the commoning from n5n to n2n would be in fact valid,100// and the current implementation will allow it. However if between two BCDCHK treetops which both do overflow101// checking (i.e. two distinct instances of n4n) the current implementation will not allow the commoning to102// happen even though it is valid. Enabling the commoning is such cases is a lot more complicated from an103// implementation perspective and is likely not worth the return on investment.104if (parent->getOpCodeValue() == TR::BCDCHK && parent->getFirstChild() == node)105{106TR::MethodSymbol* bcdchkMethodSymbol = parent->getSymbolReference()->getSymbol()->getMethodSymbol();107108TR_ASSERT(bcdchkMethodSymbol != NULL, "BCDCHK should always have a resolved method symbol since it was reduced in DataAccessAccelerator optimization");109110switch(bcdchkMethodSymbol->getRecognizedMethod())111{112case TR::com_ibm_dataaccess_PackedDecimal_lessThanPackedDecimal_:113case TR::com_ibm_dataaccess_PackedDecimal_lessThanOrEqualsPackedDecimal_:114case TR::com_ibm_dataaccess_PackedDecimal_greaterThanPackedDecimal_:115case TR::com_ibm_dataaccess_PackedDecimal_greaterThanOrEqualsPackedDecimal_:116case TR::com_ibm_dataaccess_PackedDecimal_equalsPackedDecimal_:117case TR::com_ibm_dataaccess_PackedDecimal_notEqualsPackedDecimal_:118case TR::com_ibm_dataaccess_PackedDecimal_checkPackedDecimal_:119case TR::com_ibm_dataaccess_DecimalData_convertExternalDecimalToPackedDecimal_:120case TR::com_ibm_dataaccess_DecimalData_convertPackedDecimalToExternalDecimal_:121case TR::com_ibm_dataaccess_DecimalData_convertPackedDecimalToUnicodeDecimal_:122case TR::com_ibm_dataaccess_DecimalData_convertUnicodeDecimalToPackedDecimal_:123{124// No optional checkOverflow parameter on these APIs125break;126}127128case TR::com_ibm_dataaccess_PackedDecimal_addPackedDecimal_:129case TR::com_ibm_dataaccess_PackedDecimal_subtractPackedDecimal_:130case TR::com_ibm_dataaccess_PackedDecimal_multiplyPackedDecimal_:131case TR::com_ibm_dataaccess_PackedDecimal_dividePackedDecimal_:132case TR::com_ibm_dataaccess_PackedDecimal_remainderPackedDecimal_:133case TR::com_ibm_dataaccess_PackedDecimal_shiftLeftPackedDecimal_:134case TR::com_ibm_dataaccess_PackedDecimal_shiftRightPackedDecimal_:135case TR::com_ibm_dataaccess_DecimalData_convertPackedDecimalToInteger_:136case TR::com_ibm_dataaccess_DecimalData_convertPackedDecimalToInteger_ByteBuffer_:137case TR::com_ibm_dataaccess_DecimalData_convertIntegerToPackedDecimal_:138case TR::com_ibm_dataaccess_DecimalData_convertIntegerToPackedDecimal_ByteBuffer_:139case TR::com_ibm_dataaccess_DecimalData_convertPackedDecimalToLong_:140case TR::com_ibm_dataaccess_DecimalData_convertPackedDecimalToLong_ByteBuffer_:141case TR::com_ibm_dataaccess_DecimalData_convertLongToPackedDecimal_:142case TR::com_ibm_dataaccess_DecimalData_convertLongToPackedDecimal_ByteBuffer_:143{144TR::Node* checkOverflowNode = parent->getLastChild();145146if (!(checkOverflowNode->getOpCode().isLoadConst() && checkOverflowNode->getConstValue() == 0))147{148traceMsg(comp(), "Skipping propagation of %s [%p] into the first child of %s [%p] because of potential overflow checking\n", node->getOpCode().getName(), node, parent->getOpCode().getName(), parent);149150return false;151}152153break;154}155156default:157{158TR_ASSERT_FATAL(false, "Unrecognized DAA method symbol in BCDCHK [%p]\n", parent);159160return false;161}162}163}164}165166return true;167}168169bool170J9::LocalCSE::shouldCopyPropagateNode(TR::Node *parent, TR::Node *node, int32_t childNum, TR::Node *storeNode)171{172if (!OMR::LocalCSE::shouldCopyPropagateNode(parent, node, childNum, storeNode))173return false;174175// External float types come in as aggregates and an effort during ilgen (extFloatFixup) is made to fix176// up all the aggr types to extFloat.177// However due to late arrayOp scalarization there is a chance that CSE may create incorrect types during propagation178// so prevent these transformations from happening.179// The cost of adding a conversion to make things type correct is too high here (a runtime call) so disallow these.180181int32_t childAdjust = storeNode->getOpCode().isWrtBar() ? 2 : 1;182int32_t maxChild = storeNode->getNumChildren() - childAdjust;183TR::Node *rhsOfStoreDefNode = storeNode->getChild(maxChild);184bool propagationIsTypeCorrect = true;185186if (parent && parent->getChild(childNum))187{188TR::Node *oldNode = parent->getChild(childNum);189TR::DataType oldType = oldNode->getType();190TR::DataType newType = rhsOfStoreDefNode->getType();191if (oldType.isBCD() != newType.isBCD() ||192oldType.isFloatingPoint() != newType.isFloatingPoint())193propagationIsTypeCorrect = false;194195if (!propagationIsTypeCorrect && (comp()->cg()->traceBCDCodeGen() || trace()))196{197int32_t lineNumber = comp()->getLineNumber(rhsOfStoreDefNode);198traceMsg(comp(),"z^z : skipping type invalid propagation : parent %s (%p), rhsOfStoreDefNode %s (%p) line_no=%d (offset %06X)\n",199parent->getOpCode().getName(),parent,rhsOfStoreDefNode->getOpCode().getName(),rhsOfStoreDefNode,lineNumber,lineNumber);200}201202if (!propagationIsTypeCorrect)203return false;204}205206return true;207}208209210