Path: blob/master/runtime/compiler/optimizer/IdiomRecognitionUtils.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 "optimizer/IdiomRecognitionUtils.hpp"2324#include <algorithm>25#include <stddef.h>26#include <stdint.h>27#include "codegen/CodeGenerator.hpp"28#include "env/FrontEnd.hpp"29#include "compile/Compilation.hpp"30#include "env/CompilerEnv.hpp"31#include "env/TRMemory.hpp"32#include "il/Block.hpp"33#include "il/DataTypes.hpp"34#include "il/ILOpCodes.hpp"35#include "il/ILOps.hpp"36#include "il/Node.hpp"37#include "il/Node_inlines.hpp"38#include "il/Symbol.hpp"39#include "il/SymbolReference.hpp"40#include "il/TreeTop.hpp"41#include "il/TreeTop_inlines.hpp"42#include "infra/Assert.hpp"43#include "infra/BitVector.hpp"44#include "infra/List.hpp"45#include "infra/TRCfgEdge.hpp"46#include "optimizer/IdiomRecognition.hpp"47#include "optimizer/Structure.hpp"48#include "optimizer/TranslateTable.hpp"4950/************************************/51/************ Utilities *************/52/************************************/53void54dump256Bytes(uint8_t *t, TR::Compilation * comp)55{56int i;57traceMsg(comp, " | 0 1 2 3 4 5 6 7 8 9 A B C D E F\n");58traceMsg(comp, "--+--------------------------------");59for (i = 0; i < 256; i++)60{61if ((i % 16) == 0)62{63traceMsg(comp, "\n%02X|",i);64}65traceMsg(comp, "%2x",t[i]);66}67traceMsg(comp, "\n");68}697071/******************************************************/72/************ Utilities for making idioms *************/73/******************************************************/7475//*****************************************************************************************76// create the idiom for "v = src1 op val"77//*****************************************************************************************78TR_PCISCNode *79createIdiomIOP2VarInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, int opcode, TR_PCISCNode *v, TR_PCISCNode *src1, TR_PCISCNode *val)80{81TR_PCISCNode *n0, *n1;82TR_ASSERT(v->getOpcode() == TR_variable || v->getOpcode() == TR::iload, "Error!");83n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), opcode, v->getOpcode() == TR_variable ? TR::NoType : TR::Int32, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(n0);84n1 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::istore, TR::Int32, tgt->incNumNodes(), dagId, 1, 2, n0); tgt->addNode(n1);85n0->setChildren(src1, val);86n1->setChildren(n0, v->getOpcode() == TR::iload ? v->getChild(0) : v);87n0->setIsChildDirectlyConnected();88n1->setIsChildDirectlyConnected();89n0->setIsSuccDirectlyConnected();90return n1;91}9293//*****************************************************************************************94// create the idiom for "v = v op val"95//*****************************************************************************************96TR_PCISCNode *97createIdiomIOP2VarInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, int opcode, TR_PCISCNode *v, TR_PCISCNode *val)98{99return createIdiomIOP2VarInLoop(tgt, ctrl, dagId, pred, opcode, v, v, val);100}101102//*****************************************************************************************103// create the idiom for "v = src1 - val"104//*****************************************************************************************105TR_PCISCNode *106createIdiomDecVarInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *v, TR_PCISCNode *src1, TR_PCISCNode *subval)107{108return createIdiomIOP2VarInLoop(tgt, ctrl, dagId, pred, TR::isub, v, src1, subval);109}110111//*****************************************************************************************112// create the idiom for "v = src1 + val"113//*****************************************************************************************114TR_PCISCNode *115createIdiomIncVarInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *v, TR_PCISCNode *src1, TR_PCISCNode *addval)116{117return createIdiomIOP2VarInLoop(tgt, ctrl, dagId, pred, TR::iadd, v, src1, addval);118}119120//*****************************************************************************************121// create the idiom for "v = v - val"122//*****************************************************************************************123TR_PCISCNode *124createIdiomDecVarInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *v, TR_PCISCNode *subval)125{126return createIdiomDecVarInLoop(tgt, ctrl, dagId, pred, v, v, subval);127}128129//*****************************************************************************************130// create the idiom for "v = v + val"131//*****************************************************************************************132TR_PCISCNode *133createIdiomIncVarInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *v, TR_PCISCNode *addval)134{135return createIdiomIncVarInLoop(tgt, ctrl, dagId, pred, v, v, addval);136}137138//*****************************************************************************************139// create "iconst val" or "lconst val". Use lconst for a 64-bit environment140//*****************************************************************************************141TR_PCISCNode *142createIdiomArrayRelatedConst(TR_PCISCGraph *tgt, int32_t ctrl, uint16_t id, int dagId, int32_t val)143{144TR_PCISCNode *ret;145uint32_t opcode = (ctrl & CISCUtilCtl_64Bit) ? TR::lconst : TR::iconst;146ret = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), opcode, opcode == TR::lconst ? TR::Int64 : TR::Int32, id, dagId, 0, 0, val);147tgt->addNode(ret);148return ret;149}150151152//*****************************************************************************************153// create "iconst -sizeof(array header)" or "lconst -sizeof(array header)".154// Use lconst for a 64-bit environment.155//*****************************************************************************************156TR_PCISCNode *157createIdiomArrayHeaderConst(TR_PCISCGraph *tgt, int32_t ctrl, uint16_t id, int dagId, TR::Compilation *c)158{159return createIdiomArrayRelatedConst(tgt, ctrl, id, dagId, -(int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());160}161162//*****************************************************************************************163// when the environment is under 64-bit, it'll insert "i2l" to the node.164//*****************************************************************************************165TR_PCISCNode *166createIdiomI2LIfNecessary(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode **pred, TR_PCISCNode *node)167{168TR_PCISCNode *ret = node;169if ((ctrl & (CISCUtilCtl_64Bit|CISCUtilCtl_NoI2L)) == (CISCUtilCtl_64Bit|0))170{171ret = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::i2l, TR::Int64, tgt->incNumNodes(), dagId, 1, 1, *pred, node); tgt->addNode(ret);172*pred = ret;173}174return ret;175}176177#if 0178//*****************************************************************************************179// It creates an address tree of "index part" for a byte array. (e.g. index-header)180// It may insert I2L depending on the given flag.181//182// "InLoop" means that it sets the given dagId to all nodes in this subroutine.183//*****************************************************************************************184TR_PCISCNode *185createIdiomByteArrayAddressIndexTreeInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *index, TR_PCISCNode *cmah)186{187TR_PCISCNode *n0;188TR_PCISCNode *parentIndex;189if (ctrl & CISCUtilCtl_64Bit)190{191if (ctrl & CISCUtilCtl_NoI2L)192{193n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::lsub, TR::Int64, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(n0);194parentIndex = n0;195}196else197{198parentIndex = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::i2l, TR::Int64, tgt->incNumNodes(), dagId, 1, 1, pred); tgt->addNode(parentIndex);199n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::lsub, TR::Int64, tgt->incNumNodes(), dagId, 1, 2, parentIndex); tgt->addNode(n0);200n0->setChild(parentIndex);201n0->setIsChildDirectlyConnected();202}203}204else205{206n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::isub, TR::Int32, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(n0);207parentIndex = n0;208}209parentIndex->setChild(index);210if ((ctrl & CISCUtilCtl_ChildDirectConnected) || index->getOpcode() == TR_variable || index->getOpcode() == TR_arrayindex)211parentIndex->setIsChildDirectlyConnected();212n0->setChild(1, cmah);213return n0;214}215216//*****************************************************************************************217// It creates an effective address tree for a byte array. (e.g. base+(index-header))218// It may insert I2L depending on the given flag.219//220// "InLoop" means that it sets the given dagId to all nodes in this subroutine.221//*****************************************************************************************222TR_PCISCNode *223createIdiomByteArrayAddressInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah)224{225TR_PCISCNode *n0, *n1;226227n0 = createIdiomByteArrayAddressIndexTreeInLoop(tgt, ctrl, dagId, pred, index, cmah);228n1 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), (ctrl & CISCUtilCtl_64Bit) ? TR::aladd : TR::aiadd, TR::Address, tgt->incNumNodes(), dagId, 1, 2, n0); tgt->addNode(n1);229n1->setChildren(base, n0);230if (base->getOpcode() == TR_variable || base->getOpcode() == TR_arraybase)231n1->setIsChildDirectlyConnected();232return n1;233}234#endif235236//*****************************************************************************************237// It creates an address tree of "index part" for a non-byte array. (e.g. index*4-header)238// It may insert I2L depending on the given flag.239//240// "InLoop" means that it sets the given dagId to all nodes in this subroutine.241//*****************************************************************************************242TR_PCISCNode *243createIdiomArrayAddressIndexTreeInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *index, TR_PCISCNode *cmah, TR_PCISCNode *constForMul)244{245TR_PCISCNode *n0, *mul;246if (ctrl & CISCUtilCtl_64Bit)247{248TR_PCISCNode *i2l;249if (ctrl & CISCUtilCtl_NoI2L)250{251mul = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::lmul, TR::Int64, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(mul);252i2l = mul;253}254else255{256i2l = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::i2l, TR::Int64, tgt->incNumNodes(), dagId, 1, 1, pred); tgt->addNode(i2l);257mul = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::lmul, TR::Int64, tgt->incNumNodes(), dagId, 1, 2, i2l); tgt->addNode(mul);258mul->setIsChildDirectlyConnected();259mul->setChild(i2l);260}261n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::lsub, TR::Int64, tgt->incNumNodes(), dagId, 1, 2, mul); tgt->addNode(n0);262i2l->setChild(index);263switch(index->getOpcode())264{265case TR_variable:266case TR_arrayindex:267i2l->setIsChildDirectlyConnected();268break;269}270n0->setIsChildDirectlyConnected();271}272else273{274mul = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::imul, TR::Int32, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(mul);275n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::isub, TR::Int32, tgt->incNumNodes(), dagId, 1, 2, mul); tgt->addNode(n0);276mul->setChild(index);277n0->setIsChildDirectlyConnected();278switch(index->getOpcode())279{280case TR_variable:281case TR_arrayindex:282mul->setIsChildDirectlyConnected();283break;284}285}286mul->setChild(1, constForMul);287n0->setChildren(mul, cmah);288return n0;289}290291//*****************************************************************************************292// It creates an effective address tree for a non-byte array. (e.g. base+(index*4-header))293// It may insert I2L depending on the given flag.294//295// "InLoop" means that it sets the given dagId to all nodes in this subroutine.296//*****************************************************************************************297TR_PCISCNode *298createIdiomArrayAddressInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah, TR_PCISCNode *constForMul)299{300TR_PCISCNode *n0, *n1;301n0 = createIdiomArrayAddressIndexTreeInLoop(tgt, ctrl, dagId, pred, index, cmah, constForMul);302n1 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), (ctrl & CISCUtilCtl_64Bit) ? TR::aladd : TR::aiadd, TR::Address, tgt->incNumNodes(), dagId, 1, 2, n0); tgt->addNode(n1);303n1->setChildren(base, n0);304if (base->getOpcode() == TR_variable || base->getOpcode() == TR_arraybase)305n1->setIsChildDirectlyConnected();306return n1;307}308309//*****************************************************************************************310// It creates an effective address tree for an array using the given index tree. (e.g. base+indexTree)311//312// "InLoop" means that it sets the given dagId to all nodes in this subroutine.313//*****************************************************************************************314TR_PCISCNode *315createIdiomArrayAddressInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *indexTree)316{317TR_PCISCNode *n1;318319n1 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), (ctrl & CISCUtilCtl_64Bit) ? TR::aladd : TR::aiadd, TR::Address, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(n1);320n1->setChildren(base, indexTree);321return n1;322}323324#if 0325//*****************************************************************************************326// It creates a byte array load.327// "InLoop" means that it sets the given dagId to all nodes in this subroutine.328//*****************************************************************************************329TR_PCISCNode *330createIdiomByteArrayLoadInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah)331{332TR_PCISCNode *n1, *n2;333n1 = createIdiomByteArrayAddressInLoop(tgt, ctrl, dagId, pred, base, index, cmah);334n2 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::bloadi, TR::Int8, tgt->incNumNodes(), dagId, 1, 1, n1); tgt->addNode(n2);335336n2->setChild(n1);337n2->setIsChildDirectlyConnected();338return n2;339}340341//*****************************************************************************************342// It creates a byte array store from the given address and storeval trees.343// "InLoop" means that it sets the given dagId to all nodes in this subroutine.344//*****************************************************************************************345TR_PCISCNode *346createIdiomByteArrayStoreBodyInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *addr, TR_PCISCNode *storeval)347{348TR_PCISCNode *n2, *i2b;349if (ctrl & CISCUtilCtl_NoConversion)350{351i2b = storeval;352}353else354{355i2b = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), (ctrl & CISCUtilCtl_AllConversion) ? TR_conversion : (TR_CISCOps)TR::i2b,356TR::Int8,357tgt->incNumNodes(), dagId, 1, 1, pred); tgt->addNode(i2b);358pred = i2b;359i2b->setChild(storeval);360}361362n2 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::bstorei, TR::Int8, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(n2);363n2->setChildren(addr, i2b);364return n2;365}366367//*****************************************************************************************368// It creates a byte array store from the given base, index, cmah, and storeval trees.369// "InLoop" means that it sets the given dagId to all nodes in this subroutine.370//*****************************************************************************************371TR_PCISCNode *372createIdiomByteArrayStoreInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah, TR_PCISCNode *storeval)373{374TR_PCISCNode *n1, *n2;375n1 = createIdiomByteArrayAddressInLoop(tgt, ctrl, dagId, pred, base, index, cmah);376n2 = createIdiomByteArrayStoreBodyInLoop(tgt, ctrl, dagId, n1, n1, storeval);377n2->setIsChildDirectlyConnected();378return n2;379}380#endif381382//*****************************************************************************************383// It creates a char array load.384// "InLoop" means that it sets the given dagId to all nodes in this subroutine.385//*****************************************************************************************386TR_PCISCNode *387createIdiomCharArrayLoadInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah, TR_PCISCNode *const2)388{389return createIdiomArrayLoadInLoop(tgt, ctrl, dagId, pred, TR::sloadi, TR::Int16, base, index, cmah, const2);390}391392//*****************************************************************************************393// It creates a non-byte array load.394// "InLoop" means that it sets the given dagId to all nodes in this subroutine.395//*****************************************************************************************396TR_PCISCNode *397createIdiomArrayLoadInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, int opcode, TR::DataType dataType, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah, TR_PCISCNode *mulconst)398{399TR_PCISCNode *n1, *n2;400n1 = createIdiomArrayAddressInLoop(tgt, ctrl, dagId, pred, base, index, cmah, mulconst);401n2 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), opcode, dataType, tgt->incNumNodes(), dagId, 1, 1, n1); tgt->addNode(n2);402403n2->setChild(n1);404n2->setIsChildDirectlyConnected();405return n2;406}407408//*****************************************************************************************409// It creates a non-byte array store from the given address and storeval trees.410// "InLoop" means that it sets the given dagId to all nodes in this subroutine.411//*****************************************************************************************412TR_PCISCNode *413createIdiomArrayStoreBodyInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, int opcode, TR::DataType dataType, TR_PCISCNode *addr, TR_PCISCNode *storeval)414{415TR_PCISCNode *n2, *i2c;416if (ctrl & CISCUtilCtl_NoConversion)417{418i2c = storeval;419}420else421{422i2c = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(),423(opcode == TR::sstorei) ? (TR_CISCOps)TR::i2s : TR_conversion,424(opcode == TR::sstorei) ? TR::Int16 : TR::NoType,425tgt->incNumNodes(), dagId, 1, 1, pred); tgt->addNode(i2c);426i2c->setIsOptionalNode();427pred = i2c;428i2c->setChild(storeval);429}430n2 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), opcode, dataType, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(n2);431n2->setChildren(addr, i2c);432return n2;433}434435//*****************************************************************************************436// It creates a char array store from the given address and storeval trees.437// "InLoop" means that it sets the given dagId to all nodes in this subroutine.438//*****************************************************************************************439TR_PCISCNode *440createIdiomCharArrayStoreBodyInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *addr, TR_PCISCNode *storeval)441{442return createIdiomArrayStoreBodyInLoop(tgt, ctrl, dagId, pred, TR::sstorei, TR::Int16, addr, storeval);443}444445//*****************************************************************************************446// It creates a char array store from the given base, index, cmah, and storeval trees.447// "InLoop" means that it sets the given dagId to all nodes in this subroutine.448//*****************************************************************************************449TR_PCISCNode *450createIdiomArrayStoreInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, int opcode, TR::DataType dataType, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah, TR_PCISCNode *const2, TR_PCISCNode *storeval)451{452TR_PCISCNode *n1, *n2;453n1 = createIdiomArrayAddressInLoop(tgt, ctrl, dagId, pred, base, index, cmah, const2);454n2 = createIdiomArrayStoreBodyInLoop(tgt, ctrl, dagId, n1, opcode, dataType, n1, storeval);455n2->setIsChildDirectlyConnected();456return n2;457}458459//*****************************************************************************************460// It creates a char array store from the given base, index, cmah, and storeval trees.461// "InLoop" means that it sets the given dagId to all nodes in this subroutine.462//*****************************************************************************************463TR_PCISCNode *464createIdiomCharArrayStoreInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *index, TR_PCISCNode *cmah, TR_PCISCNode *const2, TR_PCISCNode *storeval)465{466return createIdiomArrayStoreInLoop(tgt, ctrl, dagId, pred, TR::sstorei, TR::Int16, base, index, cmah, const2, storeval);467}468469//*****************************************************************************************470// It creates a byte array load particularly for "sun/io/CharToByteSingleByte.JITintrinsicConvert".471// The base address is given via java.nio.DirectByteBuffer.472//473// "InLoop" means that it sets the given dagId to all nodes in this subroutine.474//*****************************************************************************************475TR_PCISCNode *476createIdiomByteDirectArrayLoadInLoop(TR_PCISCGraph *tgt, int32_t ctrl, int dagId, TR_PCISCNode *pred, TR_PCISCNode *base, TR_PCISCNode *index)477{478TR_PCISCNode *n2;479TR_PCISCNode *n0;480TR_PCISCNode *parentIndex;481if (ctrl & CISCUtilCtl_64Bit)482{483if (ctrl & CISCUtilCtl_NoI2L)484{485n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::ladd, TR::Int64, tgt->incNumNodes(), dagId, 1, 2, pred); tgt->addNode(n0);486parentIndex = n0;487}488else489{490parentIndex = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::i2l, TR::Int64, tgt->incNumNodes(), dagId, 1, 1, pred); tgt->addNode(parentIndex);491n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::ladd, TR::Int64, tgt->incNumNodes(), dagId, 1, 2, parentIndex); tgt->addNode(n0);492n0->setChild(parentIndex);493n0->setIsChildDirectlyConnected();494}495parentIndex->setChild(index);496if ((ctrl & CISCUtilCtl_ChildDirectConnected) || index->getOpcode() == TR_variable || index->getOpcode() == TR_arrayindex)497parentIndex->setIsChildDirectlyConnected();498}499else500{501parentIndex = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::l2i, TR::Int32, tgt->incNumNodes(), dagId, 1, 1, pred); tgt->addNode(parentIndex);502parentIndex->setChild(base);503parentIndex->setIsChildDirectlyConnected();504base = parentIndex;505n0 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::iadd, TR::Int32, tgt->incNumNodes(), dagId, 1, 2, parentIndex); tgt->addNode(n0);506n0->setChild(index);507if ((ctrl & CISCUtilCtl_ChildDirectConnected) || index->getOpcode() == TR_variable || index->getOpcode() == TR_arrayindex)508n0->setIsChildDirectlyConnected();509}510n0->setChild(1, base);511n2 = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::bloadi, TR::Int8, tgt->incNumNodes(), dagId, 1, 1, n0); tgt->addNode(n2);512513n2->setChild(n0);514n2->setIsChildDirectlyConnected();515return n2;516}517518//*****************************************************************************************519// It creates the idiom for "divide by 10" or the corresponding multiplication idiom520// based on the given flag.521//522// "InLoop" means that it sets the given dagId to all nodes in this subroutine.523//*****************************************************************************************524TR_PCISCNode *525createIdiomIDiv10InLoop(TR_PCISCGraph *tgt, int32_t ctrl, bool isDiv2Mul, int dagId, TR_PCISCNode *pred, TR_PCISCNode *src1, TR_PCISCNode *src2, TR_PCISCNode *c2, TR_PCISCNode *c31)526{527TR_PCISCNode *ret;528if (isDiv2Mul)529{530TR_PCISCNode *nmul= new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::imulh, TR::Int32 ,tgt->incNumNodes(), 1, 1, 2, pred, src1, src2); tgt->addNode(nmul);531TR_PCISCNode *nshr= new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::ishr, TR::Int32 ,tgt->incNumNodes(), 1, 1, 2, nmul, nmul, c2); tgt->addNode(nshr);532TR_PCISCNode *ushr= new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::iushr, TR::Int32 ,tgt->incNumNodes(), 1, 1, 2, nshr, src1, c31); tgt->addNode(ushr); // optional533ret = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::iadd, TR::Int32 ,tgt->incNumNodes(), 1, 1, 2, ushr, nshr, ushr); tgt->addNode(ret); // optional534ushr->setIsOptionalNode();535ushr->setSkipParentsCheck();536ret->setIsOptionalNode();537}538else539{540ret = new (PERSISTENT_NEW) TR_PCISCNode(tgt->trMemory(), TR::idiv, TR::Int32 ,tgt->incNumNodes(), 1, 1, 2, pred, src1, src2); tgt->addNode(ret);541}542return ret;543}544545546//*****************************************************************************************547// Search the node "target" starting from "start" within this basic block548//*****************************************************************************************549bool550searchNodeInBlock(TR_CISCNode *start,551TR_CISCNode *target)552{553TR_CISCNode *t = start;554555while (t->getNumSuccs() == 1 && t->getPreds()->isSingleton())556{557if (t == target) return true;558t = t->getSucc(0);559if (t == start) break; // maybe, this condition never happen.560}561562return false;563}564565566//*****************************************************************************************567// Check if all successors of t will reach any node included in pBV.568//*****************************************************************************************569bool570checkSuccsSet(TR_CISCTransformer *const trans,571TR_CISCNode *t,572TR_BitVector *const pBV)573{574List<TR_CISCNode> *T2P = trans->getT2P();575TR_CISCNode *p;576577while (t->getNumSuccs() == 1)578{579t = t->getSucc(0);580if (!t->isNegligible())581{582ListIterator<TR_CISCNode> li(T2P + t->getID());583for (p = li.getFirst(); p; p = li.getNext()) if (pBV->isSet(p->getID())) return true; // found the pattern node in pBV584return false; // cannot find the pattern node.585}586}587588for (int i = t->getNumSuccs(); --i >= 0; )589{590TR_CISCNode *tn = t->getSucc(i);591if (!tn->isNegligible())592{593ListIterator<TR_CISCNode> li(T2P + tn->getID());594for (p = li.getFirst(); p; p = li.getNext()) if (pBV->isSet(p->getID())) break; // found the pattern node in pBV595if (!p) return false; // cannot find the pattern node.596}597else598{599if (!checkSuccsSet(trans, tn, pBV)) return false;600}601}602return true;603}604605606//*****************************************************************************************607// It searches an iload in the tree "q", and it returns the iload608//*****************************************************************************************609static TR_CISCNode *610searchIload(TR_CISCNode *q, bool allowArrayIndex)611{612while(true)613{614bool fail = false;615if (q->getOpcode() == TR::i2l)616{617q = q->getChild(0); // allow only TR::iload or TR_variable618fail = true;619}620if (q->getOpcode() == TR::iload || q->getOpcode() == TR_variable) return q;621if (allowArrayIndex && q->getOpcode() == TR_arrayindex) return q;622if (fail || q->getOpcode() == TR::lload || q->getNumChildren() < 1) return 0;623q = q->getChild(0);624}625return 0;626}627628629//*****************************************************************************************630// It searches an array load in the tree "top", and it returns the type of an array load,631// a base variable, and an index variable.632//*****************************************************************************************633bool634getThreeNodesForArray(TR_CISCNode *top, TR_CISCNode **ixloadORstore, TR_CISCNode **aload, TR_CISCNode **iload, bool allowArrayIndex)635{636TR_CISCNode *p;637638// search ixloadORstore639p = top;640while(true)641{642if (p->getNumChildren() == 0) return false;643if (p->getIlOpCode().isLoadIndirect() || p->getIlOpCode().isStoreIndirect() ||644p->getOpcode() == TR_inbload || p->getOpcode() == TR_inbstore ||645p->getOpcode() == TR_indload || p->getOpcode() == TR_indstore ||646p->getOpcode() == TR_ibcload || p->getOpcode() == TR_ibcstore)647{648*ixloadORstore = p;649break;650}651p = p->getChild(0);652}653654p = p->getChild(0);655656TR_CISCNode *q;657switch(p->getOpcode())658{659case TR::aladd:660case TR::aiadd:661// search aload662q = p->getChild(0);663while(true)664{665if (q->getOpcode() == TR::aload || q->getOpcode() == TR_variable || q->getOpcode() == TR_arraybase)666{667*aload = q;668break;669}670if (q->getNumChildren() != 1) return false;671q = q->getChild(0);672}673674// search iload675if ((q = searchIload(p->getChild(1), allowArrayIndex)) == 0) return false;676*iload = q;677break;678679case TR::ladd:680case TR::iadd:681// search iload682if ((q = searchIload(p->getChild(1), allowArrayIndex)))683{684*iload = q;685q = p->getChild(0);686}687else if ((q = searchIload(p->getChild(0), allowArrayIndex)))688{689*iload = q;690q = p->getChild(1);691}692else693{694return false;695}696697// search aload698while(true)699{700if (q->getOpcode() == TR::lload || q->getOpcode() == TR_variable)701{702*aload = q;703break;704}705if (q->getOpcode() == TR::iload || q->getNumChildren() != 1) return false;706q = q->getChild(0);707}708break;709710default:711return false;712}713return true;714}715716717//*****************************************************************************************718// It returns isDcrement and modification length by analyzing if-opcode719//*****************************************************************************************720bool721testExitIF(int opcode, bool *isDecrement, int32_t *modLength, int32_t *modStartIdx)722{723switch(opcode)724{725case TR::ificmplt:726if (isDecrement) *isDecrement = true;727if (modLength) *modLength = 1;728if (modStartIdx) *modStartIdx = 0;729return true;730case TR::ificmple:731if (isDecrement) *isDecrement = true;732if (modLength) *modLength = 0;733if (modStartIdx) *modStartIdx = 1;734return true;735case TR::ificmpgt:736if (isDecrement) *isDecrement = false;737if (modLength) *modLength = 1;738if (modStartIdx) *modStartIdx = 0;739return true;740case TR::ificmpge:741if (isDecrement) *isDecrement = false;742if (modLength) *modLength = 0;743if (modStartIdx) *modStartIdx = 0;744return true;745}746return false;747}748749750/********************************************************************/751/************ Utilities for analyzing or making TR::Node *************/752/********************************************************************/753754//*****************************************************************************************755// It returns the n'th child is "iconst value".756//*****************************************************************************************757bool758testIConst(TR_CISCNode *n, int idx, int32_t value)759{760TR_CISCNode *ch = n->getChild(idx);761return (ch->getOpcode() == TR::iconst && ch->getOtherInfo() == value);762}763764765//*****************************************************************************************766// It inserts i2l based on the given flag.767//*****************************************************************************************768TR::Node*769createI2LIfNecessary(TR::Compilation *comp, bool is64bit, TR::Node *child)770{771return is64bit ? TR::Node::create(TR::i2l, 1, child) : child;772}773774775//*****************************************************************************************776// It converts from store to load.777//*****************************************************************************************778TR::Node*779createLoad(TR::Node *baseNode)780{781return baseNode->getOpCode().isStoreDirect() ? TR::Node::createLoad(baseNode, baseNode->getSymbolReference()) :782baseNode->duplicateTree();783}784785786//*****************************************************************************************787// It creates a load instruction, and it inserts i2l based on the given flag.788//*****************************************************************************************789TR::Node*790createLoadWithI2LIfNecessary(TR::Compilation *comp, bool is64bit, TR::Node *indexNode)791{792TR_ASSERT(indexNode->getOpCode().hasSymbolReference(), "parameter error");793TR::Node *iload = createLoad(indexNode);794return createI2LIfNecessary(comp, is64bit, iload);795}796797798//*****************************************************************************************799// It creates a node of the constant value of the array header size.800//*****************************************************************************************801TR::Node*802createArrayHeaderConst(TR::Compilation *comp, bool is64bit, TR::Node *baseNode)803{804TR::Node *c2;805if (is64bit)806{807c2 = TR::Node::create(baseNode, TR::lconst, 0);808c2->setLongInt(-(int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());809}810else811{812c2 = TR::Node::create(baseNode, TR::iconst, 0, -(int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());813}814return c2;815}816817818//*****************************************************************************************819// It creates an effective address tree for the top of the given array.820//*****************************************************************************************821TR::Node*822createArrayTopAddressTree(TR::Compilation *comp, bool is64bit, TR::Node *baseNode)823{824TR::Node *top, *c2;825TR::Node *aload = createLoad(baseNode);826if (is64bit)827{828top = TR::Node::create(baseNode, TR::aladd, 2);829c2 = TR::Node::create(baseNode, TR::lconst, 0);830c2->setLongInt((int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());831}832else833{834top = TR::Node::create(baseNode, TR::aiadd, 2);835c2 = TR::Node::create(baseNode, TR::iconst, 0, (int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());836}837top->setAndIncChild(0, aload);838top->setAndIncChild(1, c2);839return top;840}841842843//*****************************************************************************************844// It converts from store to load, and it inserts i2l based on the given flag.845//*****************************************************************************************846TR::Node*847convertStoreToLoadWithI2LIfNecessary(TR::Compilation *comp, bool is64bit, TR::Node *indexNode)848{849return (indexNode->getOpCode().isStoreDirect()) ?850createLoadWithI2LIfNecessary(comp, is64bit, indexNode) :851createI2LIfNecessary(comp, is64bit, indexNode->getReferenceCount() ?852indexNode->duplicateTree() : indexNode);853}854855856//*****************************************************************************************857// It converts from store to load.858//*****************************************************************************************859TR::Node*860convertStoreToLoad(TR::Compilation *comp, TR::Node *indexNode)861{862return (indexNode->getOpCode().isStoreDirect()) ?863TR::Node::createLoad(indexNode, indexNode->getSymbolReference()) :864indexNode->getReferenceCount() ? indexNode->duplicateTree() : indexNode;865}866867868//*****************************************************************************************869// It creates the byte size from an element size. (i.e. ret = index * multiply)870//*****************************************************************************************871TR::Node*872createBytesFromElement(TR::Compilation *comp, bool is64bit, TR::Node *indexNode, int multiply)873{874TR::Node *top, *c2;875top = convertStoreToLoadWithI2LIfNecessary(comp, is64bit, indexNode);876877if (is64bit)878{879if (multiply > 1)880{881c2 = TR::Node::create(indexNode, TR::lconst, 0); // c2 is used temporary882c2->setLongInt(multiply);883top = TR::Node::create(TR::lmul, 2, top, c2);884}885}886else887{888if (multiply > 1)889{890c2 = TR::Node::create(indexNode, TR::iconst, 0, multiply); // c2 is used temporary891top = TR::Node::create(TR::imul, 2, top, c2);892}893}894return top;895}896897898//*****************************************************************************************899// It creates an index address tree for the given indexNode and size.900//*****************************************************************************************901TR::Node*902createIndexOffsetTree(TR::Compilation *comp, bool is64bit, TR::Node *indexNode, int multiply)903{904TR::Node *top, *c1, *c2;905c1 = createBytesFromElement(comp, is64bit, indexNode, multiply);906907if (is64bit)908{909c2 = TR::Node::create(indexNode, TR::lconst, 0);910c2->setLongInt(-(int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());911top = TR::Node::create(indexNode, TR::lsub, 2);912}913else914{915c2 = TR::Node::create(indexNode, TR::iconst, 0, -(int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());916top = TR::Node::create(indexNode, TR::isub, 2);917}918top->setAndIncChild(0, c1);919top->setAndIncChild(1, c2);920return top;921}922923924//*****************************************************************************************925// It creates an effective address tree for the given baseNode, indexNode and size.926//*****************************************************************************************927TR::Node*928createArrayAddressTree(TR::Compilation *comp, bool is64bit, TR::Node *baseNode, TR::Node *indexNode, int multiply)929{930if (indexNode->getOpCodeValue() == TR::iconst && indexNode->getInt() == 0)931{932return createArrayTopAddressTree(comp, is64bit, baseNode);933}934else935{936TR::Node *top, *c2;937TR::Node *aload = createLoad(baseNode);938c2 = createIndexOffsetTree(comp, is64bit, indexNode, multiply);939top = TR::Node::create(baseNode, is64bit ? TR::aladd : TR::aiadd, 2);940top->setAndIncChild(0, aload);941top->setAndIncChild(1, c2);942return top;943}944}945946947//*****************************************************************************************948// It creates an array load tree for the given load type, baseNode, indexNode and size.949//*****************************************************************************************950TR::Node*951createArrayLoad(TR::Compilation *comp, bool is64bit, TR::Node *ixload, TR::Node *baseNode, TR::Node *indexNode, int multiply)952{953TR::Node *top, *c1;954955if (comp->useCompressedPointers() &&956(ixload->getDataType() == TR::Address))957multiply = multiply >> 1;958959c1 = createArrayAddressTree(comp, is64bit, baseNode, indexNode, multiply);960TR::SymbolReference *symref=ixload->getSymbolReference();961top = TR::Node::createWithSymRef(ixload, ixload->getOpCodeValue(), 1, symref);962top->setAndIncChild(0, c1);963return top;964}965966967//*****************************************************************************************968// It replaces the array index in the address tree.969//*****************************************************************************************970TR::Node *971replaceIndexInAddressTree(TR::Compilation *comp, TR::Node *tree, TR::SymbolReference *symRef, TR::Node *newNode)972{973TR::Node *orgTree = tree;974if (tree->getOpCode().isIndirect()) tree = tree->getChild(0);975if (tree->getOpCode().isAdd())976{977tree = tree->getChild(1);978while(true)979{980TR::Node *parent = tree;981if (tree->getOpCodeValue() == TR::iadd)982{983TR::Node *ch1 = tree->getChild(1);984if (ch1->getOpCodeValue() == TR::iload)985{986if (ch1->getSymbolReference() == symRef)987{988parent->getAndDecChild(1);989parent->setAndIncChild(1, newNode);990return orgTree;991}992}993}994995tree = tree->getChild(0);996if (!tree) break;997if (tree->getOpCodeValue() == TR::iload)998{999if (tree->getSymbolReference() == symRef)1000{1001parent->getAndDecChild(0);1002parent->setAndIncChild(0, newNode);1003return orgTree;1004}1005else1006{1007return NULL;1008}1009}1010}1011}1012return NULL;1013}10141015//*****************************************************************************************1016// It modifies the array header constant in the given tree1017//*****************************************************************************************1018TR::Node *1019modifyArrayHeaderConst(TR::Compilation *comp, TR::Node *tree, int32_t offset)1020{1021if (offset == 0) return tree;1022if (!tree->getOpCode().isAdd()) tree = tree->getFirstChild();1023if (tree->getOpCodeValue() == TR::aiadd || tree->getOpCodeValue() == TR::aladd)1024{1025TR::Node *addOrSubNode = tree->getSecondChild();1026TR::Node *constLoad = addOrSubNode->getSecondChild();1027if (addOrSubNode->getOpCode().isSub())1028{1029offset = -offset;1030}1031else if (!addOrSubNode->getOpCode().isAdd())1032{1033return NULL; // failed1034}1035switch(constLoad->getOpCodeValue())1036{1037case TR::iconst:1038constLoad->setInt(constLoad->getInt() + offset);1039return constLoad;1040break;1041case TR::lconst:1042constLoad->setLongInt(constLoad->getLongInt() + offset);1043return constLoad;1044break;1045default:1046return NULL;1047}1048}1049return NULL;1050}10511052//*****************************************************************************************1053// It creates a table load node especially for function tables for TRT or TRxx1054//*****************************************************************************************1055TR::Node*1056createTableLoad(TR::Compilation *comp, TR::Node* repNode, uint8_t inputSize, uint8_t outputSize, void *array, bool dispTrace)1057{1058TR_SetTranslateTable setTable(comp, inputSize, outputSize, array,1059TR_TranslateTable::tableSize(inputSize, outputSize));1060TR::SymbolReference *tableSymRef = setTable.createSymbolRef();1061if (dispTrace)1062setTable.dumpTable();1063return TR::Node::createWithSymRef(repNode, TR::loadaddr, 0, tableSymRef);1064}10651066//*****************************************************************************************1067// It basically creates "ch1 op2 ch2", but it performs a simple constant folding.1068//*****************************************************************************************1069TR::Node*1070createOP2(TR::Compilation *comp, TR::ILOpCodes op2, TR::Node* ch1, TR::Node* ch2)1071{1072TR::Node* op2Node;1073bool done = false;1074if (ch2->getOpCodeValue() == TR::iconst)1075{1076int value = ch2->getInt();1077int32_t newVal;1078switch(op2)1079{1080case TR::iadd:1081case TR::isub:1082if (value == 0)1083{1084op2Node = ch1;1085done = true;1086}1087else if (ch1->getOpCodeValue() == TR::iconst)1088{1089newVal = (op2 == TR::iadd) ? (ch1->getInt() + ch2->getInt()) :1090(ch1->getInt() - ch2->getInt());1091op2Node = TR::Node::create(ch1, TR::iconst, 0, newVal);1092done = true;1093}1094break;1095case TR::imul:1096case TR::idiv:1097if (value == 1)1098{1099op2Node = ch1;1100done = true;1101}1102else if (ch1->getOpCodeValue() == TR::iconst)1103{1104if (ch2->getInt() == 0 && op2 == TR::idiv)1105break; // divide by 01106newVal = (op2 == TR::imul) ? (ch1->getInt() * ch2->getInt()) :1107(ch1->getInt() / ch2->getInt());1108op2Node = TR::Node::create(ch1, TR::iconst, 0, newVal);1109done = true;1110}1111break;1112default:1113break;1114}1115}1116if (!done) op2Node = TR::Node::create(op2, 2, ch1, ch2);1117return op2Node;1118}11191120//*****************************************************************************************1121// It creates like the following tree "storeNode = ch1 op2 ch2"1122//*****************************************************************************************1123TR::Node*1124createStoreOP2(TR::Compilation *comp, TR::Node* storeNode, TR::ILOpCodes op2, TR::Node* ch1, TR::Node* ch2)1125{1126TR::Node* op2Node = createOP2(comp, op2, ch1, ch2);1127storeNode->setAndIncChild(0, op2Node);1128return storeNode;1129}11301131//*****************************************************************************************1132// It creates like the following tree "storeNode = ch1 op2 ch2" from the given symbol references.1133//*****************************************************************************************1134TR::Node*1135createStoreOP2(TR::Compilation *comp, TR::SymbolReference* store, TR::ILOpCodes op2, TR::SymbolReference* ch1, TR::Node* ch2, TR::Node *rep)1136{1137return createStoreOP2(comp,1138TR::Node::createWithSymRef(rep, comp->il.opCodeForDirectStore(store->getSymbol()->getDataType()), 1, store),1139op2,1140TR::Node::createWithSymRef(rep, comp->il.opCodeForDirectLoad(ch1->getSymbol()->getDataType()), 0, ch1),1141ch2);1142}11431144//*****************************************************************************************1145// It creates like the following tree "storeNode = ch1 op2 ch2" from the given symbol references.1146//*****************************************************************************************1147TR::Node*1148createStoreOP2(TR::Compilation *comp, TR::SymbolReference* store, TR::ILOpCodes op2, TR::SymbolReference* ch1, TR::SymbolReference* ch2, TR::Node *rep)1149{1150return createStoreOP2(comp, store, op2, ch1,1151TR::Node::createWithSymRef(rep, comp->il.opCodeForDirectLoad(ch2->getSymbol()->getDataType()), 0, ch2),1152rep);1153}11541155//*****************************************************************************************1156// It creates like the following tree "storeNode = ch1 op2 ch2" from the given symbol1157// references and constant value.1158//*****************************************************************************************1159TR::Node*1160createStoreOP2(TR::Compilation *comp, TR::SymbolReference* store, TR::ILOpCodes op2, TR::SymbolReference* ch1, int ch2Const, TR::Node *rep)1161{1162return createStoreOP2(comp, store, op2, ch1,1163TR::Node::create( rep, TR::iconst, 0, ch2Const),1164rep);1165}116611671168//*****************************************************************************************1169// It creates "min(x, y)", whose tree is x+(((y-x)>>31)&(y-x)).1170//*****************************************************************************************1171TR::Node*1172createMin(TR::Compilation *comp, TR::Node* x, TR::Node* y)1173{1174if (x->getOpCodeValue() == TR::iconst &&1175y->getOpCodeValue() == TR::iconst)1176{1177return TR::Node::create(x, TR::iconst, 0, std::min(x->getInt(), y->getInt()));1178}1179else1180{1181TR::Node *y_x = TR::Node::create(TR::isub, 2, y, x); // y-x1182TR::Node *shift = TR::Node::create(TR::ishr, 2, y_x,1183TR::Node::create(y_x, TR::iconst, 0, 31)); // y_x >> 311184TR::Node *andop = TR::Node::create(TR::iand, 2, shift, y_x); // shift & y_x1185TR::Node *ret = TR::Node::create(TR::iadd, 2, x, andop); // x + andop1186return ret;1187}1188}118911901191//*****************************************************************************************1192// It creates "max(x, y)", whose tree is x-(((x-y)>>31)&(x-y)).1193//*****************************************************************************************1194TR::Node*1195createMax(TR::Compilation *comp, TR::Node* x, TR::Node* y)1196{1197if (x->getOpCodeValue() == TR::iconst &&1198y->getOpCodeValue() == TR::iconst)1199{1200return TR::Node::create(x, TR::iconst, 0, std::max(x->getInt(), y->getInt()));1201}1202else1203{1204TR::Node *x_y = TR::Node::create(TR::isub, 2, x, y); // x-y1205TR::Node *shift = TR::Node::create(TR::ishr, 2, x_y,1206TR::Node::create(x_y, TR::iconst, 0, 31)); // x_y >> 311207TR::Node *andop = TR::Node::create(TR::iand, 2, shift, x_y); // shift & x_y1208TR::Node *ret = TR::Node::create(TR::isub, 2, x, andop); // x - andop1209return ret;1210}1211}121212131214//*****************************************************************************************1215// It will return a constant load in the target graph corresponding to the pattern node mulConst.1216// If mulConst is NULL, *elementSize will be set to 1.1217// Otherwise, *elementSize will be set to the value of the constant, and *multiplier will be set1218// to that TR::Node.1219//*****************************************************************************************1220bool1221getMultiplier(TR_CISCTransformer *trans, TR_CISCNode *mulConst, TR::Node **multiplier, int *elementSize, TR::DataType srcNodeType)1222{1223TR::Node *mulFactorNode = 0;1224if (mulConst)1225{1226TR_CISCNode *mulConstT = trans->getP2TRep(mulConst);1227if (!mulConstT->isNewCISCNode())1228mulFactorNode = mulConstT->getHeadOfTrNodeInfo()->_node;1229}1230if (mulFactorNode)1231{1232TR_ASSERT(mulFactorNode->getOpCode().isLoadConst(), "error!");1233switch(mulFactorNode->getOpCodeValue())1234{1235case TR::iconst:1236*elementSize = mulFactorNode->getInt();1237*multiplier = mulFactorNode;1238return true;1239case TR::lconst:1240*elementSize = (int)mulFactorNode->getLongInt();1241*multiplier = mulFactorNode;1242return true;1243default:1244TR_ASSERT(false, "error!");1245return false;1246}1247}1248else1249{1250*multiplier = NULL;1251*elementSize = 1;1252}1253return true;1254}125512561257//*****************************************************************************************1258// It will get each representative target node using P2T table for each pattern node.1259// The number of pattern nodes is given by "count".1260// The result (several TR::Nodes) is set to "array".1261//*****************************************************************************************1262void1263getP2TTrRepNodes(TR_CISCTransformer *trans, TR::Node** array, int count)1264{1265TR_CISCGraph *P = trans->getP();1266ListIterator<TR_CISCNode> pi(P->getOrderByData());1267TR_CISCNode *pn;1268int index = 0;1269for (pn = pi.getFirst(); pn && index < count; pn = pi.getNext(), index++)1270{1271TR_CISCNode *tn = trans->getP2TRepInLoop(pn);1272if (!tn) tn = trans->getP2TRep(pn);1273TR::Node *candidate = NULL;1274if (tn)1275{1276ListIterator<TrNodeInfo> li(tn->getTrNodeInfo());1277candidate = tn->getHeadOfTrNodeInfo()->_node;1278TrNodeInfo *p;1279for (p = li.getFirst(); p; p = li.getNext())1280{1281if (!p->_node->getOpCode().isStoreDirect())1282{1283candidate = p->_node;1284break;1285}1286}1287if (candidate->getOpCode().isStoreDirect())1288{1289ListIterator<TR_CISCNode> pi(tn->getParents());1290TR_CISCNode *p;1291bool noLoad = true;1292for (p = pi.getFirst(); p; p = pi.getNext())1293{1294if (p->isLoadVarDirect()) noLoad = false;1295}1296if (noLoad)1297{1298for (p = pi.getFirst(); p; p = pi.getNext())1299{1300if (!p->isOutsideOfLoop() &&1301p->isStoreDirect() &&1302p->isNegligible())1303{1304trans->getBeforeInsertionList()->add(candidate->duplicateTree());1305break;1306}1307}1308}1309}1310}1311array[index] = candidate;1312}1313}13141315//*****************************************************************************************1316// Get first two representative target nodes.1317//*****************************************************************************************1318void1319getP2TTrRepNodes(TR_CISCTransformer *trans, TR::Node** n1, TR::Node** n2)1320{1321TR::Node* array[2];1322getP2TTrRepNodes(trans, array, 2);1323if (n1) *n1 = array[0];1324if (n2) *n2 = array[1];1325}13261327//*****************************************************************************************1328// Get first three representative target nodes.1329//*****************************************************************************************1330void1331getP2TTrRepNodes(TR_CISCTransformer *trans, TR::Node** n1, TR::Node** n2, TR::Node** n3)1332{1333TR::Node* array[3];1334getP2TTrRepNodes(trans, array, 3);1335if (n1) *n1 = array[0];1336if (n2) *n2 = array[1];1337if (n3) *n3 = array[2];1338}13391340//*****************************************************************************************1341// Get first four representative target nodes.1342//*****************************************************************************************1343void1344getP2TTrRepNodes(TR_CISCTransformer *trans, TR::Node** n1, TR::Node** n2, TR::Node** n3, TR::Node** n4)1345{1346TR::Node* array[4];1347getP2TTrRepNodes(trans, array, 4);1348if (n1) *n1 = array[0];1349if (n2) *n2 = array[1];1350if (n3) *n3 = array[2];1351if (n4) *n4 = array[3];1352}13531354//*****************************************************************************************1355// Get first five representative target nodes.1356//*****************************************************************************************1357void1358getP2TTrRepNodes(TR_CISCTransformer *trans, TR::Node** n1, TR::Node** n2, TR::Node** n3, TR::Node** n4, TR::Node** n5)1359{1360TR::Node* array[5];1361getP2TTrRepNodes(trans, array, 5);1362if (n1) *n1 = array[0];1363if (n2) *n2 = array[1];1364if (n3) *n3 = array[2];1365if (n4) *n4 = array[3];1366if (n5) *n5 = array[4];1367}13681369//*****************************************************************************************1370// Get first six representative target nodes.1371//*****************************************************************************************1372void1373getP2TTrRepNodes(TR_CISCTransformer *trans, TR::Node** n1, TR::Node** n2, TR::Node** n3, TR::Node** n4, TR::Node** n5, TR::Node** n6)1374{1375TR::Node* array[6];1376getP2TTrRepNodes(trans, array, 6);1377if (n1) *n1 = array[0];1378if (n2) *n2 = array[1];1379if (n3) *n3 = array[2];1380if (n4) *n4 = array[3];1381if (n5) *n5 = array[4];1382if (n6) *n6 = array[5];1383}13841385//*****************************************************************************************1386// Get first seven representative target nodes.1387//*****************************************************************************************1388void1389getP2TTrRepNodes(TR_CISCTransformer *trans, TR::Node** n1, TR::Node** n2, TR::Node** n3, TR::Node** n4, TR::Node** n5, TR::Node** n6, TR::Node** n7)1390{1391TR::Node* array[7];1392getP2TTrRepNodes(trans, array, 7);1393if (n1) *n1 = array[0];1394if (n2) *n2 = array[1];1395if (n3) *n3 = array[2];1396if (n4) *n4 = array[3];1397if (n5) *n5 = array[4];1398if (n6) *n6 = array[5];1399if (n7) *n7 = array[6];1400}14011402//*****************************************************************************************1403// Confirm whether only the table[0] is zero and other entries (table[1 to 256]) are non-zero1404//*****************************************************************************************1405bool1406isFitTRTFunctionTable(uint8_t *table)1407{1408if (*table) return false;1409for (int i = 1; i < 256; i++)1410if (table[i] == 0) return false;1411return true;1412}141314141415//*****************************************************************************************1416// create table alignment check node for arraytranslate1417//*****************************************************************************************1418TR::Node*1419createTableAlignmentCheck(TR::Compilation *comp, TR::Node *tableNode, bool isByteSource, bool isByteTarget, bool tableBackedByRawStorage)1420{1421int32_t mask = comp->cg()->arrayTranslateTableRequiresAlignment(isByteSource, isByteTarget);1422TR::Node * compareNode = NULL;1423if (mask != 0 && mask != 7)1424{1425if (comp->target().is64Bit())1426{1427TR::Node * zeroNode = TR::Node::create(tableNode, TR::lconst);1428zeroNode->setLongInt(0);1429TR::Node * pageNode = TR::Node::create(tableNode, TR::lconst);1430pageNode->setLongInt(mask);1431TR::Node * dupTableNode = tableNode->duplicateTree();1432if (!tableBackedByRawStorage)1433{1434TR::Node * hdrSizeNode = TR::Node::create(tableNode, TR::lconst, 0);1435hdrSizeNode->setLongInt((int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes());1436dupTableNode = TR::Node::create(TR::ladd, 2, dupTableNode, hdrSizeNode);1437}1438TR::Node * andNode = TR::Node::create(TR::land, 2, dupTableNode, pageNode);14391440compareNode = TR::Node::createif(TR::iflcmpne, zeroNode, andNode);1441}1442else1443{1444TR::Node * zeroNode = TR::Node::create(tableNode, TR::iconst, 0, 0);1445TR::Node * pageNode = TR::Node::create(tableNode, TR::iconst, 0, mask);1446TR::Node * dupTableNode = tableNode->duplicateTree();1447if (!tableBackedByRawStorage)1448{1449TR::Node * hdrSizeNode = TR::Node::create(tableNode, TR::iconst, 0, TR::Compiler->om.contiguousArrayHeaderSizeInBytes());1450dupTableNode = TR::Node::create(TR::iadd, 2, dupTableNode, hdrSizeNode);1451}1452TR::Node * andNode = TR::Node::create(TR::iand, 2, dupTableNode, pageNode);14531454compareNode = TR::Node::createif(TR::ificmpne, zeroNode, andNode);1455}1456}1457return compareNode;1458}145914601461//*****************************************************************************************1462// Sort each entry of the given list1463//*****************************************************************************************1464List<TR_CISCNode>*1465sortList(List<TR_CISCNode>* input, List<TR_CISCNode>* output, List<TR_CISCNode>* order, bool reverse)1466{1467if (input->isSingleton())1468{1469TR_CISCNode *n = input->getListHead()->getData();1470if (order->find(n))1471output->add(n);1472}1473else1474{1475ListIterator<TR_CISCNode> li(order);1476TR_CISCNode *n = li.getFirst();1477if (!reverse)1478{1479ListAppender<TR_CISCNode> appender(output);1480for (; n; n = li.getNext())1481{1482if (input->find(n)) appender.add(n);1483}1484}1485else1486{1487for (; n; n = li.getNext())1488{1489if (input->find(n)) output->add(n);1490}1491}1492}1493return output;1494}14951496//*****************************************************************************************1497// Checks if loop preheader block is last block in method.1498//*****************************************************************************************1499bool isLoopPreheaderLastBlockInMethod(TR::Compilation *comp, TR::Block *block, TR::Block **predBlock)1500{15011502// If already a loop invariant block, we likely have the preheader.1503if (block->getStructureOf() && block->getStructureOf()->isLoopInvariantBlock())1504{1505if (predBlock)1506*predBlock = block;1507if (block->getExit()->getNextTreeTop() == NULL)1508{1509traceMsg(comp, "Preheader block_%d [%p] is last block in method.\n", block->getNumber(), block);1510return true;1511}1512}1513else1514{1515// Find the loop preheader block and check its next treetop.1516for (auto edge = block->getPredecessors().begin(); edge != block->getPredecessors().end(); ++edge)1517{1518TR::Block *source = toBlock ((*edge)->getFrom());15191520if (source->getStructureOf() &&1521source->getStructureOf()->isLoopInvariantBlock())1522{1523if (predBlock)1524*predBlock = source;1525if (source->getExit()->getNextTreeTop() == NULL)1526{1527traceMsg(comp, "Preheader block_%d [%p] to block_%d [%p] is last block in method.\n", source->getNumber(), source, block->getNumber(), block);1528return true;1529}1530}1531}1532}1533return false;1534}153515361537//*****************************************************************************************1538// Search for specific symref within a given subtree. If targetNode is specified, the node with the matching symref1539// will be replaced with the targetNode.1540// @param curNode The parent node to recursively search1541// @param symRefNumberToBeMatched The symbol reference number to be matched1542// @return The load TR::Node* with the matching symbol reference number. NULL if not found.1543//*****************************************************************************************1544TR::Node*1545findLoadWithMatchingSymRefNumber(TR::Node *curNode, int32_t symRefNumberToBeMatched)1546{1547TR::Node *node = NULL;1548// Recursively iterate through each children node and look for nodes with the matching symref to replace.1549for (int32_t i = 0; i < curNode->getNumChildren(); i++)1550{1551TR::Node *childNode = curNode->getChild(i);15521553if (childNode->getOpCode().isLoad() && childNode->getOpCode().hasSymbolReference() && (childNode->getSymbolReference()->getReferenceNumber() == symRefNumberToBeMatched))1554{1555node = childNode;1556break;1557}1558else1559{1560node = findLoadWithMatchingSymRefNumber(childNode, symRefNumberToBeMatched);1561if (node != NULL)1562break;1563}1564}1565return node;1566}156715681569//*****************************************************************************************1570// Search for specific symref within a given subtree. If targetNode is specified, the node with the matching symref1571// will be replaced with the targetNode.1572//*****************************************************************************************1573bool1574findAndOrReplaceNodesWithMatchingSymRefNumber(TR::Node *curNode, TR::Node *targetNode, int32_t symRefNumberToBeMatched)1575{1576bool isFound = false;15771578// Recursively iterate through each children node and look for nodes with the matching symref to replace.1579for (int32_t i = 0; i < curNode->getNumChildren(); i++)1580{1581TR::Node *childNode = curNode->getChild(i);15821583if (childNode->getOpCode().hasSymbolReference() && (childNode->getSymbolReference()->getReferenceNumber() == symRefNumberToBeMatched))1584{1585if (targetNode != NULL)1586curNode->setAndIncChild(i,targetNode);1587isFound = true;1588}1589else1590{1591isFound = findAndOrReplaceNodesWithMatchingSymRefNumber(childNode, targetNode, symRefNumberToBeMatched) || isFound;1592}1593}1594return isFound;1595}1596159715981599