Path: blob/master/runtime/compiler/optimizer/IdiomRecognition.hpp
6000 views
/*******************************************************************************1* Copyright (c) 2000, 2022 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#ifndef IDIOMRECOGNITION_INCL23#define IDIOMRECOGNITION_INCL2425#include <stdint.h>26#include <string.h>27#include "compile/Compilation.hpp"28#include "compile/CompilationTypes.hpp"29#include "env/TRMemory.hpp"30#include "il/DataTypes.hpp"31#include "il/ILOpCodes.hpp"32#include "il/ILOps.hpp"33#include "il/ILProps.hpp"34#include "infra/Assert.hpp"35#include "infra/BitVector.hpp"36#include "infra/Flags.hpp"37#include "infra/HashTab.hpp"38#include "infra/Link.hpp"39#include "infra/List.hpp"40#include "infra/TRlist.hpp"41#include "optimizer/LoopCanonicalizer.hpp"42#include "optimizer/OptimizationManager.hpp"4344class TR_CISCTransformer;45class TR_RegionStructure;46class TR_UseDefInfo;47namespace TR { class Block; }48namespace TR { class CFG; }49namespace TR { class CFGEdge; }50namespace TR { class CFGNode; }51namespace TR { class Node; }52namespace TR { class Optimization; }53namespace TR { class Optimizer; }54namespace TR { class SymbolReference; }55namespace TR { class TreeTop; }5657typedef enum58{59TR_variable = TR::NumIlOps,60TR_booltable,61TR_entrynode,62TR_exitnode,63TR_allconst,64TR_ahconst, // constant for array header65TR_variableORconst,66TR_quasiConst, // Currently, variable or constant or arraylength67TR_quasiConst2, // Currently, variable or constant, arraylength, or *iiload* (for non-array)68// We shouldn't use it in an idiom including iistore to *non-array* variable.69TR_iaddORisub, // addition or subtraction70TR_conversion, // all data conversions, such as b2i, c2i, i2l, ...71TR_ifcmpall, // all if instructions72TR_ishrall, // ishr and iushr73TR_bitop1, // AND, OR, and XOR74TR_arrayindex, // variable or addition75TR_arraybase, // variable or iaload76TR_inbload, // indirect non-byte load77TR_inbstore, // indirect non-byte store78TR_indload, // indirect load79TR_indstore, // indirect store80TR_ibcload, // indirect byte or char load81TR_ibcstore // indirect byte or char store82} TR_CISCOps;8384struct TrNodeInfo85{86TR::Block *_block;87TR::Node *_node;88TR::TreeTop *_treeTop;89};909192class TR_CISCNode93{94public:95TR_ALLOC(TR_Memory::LoopTransformer);96TR_HeapMemory trHeapMemory() { return _trMemory; }9798bool isEqualOpc(TR_CISCNode *t);99100TR_CISCNode(TR_Memory * m, uint32_t opc, TR::DataType dt, uint16_t id, int16_t dagId, uint16_t ncfgs, uint16_t nchildren, TR_AllocationKind allocKind = heapAlloc)101: _allocKind(allocKind), _trMemory(m), _preds(m), _parents(m), _dest(m), _chains(m), _hintChildren(m), _trNodeInfo(m), _dt(dt)102{103initialize(opc, id, dagId, ncfgs, nchildren);104}105106TR_CISCNode(TR_Memory * m, uint32_t opc, TR::DataType dt, uint16_t id, int16_t dagId, uint16_t ncfgs, uint16_t nchildren, TR_CISCNode *pred, TR_AllocationKind allocKind = heapAlloc)107: _allocKind(allocKind), _trMemory(m), _preds(m), _parents(m), _dest(m), _chains(m), _hintChildren(m), _trNodeInfo(m), _dt(dt)108{109initialize(opc, id, dagId, ncfgs, nchildren);110pred->setSucc(0, this);111}112113TR_CISCNode(TR_Memory * m, uint32_t opc, TR::DataType dt, uint16_t id, int16_t dagId, uint16_t ncfgs, uint16_t nchildren, TR_CISCNode *pred, TR_CISCNode *child0, TR_AllocationKind allocKind = heapAlloc)114: _allocKind(allocKind), _trMemory(m), _preds(m), _parents(m), _dest(m), _chains(m), _hintChildren(m), _trNodeInfo(m), _dt(dt)115{116initialize(opc, id, dagId, ncfgs, nchildren);117pred->setSucc(0, this);118setChild(0, child0);119}120121TR_CISCNode(TR_Memory * m, uint32_t opc, TR::DataType dt, uint16_t id, int16_t dagId, uint16_t ncfgs, uint16_t nchildren, TR_CISCNode *pred, TR_CISCNode *child0, TR_CISCNode *child1, TR_AllocationKind allocKind = heapAlloc)122: _allocKind(allocKind), _trMemory(m), _preds(m), _parents(m), _dest(m), _chains(m), _hintChildren(m), _trNodeInfo(m), _dt(dt)123{124initialize(opc, id, dagId, ncfgs, nchildren);125pred->setSucc(0, this);126setChildren(child0, child1);127}128129TR_CISCNode(TR_Memory * m, uint32_t opc, TR::DataType dt, uint16_t id, int16_t dagId, uint16_t ncfgs, uint16_t nchildren, int32_t otherInfo, TR_AllocationKind allocKind = heapAlloc)130: _allocKind(allocKind), _trMemory(m), _preds(m), _parents(m), _dest(m), _chains(m), _hintChildren(m), _trNodeInfo(m), _dt(dt)131{132initialize(opc, id, dagId, ncfgs, nchildren, otherInfo);133}134135TR_CISCNode(TR_Memory * m, uint32_t opc, TR::DataType dt, uint16_t id, int16_t dagId, uint16_t ncfgs, uint16_t nchildren, int32_t otherInfo, TR_CISCNode *pred, TR_AllocationKind allocKind = heapAlloc)136: _allocKind(allocKind), _trMemory(m), _preds(m), _parents(m), _dest(m), _chains(m), _hintChildren(m), _trNodeInfo(m), _dt(dt)137{138initialize(opc, id, dagId, ncfgs, nchildren, otherInfo);139pred->setSucc(0, this);140}141142void initialize(uint32_t opc, uint16_t id, int16_t dagId, uint16_t ncfgs, uint16_t nchildren)143{144initializeMembers(opc, id, dagId, ncfgs, nchildren);145allocArrays(ncfgs, nchildren);146}147148void initializeMembers(uint32_t opc, uint16_t id, int16_t dagId, uint16_t ncfgs, uint16_t nchildren);149void initialize(uint32_t opc, uint16_t id, int16_t dagId, uint16_t ncfgs, uint16_t nchildren, int32_t otherInfo)150{151initialize(opc, id, dagId, ncfgs, nchildren);152setOtherInfo(otherInfo);153}154155TR_Memory * trMemory() { return _trMemory; }156157void setOtherInfo(int32_t otherInfo)158{159_flags.set(_isValidOtherInfo);160_otherInfo = otherInfo;161checkFlags();162}163164void checkFlags()165{166if (isValidOtherInfo())167{168switch(_opcode)169{170case TR::iconst:171case TR::sconst:172case TR::bconst:173case TR::lconst:174setIsInterestingConstant();175break;176}177}178}179180void replaceSucc(uint32_t index, TR_CISCNode *to);181inline void setSucc(uint32_t index, TR_CISCNode *ch)182{183TR_ASSERT(index < _numSuccs, "TR_CISCNode::setSucc index out of range");184_succs[index] = ch;185ch->addPred(this);186}187188void setSucc(TR_CISCNode *ch)189{190setSucc(0, ch);191}192193void setSuccs(TR_CISCNode *ch1, TR_CISCNode *ch2)194{195setSucc(0, ch1);196setSucc(1, ch2);197}198199void replaceChild(uint32_t index, TR_CISCNode *ch);200inline void setChild(uint32_t index, TR_CISCNode *ch)201{202TR_ASSERT(index < _numChildren, "TR_CISCNode::setChild index out of range");203_children[index] = ch;204ch->addParent(this);205}206207void setChild(TR_CISCNode *ch)208{209setChild(0, ch);210}211212void setChildren(TR_CISCNode *ch1, TR_CISCNode *ch2)213{214setChild(0, ch1);215setChild(1, ch2);216}217218inline TR_CISCNode *getSucc(uint32_t index)219{220TR_ASSERT(index < _numSuccs, "TR_CISCNode::getSucc index out of range");221return _succs[index];222}223224inline TR_CISCNode *getChild(uint32_t index)225{226TR_ASSERT(index < _numChildren, "TR_CISCNode::getChild index out of range");227return _children[index];228}229230TR_CISCNode *getNodeIfSingleChain() { return _chains.isSingleton() ? _chains.getListHead()->getData() : 0; }231232inline uint16_t getChildID(uint32_t index) { return getChild(index)->_id; }233inline uint32_t getOpcode() { return _opcode; }234inline const TR::ILOpCode& getIlOpCode() { return _ilOpCode; }235inline TR::DataType getDataType() { return _dt; }236inline uint16_t getNumChildren() { return _numChildren; }237inline uint16_t getNumSuccs() { return _numSuccs; }238inline uint16_t getID() { return _id; }239inline uint16_t getDagID() { return _dagId; }240inline void setDagID(int16_t d) { _dagId = d; }241inline int32_t getOtherInfo() { return _otherInfo; }242void initChains() { _chains.init(); }243244// flags245bool isValidOtherInfo() { return _flags.testAny(_isValidOtherInfo); }246void setIsStoreDirect(bool v = true) { _flags.set(_isStoreDirect, v); }247bool isStoreDirect() { return _flags.testAny(_isStoreDirect); }248void setIsLoadVarDirect(bool v = true) { _flags.set(_isLoadVarDirect, v); }249bool isLoadVarDirect() { return _flags.testAny(_isLoadVarDirect); }250void setIsNegligible(bool v = true) { _flags.set(_isNegligible, v); }251bool isNegligible() { return _flags.testAny(_isNegligible); }252void setIsSuccSimplyConnected(bool v = true) { _flags.set(_isSuccSimplyConnected, v); }253bool isSuccSimplyConnected() { return _flags.testAny(_isSuccSimplyConnected); }254void setIsPredSimplyConnected(bool v = true) { _flags.set(_isPredSimplyConnected, v); }255bool isPredSimplyConnected() { return _flags.testAny(_isPredSimplyConnected); }256void setIsChildSimplyConnected(bool v = true) { _flags.set(_isChildSimplyConnected, v); }257bool isChildSimplyConnected() { return _flags.testAny(_isChildSimplyConnected); }258void setIsParentSimplyConnected(bool v = true) { _flags.set(_isParentSimplyConnected, v); }259bool isParentSimplyConnected() { return _flags.testAny(_isParentSimplyConnected); }260void setIsEssentialNode(bool v = true) { _flags.set(_isEssentialNode, v); }261bool isEssentialNode() { return _flags.testAny(_isEssentialNode); }262void setIsOptionalNode(bool v = true) { _flags.set(_isOptionalNode, v); }263bool isOptionalNode() { return _flags.testAny(_isOptionalNode); }264void setIsChildDirectlyConnected(bool v = true) { _flags.set(_isChildDirectlyConnected, v); }265bool isChildDirectlyConnected() { return _flags.testAny(_isChildDirectlyConnected); }266void setIsSuccDirectlyConnected(bool v = true) { _flags.set(_isSuccDirectlyConnected, v); }267bool isSuccDirectlyConnected() { return _flags.testAny(_isSuccDirectlyConnected); }268void setIsInterestingConstant(bool v = true) { _flags.set(_isInterestingConstant, v); }269bool isInterestingConstant() { return _flags.testAny(_isInterestingConstant); }270void setIsNecessaryScreening(bool v = true) { _flags.set(_isNecessaryScreening, v); }271bool isNecessaryScreening() { return _flags.testAny(_isNecessaryScreening); }272void setIsLightScreening(bool v = true) { _flags.set(_isLightScreening, v); }273bool isLightScreening() { return _flags.testAny(_isLightScreening); }274bool isDataConnected() { return _flags.testAll(_isChildSimplyConnected |275_isParentSimplyConnected); }276bool isCFGConnected() { return _flags.testAll(_isSuccSimplyConnected |277_isPredSimplyConnected); }278bool isCFGDataConected() { return _flags.testAll(_isSuccSimplyConnected |279_isPredSimplyConnected |280_isChildSimplyConnected |281_isParentSimplyConnected); }282void setOutsideOfLoop(bool v = true) { _flags.set(_isOutsideOfLoop, v); }283bool isOutsideOfLoop() { return _flags.testAny(_isOutsideOfLoop); }284void setCISCNodeModified(bool v = true) { _flags.set(_isCISCNodeModified, v); }285bool isCISCNodeModified() { return _flags.testAny(_isCISCNodeModified); }286void setNewCISCNode(bool v = true) { _flags.set(_isNewCISCNode, v); }287bool isNewCISCNode() { return _flags.testAny(_isNewCISCNode); }288void setSkipParentsCheck(bool v = true) { _flags.set(_isSkipParentsCheck, v); }289bool isSkipParentsCheck() { return _flags.testAny(_isSkipParentsCheck); }290291// short cut292bool isCommutative() { return _ilOpCode.isCommutative(); }293294TR_CISCNode *getLatestDest()295{296TR_ASSERT( _opcode == TR_variable, "TR_CISCNode::getLatestDest()");297return _latestDest;298}299//bool checkParents(TR_CISCNode *, const int8_t level);300static bool checkParentsNonRec(TR_CISCNode *, TR_CISCNode *, int8_t level, TR::Compilation *);301void reverseBranchOpCodes();302303static const char *getName(TR_CISCOps, TR::Compilation *);304void dump(TR::FILE *pOutFile, TR::Compilation *);305void printStdout();306307void addChain(TR_CISCNode *tgt, bool alsoAddChainsTgt = false)308{309_chains.add(tgt);310if (alsoAddChainsTgt) tgt->_chains.add(this);311}312313enum // flag bits314{315_isValidOtherInfo = 0x00000001,316_isStoreDirect = 0x00000002,317_isNegligible = 0x00000004,318_isSuccSimplyConnected = 0x00000008,319_isPredSimplyConnected = 0x00000010,320_isChildSimplyConnected = 0x00000020,321_isParentSimplyConnected = 0x00000040,322_isLoadVarDirect = 0x00000080,323_isEssentialNode = 0x00000100,324_isOptionalNode = 0x00000200,325_isChildDirectlyConnected = 0x00000400,326_isSuccDirectlyConnected = 0x00000800,327_isInterestingConstant = 0x00001000,328_isNecessaryScreening = 0x00002000,329_isLightScreening = 0x00004000,330_isOutsideOfLoop = 0x00008000,331_isCISCNodeModified = 0x00010000,332_isNewCISCNode = 0x00020000,333_isSkipParentsCheck = 0x00040000,334_dummyEnum335};336337338void initializeLists()339{340_preds.init();341_parents.init();342_dest.init();343_hintChildren.init();344_trNodeInfo.init();345initChains();346}347348virtual void allocArrays(uint16_t ncfgs, uint16_t nchildren)349{350_succs = (TR_CISCNode **)(ncfgs ? trMemory()->allocateMemory(ncfgs * sizeof(*_succs), _allocKind) : 0);351_children = (TR_CISCNode **)(nchildren ? trMemory()->allocateMemory(nchildren * sizeof(*_children), _allocKind) : 0);352}353354virtual void addPred(TR_CISCNode *t) { _preds.add(t); }355virtual void addParent(TR_CISCNode *t) { _parents.add(t); }356List<TR_CISCNode> *getPreds() { return &_preds; }357TR_CISCNode *getHeadOfPredecessors() { return _preds.getListHead()->getData(); }358List<TR_CISCNode> *getParents() { return &_parents; }359TR_CISCNode *getHeadOfParents() { return _parents.getListHead()->getData(); }360361void addTrNode(TR::Block *b, TR::TreeTop *t, TR::Node *n)362{363TrNodeInfo *newInfo = (TrNodeInfo *)trMemory()->allocateMemory(sizeof(*newInfo), _allocKind);364newInfo->_block = b;365newInfo->_treeTop = t;366newInfo->_node = n;367_trNodeInfo.add(newInfo);368}369List<TrNodeInfo> *getTrNodeInfo() { return &_trNodeInfo; }370inline TrNodeInfo *getHeadOfTrNodeInfo() { return _trNodeInfo.getListHead()->getData(); }371inline TR::Node *getHeadOfTrNode() { return _trNodeInfo.getListHead()->getData()->_node; }372inline TR::TreeTop *getHeadOfTreeTop() { return _trNodeInfo.getListHead()->getData()->_treeTop; }373inline TR::Block *getHeadOfBlock() { return _trNodeInfo.getListHead()->getData()->_block; }374375void setDest(TR_CISCNode *v)376{377TR_ASSERT(v != 0 && v->_opcode == TR_variable, "TR_CISCNode::setDest(), input error");378if (v->_latestDest)379{380TR_ASSERT(v->_latestDest->_dest.find(v), "TR_CISCNode::setDest(), input variable is not found in _latestDest");381v->_latestDest->_dest.remove(v);382}383ListAppender<TR_CISCNode> appender(&_dest);384appender.add(v);385v->_latestDest = this;386}387TR_CISCNode *getFirstDest()388{389return _dest.isEmpty() ? 0 : _dest.getListHead()->getData();390}391List<TR_CISCNode> *getHintChildren() { return &_hintChildren; }392void addHint(TR_CISCNode *n) { _hintChildren.add(n); }393bool isEmptyHint() { return _hintChildren.isEmpty(); }394List<TR_CISCNode> *getChains() {return &_chains; }395bool checkDagIdInChains();396TR::TreeTop *getDestination(bool isFallThrough = false);397void deadAllChildren();398TR_CISCNode *duplicate()399{400TR_CISCNode *ret = new (trHeapMemory()) TR_CISCNode(_trMemory, _opcode, _dt, _id, _dagId, _numSuccs, _numChildren);401ret->_otherInfo = _otherInfo;402ret->_flags = _flags;403404// duplicate _trNodeIndo405ListIterator<TrNodeInfo> li(&_trNodeInfo);406ListAppender<TrNodeInfo> appender(&ret->_trNodeInfo);407for (TrNodeInfo *t = li.getFirst(); t; t = li.getNext()) appender.add(t);408409// Duplicating other lists will be performed in the caller.410411return ret;412}413414// Variables415protected:416void setOpcode(uint32_t opc)417{418_opcode = opc;419_ilOpCode.setOpCodeValue(opc < TR::NumIlOps ? (TR::ILOpCodes)opc : TR::BadILOp);420}421uint32_t _opcode; // TR::ILOpCodes enum422TR::ILOpCode _ilOpCode;423TR::DataType _dt;424TR_CISCNode **_succs;425TR_CISCNode **_children;426TR_CISCNode *_latestDest;427int32_t _otherInfo;428uint16_t _numSuccs;429uint16_t _numChildren;430431uint16_t _id;432uint16_t _dagId;433flags32_t _flags;434435TR_AllocationKind _allocKind;436TR_Memory * _trMemory;437List<TR_CISCNode> _preds;438List<TR_CISCNode> _parents;439List<TR_CISCNode> _dest; // destination operands440List<TR_CISCNode> _chains;441List<TR_CISCNode> _hintChildren;442List<TrNodeInfo> _trNodeInfo;443};444445446// Use persistent allocation447class TR_PCISCNode : public TR_CISCNode448{449public:450TR_PCISCNode(TR_Memory * m, uint32_t opc, TR::DataType dt, uint16_t id, int16_t dagId, uint16_t ncfgs, uint16_t nchildren)451: TR_CISCNode(m, opc, dt, id, dagId, ncfgs, nchildren, persistentAlloc)452{453};454455TR_PCISCNode(TR_Memory * m, uint32_t opc, TR::DataType dt, uint16_t id, int16_t dagId, uint16_t ncfgs, uint16_t nchildren, TR_CISCNode *pred)456: TR_CISCNode(m, opc, dt, id, dagId, ncfgs, nchildren, pred, persistentAlloc)457{458}459460TR_PCISCNode(TR_Memory * m, uint32_t opc, TR::DataType dt, uint16_t id, int16_t dagId, uint16_t ncfgs, uint16_t nchildren, TR_CISCNode *pred, TR_CISCNode *child0)461: TR_CISCNode(m, opc, dt, id, dagId, ncfgs, nchildren, pred, child0, persistentAlloc)462{463}464465TR_PCISCNode(TR_Memory * m, uint32_t opc, TR::DataType dt, uint16_t id, int16_t dagId, uint16_t ncfgs, uint16_t nchildren, TR_CISCNode *pred, TR_CISCNode *child0, TR_CISCNode *child1)466: TR_CISCNode(m, opc, dt, id, dagId, ncfgs, nchildren, pred, child0, child1, persistentAlloc)467{468}469470TR_PCISCNode(TR_Memory * m, uint32_t opc, TR::DataType dt, uint16_t id, int16_t dagId, uint16_t ncfgs, uint16_t nchildren, int32_t otherInfo)471: TR_CISCNode(m, opc, dt, id, dagId, ncfgs, nchildren, otherInfo, persistentAlloc)472{473}474475TR_PCISCNode(TR_Memory * m, uint32_t opc, TR::DataType dt, uint16_t id, int16_t dagId, uint16_t ncfgs, uint16_t nchildren, int32_t otherInfo, TR_CISCNode *pred)476: TR_CISCNode(m, opc, dt, id, dagId, ncfgs, nchildren, otherInfo, pred, persistentAlloc)477{478}479480TR_PCISCNode *getSucc(uint32_t index)481{482return (TR_PCISCNode *) TR_CISCNode::getSucc(index);483}484485TR_PCISCNode *getChild(uint32_t index)486{487return (TR_PCISCNode *) TR_CISCNode::getChild(index);488}489490virtual void addPred(TR_CISCNode *t)491{492TR_PersistentList<TR_CISCNode> *p = (TR_PersistentList<TR_CISCNode> *)&_preds;493p->add(t);494}495virtual void addParent(TR_CISCNode *t)496{497TR_PersistentList<TR_CISCNode> *p = (TR_PersistentList<TR_CISCNode> *)&_parents;498p->add(t);499}500virtual void allocArrays(uint16_t ncfgs, uint16_t nchildren)501{502_succs = (TR_CISCNode **)(ncfgs ? jitPersistentAlloc(ncfgs * sizeof(*_succs)) : 0);503_children = (TR_CISCNode **)(nchildren ? jitPersistentAlloc(nchildren * sizeof(*_children)) : 0);504}505};506507508class TR_CISCHash509{510public:511TR_ALLOC(TR_Memory::LoopTransformer);512513TR_CISCHash(TR_Memory * m, uint32_t num = 0, TR_AllocationKind allocKind = heapAlloc)514:_trMemory(m)515{516if (num > 0)517setNumBuckets(num, allocKind);518else519{520_numBuckets = 0;521_buckets = 0;522_allocationKind = allocKind;523}524}525526TR_Memory * trMemory() { return _trMemory; }527528void setNumBuckets(uint32_t num, TR_AllocationKind allocKind)529{530_allocationKind = allocKind;531setNumBuckets(num);532}533534void setNumBuckets(uint32_t num)535{536TR_ASSERT(num > 0, "error: num == 0!");537_numBuckets = num;538uint32_t size = num * sizeof(*_buckets);539_buckets = (HashTableEntry **)trMemory()->allocateMemory(size, _allocationKind);540memset(_buckets, 0, size);541}542543struct HashTableEntry544{545HashTableEntry *_next;546uint64_t _key;547TR_CISCNode *_node;548};549550TR_CISCNode *find(uint64_t key);551bool add(uint64_t key, TR_CISCNode *, bool checkExist = false);552uint32_t getNumBuckets() { return _numBuckets; }553554private:555556uint32_t _numBuckets;557HashTableEntry **_buckets;558TR_Memory * _trMemory;559TR_AllocationKind _allocationKind;560};561562563enum TR_GraphAspects // flag bits564{565storeShiftCount = 12,566nbValue = (0xFF & ~ILTypeProp::Size_1),567existAccess = 0x00000100,568loadMasks = 0x000001FF,569storeMasks = 0x001FF000,570sameTypeLoadStore = 0x00200000,571572bitop1 = 0x00800000,573iadd = 0x01000000,574isub = 0x02000000,575call = 0x04000000,576shr = 0x08000000,577bndchk = 0x10000000,578reminder = 0x20000000,579division = 0x40000000,580mul = 0x80000000581};582583class TR_CISCGraphAspects : public flags32_t584{585public:586587TR_CISCGraphAspects() {init();}588void init() {clear();}589void setLoadAspects(uint32_t val, bool orExistAccess = true); // assuming val as a combination of ILTypeProp::*590void setStoreAspects(uint32_t val, bool orExistAccess = true); // assuming val as a combination of ILTypeProp::*591void modifyAspects();592uint32_t getLoadAspects() { return getValue(loadMasks); }593uint32_t getStoreAspects() { return getValue(storeMasks) >> storeShiftCount; }594virtual void print(TR::Compilation *, bool noaspects);595};596597598class TR_CISCGraphAspectsWithCounts : public TR_CISCGraphAspects599{600public:601602TR_CISCGraphAspectsWithCounts() {init();}603void init() {TR_CISCGraphAspects::init(); setMinCounts(0,0,0);}604void setAspectsByOpcode(int opc);605void setAspectsByOpcode(TR_CISCNode *n) { setAspectsByOpcode(n->getOpcode()); }606void print(TR::Compilation *, bool noaspects);607608void setMinCounts(uint8_t ifCount, uint8_t iloadCount, uint8_t istoreCount)609{ _ifCount = ifCount; _indirectLoadCount = iloadCount; _indirectStoreCount = istoreCount; }610uint8_t incIfCount() { return ++_ifCount; }611uint8_t incIndirectLoadCount() { return ++_indirectLoadCount; }612uint8_t incIndirectStoreCount() { return ++_indirectStoreCount; }613uint8_t getIfCount() { return _ifCount; }614uint8_t getIndirectLoadCount() { return _indirectLoadCount; }615uint8_t getIndirectStoreCount() { return _indirectStoreCount; }616bool meetMinCounts(TR_CISCGraphAspectsWithCounts *p) // p is for the pattern617{618return (_ifCount >= p->_ifCount &&619_indirectLoadCount >= p->_indirectLoadCount &&620_indirectStoreCount >= p->_indirectStoreCount);621}622623protected:624uint8_t _ifCount;625uint8_t _indirectLoadCount;626uint8_t _indirectStoreCount;627};628629630631template <class T> class TR_ListDuplicator632{633public:634TR_ALLOC(TR_Memory::LoopTransformer);635TR_HeapMemory trHeapMemory() { return _trMemory; }636637TR_ListDuplicator<T>(TR_Memory * m)638: _trMemory(m), _list(0)639{640_flags.clear();641}642643virtual void setList(List<T>* l) { setRegistered(); setDuplicated(false); _list = l; }644List<T>* getList() { TR_ASSERT(isRegistered(), "error"); return _list; }645virtual List<T>* duplicateList(bool ifNecessary = true)646{647if (ifNecessary && isDuplicated()) return _list;648setDuplicated();649List<T>* ret = new (trHeapMemory()) List<T>(_trMemory);650ListAppender<T> appender(ret);651ListIterator<T> li(_list);652T *t;653for (t = li.getFirst(); t; t = li.getNext()) appender.add(t);654_list = ret;655return ret;656}657658enum // flag bits659{660_isRegistered = 0x0001,661_isDuplicated = 0x0002,662_isDuplicateElement = 0x0004,663_dummyEnum664};665666void setRegistered(bool v = true) { _flags.set(_isRegistered, v); }667bool isRegistered() { return _flags.testAny(_isRegistered); }668void setDuplicated(bool v = true) { _flags.set(_isDuplicated, v); }669bool isDuplicated() { return _flags.testAny(_isDuplicated); }670void setDuplicateElement(bool v = true) { _flags.set(_isDuplicateElement, v); }671bool isDuplicateElement() { return _flags.testAny(_isDuplicateElement); }672673protected:674List<T> *_list;675flags8_t _flags;676TR_Memory * _trMemory;677};678679680class ListOfCISCNodeDuplicator : public TR_ListDuplicator<TR_CISCNode>681{682public:683ListOfCISCNodeDuplicator(TR_Memory * m) : TR_ListDuplicator<TR_CISCNode>(m), _mapping(m) {};684virtual void setList(List<TR_CISCNode>* l)685{686TR_ListDuplicator<TR_CISCNode>::setList(l);687_mapping.init();688}689virtual List<TR_CISCNode> *duplicateList(bool ifNecessary = true)690{691if (ifNecessary && isDuplicated()) return _list;692setDuplicated();693List<TR_CISCNode>* ret = new (trHeapMemory()) List<TR_CISCNode>(_trMemory);694ListAppender<TR_CISCNode> appender(ret);695ListIterator<TR_CISCNode> li(_list);696TR_CISCNode *t;697_list = ret;698if (isDuplicateElement())699{700TR_CISCNode *newCISC;701for (t = li.getFirst(); t; t = li.getNext())702{703newCISC = t->duplicate();704appender.add(newCISC);705TR_Pair<TR_CISCNode,TR_CISCNode> *pair = new (trHeapMemory()) TR_Pair<TR_CISCNode,TR_CISCNode>(t, newCISC);706_mapping.add(pair);707}708ListIterator<TR_CISCNode> liNew(ret);709for (t = li.getFirst(), newCISC = liNew.getFirst(); t; t = li.getNext(), newCISC = liNew.getNext())710{711int32_t i;712for (i = 0; i < t->getNumChildren(); i++)713newCISC->setChild(i, findCorrespondingNode(t->getChild(i)));714for (i = 0; i < t->getNumSuccs(); i++)715newCISC->setSucc(i, findCorrespondingNode(t->getSucc(i)));716restructureList(t->getChains(), newCISC->getChains());717restructureList(t->getHintChildren(), newCISC->getHintChildren());718}719}720else721{722for (t = li.getFirst(); t; t = li.getNext()) { appender.add(t); }723}724return ret;725}726727TR_CISCNode *findCorrespondingNode(TR_CISCNode *old)728{729TR_Pair<TR_CISCNode,TR_CISCNode> *pair;730ListElement<TR_Pair<TR_CISCNode,TR_CISCNode> > *le;731// Search for old732for (le = _mapping.getListHead(); le; le = le->getNextElement())733{734pair = le->getData();735if (pair->getKey() == old) return pair->getValue();736}737TR_ASSERT(false, "error");738return NULL;739}740741void restructureList(List<TR_CISCNode> *oldList, List<TR_CISCNode> *newList)742{743TR_ASSERT(newList->isEmpty(), "error");744ListAppender<TR_CISCNode> appender(newList);745ListIterator<TR_CISCNode> li(oldList);746TR_CISCNode *t;747for (t = li.getFirst(); t; t = li.getNext()) appender.add(findCorrespondingNode(t));748}749750protected:751List<TR_Pair<TR_CISCNode,TR_CISCNode> > _mapping;752};753754755756#define MAX_IMPORTANT_NODES 8757#define MAX_SPECIALCARE_NODES 4758typedef bool (* TransformerPtr)(TR_CISCTransformer *);759typedef bool (* SpecialNodeTransformerPtr)(TR_CISCTransformer *);760class TR_CISCGraph761{762public:763TR_ALLOC(TR_Memory::LoopTransformer);764765static void setEssentialNodes(TR_CISCGraph*);766static void makePreparedCISCGraphs(TR::Compilation *c);767static void initializeGraphs(TR::Compilation *c);768769TR_CISCGraph(TR_Memory * m, const char *title = 0, int32_t numHashTrNode = 31, int32_t numHashOpc = 17)770: _titleOfCISC(title), _entryNode(0), _exitNode(0), _numNodes(0), _numDagIds(0),771_dagId2Nodes(0), _transformer(0), _specialNodeTransformer(0), _hotness(noOpt),772_javaSource(0), _versionLength(0), _trMemory(m),773_trNode2CISCNode(m), _opc2CISCNode(m), _nodes(m), _orderByData(m),774_duplicatorNodes(m), _patternType(-1)775{776initializeLists();777_flags.clear();778_aspects.init();779if (numHashTrNode > 0) _trNode2CISCNode.setNumBuckets(numHashTrNode);780if (numHashOpc > 0) _opc2CISCNode.setNumBuckets(numHashOpc);781int32_t i;782for (i = MAX_IMPORTANT_NODES; --i >= 0; ) _importantNode[i] = 0;783for (i = MAX_SPECIALCARE_NODES; --i >= 0; ) _specialCareNode[i] = 0;784}785786TR_CISCNode *getCISCNode(TR::Node *n) { return _trNode2CISCNode.find(getHashKeyTrNode(n)); }787TR_CISCNode *getCISCNode(uint32_t opc, bool validOther, int32_t other)788{789return _opc2CISCNode.find(getHashKeyOpcs(opc, validOther, other));790}791792void setEntryNode(TR_CISCNode *n) {_entryNode = n;}793TR_CISCNode *getEntryNode() {return _entryNode;}794795void setExitNode(TR_CISCNode *n) {_exitNode = n;}796TR_CISCNode *getExitNode() {return _exitNode;}797798void setImportantNode(uint32_t idx, TR_CISCNode *n)799{800TR_ASSERT(idx < MAX_IMPORTANT_NODES, "TR_CISCGraph::setImportantNode index out of range");801_importantNode[idx] = n;802}803void setImportantNodes(TR_CISCNode *n1, TR_CISCNode *n2)804{805setImportantNode(0, n1);806setImportantNode(1, n2);807}808void setImportantNodes(TR_CISCNode *n1, TR_CISCNode *n2, TR_CISCNode *n3)809{810setImportantNode(0, n1);811setImportantNode(1, n2);812setImportantNode(2, n3);813}814void setImportantNodes(TR_CISCNode *n1, TR_CISCNode *n2, TR_CISCNode *n3, TR_CISCNode *n4)815{816setImportantNode(0, n1);817setImportantNode(1, n2);818setImportantNode(2, n3);819setImportantNode(3, n4);820}821void setImportantNodes(TR_CISCNode *n1, TR_CISCNode *n2, TR_CISCNode *n3, TR_CISCNode *n4, TR_CISCNode *n5)822{823setImportantNode(0, n1);824setImportantNode(1, n2);825setImportantNode(2, n3);826setImportantNode(3, n4);827setImportantNode(4, n5);828}829void setImportantNodes(TR_CISCNode *n1, TR_CISCNode *n2, TR_CISCNode *n3, TR_CISCNode *n4, TR_CISCNode *n5, TR_CISCNode *n6)830{831setImportantNode(0, n1);832setImportantNode(1, n2);833setImportantNode(2, n3);834setImportantNode(3, n4);835setImportantNode(4, n5);836setImportantNode(5, n6);837}838void setImportantNodes(TR_CISCNode *n1, TR_CISCNode *n2, TR_CISCNode *n3, TR_CISCNode *n4, TR_CISCNode *n5, TR_CISCNode *n6, TR_CISCNode *n7)839{840setImportantNode(0, n1);841setImportantNode(1, n2);842setImportantNode(2, n3);843setImportantNode(3, n4);844setImportantNode(4, n5);845setImportantNode(5, n6);846setImportantNode(6, n7);847}848void setImportantNodes(TR_CISCNode *n1, TR_CISCNode *n2, TR_CISCNode *n3, TR_CISCNode *n4, TR_CISCNode *n5, TR_CISCNode *n6, TR_CISCNode *n7, TR_CISCNode *n8)849{850setImportantNode(0, n1);851setImportantNode(1, n2);852setImportantNode(2, n3);853setImportantNode(3, n4);854setImportantNode(4, n5);855setImportantNode(5, n6);856setImportantNode(6, n7);857setImportantNode(7, n8);858}859TR_CISCNode *getImportantNode(uint32_t idx)860{861TR_ASSERT(idx < MAX_IMPORTANT_NODES, "TR_CISCGraph::getImportantNode index out of range");862return _importantNode[idx];863}864865void setSpecialCareNode(uint32_t idx, TR_CISCNode *n)866{867TR_ASSERT(idx < MAX_SPECIALCARE_NODES, "TR_CISCGraph::setSpecialCareNode index out of range");868_specialCareNode[idx] = n;869}870TR_CISCNode *getSpecialCareNode(uint32_t idx)871{872TR_ASSERT(idx < MAX_SPECIALCARE_NODES, "TR_CISCGraph::getSpecialCareNode index out of range");873return _specialCareNode[idx];874}875876TR_Memory * trMemory() { return _trMemory; }877878uint16_t getNumNodes() {return _numNodes;}879uint16_t incNumNodes() {return _numNodes++;}880881uint16_t getNumDagIds() {return _numDagIds;}882void setNumDagIds(uint16_t n) {_numDagIds = n;}883884TR_CISCNode *getHeadOfNodes()885{886return _nodes.isEmpty() ? 0 : _nodes.getListHead()->getData();887}888void addTrNode(TR_CISCNode *n, TR::Block *block, TR::TreeTop *top, TR::Node *trNode);889virtual void addNode(TR_CISCNode *n, TR::Block *block = 0, TR::TreeTop *top = 0, TR::Node *trNode = 0);890891void createInternalData(int32_t loopBodyDagId)892{893createDagId2NodesTable();894createOrderByData();895setOutsideOfLoopFlag(loopBodyDagId);896}897898bool isDagIdCycle(uint16_t dagId) { TR_ASSERT(dagId < _numDagIds, "error"); return getDagId2Nodes()[dagId].isMultipleEntry(); }899bool isDagIdDag(uint16_t dagId) { TR_ASSERT(dagId < _numDagIds, "error"); return getDagId2Nodes()[dagId].isSingleton(); }900void dump(TR::FILE *pOutFile, TR::Compilation *);901902void importUDchains(TR::Compilation *comp, TR_UseDefInfo *useDefInfo, bool reinitialize = false);903904void setTransformer(TransformerPtr t) { _transformer = t; }905TransformerPtr getTransformer() { return _transformer; }906bool isPatternGraph() { return _transformer != 0; }907908void setSpecialNodeTransformer(SpecialNodeTransformerPtr t) { _specialNodeTransformer = t; }909SpecialNodeTransformerPtr getSpecialNodeTransformer() { return _specialNodeTransformer; }910911// flags912bool isSetUDDUchains() { return _flags.testAny(_isSetUDDUchains); }913void setIsSetUDDUchains(bool v = true) { _flags.set(_isSetUDDUchains, v); }914bool isInhibitAfterVersioning() { TR_ASSERT(isPatternGraph(), "error"); return _flags.testAny(_inhibitAfterVersioning); }915void setInhibitAfterVersioning(bool v = true) { TR_ASSERT(isPatternGraph(), "error"); _flags.set(_inhibitAfterVersioning, v); }916bool isInhibitBeforeVersioning() { TR_ASSERT(isPatternGraph(), "error"); return _flags.testAny(_inhibitBeforeVersioning); }917void setInhibitBeforeVersioning(bool v = true) { TR_ASSERT(isPatternGraph(), "error"); _flags.set(_inhibitBeforeVersioning, v); }918bool isInsideOfFastVersioned() { TR_ASSERT(!isPatternGraph(), "error"); return _flags.testAny(_insideOfFastVersioned); }919void setInsideOfFastVersioned(bool v = true) { TR_ASSERT(!isPatternGraph(), "error"); _flags.set(_insideOfFastVersioned, v); }920bool isRequireAHconst() { TR_ASSERT(isPatternGraph(), "error"); return _flags.testAny(_requireAHconst); }921void setRequireAHconst(bool v = true) { TR_ASSERT(isPatternGraph(), "error"); _flags.set(_requireAHconst, v); }922bool isHighFrequency() { return _flags.testAny(_highFrequency); }923void setHighFrequency(bool v = true) { _flags.set(_highFrequency, v); }924bool isNoFragmentDagId() { return _flags.testAny(_noFragmentDagId); }925void setNoFragmentDagId(bool v = true) { _flags.set(_noFragmentDagId, v); }926bool isRecordingAspectsByOpcode() { return _flags.testAny(_recordingAspectsByOpcode); }927void setRecordingAspectsByOpcode(bool v = true) { _flags.set(_recordingAspectsByOpcode, v); }928929bool needsInductionVariableInit() { return _flags.testAny(_needsInductionVariableInit); }930void setNeedsInductionVariableInit(bool v = false) { _flags.set(_needsInductionVariableInit, v); }931932enum // flag bits933{934_isSetUDDUchains = 0x0001,935_inhibitAfterVersioning = 0x0002, // for compilation time reduction936_inhibitBeforeVersioning = 0x0004, // for compilation time reduction937_insideOfFastVersioned = _inhibitAfterVersioning,938_highFrequency = 0x0008,939_noFragmentDagId = 0x0010,940_recordingAspectsByOpcode = 0x0020,941_requireAHconst = 0x0040,942_needsInductionVariableInit = 0x0080,943_dummyEnum944};945946void initializeLists()947{948_nodes.init();949_orderByData.init();950}951952List<TR_CISCNode> *getNodes() { return &_nodes; }953List<TR_CISCNode> *getDagId2Nodes() { return _dagId2Nodes; }954List<TR_CISCNode> *getOrderByData() { return &_orderByData; }955ListOfCISCNodeDuplicator *getDuplicatorNodes() { return &_duplicatorNodes; }956virtual void createDagId2NodesTable();957virtual void createOrderByData();958const char *getTitle() { return _titleOfCISC; }959void setMemAspects(uint32_t load, uint32_t store)960{961_aspects.setLoadAspects(load);962_aspects.setStoreAspects(store);963}964void setAspects(uint32_t val) { _aspects.set(val); }965void setAspects(uint32_t val, uint32_t load, uint32_t store)966{967setAspects(val);968setMemAspects(load, store);969}970uint32_t getAspectsValue() { return _aspects.getValue(); }971bool testAllAspects(TR_CISCGraph *P) { return _aspects.testAll(P->getAspectsValue()); }972void modifyTargetGraphAspects() { _aspects.modifyAspects(); }973974void setNoMemAspects(uint32_t load, uint32_t store)975{976_noaspects.setLoadAspects(load, false);977_noaspects.setStoreAspects(store, false);978}979void setNoAspects(uint32_t val) { _noaspects.set(val); }980void setNoAspects(uint32_t val, uint32_t load, uint32_t store)981{982setNoAspects(val);983setNoMemAspects(load, store);984}985uint32_t getNoAspectsValue() { return _noaspects.getValue(); }986bool testAnyNoAspects(TR_CISCGraph *P) { return _aspects.testAny(P->getNoAspectsValue()); }987988TR_Hotness getHotness() { return _hotness; }989void setHotness(TR_Hotness hotness) { _hotness = hotness; }990void setHotness(TR_Hotness hotness, bool highFreq) { setHotness(hotness); setHighFrequency(highFreq); }991int32_t defragDagId();992void setJavaSource(char *s) { _javaSource = s; }993char *getJavaSource() { return _javaSource; }994TR_CISCGraphAspectsWithCounts * getAspects() { return &_aspects; }995void setMinCounts(uint8_t ifCount, uint8_t iloadCount, uint8_t istoreCount) { _aspects.setMinCounts(ifCount,iloadCount,istoreCount);}996bool meetMinCounts(TR_CISCGraph *p) { return _aspects.meetMinCounts(&p->_aspects); }997uint16_t getVersionLength() { return _versionLength; }998void setVersionLength(uint16_t len) { _versionLength = len; }999void setListsDuplicator()1000{1001_duplicatorNodes.setList(&_nodes);1002_duplicatorNodes.setDuplicateElement();1003}1004void duplicateListsDuplicator()1005{1006_duplicatorNodes.duplicateList();1007}1008void restoreListsDuplicator()1009{1010_nodes.setListHead(_duplicatorNodes.getList()->getListHead());1011if (_duplicatorNodes.isDuplicated())1012{1013createOrderByData();1014createDagId2NodesTable();1015_entryNode = _duplicatorNodes.findCorrespondingNode(_entryNode);1016_exitNode = _duplicatorNodes.findCorrespondingNode(_exitNode);1017}1018}1019TR_CISCNode *searchStore(TR_CISCNode *target, TR_CISCNode *to);10201021int32_t getPatternType() { return _patternType; }1022void setPatternType(int32_t v) { _patternType = v; }10231024protected:1025uint64_t getHashKeyTrNode(TR::Node *n) { return ((uintptr_t)n) >> 2; }1026uint64_t getHashKeyOpcs(uint32_t opc, bool validOtherInfo, uint32_t otherInfo)1027{1028return (((uint64_t)(opc << 1) | (uint64_t)(validOtherInfo ? 1 : 0)) << 32) ^ (uint64_t)otherInfo;1029}1030bool addTrNode2CISCNode(TR::Node *n, TR_CISCNode *c)1031{1032return _trNode2CISCNode.add(getHashKeyTrNode(n), c, true);1033}1034void addOpc2CISCNode(TR_CISCNode *c);1035bool addOpc2CISCNode(uint32_t opc, bool valid, int32_t other, TR_CISCNode *c)1036{1037return _opc2CISCNode.add(getHashKeyOpcs(opc, valid, other), c, true);1038}1039void setOutsideOfLoopFlag(uint16_t loopBodyDagId);1040const char *_titleOfCISC; // title for debug message10411042TR_Memory * _trMemory;1043TransformerPtr _transformer;1044SpecialNodeTransformerPtr _specialNodeTransformer;1045TR_CISCNode *_entryNode;1046TR_CISCNode *_exitNode;1047TR_CISCNode *_importantNode[MAX_IMPORTANT_NODES];1048TR_CISCNode *_specialCareNode[MAX_SPECIALCARE_NODES];1049TR_CISCHash _trNode2CISCNode;1050TR_CISCHash _opc2CISCNode;1051TR_CISCGraphAspectsWithCounts _aspects;1052TR_CISCGraphAspects _noaspects;1053TR_Hotness _hotness;1054uint16_t _numNodes;1055uint16_t _numDagIds;1056flags16_t _flags;1057uint16_t _versionLength;10581059List<TR_CISCNode> _nodes;1060List<TR_CISCNode> *_dagId2Nodes;1061List<TR_CISCNode> _orderByData;1062ListOfCISCNodeDuplicator _duplicatorNodes;1063char *_javaSource; // corresponding Java code to assist programmers1064int32_t _patternType;1065};106610671068class TR_PCISCGraph : public TR_CISCGraph1069{1070public:1071TR_PCISCGraph(TR_Memory * m, const char *title = 0, int32_t numHashTrNode = 31, int32_t numHashOpc = 17)1072: TR_CISCGraph(m, title, 0, 0)1073{1074if (numHashTrNode > 0) _trNode2CISCNode.setNumBuckets(numHashTrNode, persistentAlloc);1075if (numHashOpc > 0) _opc2CISCNode.setNumBuckets(numHashOpc, persistentAlloc);1076};1077virtual void createDagId2NodesTable();1078virtual void createOrderByData();1079virtual void addNode(TR_CISCNode *n, TR::Block *block = 0, TR::TreeTop *top = 0, TR::Node *trNode = 0);1080};108110821083/*********** FOR OPTIMIZATION ************/1084class TR_CISCNodeRegion : public ListHeadAndTail<TR_CISCNode>1085{1086private:1087flags16_t _flags;1088TR_BitVector _bv;1089int32_t _bvnum;10901091public:10921093TR_ALLOC(TR_Memory::LLList)10941095TR_CISCNodeRegion(int32_t bvnum, TR::Region ®ion) : ListHeadAndTail<TR_CISCNode>(region) { init(bvnum, region); }1096//void init() {ListHeadAndTail<TR_CISCNode>::init(); _flags.clear();}10971098void init(int32_t bvnum, TR::Region ®ion)1099{ListHeadAndTail<TR_CISCNode>::init(); _flags.clear(); _bvnum = bvnum; _bv.init(bvnum, region);}1100// flags1101bool isIncludeEssentialNode() { return _flags.testAny(_isIncludeEssentialNode); }1102void setIncludeEssentialNode(bool v = true) { _flags.set(_isIncludeEssentialNode, v); }1103bool isOptionalNode() { return _flags.testAny(_isOptionalNode); }1104void setIsOptionalNode(bool v = true) { _flags.set(_isOptionalNode, v); }11051106enum // flag bits1107{1108_isIncludeEssentialNode = 0x0001,1109_isOptionalNode = 0x0002,1110_dummyEnum1111};11121113bool isIncluded(int32_t id) { return _bv.isSet(id); }1114bool isIncluded(TR_CISCNode *n) { return _bv.isSet(n->getID()); }11151116ListElement<TR_CISCNode> *add(TR_CISCNode *p)1117{1118if (p->isEssentialNode()) setIncludeEssentialNode();1119if (p->isOptionalNode()) setIsOptionalNode();1120_bv.set(p->getID());1121return ListHeadAndTail<TR_CISCNode>::add(p);1122}11231124ListElement<TR_CISCNode> *append(TR_CISCNode *p)1125{1126if (p->isEssentialNode()) setIncludeEssentialNode();1127if (p->isOptionalNode()) setIsOptionalNode();1128_bv.set(p->getID());1129return ListHeadAndTail<TR_CISCNode>::append(p);1130}11311132TR_CISCNodeRegion *clone();1133};113411351136class TR_CFGReversePostOrder1137{1138public:1139TR_ALLOC(TR_Memory::LoopTransformer);11401141TR_CFGReversePostOrder(TR_Memory * m) : _revPost(m) { }11421143List<TR::CFGNode> *compute( TR::CFG *cfg);1144void createReversePostOrder(TR::CFG *cfg, TR::CFGNode *n);1145void dump(TR::Compilation * comp);1146//void initReversePostOrder();1147//void initReversePostOrder(TR::CFG *cfg);1148//void createReversePostOrderRec(TR::CFGNode *n);11491150protected:1151struct TR_StackForRevPost : public TR_Link<TR_StackForRevPost>1152{1153TR::CFGNode *n;1154// ListElement<TR::CFGEdge> *le;1155TR::CFGEdgeList::iterator le;1156};11571158ListHeadAndTail<TR::CFGNode> _revPost;1159// TR::CFG *_cfg;1160//TR_BitVector _visited;1161};116211631164class TR_CISCCandidate1165{1166public:1167TR_ALLOC(TR_Memory::LoopTransformer);11681169TR_CISCCandidate(TR_Memory * m) : _listIdioms(m) { init(); }1170void init()1171{1172_minBCIndex = 0x7fffffff;1173_maxBCIndex = -_minBCIndex;1174_minLineNumber = 0x7fffffff;1175_maxLineNumber = -_minBCIndex;1176_listIdioms.init();1177}1178void add(TR_CISCGraph *idiom, int32_t minBC, int32_t maxBC, int32_t minLN, int32_t maxLN)1179{1180_listIdioms.add(idiom);1181if (_minBCIndex > minBC) _minBCIndex = minBC;1182if (_maxBCIndex < maxBC) _maxBCIndex = maxBC;1183if (_minLineNumber > minLN) _minLineNumber = minLN;1184if (_maxLineNumber < maxLN) _maxLineNumber = maxLN;1185}1186int32_t getMinBCIndex() { return _minBCIndex; }1187int32_t getMaxBCIndex() { return _maxBCIndex; }1188int32_t getMinLineNumber() { return _minLineNumber; }1189int32_t getMaxLineNumber() { return _maxLineNumber; }1190List<TR_CISCGraph> *getListIdioms() { return &_listIdioms; }11911192protected:1193int32_t _minBCIndex;1194int32_t _maxBCIndex;1195int32_t _minLineNumber;1196int32_t _maxLineNumber;1197List<TR_CISCGraph> _listIdioms;1198};119912001201class TR_NodeDuplicator1202{1203public:1204TR_ALLOC(TR_Memory::LoopTransformer);12051206TR_NodeDuplicator(TR::Compilation * comp) : _list(comp->trMemory()), _comp(comp) { init(); }12071208TR::Compilation * comp() { return _comp; }12091210TR_HeapMemory trHeapMemory() { return _comp->trMemory(); }12111212void init() { _list.init(); }1213TR::Node *duplicateTree(TR::Node *org);12141215protected:1216TR::Node *restructureTree(TR::Node *oldTree, TR::Node *newTree);1217List<TR_Pair<TR::Node,TR::Node> > _list;12181219private:1220TR::Compilation * _comp;1221};122212231224class TR_UseTreeTopMap1225{1226public:1227TR_ALLOC(TR_Memory::LoopTransformer);12281229TR_UseTreeTopMap(TR::Compilation * comp, TR::Optimizer * optimizer);1230TR_HashTabInt _useToParentMap; // lists of owning treetops indexed by use index1231int32_t buildAllMap();1232void buildUseTreeTopMap(TR::TreeTop* treeTop,TR::Node *node);1233TR::TreeTop * findParentTreeTop(TR::Node *useNode);1234TR::Compilation *comp() { return _compilation; }12351236protected:1237bool _buildAllMap;1238TR::Compilation *_compilation;1239TR::Optimizer *_optimizer;1240TR_UseDefInfo *_info;1241};124212431244typedef enum1245{1246_T2P_NULL = 0,1247_T2P_NotMatch = 1,1248_T2P_MatchMask = 2,1249_T2P_Single = 4,1250_T2P_Multiple = 8,1251_T2P_MatchAndSingle = _T2P_MatchMask | _T2P_Single, // Match and T2P is single1252_T2P_MatchAndMultiple = _T2P_MatchMask | _T2P_Multiple, // Match and T2P is multiple1253} CISCT2PCond;12541255class TR_CISCTransformer : public TR_LoopTransformer1256{1257public:1258static void showCISCNodeRegion(TR_CISCNodeRegion *region, TR::Compilation * );1259static void showCISCNodeRegions(List<TR_CISCNodeRegion> *regions, TR::Compilation * );1260static TR::Block *getSuccBlockIfSingle(TR::Block *block);1261static bool searchNodeInTrees(TR::Node *top, TR::Node *target, TR::Node **retParent = NULL, int *retChildNum = NULL);1262static bool compareTrNodeTree(TR::Node *a, TR::Node *b);1263static bool compareBlockTrNodeTree(TR::Block *a, TR::Block *b);1264bool getBCIndexMinMax(List<TR_CISCNode> *l, int32_t *minIndex, int32_t *maxIndex, int32_t *_minLN, int32_t *_maxLN, bool allowInlined);12651266TR_CISCTransformer(TR::OptimizationManager *manager);1267static TR::Optimization *create(TR::OptimizationManager *manager)1268{1269return new (manager->allocator()) TR_CISCTransformer(manager);1270}12711272void easyTreeSimplification(TR::Node *const node);1273TR_CISCNode *addAllSubNodes(TR_CISCGraph *const graph, TR::Block *const block, TR::TreeTop *const top, TR::Node *const parent, TR::Node *const node, const int32_t dagId);1274bool makeCISCGraphForBlock(TR_CISCGraph *graph, TR::Block *const block, int32_t dagId);1275void resolveBranchTargets(TR_CISCGraph *graph, TR_CISCNode *);1276uint16_t renumberDagId(TR_CISCGraph *graph, int32_t tempMaxDagId, int32_t bodyDagId);1277TR_CISCGraph *makeCISCGraph(List<TR::Block> *pred, List<TR::Block> *body, List<TR::Block> *succ);12781279struct TR_BitsKeepAliveInfo1280{1281TR_ALLOC(TR_Memory::LoopTransformer);12821283TR_BitsKeepAliveInfo(TR::Block * block, TR::TreeTop *treeTop, TR::TreeTop *prevTreeTop):1284_block(block), _treeTop(treeTop), _prevTreeTop(prevTreeTop)1285{}12861287TR::Block *_block;1288TR::TreeTop *_treeTop;1289TR::TreeTop *_prevTreeTop;1290};12911292bool removeBitsKeepAliveCalls(List<TR::Block> *body);1293void insertBitsKeepAliveCalls(TR::Block * block);1294void restoreBitsKeepAliveCalls();12951296virtual int32_t perform();1297virtual const char * optDetailString() const throw();12981299bool createLoopCandidates(List<TR_RegionStructure> *ret);1300TR::Block * findPredecessorBlockOfLoopEntry(TR_RegionStructure *loop);1301TR::Block *addPreHeaderIfNeeded(TR_RegionStructure *loop);13021303bool computeTopologicalEmbedding(TR_CISCGraph *P, TR_CISCGraph *T);1304bool embeddingHasConflictingBranches();1305void showEmbeddedData(char *title, uint8_t *data);1306bool computeEmbeddedForData();1307bool computeEmbeddedForCFG();1308bool dagEmbed(TR_CISCNode *, TR_CISCNode*);1309bool cycleEmbed(uint16_t, uint16_t);1310bool checkParents(TR_CISCNode *p, TR_CISCNode *t, uint8_t *result, bool *inLoop, bool *optionalParents);1311bool makeLists();1312int32_t analyzeConnectionOnePairChild(TR_CISCNode *const p, TR_CISCNode *const t, TR_CISCNode *const pn, TR_CISCNode *tn);1313void analyzeConnectionOnePair(TR_CISCNode *const p, TR_CISCNode *const t);1314void analyzeConnection();1315void analyzeArrayHeaderConst();1316void showT2P();1317TR_CISCNodeRegion* extractMatchingRegion();1318bool findFirstNode(TR::TreeTop **retTree, TR::Node **retNode, TR::Block **retBlock);1319int countP2T(TR_CISCNode *p, bool inLoop = false);1320TR_CISCNode *getP2TRep(TR_CISCNode *p);1321TR_CISCNode *getP2TRepInLoop(TR_CISCNode *p, TR_CISCNode *exclude = NULL);1322TR_CISCNode *getP2TInLoopIfSingle(TR_CISCNode *p);1323TR_CISCNode *getP2TInLoopAllowOptionalIfSingle(TR_CISCNode *p);1324bool verifyCandidate();1325void addEdge(TR::CFGEdgeList *succList, TR::Block *, TR::Block *);1326void removeEdge(List<TR::CFGEdge> *succList, TR::Block *, TR::Block *);1327void removeEdgesExceptFor(TR::CFGEdgeList *succList, TR::Block *, TR::Block *);1328void setEdge(TR::CFGEdgeList *succList, TR::Block *, TR::Block *);1329TR::Block *analyzeSuccessorBlock(TR::Node *ignoreTree = 0);1330void setSuccessorEdge(TR::Block *block, TR::Block *target = 0);1331void setEdges(TR::CFGEdgeList *succList, TR::Block *, TR::Block *, TR::Block *);1332TR::Block *searchOtherBlockInSuccBlocks(TR::Block *target0, TR::Block *target1);1333TR::Block *searchOtherBlockInSuccBlocks(TR::Block *target0);1334TR::Block *setSuccessorEdges(TR::Block *block, TR::Block *target, TR::Block *);1335TR::TreeTop *removeAllNodes(TR::TreeTop *start, TR::TreeTop *end);1336void initTopologicalEmbedding()1337{1338_beforeInsertions.init();1339_afterInsertions.init();1340_afterInsertionsIdiom[0].init();1341_afterInsertionsIdiom[1].init();1342_offsetOperand1 = 0;1343_offsetOperand2 = 0;1344}1345TR::Block *insertBeforeNodes(TR::Block *block);1346TR::Block *insertAfterNodes(TR::Block *block, List<TR::Node> *l, bool prepend = false);1347TR::Block *insertAfterNodes(TR::Block *block, bool prepend = false);1348TR::Block *insertAfterNodesIdiom(TR::Block *block, int32_t pos, bool prepend = false);1349TR::Node *findStoreToSymRefInInsertBeforeNodes(int32_t symRefNumberToBeMatched);1350bool areAllNodesIncluded(TR_CISCNodeRegion *r);13511352inline uint32_t idx(uint32_t a, uint32_t x) { return (a * _numTNodes) + x; }13531354TR_CISCGraph *getP() { return _P; }1355TR_CISCGraph *getT() { return _T; }1356List<TR_CISCNode> *getP2T() { return _P2T; }1357List<TR_CISCNode> *getT2P() { return _T2P; }1358TR_CISCNode *getT2PheadRep(int32_t tid)1359{1360List<TR_CISCNode> *l = _T2P + tid;1361return l->isEmpty() ? 0 : l->getListHead()->getData();1362}1363TR_CISCNode *getT2PheadRep(TR_CISCNode *t) {return getT2PheadRep(t->getID());}1364TR_CISCNode *getT2Phead(int32_t tid)1365{1366TR_ASSERT(!_T2P[tid].isMultipleEntry(), "maybe error");1367return getT2PheadRep(tid);1368}1369TR_CISCNode *getT2Phead(TR_CISCNode *t) {return getT2Phead(t->getID());}1370bool isGenerateI2L() { return _isGenerateI2L; }1371bool showMesssagesStdout() { return _showMesssagesStdout; }1372TR_CISCNodeRegion *getCandidateRegion() { return _candidateRegion; }1373bool analyzeBoolTable(TR_BitVector **bv, TR::TreeTop **retTreeTop, TR_CISCNode *boolTable,1374TR_BitVector *defBV, TR_CISCNode *defNode,1375TR_CISCNode *ignoreNode,1376int32_t bvoffset, int32_t allocBVSize);1377int32_t analyzeByteBoolTable(TR_CISCNode *booltable, uint8_t *table256, TR_CISCNode *ignoreNode = 0, TR::TreeTop **retSameExit = 0);1378int32_t analyzeCharBoolTable(TR_CISCNode *booltable, uint8_t *table65536, TR_CISCNode *ignoreNode = 0, TR::TreeTop **retSameExit = 0);1379bool isEmptyBeforeInsertionList() { return _beforeInsertions.isEmpty(); }1380ListHeadAndTail<TR::Node> *getBeforeInsertionList() { return &_beforeInsertions; }1381bool isEmptyAfterInsertionList() { return _afterInsertions.isEmpty(); }1382ListHeadAndTail<TR::Node> *getAfterInsertionList() { return &_afterInsertions; }1383bool isEmptyAfterInsertionIdiomList(int32_t pos) { return _afterInsertionsIdiom[pos].isEmpty(); }1384ListHeadAndTail<TR::Node> *getAfterInsertionIdiomList(int32_t pos) { TR_ASSERT(pos < 2, "error"); return _afterInsertionsIdiom+pos; }1385bool alignTopOfRegion(TR_CISCNodeRegion *r);1386static bool isInsideOfFastVersionedLoop(TR_RegionStructure *l);1387void setColdLoopBody();1388void analyzeHighFrequencyLoop(TR_CISCGraph *graph, TR_RegionStructure *naturalLoop);1389int32_t getNumOfBBlistPred() { return _bblistPred.getSize(); }1390int32_t getNumOfBBlistBody() { return _bblistBody.getSize(); }1391int32_t getNumOfBBlistSucc() { return _bblistSucc.getSize(); }1392bool isBlockInLoopBody(TR::Block *b);1393int16_t getOffsetOperand1() { return _offsetOperand1; }1394int16_t getOffsetOperand2() { return _offsetOperand2; }1395void setOffsetOperand1(int16_t v) { _offsetOperand1 = v; }1396void setOffsetOperand2(int16_t v) { _offsetOperand2 = v; }13971398CISCT2PCond analyzeT2P(TR_CISCNode *t, TR_CISCNode *p = 0);13991400enum1401{1402_Unknown = 0, // the pair (p, t) is not processed yet.1403_NotEmbed = 0x1, // the status when the other four status are not satisfied1404_Desc = (_NotEmbed | 0x2), // there is the _Embed status within a pair (p, a descendent of t).1405_Cond = 4, // (1) the labels of p and t are equivalent but (2) all children of p and t are not processed yet.1406_Embed = (_Desc | 0x4) // (1) the labels of p and t are equivalent and (2) descendents of t include all children of p.1407};1408static inline bool isDescOrEmbed(uint8_t status) { return ((status & _Desc) == _Desc); } // Assume _Desc=3 and _Embed=714091410void setFlag1(bool v = true) { _flagsForTransformer.set(_flag1, v); }1411bool isFlag1() { return _flagsForTransformer.testAny(_flag1); }1412void setFlag2(bool v = true) { _flagsForTransformer.set(_flag2, v); }1413bool isFlag2() { return _flagsForTransformer.testAny(_flag2); }1414void setFlag3(bool v = true) { _flagsForTransformer.set(_flag3, v); }1415bool isFlag3() { return _flagsForTransformer.testAny(_flag3); }1416void setFlag4(bool v = true) { _flagsForTransformer.set(_flag4, v); }1417bool isFlag4() { return _flagsForTransformer.testAny(_flag4); }1418void resetFlags() { _flagsForTransformer.reset(_maskForFlagsPtr); }1419void setIsInitializeNegative128By1(bool v = true) { setFlag1(v); }1420bool isInitializeNegative128By1() { return isFlag1(); }1421void setTableBackedByRawStorage(bool v = true) { setFlag1(v); }1422bool isTableBackedByRawStorage() { return isFlag1(); }1423void setCompareTo(bool v = true) { setFlag1(v); }1424bool isCompareTo() { return isFlag1(); }1425void setIndexOf(bool v = true) { setFlag2(v); }1426bool isIndexOf() { return isFlag2(); }1427void setMEMCPYDec(bool v = true) { setFlag1(v); }1428bool isMEMCPYDec() { return isFlag1(); }1429bool isAfterVersioning() { return manager()->numPassesCompleted() > 0; }1430void setShowingCandidates(bool v = true) { _flagsForTransformer.set(_isShowingCandidates, v); }1431bool isShowingCandidates() { return _flagsForTransformer.testAny(_isShowingCandidates); }1432void setFirstTime(bool v = true) { _flagsForTransformer.set(_isFirstTime, v); }1433bool isFirstTime() { return _flagsForTransformer.testAny(_isFirstTime); }1434void setConverged(bool v = true) { _flagsForTransformer.set(_isConverged, v); }1435bool isConverged() { return _flagsForTransformer.testAny(_isConverged); }1436enum // flag bits for _flagsForTransformer1437{1438_flag1 = 0x0001, // for TransformerPtr1439_flag2 = 0x0002, // for TransformerPtr1440_flag3 = 0x0004, // for TransformerPtr1441_flag4 = 0x0008, // for TransformerPtr1442_maskForFlagsPtr = _flag1|_flag2|_flag3|_flag4, // for TransformerPtr1443// UNUSED = 0x1000,1444_isShowingCandidates = 0x2000,1445_isFirstTime = 0x4000,1446_isConverged = 0x8000,1447_dummyEnum1448};1449TR_UseDefInfo *getUseDefInfo() { return _useDefInfo; }1450void showCandidates();1451void registerCandidates();1452void moveCISCNodesInList(List<TR_CISCNode> *l, TR_CISCNode *from, TR_CISCNode *to, TR_CISCNode *moveTo);1453void moveCISCNodes(TR_CISCNode *from, TR_CISCNode *to, TR_CISCNode *moveTo, char *debugStr = NULL);1454TR::Block *searchPredecessorOfBlock(TR::Block *block);1455TR::Block *modifyBlockByVersioningCheck(TR::Block *block, TR::TreeTop *startTop, TR::Node *lengthNode, List<TR::Node> *guardList = NULL);1456TR::Block *modifyBlockByVersioningCheck(TR::Block *block, TR::TreeTop *startTop, List<TR::Node> *guardList);1457TR::Block *cloneLoopBodyForPeel(TR::Block **firstBlock, TR::Block **lastBlock, TR_CISCNode *cmpifCISCNode = NULL);1458TR::Block *appendBlocks(TR::Block *block, TR::Block *firstBlock, TR::Block *lastBlock);1459bool isDeadStore(TR::Node *node);1460TR::Block *skipGoto(TR::Block *block, TR::Node *ignoreTree);1461bool analyzeOneArrayIndex(TR_CISCNode *arrayindex, TR::SymbolReference *tInductionVariable);1462bool analyzeArrayIndex(TR::SymbolReference *tInductionVariable);1463int32_t countGoodArrayIndex(TR::SymbolReference *tInductionVariable);1464bool simpleOptimization();1465uint64_t getHashValue(TR_CISCNodeRegion *);1466bool canConvertArrayCmpSign(TR::Node *storeNode, List<TR::TreeTop> *compareIfs, bool *canConvertToArrayCmp);14671468TR_RegionStructure *getCurrentLoop() { return _loopStructure; }1469void setCurrentLoop(TR_RegionStructure *loop) { _loopStructure = loop; }14701471private:1472List<TR::Block> _bblistPred;1473List<TR::Block> _bblistBody;1474List<TR::Block> _bblistSucc;1475List<TR_BitsKeepAliveInfo> _BitsKeepAliveList;14761477TR_CISCNodeRegion *_candidateRegion;1478TR_CISCCandidate _candidatesForShowing;1479List<TR_CISCNodeRegion> _candidatesForRegister;1480ListHeadAndTail<TR_CISCNode> *_candidateBBStartEnd;14811482TR_UseDefInfo *_useDefInfo;1483TR_CISCNode *_lastCFGNode; // just for working1484List<TR_CISCNode> _backPatchList; // just for working1485TR_UseTreeTopMap _useTreeTopMap;14861487// embedded information1488List<TR_CISCNode> *_P2T; // just for working1489List<TR_CISCNode> *_T2P; // just for working1490ListHeadAndTail<TR::Node> _beforeInsertions;1491ListHeadAndTail<TR::Node> _afterInsertions;1492ListHeadAndTail<TR::Node> * _afterInsertionsIdiom; // Idiom specific1493TR_RegionStructure *_loopStructure; // current loop being analyzed14941495uint16_t _sizeP2T;1496uint16_t _sizeT2P;1497uint16_t _numPNodes;1498uint16_t _numTNodes;1499uint16_t _sizeResult;1500uint16_t _sizeDE;1501int16_t _offsetOperand1;1502int16_t _offsetOperand2;1503flags16_t _flagsForTransformer;1504TR_CISCGraph *_P;1505TR_CISCGraph *_T;1506uint8_t *_embeddedForData; // result of data dependence1507uint8_t *_embeddedForCFG; // result of control flow graph1508uint8_t *_EM; // just for working1509uint8_t *_DE; // just for working1510bool _isGenerateI2L;1511bool _showMesssagesStdout;1512};15131514#endif151515161517