Path: blob/master/runtime/compiler/infra/J9Cfg.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 <algorithm>23#include <limits.h>24#include <stdio.h>25#include <stdint.h>26#include <string.h>27#include "compile/Compilation.hpp"28#include "control/Options.hpp"29#include "control/Options_inlines.hpp"30#include "control/Recompilation.hpp"31#include "control/RecompilationInfo.hpp"32#include "cs2/arrayof.h"33#include "cs2/bitvectr.h"34#include "cs2/listof.h"35#include "env/TRMemory.hpp"36#include "env/PersistentInfo.hpp"37#include "env/VMJ9.h"38#include "il/Block.hpp"39#include "il/ILOpCodes.hpp"40#include "il/ILOps.hpp"41#include "il/LabelSymbol.hpp"42#include "il/Node.hpp"43#include "il/Node_inlines.hpp"44#include "il/ResolvedMethodSymbol.hpp"45#include "il/Symbol.hpp"46#include "il/SymbolReference.hpp"47#include "il/TreeTop.hpp"48#include "il/TreeTop_inlines.hpp"49#include "infra/Assert.hpp"50#include "infra/Cfg.hpp"51#include "infra/Link.hpp"52#include "infra/List.hpp"53#include "infra/Stack.hpp"54#include "infra/TRCfgEdge.hpp"55#include "infra/TRCfgNode.hpp"56#include "optimizer/Optimizer.hpp"57#include "optimizer/Structure.hpp"58#include "optimizer/StructuralAnalysis.hpp"59#include "ras/Debug.hpp"60#include "runtime/ExternalProfiler.hpp"61#include "runtime/J9Profiler.hpp"6263#ifdef __MVS__64#include <stdlib.h>65#endif666768static TR_PersistentProfileInfo *getProfilingInfoForCFG(TR::Compilation *comp, TR::CFG *cfg)69{70TR_PersistentProfileInfo *info = TR_PersistentProfileInfo::get(comp);71if (cfg == comp->getFlowGraph()72&& comp->getRecompilationInfo())73return info;7475if ((*(TR_BlockFrequencyInfo::getEnableJProfilingRecompilation())) == -176&& cfg->getMethodSymbol()77&& cfg->getMethodSymbol()->getResolvedMethod()78&& info79&& info->getBlockFrequencyInfo()80&& info->getBlockFrequencyInfo()->isJProfilingData())81{82return info;83}84return NULL;85}8687static bool hasBlockFrequencyInfo(TR::Compilation *comp, TR::CFG *cfg)88{89TR_PersistentProfileInfo *profileInfo = getProfilingInfoForCFG(comp, cfg);90return profileInfo && profileInfo->getBlockFrequencyInfo();91}9293static bool hasJProfilingInfo(TR::Compilation *comp, TR::CFG *cfg)94{95static char *disableJProfilingForInner = feGetEnv("TR_disableJProfilingForInner");96TR_PersistentProfileInfo *profileInfo = getProfilingInfoForCFG(comp, cfg);97if (disableJProfilingForInner == NULL98&& profileInfo99&& profileInfo->getBlockFrequencyInfo()100&& profileInfo->getBlockFrequencyInfo()->isJProfilingData()101&& ((*(TR_BlockFrequencyInfo::getEnableJProfilingRecompilation())) == -1))102{103TR_ByteCodeInfo toCheck;104toCheck.setByteCodeIndex(0);105toCheck.setCallerIndex(comp->getCurrentInlinedSiteIndex());106int32_t entryFrequency = profileInfo->getBlockFrequencyInfo()->getFrequencyInfo(toCheck, comp, false, false);107if (entryFrequency > -1)108{109return true;110}111}112return false;113}114115bool116J9::CFG::setFrequencies()117{118if (this == comp()->getFlowGraph())119{120resetFrequencies();121}122_max_edge_freq = MAX_PROF_EDGE_FREQ;123124TR_ExternalProfiler *profiler;125126// Do not use JIT profiler info for estimate code size.127bool externFreq = ! comp()->getOption(TR_EnableScorchInterpBlockFrequencyProfiling);128bool hasJPI = hasJProfilingInfo(comp(), self());129if (externFreq130&& comp()->hasBlockFrequencyInfo()131&& (132(!hasJPI && (this == comp()->getFlowGraph()))133|| (hasJPI && ((*(TR_BlockFrequencyInfo::getEnableJProfilingRecompilation())) == -1))134)135)136{137if (!self()->consumePseudoRandomFrequencies())138{139_externalProfiler = comp()->fej9()->hasIProfilerBlockFrequencyInfo(*comp());140TR_BitVector *nodesToBeNormalized = self()->setBlockAndEdgeFrequenciesBasedOnJITProfiler();141self()->normalizeFrequencies(nodesToBeNormalized);142if (comp()->getOption(TR_TraceBFGeneration))143{144traceMsg(comp(), "CFG of %s after setting frequencies using JITProfiling\n", self()->getMethodSymbol()->signature(comp()->trMemory()));145comp()->dumpFlowGraph(self());146}147if (this == comp()->getFlowGraph() && comp()->getInlinedCalls() > 0)148{149for (TR::Block *block = comp()->getStartBlock(); block; block = block->getNextBlock())150{151if (!block->getEntry() || !block->getEntry()->getNode())152{153continue;154}155TR_ByteCodeInfo &bci = block->getEntry()->getNode()->getByteCodeInfo();156TR::ResolvedMethodSymbol *inlinedMethod = bci.getCallerIndex() == -1 ? comp()->getMethodSymbol() : comp()->getInlinedResolvedMethodSymbol(bci.getCallerIndex());157}158}159}160161if (comp()->getOption(TR_VerbosePseudoRandom))162emitVerbosePseudoRandomFrequencies();163164return true;165}166else if ((profiler = comp()->fej9()->hasIProfilerBlockFrequencyInfo(*comp())))167{168if (!self()->consumePseudoRandomFrequencies())169{170profiler->setBlockAndEdgeFrequencies(self(), comp());171if (self()->getMethodSymbol())172{173TR::CFGNode *nextNode = self()->getFirstNode();174for (; nextNode != NULL; nextNode = nextNode->getNext())175{176if (nextNode->asBlock()->getEntry()177&& self()->getMethodSymbol()->getProfilerFrequency(nextNode->asBlock()->getEntry()->getNode()->getByteCodeIndex()) < 0)178self()->getMethodSymbol()->setProfilerFrequency(nextNode->asBlock()->getEntry()->getNode()->getByteCodeIndex(), nextNode->asBlock()->getFrequency());179}180}181}182183if (comp()->getOption(TR_VerbosePseudoRandom))184emitVerbosePseudoRandomFrequencies();185186return true;187}188else if (comp()->getFlowGraph()->getStructure() && (comp()->getFlowGraph() == self()))189{190if (!self()->consumePseudoRandomFrequencies())191{192_max_edge_freq = MAX_STATIC_EDGE_FREQ;193self()->setBlockAndEdgeFrequenciesBasedOnStructure();194if (comp()->getOption(TR_TraceBFGeneration))195comp()->dumpMethodTrees("Trees after setting frequencies from structures", comp()->getMethodSymbol());196}197198if (comp()->getOption(TR_VerbosePseudoRandom))199emitVerbosePseudoRandomFrequencies();200201return true;202}203204return false;205}206207208#define GUESS_THRESHOLD 100209210static bool isVirtualGuard(TR::Node *ifNode)211{212return (ifNode->isTheVirtualGuardForAGuardedInlinedCall() || ifNode->isProfiledGuard());213}214215216TR_BitVector *217J9::CFG::setBlockAndEdgeFrequenciesBasedOnJITProfiler()218{219TR_PersistentProfileInfo *profileInfo = getProfilingInfoForCFG(comp(), self());220221if (!profileInfo)222return NULL;223224TR_BlockFrequencyInfo *blockFrequencyInfo = profileInfo->getBlockFrequencyInfo();225226int32_t maxCount = profileInfo->getMaxCount();227228TR_BitVector *nodesToBeNormalized = NULL;229TR::CFGNode *node;230231int32_t *nodeFrequencies = NULL;232if (_maxFrequency < 0)233{234nodeFrequencies = (int32_t*) trMemory()->allocateStackMemory(sizeof(int32_t) * self()->getNextNodeNumber());235for (node = getFirstNode(); node; node = node->getNext())236{237int32_t nodeNumber = toBlock(node)->getNumber();238nodeFrequencies[nodeNumber] = blockFrequencyInfo->getFrequencyInfo(toBlock(node), comp());239if ((nodeFrequencies[nodeNumber] >= _maxFrequency) && (nodeFrequencies[nodeNumber] >= 0))240_maxFrequency = nodeFrequencies[nodeNumber];241}242}243244int32_t origMaxFrequency = _maxFrequency;245246createTraversalOrder(true, stackAlloc);247248TR::CFGNode *nextNode = getFirstNode();249for (; nextNode != NULL; nextNode = nextNode->getNext())250{251TR_SuccessorIterator sit(nextNode);252TR::CFGEdge * edge = sit.getFirst();253for(; edge != NULL; edge=sit.getNext())254{255if (comp()->getOption(TR_TraceBFGeneration))256traceMsg(comp(), "edge visit count = %d\n", edge->getVisitCount());257edge->setVisitCount(1);258}259}260261for (int32_t traversalIndex = 0; traversalIndex < getForwardTraversalLength(); traversalIndex++)262{263node = getForwardTraversalElement(traversalIndex);264int32_t frequency = node->getFrequency();265if (frequency < 0)266{267frequency = nodeFrequencies ? nodeFrequencies[toBlock(node)->getNumber()] : blockFrequencyInfo->getFrequencyInfo(toBlock(node), comp());268//frequency = nodeFrequencies[toBlock(node)->getNumber()];269270bool isGuardedBlock = false;271bool isProfiledGuard = false;272bool isGuardedBlockFallThrough = false;273int32_t combinedPredRawFrequency = 0;274TR_PredecessorIterator pit(node);275TR::CFGEdge *edge;276for (edge = pit.getFirst(); edge; edge = pit.getNext())277{278TR::Block *block = edge->getFrom()->asBlock();279TR::TreeTop *lastTree = NULL;280if (block->getExit())281lastTree = block->getLastRealTreeTop();282if (lastTree &&283lastTree->getNode()->getOpCode().isIf() &&284isVirtualGuard(lastTree->getNode()))285{286if (lastTree->getNode()->getBranchDestination() == node->asBlock()->getEntry())287{288isGuardedBlock = true;289if (lastTree->getNode()->isProfiledGuard())290isProfiledGuard = true;291}292else293isGuardedBlockFallThrough = true;294}295}296297// Infer a frequency based on frequencies of predecessors.298// We can use this if we have nothing better.299//300for (edge = pit.getFirst(); edge; edge = pit.getNext())301{302TR::Block *pred = edge->getFrom()->asBlock();303304// Compute this predecessor's raw frequency305//306int32_t predRawFrequency = pred->getFrequency();307if (predRawFrequency < 0)308{309// This should be unusual. Getting here means we haven't310// processed a predecessor, which (due to our reverse postorder311// traversal) means we're in a loop. Even then, loops usually312// have pretty good raw profiling info, so we still usually don't313// see -1. However, it can happen, so let's make some attempt to314// get a decent guess at a frequency.315//316predRawFrequency = blockFrequencyInfo->getFrequencyInfo(pred, comp());317predRawFrequency = std::max(predRawFrequency, 0);318predRawFrequency = std::min(predRawFrequency, maxCount);319}320else if (nodesToBeNormalized && nodesToBeNormalized->isSet(pred->getNumber()))321{322// Frequency is already raw; leave it alone323}324else325{326predRawFrequency = TR::CFGNode::denormalizedFrequency(predRawFrequency, origMaxFrequency);327}328329bool effectiveSingleton = false;330TR::TreeTop *lastTree = NULL;331if (pred && pred->getExit())332lastTree = pred->getLastRealTreeTop();333if (lastTree &&334lastTree->getNode()->getOpCode().isIf())335{336TR::Block *fallThrough = pred->getNextBlock();337TR::Block *branchTarget = lastTree->getNode()->getBranchDestination()->getEnclosingBlock();338if (fallThrough && branchTarget)339{340if (comp()->getOption(TR_TraceBFGeneration))341traceMsg(comp(), " checking effective singleton on block_%d with fallthrough block_%d and branchTarget block_%d\n", pred->getNumber(), fallThrough->getNumber(), branchTarget->getNumber());342if (fallThrough == node && !fallThrough->isCold() && branchTarget->isCold())343effectiveSingleton = true;344else if (branchTarget == node && !branchTarget->isCold() && fallThrough->isCold())345effectiveSingleton = true;346}347}348349if (comp()->getOption(TR_TraceBFGeneration) && pred)350traceMsg(comp(), " block_%d's pred block_%d has normalized frequency %d and %s\n",351node->getNumber(),352pred->getNumber(),353predRawFrequency,354(pred->getSuccessors().size() == 1)? "one successor" : (effectiveSingleton ? "one effective successor" : "multiple successors"));355356// Use predecessor's frequency as appropriate357//358if (((pred->getSuccessors().size() == 1) && pred->hasSuccessor(node)) || effectiveSingleton)359{360combinedPredRawFrequency += predRawFrequency;361if (comp()->getOption(TR_TraceBFGeneration))362traceMsg(comp(), " combinedPredRawFrequency is now %d\n", combinedPredRawFrequency);363}364else if (isGuardedBlock)365{366if (comp()->getOption(TR_TraceBFGeneration))367traceMsg(comp(), " %d is a guarded block; ignoring predecessor\n", node->getNumber());368}369else if (pred && pred->hasSuccessor(node) && (frequency < 0 || (!blockFrequencyInfo->isJProfilingData() && pred->getFrequency() <= GUESS_THRESHOLD)))370{371int32_t succCount = 0;372for (auto edge = pred->getSuccessors().begin(); edge != pred->getSuccessors().end(); ++edge)373{374if ((*edge)->getTo() && (*edge)->getTo()->asBlock() && node->asBlock()375&& (*edge)->getTo()->asBlock() != node->asBlock()376&& (*edge)->getTo()->getFrequency() > -1)377predRawFrequency -= (*edge)->getTo()->getFrequency();378else379succCount++;380}381if (predRawFrequency > 0)382{383combinedPredRawFrequency += succCount ? (predRawFrequency / succCount) : predRawFrequency;384if (comp()->getOption(TR_TraceBFGeneration))385traceMsg(comp(), " combinedPredRawFrequency is now %d based on succCount %d and predRawFrequency %d\n", combinedPredRawFrequency, succCount, predRawFrequency);386}387else388{389// Can't figure out how often we get here from this pred, and can't ignore it.390// Fall back on old wild-guess heuristic.391// NOTE: this uses a normalized frequency where it should be a392// raw one, but this bug has been in Java6 for ages, so we don't393// want to change in an SR.394//395combinedPredRawFrequency += origMaxFrequency / 4; // probably intended something like denormalizedFrequency(25,100)396if (comp()->getOption(TR_TraceBFGeneration))397traceMsg(comp(), " can't figure out frequency; defaulting to wild guess %d\n", combinedPredRawFrequency);398}399}400else if (frequency < 0 || (!blockFrequencyInfo->isJProfilingData() && pred->getFrequency() <= GUESS_THRESHOLD))401{402// Can't figure out how often we get here from this pred, and can't ignore it.403// Fall back on old wild-guess heuristic.404// NOTE: this uses a normalized frequency where it should be a405// raw one, but this bug has been in Java6 for ages, so we don't406// want to change in an SR.407//408combinedPredRawFrequency = origMaxFrequency / 4; // probably intended something like denormalizedFrequency(25,100)409if (comp()->getOption(TR_TraceBFGeneration))410traceMsg(comp(), " can't figure out frequency; defaulting to wild guess %d\n", combinedPredRawFrequency);411break;412}413}414415combinedPredRawFrequency = std::min(maxCount, combinedPredRawFrequency);416417if (_compilation->getOption(TR_TraceBFGeneration))418traceMsg(comp(), "Raw frequency for block_%d is %d (maxCount %d origMax %d combinedPredRawFrequency %d)\n", node->getNumber(), frequency, maxCount, origMaxFrequency, combinedPredRawFrequency);419420if (frequency <= 0)421frequency = combinedPredRawFrequency;422423if (frequency > maxCount)424frequency = maxCount;425426if (isGuardedBlock)427{428if (isProfiledGuard)429frequency = MAX_COLD_BLOCK_COUNT+1;430else431frequency = VERSIONED_COLD_BLOCK_COUNT;432}433434435//if (!isGuardedBlock)436{437if (comp()->getOption(TR_TraceBFGeneration))438traceMsg(comp(), " Setting block_%d frequency %d (origMaxFrequency %d)\n", node->getNumber(), frequency, origMaxFrequency);439if ((frequency > origMaxFrequency) &&440(origMaxFrequency > -1))441{442if (!isGuardedBlock)443{444if (!nodesToBeNormalized)445nodesToBeNormalized = new (trStackMemory()) TR_BitVector(getNextNodeNumber(), trMemory(), stackAlloc);446447nodesToBeNormalized->set(node->getNumber());448//dumpOptDetails(comp(),"NOT normalized %d freq %d\n", node->getNumber(), frequency);449}450node->setFrequency(frequency);451}452else453{454node->setFrequency(frequency);455if (!isGuardedBlock)456node->normalizeFrequency(frequency, origMaxFrequency);457//dumpOptDetails(comp(),"Normalized %d freq %d\n", node->getNumber(), node->getFrequency());458}459}460//else461// node->setFrequency(frequency);462}463464// DORIT: node->frequency is finalized and set. See if can infer anything about edge frequency:465// visitCount>1 indicates that a final frequency for the edge had been set.466frequency = node->getFrequency();467if (frequency >= 0 && (node->getSuccessors().size() == 1) && (node->getSuccessors().front()->getTo()->getPredecessors().size() == 1))468{469TR::CFGEdge *edge = node->getSuccessors().front();470TR::Block *succ = edge->getTo()->asBlock();471472if (comp()->getOption(TR_TraceBFGeneration))473traceMsg(comp(), "node %d has single succ. set Frequency for edge %d->%d to %d final.\n", node->getNumber(), node->getNumber(), succ->getNumber(), frequency);474475if (edge->getVisitCount()>1)476{477if (comp()->getOption(TR_TraceBFGeneration))478traceMsg(comp(), "edge visitCount=%d.\n",edge->getVisitCount());479}480else481{482edge->setFrequency(frequency);483edge->setVisitCount(2);484}485}486487if (frequency >= 0 && (node->getPredecessors().size() == 1) && (node->getPredecessors().front()->getFrom()->getSuccessors().size() == 1))488{489TR::CFGEdge *edge = node->getPredecessors().front();490TR::Block *pred = edge->getFrom()->asBlock();491492if (comp()->getOption(TR_TraceBFGeneration))493traceMsg(comp(), "node %d has single pred. set Frequency for edge %d->%d to %d final.\n", node->getNumber(), pred->getNumber(), node->getNumber(), frequency);494495if (edge->getVisitCount()>1)496{497if (comp()->getOption(TR_TraceBFGeneration))498traceMsg(comp(), "edge visitCount=%d.\n",edge->getVisitCount());499}500else501{502edge->setFrequency(frequency);503edge->setVisitCount(2);504}505}506}507508if (nodesToBeNormalized)509{510for (node = getFirstNode(); node; node = node->getNext())511{512int32_t frequency = node->getFrequency();513if (!nodesToBeNormalized->get(node->getNumber()) &&514!node->asBlock()->isCold())515{516nodesToBeNormalized->set(node->getNumber());517//dumpOptDetails(comp(),"denormalizing node %d (BEFORE) with freq %d\n", node->getNumber(), frequency);518frequency = node->denormalizeFrequency(origMaxFrequency);519//dumpOptDetails(comp(),"denormalizing node %d (AFTER) with freq %d\n", node->getNumber(), frequency);520}521522if (frequency > _maxFrequency)523_maxFrequency = frequency;524//dumpOptDetails(comp(), "_maxFrequency = %d\n", _maxFrequency);525}526}527528//dumpOptDetails(comp(), "_maxFrequency = %d\n", _maxFrequency);529530_maxEdgeFrequency = -1;531532// Turn off this loop code below when propagation is533// fixed534//535for (node = getFirstNode(); node; node = node->getNext())536{537int32_t frequency = node->getFrequency();538if (frequency >= 0)539{540int32_t successorFrequency = 0;541for (auto e = node->getSuccessors().begin(); e != node->getSuccessors().end(); ++e)542{543int32_t normalizedFrequency = (*e)->getTo()->getFrequency();544545// DORIT: try to infer about edge frequencies546// visitCount>1 indicates that a final frequency for the edge had been set.547if ((*e)->getVisitCount() > 1)548{549// don't add to successorFrequency sum;550// peek at "cousin" blocks to see if frequency of other edges can be determined.551// step1: if this successor has only one other predecessor...:552TR::Block *succ = (*e)->getTo()->asBlock();553if (succ->getPredecessors().size() == 2) //succ has only one other predecessor554{555TR::CFGEdge *ee = succ->getPredecessors().front();556if (ee->getFrom() == node)557ee = *(++(succ->getPredecessors().begin()));558if ((succ->getFrequency() >= 0) && (succ->getFrequency() >= (*e)->getFrequency()))559{560int32_t ff = succ->getFrequency() - (*e)->getFrequency();561if (comp()->getOption(TR_TraceBFGeneration))562traceMsg(comp(), "\t\tedge(%d->%d) frequency can be set to succ_%d(%d) - e_freq(%d->%d)(%d) = ee_freq(%d)\n",563ee->getFrom()->getNumber(), ee->getTo()->getNumber(), succ->getNumber(), succ->getFrequency(), (*e)->getFrom()->getNumber(), (*e)->getTo()->getNumber(),(*e)->getFrequency(), ff);564if (ee->getVisitCount()>1)565{566if (comp()->getOption(TR_TraceBFGeneration))567traceMsg(comp(), "\t\tedge frequency = %d already final\n", ee->getFrequency());568}569else570{571ee->setFrequency(ff);572ee->setVisitCount(2);573if (comp()->getOption(TR_TraceBFGeneration))574traceMsg(comp(), "\t\tset edge frequency = %d as final\n", ff);575}576577//TODO: can continue to check the other successors of this predecessor578}579}580}581else582successorFrequency = successorFrequency + normalizedFrequency;583584//dumpOptDetails("normalizedFreq %d succFreq %d node %d succ %d\n", normalizedFrequency, successorFrequency, node->getNumber(), e->getTo()->getNumber());585}586587//if (successorFrequency > 0)588{589for (auto e = node->getSuccessors().begin(); e != node->getSuccessors().end(); ++e)590{591//if (e->getFrequency() <= 0)592{593int32_t toFrequency = (*e)->getTo()->getFrequency();594int32_t edgeFrequency;595if ((toFrequency > MAX_COLD_BLOCK_COUNT) && (frequency > MAX_COLD_BLOCK_COUNT))596{597if (successorFrequency > 0)598{599edgeFrequency = (frequency*toFrequency)/successorFrequency;600if (edgeFrequency <= MAX_COLD_BLOCK_COUNT)601edgeFrequency = MAX_COLD_BLOCK_COUNT+1;602}603else604edgeFrequency = 0;605}606else607{608if (toFrequency < frequency)609edgeFrequency = toFrequency;610else611edgeFrequency = frequency;612}613614//dumpOptDetails("edgeFrequency %d frequency %d toFrequency %d succFrequency %d max %d\n", edgeFrequency, frequency, toFrequency, successorFrequency, SHRT_MAX);615if ((*e)->getVisitCount() > 1)616{617if (comp()->getOption(TR_TraceBFGeneration))618traceMsg(comp(), "\t\tedge frequency = %d is final, don't change\n", (*e)->getFrequency());619edgeFrequency = (*e)->getFrequency();620}621else622(*e)->setFrequency(edgeFrequency);623624if (edgeFrequency > _maxEdgeFrequency)625_maxEdgeFrequency = edgeFrequency;626//dumpOptDetails("Edge %p between %d and %d has freq %d max %d\n", e, e->getFrom()->getNumber(), e->getTo()->getNumber(), e->getFrequency(), _maxEdgeFrequency);627}628}629}630631if (_externalProfiler && (node->getSuccessors().size() == 2))632{633bool frequencyIsIdentical = true;634int32_t deFrq = node->getSuccessors().front()->getFrequency();635if(deFrq != (*(++node->getSuccessors().begin()))->getFrequency())636frequencyIsIdentical = false;637// if both edges have same frequency then break the tie638// using interpreter frequencies639if (frequencyIsIdentical)640{641TR::Block *block = node->asBlock();642if (!block->isCold() && block->getEntry()!=NULL && block->getLastRealTreeTop()->getNode()->getOpCode().isBranch())643{644TR::Node *ifNode = block->getLastRealTreeTop()->getNode();645int32_t fallThroughCount = 0;646int32_t branchToCount = 0;647648_externalProfiler->getBranchCounters(ifNode, block->getNextBlock()->getEntry(), &branchToCount, &fallThroughCount, comp());649650if (branchToCount > fallThroughCount)651{652TR::Block *branchToBlock = ifNode->getBranchDestination()->getNode()->getBlock();653654for (auto e = node->getSuccessors().begin(); e != node->getSuccessors().end(); ++e)655{656if ((*e)->getTo()->asBlock() == branchToBlock)657{658//dumpOptDetails(comp(), "\tadjusting branch to frequency to %d in order to break the tie\n", deFrq+1);659(*e)->setFrequency(deFrq+1);660branchToBlock->setFrequency(branchToBlock->getFrequency()+1);661break;662}663}664}665}666}667}668669int32_t predecessorFrequency = 0;670for (auto e = node->getPredecessors().begin(); e != node->getPredecessors().end(); ++e)671{672int32_t normalizedFrequency = (*e)->getFrom()->getFrequency();673674// DORIT: try to infer about edge frequencies675if ((*e)->getVisitCount() > 1)676{677// don't add to successorFrequency sum;678// peek at cousin blocks to see if frequency of other edges can be determined.679// step1: if this successor has only one other predecessor...:680TR::Block *pred = (*e)->getFrom()->asBlock();681if (pred->getSuccessors().size() == 2) //pred has only one other successor682{683TR::CFGEdge *ee = pred->getSuccessors().front();684if (ee->getTo() == node)685ee = *(++pred->getSuccessors().begin());686if ((pred->getFrequency() >= 0) &&687(pred->getFrequency() >= (*e)->getFrequency()))688{689int32_t ff = pred->getFrequency() - (*e)->getFrequency();690if (comp()->getOption(TR_TraceBFGeneration))691traceMsg(comp(), "\t\tedge(%d->%d) frequency can be set to pred_%d(%d) - e_freq(%d->%d)(%d) = ee_freq(%d)\n",692ee->getFrom()->getNumber(), ee->getTo()->getNumber(), pred->getNumber(), pred->getFrequency(), (*e)->getFrom()->getNumber(), (*e)->getTo()->getNumber(), (*e)->getFrequency(), ff);693694if (ee->getVisitCount()>1)695{696if (comp()->getOption(TR_TraceBFGeneration))697traceMsg(comp(), "\t\tedge frequency = %d already final\n", ee->getFrequency());698}699else700{701ee->setFrequency(ff);702ee->setVisitCount(2);703if (comp()->getOption(TR_TraceBFGeneration))704traceMsg(comp(), "\t\tset edge frequency = %d as final\n", ff);705}706707//TODO: can continue to check the other successors of this predecessor708}709}710}711else712predecessorFrequency = predecessorFrequency + normalizedFrequency;713714//dumpOptDetails("normalizedFreq %d succFreq %d node %d succ %d\n", normalizedFrequency, successorFrequency, node->getNumber(), e->getTo()->getNumber());715}716717//if (predecessorFrequency > 0)718{719for (auto e = node->getPredecessors().begin(); e != node->getPredecessors().end(); ++e)720{721//if (e->getFrequency() <= 0)722{723int32_t fromFrequency = (*e)->getFrom()->getFrequency();724int32_t edgeFrequency;725if ((fromFrequency > MAX_COLD_BLOCK_COUNT) && (frequency > MAX_COLD_BLOCK_COUNT))726{727if (predecessorFrequency > 0)728{729edgeFrequency = (frequency*fromFrequency)/predecessorFrequency;730if (edgeFrequency <= MAX_COLD_BLOCK_COUNT)731edgeFrequency = MAX_COLD_BLOCK_COUNT+1;732}733else734edgeFrequency = 0;735}736else737{738if (fromFrequency < frequency)739edgeFrequency = fromFrequency;740else741edgeFrequency = frequency;742}743744//dumpOptDetails("edgeFrequency %d frequency %d toFrequency %d succFrequency %d max %d\n", edgeFrequency, frequency, toFrequency, successorFrequency, SHRT_MAX);745746if ((*e)->getVisitCount() > 1)747{748if (comp()->getOption(TR_TraceBFGeneration))749traceMsg(comp(), "\t\tedge frequency = %d is final, don't change\n", (*e)->getFrequency());750edgeFrequency = (*e)->getFrequency();751}752else753(*e)->setFrequency(edgeFrequency);754755if (edgeFrequency > _maxEdgeFrequency)756_maxEdgeFrequency = edgeFrequency;757//dumpOptDetails("Edge %p between %d and %d has freq %d max %d\n", e, e->getFrom()->getNumber(), e->getTo()->getNumber(), e->getFrequency(), _maxEdgeFrequency);758}759}760}761}762else763{764if (frequency > origMaxFrequency)765{766if (!nodesToBeNormalized)767nodesToBeNormalized = new (trStackMemory()) TR_BitVector(getNextNodeNumber(), trMemory(), stackAlloc);768769nodesToBeNormalized->set(node->getNumber());770//dumpOptDetails(comp(),"NOT normalized %d freq %d\n", node->getNumber(), frequency);771}772}773}774775776nextNode = getFirstNode();777for (; nextNode != NULL; nextNode = nextNode->getNext())778{779TR_SuccessorIterator sit(nextNode);780TR::CFGEdge * edge = sit.getFirst();781for(; edge != NULL; edge=sit.getNext())782edge->setVisitCount(0);783}784785return nodesToBeNormalized;786}787788789static int32_t summarizeFrequencyFromPredecessors(TR::CFGNode *node, TR::CFG *cfg)790{791int32_t sum = 0;792TR_PredecessorIterator pit(node);793794for (TR::CFGEdge *edge = pit.getFirst(); edge; edge = pit.getNext())795{796TR::CFGNode *pred = edge->getFrom();797798if (edge->getFrequency()<=0)799continue;800801int32_t edgeFreq = edge->getFrequency();802803/*TR_BitVector *frequencySet = cfg->getFrequencySet();804805if (frequencySet)806{807if (!frequencySet->get(pred->getNumber()))808{809int32_t rawScalingFactor = cfg->getOldMaxEdgeFrequency();810if (rawScalingFactor < 0)811rawScalingFactor = cfg->getMaxEdgeFrequency();812813//traceMsg(comp, "raw scaling %d max %d old max %d\n", rawScalingFactor, cfg->getMaxEdgeFrequency(), cfg->getOldMaxEdgeFrequency());814815if (rawScalingFactor > 0)816{817if (edgeFreq > MAX_COLD_BLOCK_COUNT)818{819edgeFreq = (rawScalingFactor*edgeFreq)/(MAX_COLD_BLOCK_COUNT+MAX_BLOCK_COUNT);820}821}822}823} */824825sum += edgeFreq;826}827828return sum;829}830831832void833J9::CFG::setBlockFrequenciesBasedOnInterpreterProfiler()834{835TR::StackMemoryRegion stackMemoryRegion(*trMemory());836int32_t numBlocks = getNextNodeNumber();837838TR_BitVector *_seenNodes = new (trStackMemory()) TR_BitVector(numBlocks, trMemory(), stackAlloc, notGrowable);839TR_BitVector *_seenNodesInCycle = new (trStackMemory()) TR_BitVector(numBlocks, trMemory(), stackAlloc, notGrowable);840_frequencySet = new (trHeapMemory()) TR_BitVector(numBlocks, trMemory(), heapAlloc, notGrowable);841int32_t startFrequency = AVG_FREQ;842int32_t taken = AVG_FREQ;843int32_t nottaken = AVG_FREQ;844int32_t initialCallScanFreq = -1;845int32_t inlinedSiteIndex = -1;846847// Walk until we find if or switch statement848TR::CFGNode *start = getStart();849TR::CFGNode *temp = start;850TR_ScratchList<TR::CFGNode> upStack(trMemory());851852bool backEdgeExists = false;853TR::TreeTop *methodScanEntry = NULL;854//_maxFrequency = 0;855while ( (temp->getSuccessors().size() == 1) ||856!temp->asBlock()->getEntry() ||857!((temp->asBlock()->getLastRealTreeTop()->getNode()->getOpCode().isBranch()858&& !temp->asBlock()->getLastRealTreeTop()->getNode()->getByteCodeInfo().doNotProfile()) ||859temp->asBlock()->getLastRealTreeTop()->getNode()->getOpCodeValue() == TR::lookup ||860temp->asBlock()->getLastRealTreeTop()->getNode()->getOpCodeValue() == TR::table))861{862if (_seenNodes->isSet(temp->getNumber()))863break;864865upStack.add(temp);866_seenNodes->set(temp->getNumber());867868if (!backEdgeExists && !temp->getPredecessors().empty() && !(temp->getPredecessors().size() == 1))869{870if (comp()->getHCRMode() != TR::osr)871backEdgeExists = true;872else873{874// Count the number of edges from non OSR blocks875int32_t nonOSREdges = 0;876for (auto edge = temp->getPredecessors().begin(); edge != temp->getPredecessors().end(); ++edge)877{878if ((*edge)->getFrom()->asBlock()->isOSRCodeBlock() || (*edge)->getFrom()->asBlock()->isOSRCatchBlock())879continue;880if (nonOSREdges > 0)881{882backEdgeExists = true;883break;884}885nonOSREdges++;886}887}888}889890if (temp->asBlock()->getEntry() && initialCallScanFreq < 0)891{892int32_t methodScanFreq = scanForFrequencyOnSimpleMethod(temp->asBlock()->getEntry(), temp->asBlock()->getExit());893if (methodScanFreq > 0)894initialCallScanFreq = methodScanFreq;895inlinedSiteIndex = temp->asBlock()->getEntry()->getNode()->getInlinedSiteIndex();896methodScanEntry = temp->asBlock()->getEntry();897}898899if (!temp->getSuccessors().empty())900{901if ((temp->getSuccessors().size() == 2) && temp->asBlock() && temp->asBlock()->getNextBlock())902{903temp = temp->asBlock()->getNextBlock();904}905else906temp = temp->getSuccessors().front()->getTo();907}908else909break;910}911912if (comp()->getOption(TR_TraceBFGeneration))913dumpOptDetails(comp(),"Propagation start block_%d\n", temp->getNumber());914915if (temp->asBlock()->getEntry())916inlinedSiteIndex = temp->asBlock()->getEntry()->getNode()->getInlinedSiteIndex();917918if ((temp->getSuccessors().size() == 2) &&919temp->asBlock()->getEntry() &&920temp->asBlock()->getLastRealTreeTop()->getNode()->getOpCode().isBranch() &&921!temp->asBlock()->getLastRealTreeTop()->getNode()->getByteCodeInfo().doNotProfile())922{923getInterpreterProfilerBranchCountersOnDoubleton(temp, &taken, ¬taken);924startFrequency = taken + nottaken;925self()->setEdgeFrequenciesOnNode( temp, taken, nottaken, comp());926}927else if (temp->asBlock()->getEntry() &&928(temp->asBlock()->getLastRealTreeTop()->getNode()->getOpCodeValue() == TR::lookup ||929temp->asBlock()->getLastRealTreeTop()->getNode()->getOpCodeValue() == TR::table))930{931startFrequency = _externalProfiler->getSumSwitchCount(temp->asBlock()->getLastRealTreeTop()->getNode(), comp());932if (comp()->getOption(TR_TraceBFGeneration))933dumpOptDetails(comp(),"Switch with total frequency of %d\n", startFrequency);934setSwitchEdgeFrequenciesOnNode(temp, comp());935}936else937{938if (_calledFrequency > 0)939startFrequency = _calledFrequency;940else if (initialCallScanFreq > 0)941startFrequency = initialCallScanFreq;942else943{944startFrequency = AVG_FREQ;945}946947if ((temp->getSuccessors().size() == 2) && (startFrequency > 0) && temp->asBlock()->getEntry() && temp->asBlock()->getLastRealTreeTop()->getNode()->getOpCode().isBranch())948self()->setEdgeFrequenciesOnNode( temp, 0, startFrequency, comp());949else950self()->setUniformEdgeFrequenciesOnNode(temp, startFrequency, false, comp());951}952953setBlockFrequency (temp, startFrequency);954_initialBlockFrequency = startFrequency;955956if (comp()->getOption(TR_TraceBFGeneration))957dumpOptDetails(comp(),"Set frequency of %d on block_%d\n", temp->asBlock()->getFrequency(), temp->getNumber());958959start = temp;960961// Walk backwards to the start and propagate this frequency962963if (comp()->getOption(TR_TraceBFGeneration))964dumpOptDetails(comp(),"Propagating start frequency backwards...\n");965966ListIterator<TR::CFGNode> upit(&upStack);967for (temp = upit.getFirst(); temp; temp = upit.getNext())968{969if (!temp->asBlock()->getEntry())970continue;971if ((temp->getSuccessors().size() == 2) && (startFrequency > 0) && temp->asBlock()->getEntry() && temp->asBlock()->getLastRealTreeTop()->getNode()->getOpCode().isBranch())972self()->setEdgeFrequenciesOnNode( temp, 0, startFrequency, comp());973else974self()->setUniformEdgeFrequenciesOnNode( temp, startFrequency, false, comp());975setBlockFrequency (temp, startFrequency);976_seenNodes->set(temp->getNumber());977978if (comp()->getOption(TR_TraceBFGeneration))979dumpOptDetails(comp(),"Set frequency of %d on block_%d\n", temp->asBlock()->getFrequency(), temp->getNumber());980}981982if (comp()->getOption(TR_TraceBFGeneration))983dumpOptDetails(comp(),"Propagating block frequency forward...\n");984985// Walk reverse post-order986// we start at the first if or switch statement987TR_ScratchList<TR::CFGNode> stack(trMemory());988stack.add(start);989990while (!stack.isEmpty())991{992TR::CFGNode *node = stack.popHead();993994if (comp()->getOption(TR_TraceBFGeneration))995traceMsg(comp(), "Considering block_%d\n", node->getNumber());996997if (_seenNodes->isSet(node->getNumber()))998continue;9991000_seenNodes->set(node->getNumber());10011002if (!node->asBlock()->getEntry())1003continue;10041005inlinedSiteIndex = node->asBlock()->getEntry()->getNode()->getInlinedSiteIndex();10061007if (node->asBlock()->isCold())1008{1009if (comp()->getOption(TR_TraceBFGeneration))1010dumpOptDetails(comp(),"Analyzing COLD block_%d\n", node->getNumber());1011//node->asBlock()->setFrequency(0);1012int32_t freq = node->getFrequency();1013if ((node->getSuccessors().size() == 2) && (freq > 0) && node->asBlock()->getEntry() && node->asBlock()->getLastRealTreeTop()->getNode()->getOpCode().isBranch())1014self()->setEdgeFrequenciesOnNode( node, 0, freq, comp());1015else1016self()->setUniformEdgeFrequenciesOnNode(node, freq, false, comp());1017setBlockFrequency (node, freq);1018//continue;1019}10201021// ignore the first node1022if (!node->asBlock()->isCold() && (node != start))1023{1024if ((node->getSuccessors().size() == 2) &&1025node->asBlock()->getLastRealTreeTop()->getNode()->getOpCode().isBranch())1026{1027// if it's an if and it's not JIT inserted artificial if then just1028// read the outgoing branches and put that as node frequency1029// else get frequency from predecessors1030if (!isVirtualGuard(node->asBlock()->getLastRealTreeTop()->getNode()) &&1031!node->asBlock()->getLastRealTreeTop()->getNode()->getByteCodeInfo().doNotProfile())1032{1033_seenNodesInCycle->empty();1034getInterpreterProfilerBranchCountersOnDoubleton(node, &taken, ¬taken);10351036if ((taken <= 0) && (nottaken <= 0))1037{1038taken = LOW_FREQ;1039nottaken = LOW_FREQ;1040}10411042self()->setEdgeFrequenciesOnNode( node, taken, nottaken, comp());1043setBlockFrequency (node, taken + nottaken);10441045if (comp()->getOption(TR_TraceBFGeneration))1046dumpOptDetails(comp(),"If on node %p is not guard I'm using the taken and nottaken counts for producing block frequency\n", node->asBlock()->getLastRealTreeTop()->getNode());1047}1048else1049{1050if (comp()->getOption(TR_TraceBFGeneration))1051{1052TR_PredecessorIterator pit(node);1053for (TR::CFGEdge *edge = pit.getFirst(); edge; edge = pit.getNext())1054{1055TR::CFGNode *pred = edge->getFrom();10561057if (edge->getFrequency()<=0)1058continue;10591060int32_t edgeFreq = edge->getFrequency();10611062if (comp()->getOption(TR_TraceBFGeneration))1063traceMsg(comp(), "11Pred %d has freq %d\n", pred->getNumber(), edgeFreq);1064}1065}10661067TR::CFGNode *predNotSet = NULL;1068TR_PredecessorIterator pit(node);1069for (TR::CFGEdge *edge = pit.getFirst(); edge; edge = pit.getNext())1070{1071TR::CFGNode *pred = edge->getFrom();10721073if (pred->getFrequency()< 0)1074{1075predNotSet = pred;1076break;1077}1078}10791080if (predNotSet &&1081!_seenNodesInCycle->get(node->getNumber()))1082{1083stack.add(predNotSet);1084_seenNodesInCycle->set(node->getNumber());1085_seenNodes->reset(node->getNumber());1086continue;1087}10881089if (!predNotSet)1090_seenNodesInCycle->empty();10911092int32_t sumFreq = summarizeFrequencyFromPredecessors(node, self());1093if (sumFreq <= 0)1094sumFreq = AVG_FREQ;1095self()->setEdgeFrequenciesOnNode( node, 0, sumFreq, comp());1096setBlockFrequency (node, sumFreq);10971098if (comp()->getOption(TR_TraceBFGeneration))1099dumpOptDetails(comp(),"If on node %p is guard I'm using the predecessor frequency sum\n", node->asBlock()->getLastRealTreeTop()->getNode());1100}11011102if (comp()->getOption(TR_TraceBFGeneration))1103dumpOptDetails(comp(),"Set frequency of %d on block_%d\n", node->asBlock()->getFrequency(), node->getNumber());1104}1105else if (node->asBlock()->getEntry() &&1106(node->asBlock()->getLastRealTreeTop()->getNode()->getOpCodeValue() == TR::lookup ||1107node->asBlock()->getLastRealTreeTop()->getNode()->getOpCodeValue() == TR::table))1108{1109_seenNodesInCycle->empty();1110int32_t sumFreq = _externalProfiler->getSumSwitchCount(node->asBlock()->getLastRealTreeTop()->getNode(), comp());1111setSwitchEdgeFrequenciesOnNode(node, comp());1112setBlockFrequency (node, sumFreq);1113if (comp()->getOption(TR_TraceBFGeneration))1114{1115dumpOptDetails(comp(),"Found a Switch statement at exit of block_%d\n", node->getNumber());1116dumpOptDetails(comp(),"Set frequency of %d on block_%d\n", node->asBlock()->getFrequency(), node->getNumber());1117}1118}1119else1120{1121TR::CFGNode *predNotSet = NULL;1122int32_t sumFreq = 0;1123TR_PredecessorIterator pit(node);1124for (TR::CFGEdge *edge = pit.getFirst(); edge; edge = pit.getNext())1125{1126TR::CFGNode *pred = edge->getFrom();11271128if (pred->getFrequency()< 0)1129{1130predNotSet = pred;1131break;1132}11331134int32_t edgeFreq = edge->getFrequency();1135sumFreq += edgeFreq;1136}11371138if (predNotSet &&1139!_seenNodesInCycle->get(node->getNumber()))1140{1141_seenNodesInCycle->set(node->getNumber());1142_seenNodes->reset(node->getNumber());1143stack.add(predNotSet);1144continue;1145}1146else1147{1148if (!predNotSet)1149_seenNodesInCycle->empty();11501151if (comp()->getOption(TR_TraceBFGeneration))1152traceMsg(comp(), "2Setting block and uniform freqs\n");11531154if ((node->getSuccessors().size() == 2) && (sumFreq > 0) && node->asBlock()->getEntry() && node->asBlock()->getLastRealTreeTop()->getNode()->getOpCode().isBranch())1155self()->setEdgeFrequenciesOnNode( node, 0, sumFreq, comp());1156else1157self()->setUniformEdgeFrequenciesOnNode( node, sumFreq, false, comp());1158setBlockFrequency (node, sumFreq);1159}11601161if (comp()->getOption(TR_TraceBFGeneration))1162{1163dumpOptDetails(comp(),"Not an if (or unknown if) at exit of block %d (isSingleton=%d)\n", node->getNumber(), (node->getSuccessors().size() == 1));1164dumpOptDetails(comp(),"Set frequency of %d on block %d\n", node->asBlock()->getFrequency(), node->getNumber());1165}1166}1167}11681169TR_SuccessorIterator sit(node);1170// add the successors on the list1171for (TR::CFGEdge *edge = sit.getFirst(); edge; edge = sit.getNext())1172{1173TR::CFGNode *succ = edge->getTo();11741175if (!_seenNodes->isSet(succ->getNumber()))1176stack.add(succ);1177else1178{1179if (!(((succ->getSuccessors().size() == 2) &&1180succ->asBlock()->getLastRealTreeTop()->getNode()->getOpCode().isBranch()) ||1181(succ->asBlock()->getEntry() &&1182(succ->asBlock()->getLastRealTreeTop()->getNode()->getOpCodeValue() == TR::lookup ||1183succ->asBlock()->getLastRealTreeTop()->getNode()->getOpCodeValue() == TR::table))))1184{1185setBlockFrequency ( succ, edge->getFrequency(), true);11861187// addup this edge to the frequency of the blocks following it1188// propagate downward until you reach a block that doesn't end in1189// goto or cycle1190if (succ->getSuccessors().size() == 1)1191{1192TR::CFGNode *tempNode = succ->getSuccessors().front()->getTo();1193TR_BitVector *_seenGotoNodes = new (trStackMemory()) TR_BitVector(numBlocks, trMemory(), stackAlloc, notGrowable);1194_seenGotoNodes->set(succ->getNumber());1195while ((tempNode->getSuccessors().size() == 1) &&1196(tempNode != succ) &&1197(tempNode != getEnd()) &&1198!_seenGotoNodes->isSet(tempNode->getNumber()))1199{1200TR::CFGNode *nextTempNode = tempNode->getSuccessors().front()->getTo();12011202if (comp()->getOption(TR_TraceBFGeneration))1203traceMsg(comp(), "3Setting block and uniform freqs\n");12041205self()->setUniformEdgeFrequenciesOnNode( tempNode, edge->getFrequency(), true, comp());1206setBlockFrequency (tempNode, edge->getFrequency(), true);12071208_seenGotoNodes->set(tempNode->getNumber());1209tempNode = nextTempNode;1210}1211}1212}1213}1214}1215}121612171218if (backEdgeExists)1219{1220while (!upStack.isEmpty())1221{1222TR::CFGNode *temp = upStack.popHead();1223if (temp == start)1224continue;12251226if (backEdgeExists)1227temp->setFrequency(std::max(MAX_COLD_BLOCK_COUNT+1, startFrequency/10));1228}1229}123012311232// now set all the blocks that haven't been seen to have 0 frequency1233// catch blocks are one example, we don't try to set frequency there to1234// save compilation time, since those are most frequently cold. Future might prove1235// this otherwise.12361237TR::CFGNode *node;1238start = getStart();1239for (node = getFirstNode(); node; node=node->getNext())1240{1241if ((node == getEnd()) || (node == start))1242node->asBlock()->setFrequency(0);12431244if (_seenNodes->isSet(node->getNumber()))1245continue;12461247if (node->asBlock()->getEntry() &&1248(node->asBlock()->getFrequency()<0))1249node->asBlock()->setFrequency(0);1250}12511252//scaleEdgeFrequencies();12531254TR_BitVector *nodesToBeNormalized = new (trStackMemory()) TR_BitVector(numBlocks, trMemory(), stackAlloc, notGrowable);1255nodesToBeNormalized->setAll(numBlocks);1256_maxFrequency = -1;1257_maxEdgeFrequency = -1;1258normalizeFrequencies(nodesToBeNormalized);1259_oldMaxFrequency = _maxFrequency;1260_oldMaxEdgeFrequency = _maxEdgeFrequency;12611262if (comp()->getOption(TR_TraceBFGeneration))1263traceMsg(comp(), "max freq %d max edge freq %d\n", _maxFrequency, _maxEdgeFrequency);12641265}126612671268void1269J9::CFG::computeInitialBlockFrequencyBasedOnExternalProfiler(TR::Compilation *comp)1270{1271TR_ExternalProfiler* profiler = comp->fej9()->hasIProfilerBlockFrequencyInfo(*comp);1272if (!profiler)1273{1274_initialBlockFrequency = AVG_FREQ;1275return;1276}12771278_externalProfiler = profiler;12791280TR::StackMemoryRegion stackMemoryRegion(*trMemory());1281int32_t numBlocks = getNextNodeNumber();12821283TR_BitVector *_seenNodes = new (trStackMemory()) TR_BitVector(numBlocks, trMemory(), stackAlloc, notGrowable);1284_frequencySet = new (trHeapMemory()) TR_BitVector(numBlocks, trMemory(), heapAlloc, notGrowable);1285int32_t startFrequency = AVG_FREQ;1286int32_t taken = AVG_FREQ;1287int32_t nottaken = AVG_FREQ;1288int32_t initialCallScanFreq = -1;1289int32_t inlinedSiteIndex = -1;12901291// Walk until we find if or switch statement1292TR::CFGNode *start = getStart();1293TR::CFGNode *temp = start;12941295bool backEdgeExists = false;1296TR::TreeTop *methodScanEntry = NULL;12971298while ( (temp->getSuccessors().size() == 1) ||1299!temp->asBlock()->getEntry() ||1300!((temp->asBlock()->getLastRealTreeTop()->getNode()->getOpCode().isBranch()1301&& !temp->asBlock()->getLastRealTreeTop()->getNode()->getByteCodeInfo().doNotProfile()) ||1302temp->asBlock()->getLastRealTreeTop()->getNode()->getOpCodeValue() == TR::lookup ||1303temp->asBlock()->getLastRealTreeTop()->getNode()->getOpCodeValue() == TR::table))1304{1305if (_seenNodes->isSet(temp->getNumber()))1306break;13071308_seenNodes->set(temp->getNumber());13091310if (!temp->getPredecessors().empty() && !(temp->getPredecessors().size() == 1))1311backEdgeExists = true;13121313if (temp->asBlock()->getEntry() && initialCallScanFreq < 0)1314{1315int32_t methodScanFreq = scanForFrequencyOnSimpleMethod(temp->asBlock()->getEntry(), temp->asBlock()->getExit());1316if (methodScanFreq > 0)1317initialCallScanFreq = methodScanFreq;1318inlinedSiteIndex = temp->asBlock()->getEntry()->getNode()->getInlinedSiteIndex();1319methodScanEntry = temp->asBlock()->getEntry();1320}13211322if (!temp->getSuccessors().empty())1323{1324if ((temp->getSuccessors().size() == 2) && temp->asBlock() && temp->asBlock()->getNextBlock())1325{1326temp = temp->asBlock()->getNextBlock();1327}1328else1329temp = temp->getSuccessors().front()->getTo();1330}1331else1332break;1333}13341335if (temp->asBlock()->getEntry())1336inlinedSiteIndex = temp->asBlock()->getEntry()->getNode()->getInlinedSiteIndex();13371338if ((temp->getSuccessors().size() == 2) &&1339temp->asBlock()->getEntry() &&1340temp->asBlock()->getLastRealTreeTop()->getNode()->getOpCode().isBranch() &&1341!temp->asBlock()->getLastRealTreeTop()->getNode()->getByteCodeInfo().doNotProfile())1342{1343getInterpreterProfilerBranchCountersOnDoubleton(temp, &taken, ¬taken);1344if ((taken <= 0) && (nottaken <= 0))1345{1346taken = LOW_FREQ;1347nottaken = LOW_FREQ;1348}1349startFrequency = taken + nottaken;1350}1351else if (temp->asBlock()->getEntry() &&1352(temp->asBlock()->getLastRealTreeTop()->getNode()->getOpCodeValue() == TR::lookup ||1353temp->asBlock()->getLastRealTreeTop()->getNode()->getOpCodeValue() == TR::table))1354{1355startFrequency = _externalProfiler->getSumSwitchCount(temp->asBlock()->getLastRealTreeTop()->getNode(), comp);1356}1357else1358{1359if (_calledFrequency > 0)1360startFrequency = _calledFrequency;1361else if (initialCallScanFreq > 0)1362startFrequency = initialCallScanFreq;1363else1364{1365startFrequency = AVG_FREQ;1366}1367}13681369if (startFrequency <= 0)1370startFrequency = LOW_FREQ;13711372_initialBlockFrequency = startFrequency;1373}137413751376static int32_t1377getParentCallCount(TR::CFG *cfg, TR::Node *node)1378{1379if (node->getByteCodeInfo().getCallerIndex() >=-1)1380{1381int32_t parentSiteIndex = node->getInlinedSiteIndex();13821383if (parentSiteIndex >= 0)1384{1385TR_InlinedCallSite & site = cfg->comp()->getInlinedCallSite(parentSiteIndex);1386int32_t callCount = cfg->comp()->fej9()->getIProfilerCallCount(site._byteCodeInfo, cfg->comp());13871388if (callCount != 0)1389return callCount;1390}1391}1392else1393{ // It's a dummy block in estimate code size1394// The called frequency is set by estimate code size because at that time1395// we don't have the final caller information.1396int32_t callCount = cfg->_calledFrequency;13971398if (callCount != 0)1399return callCount;1400}14011402return 0;1403}140414051406void1407J9::CFG::getInterpreterProfilerBranchCountersOnDoubleton(TR::CFGNode *cfgNode, int32_t *taken, int32_t *nottaken)1408{1409TR::Node *node = cfgNode->asBlock()->getLastRealTreeTop()->getNode();14101411if (this != comp()->getFlowGraph())1412{1413TR::TreeTop *entry = (cfgNode->asBlock()->getNextBlock()) ? cfgNode->asBlock()->getNextBlock()->getEntry() : NULL;1414_externalProfiler->getBranchCounters(node, entry, taken, nottaken, comp());1415}1416else1417{1418getBranchCounters(node, cfgNode->asBlock(), taken, nottaken, comp());1419}14201421if (*taken || *nottaken)1422{1423if (comp()->getOption(TR_TraceBFGeneration))1424dumpOptDetails(comp(),"If on node %p has branch counts: taken=%d, not taken=%d\n", node, *taken, *nottaken);1425}1426else if (isVirtualGuard(node))1427{1428*taken = 0;1429*nottaken = AVG_FREQ;1430int32_t sumFreq = summarizeFrequencyFromPredecessors(cfgNode, self());14311432if (sumFreq>0)1433*nottaken = sumFreq;14341435if (comp()->getOption(TR_TraceBFGeneration))1436dumpOptDetails(comp(),"Guard on node %p has default branch counts: taken=%d, not taken=%d\n", node, *taken, *nottaken);1437}1438else if (!cfgNode->asBlock()->isCold())1439{1440if (node->getBranchDestination()->getNode()->getBlock()->isCold())1441*taken = 0;1442else1443*taken = LOW_FREQ;14441445if (cfgNode->asBlock()->getNextBlock() &&1446cfgNode->asBlock()->getNextBlock()->isCold())1447*nottaken = 0;1448else1449*nottaken = LOW_FREQ;14501451/*int32_t sumFreq = summarizeFrequencyFromPredecessors(cfgNode, this);14521453if (sumFreq>0)1454{1455*nottaken = sumFreq>>1;1456*taken = *nottaken;1457}1458else1459{1460if (node->getByteCodeIndex()==0)1461{1462int32_t callCount = getParentCallCount(this, node);14631464// we don't know what the call count is, assign some1465// moderate frequency1466if (callCount<=0)1467callCount = AVG_FREQ;14681469*taken = 0;1470*nottaken = callCount;1471}1472}1473*/1474if (comp()->getOption(TR_TraceBFGeneration))1475dumpOptDetails(comp(),"If with no profiling information on node %p has low branch counts: taken=%d, not taken=%d\n", node, *taken, *nottaken);1476}1477}147814791480TR::CFGEdge * getCFGEdgeForNode(TR::CFGNode *node, TR::Node *child)1481{1482for (auto e = node->getSuccessors().begin(); e != node->getSuccessors().end(); ++e)1483{1484if ((*e)->getTo()->asBlock() == child->getBranchDestination()->getNode()->getBlock())1485return *e;1486}14871488return NULL;1489}149014911492void1493J9::CFG::setSwitchEdgeFrequenciesOnNode(TR::CFGNode *node, TR::Compilation *comp)1494{1495TR::Block *block = node->asBlock();1496TR::Node *treeNode = node->asBlock()->getLastRealTreeTop()->getNode();1497int32_t sumFrequency = _externalProfiler->getSumSwitchCount(treeNode, comp);14981499if (sumFrequency < 10)1500{1501if (comp->getOption(TR_TraceBFGeneration))1502dumpOptDetails(comp,"Low count switch I'll set frequencies using uniform edge distribution\n");15031504self()->setUniformEdgeFrequenciesOnNode (node, sumFrequency, false, comp);1505return;1506}15071508if (treeNode->getInlinedSiteIndex() < -1)1509{1510if (comp->getOption(TR_TraceBFGeneration))1511dumpOptDetails(comp,"Dummy switch generated in estimate code size I'll set frequencies using uniform edge distribution\n");15121513self()->setUniformEdgeFrequenciesOnNode (node, sumFrequency, false, comp);1514return;1515}15161517if (_externalProfiler->isSwitchProfileFlat(treeNode, comp))1518{1519if (comp->getOption(TR_TraceBFGeneration))1520dumpOptDetails(comp,"Flat profile switch, setting average frequency on each case.\n");15211522self()->setUniformEdgeFrequenciesOnNode(node, _externalProfiler->getFlatSwitchProfileCounts(treeNode, comp), false, comp);1523return;1524}15251526for ( int32_t count=1; count < treeNode->getNumChildren(); count++)1527{1528TR::Node *child = treeNode->getChild(count);1529TR::CFGEdge *e = getCFGEdgeForNode(node, child);15301531int32_t frequency = _externalProfiler->getSwitchCountForValue (treeNode, (count-1), comp);1532e->setFrequency( std::max(frequency,1) );1533if (comp->getOption(TR_TraceBFGeneration))1534dumpOptDetails(comp,"Edge %p between %d and %d has freq %d (Switch)\n", e, e->getFrom()->getNumber(), e->getTo()->getNumber(), e->getFrequency());1535}1536}153715381539void1540J9::CFG::setBlockFrequency(TR::CFGNode *node, int32_t frequency, bool addFrequency)1541{1542TR::Block *block = node->asBlock();1543if (!block)1544return;15451546if (block->isCold())1547{1548if (comp()->getOption(TR_TraceBFGeneration))1549{1550traceMsg(1551comp(),1552"Leaving cold reason %d on block_%d\n",1553block->getFrequency(),1554block->getNumber());1555}1556return;1557}15581559if (comp()->getOption(TR_TraceBFGeneration))1560traceMsg(comp(), "Original freq %d on block_%d incoming freq %d\n", block->getFrequency(), block->getNumber(), frequency);15611562if (_frequencySet)1563{1564if (!_frequencySet->get(block->getNumber()))1565{1566_frequencySet->set(block->getNumber());1567if (comp()->getOption(TR_TraceBFGeneration))1568traceMsg(comp(), "00 Setting freq %d on block_%d added freq %d\n", block->getFrequency(), block->getNumber(), 0);1569block->setFrequency(0);1570}1571}15721573if ((block->getFrequency() < 0) || block->isCatchBlock())1574addFrequency = false;15751576if (addFrequency)1577{1578int32_t addedFrequency = block->getFrequency() + frequency;1579//if (addedFrequency > _maxFrequency)1580// _maxFrequency = addedFrequency;15811582block->setFrequency(addedFrequency);1583if (comp()->getOption(TR_TraceBFGeneration))1584traceMsg(comp(), "11 Setting freq %d on block_%d added freq %d\n", block->getFrequency(), block->getNumber(), addedFrequency);1585}1586else1587{1588//if (frequency > _maxFrequency)1589// _maxFrequency = frequency;15901591block->setFrequency(frequency);1592if (comp()->getOption(TR_TraceBFGeneration))1593traceMsg(comp(), "22 Setting freq %d on block_%d\n", block->getFrequency(), block->getNumber());1594}1595return;1596}159715981599// We currently don't handle well straight line methods without branches1600// when using interpreter profiler. If there are no branches or calls1601// we don't have a frequency to set. The function below tries to find any1602// possible interpreter profiling information to continue on.1603int32_t1604J9::CFG::scanForFrequencyOnSimpleMethod(TR::TreeTop *tt, TR::TreeTop *endTT)1605{1606if (comp()->getOption(TR_TraceBFGeneration))1607traceMsg(comp(), "Starting method scan...\n");1608for (; tt && tt!=endTT; tt = tt->getNextTreeTop())1609{1610if (!tt->getNode()) continue;16111612TR::Node *node = tt->getNode();16131614if (node->getOpCode().isTreeTop() && node->getNumChildren()>0 && node->getFirstChild()->getOpCode().isCall())1615node = node->getFirstChild();16161617if (comp()->getOption(TR_TraceBFGeneration))1618traceMsg(comp(), "Scanning node %p, isBranch = %d, isCall = %d, isVirtualCall =%d\n",1619node, node->getOpCode().isBranch(),1620node->getOpCode().isCall(), node->getOpCode().isCallIndirect());16211622if (node->getOpCode().isBranch()) return -1;16231624if (node->getOpCode().isCallIndirect())1625{1626int32_t newFrequency = comp()->fej9()->getIProfilerCallCount(node->getByteCodeInfo(), comp());16271628if (newFrequency >0)1629{1630if (comp()->getOption(TR_TraceBFGeneration))1631traceMsg(comp(), "Method scan found frequency %d\n", newFrequency);1632return newFrequency;1633}1634}1635}16361637return -1;1638}163916401641void1642J9::CFG::getBranchCountersFromProfilingData(TR::Node *node, TR::Block *block, int32_t *taken, int32_t *notTaken)1643{1644TR::Compilation *comp = self()->comp();1645TR::Block *branchToBlock = node->getBranchDestination()->getNode()->getBlock();1646TR::Block *fallThroughBlock = block->getNextBlock();16471648if (self() != comp->getFlowGraph())1649_externalProfiler->getBranchCounters(node, fallThroughBlock->getEntry(), taken, notTaken, comp);1650else1651{1652TR_BranchProfileInfoManager * branchManager = TR_BranchProfileInfoManager::get(comp);1653branchManager->getBranchCounters(node, fallThroughBlock->getEntry(), taken, notTaken, comp);16541655bool Confirmation = comp->getOption(TR_EnableScorchInterpBlockFrequencyProfiling);16561657if (Confirmation && ((comp->hasBlockFrequencyInfo() && (self() == comp->getFlowGraph())) /*|| hasJProfilingInfo(comp, self())*/))1658{1659TR_PersistentProfileInfo *profileInfo = getProfilingInfoForCFG(comp, self());1660if (profileInfo)1661{1662TR_BlockFrequencyInfo *blockFrequencyInfo = profileInfo->getBlockFrequencyInfo();1663// This check ensures that the JIT profiling block frequency can be properly correlated to interpreter profiling edge frequency1664// This can be only done when no other edge may come in to a block and unnaturally inflate one of the block's counts.1665//1666if((fallThroughBlock->getPredecessors().size() == 1) && (branchToBlock->getPredecessors().size() == 1))1667{1668int32_t currentBlockFreq = blockFrequencyInfo->getFrequencyInfo(block, comp);1669int32_t fallthruBlockFreq = blockFrequencyInfo->getFrequencyInfo(fallThroughBlock, comp);1670int32_t branchBlockFreq = blockFrequencyInfo->getFrequencyInfo(branchToBlock, comp);16711672if(currentBlockFreq > 0 && fallthruBlockFreq > 0 && branchBlockFreq > 0)1673{1674if( (*taken > *notTaken && fallthruBlockFreq > branchBlockFreq ) || (*notTaken > *taken && branchBlockFreq > fallthruBlockFreq) )1675{1676if (comp->getOption(TR_TraceBFGeneration))1677traceMsg(comp, "For block %d fallthru block %d and branch block %d iprofiler says taken = %d notTaken = %d jitprofiler says currentBlockfreq = %d "1678"taken = %d notTaken = %d. Scaling iprofiler info.\n",block->getNumber(),fallThroughBlock->getNumber(),branchToBlock->getNumber(),*taken,*notTaken,1679currentBlockFreq,branchBlockFreq,fallthruBlockFreq);1680*taken = ((*taken) * fallthruBlockFreq ) / (fallthruBlockFreq + branchBlockFreq) ;1681*notTaken = ((*notTaken) * branchBlockFreq) / (fallthruBlockFreq + branchBlockFreq) ;1682if (comp->getOption(TR_TraceBFGeneration))1683traceMsg(comp,"New taken = %d notTaken = %d\n",*taken,*notTaken);16841685}1686}1687}1688}1689}1690}16911692}16931694// OMR TODO:1695// This only seems necessary to NULL out the _externalProfiler field.1696// Consider eliminating this project specialization altogether.1697//1698void1699J9::CFG::setBlockAndEdgeFrequenciesBasedOnStructure()1700{1701self()->propagateFrequencyInfoFromExternalProfiler(NULL);1702}170317041705void1706J9::CFG::propagateFrequencyInfoFromExternalProfiler(TR_ExternalProfiler *profiler)1707{1708_externalProfiler = profiler;17091710if (profiler)1711{1712self()->setBlockFrequenciesBasedOnInterpreterProfiler();1713return;1714}17151716// Call super class1717//1718OMR::CFGConnector::setBlockAndEdgeFrequenciesBasedOnStructure();1719}172017211722bool1723J9::CFG::emitVerbosePseudoRandomFrequencies()1724{1725TR::CFGNode *nextNode = getFirstNode();1726int32_t count = 1;1727int32_t edgeIndex = 0;1728comp()->fej9()->emitNewPseudoRandomNumberVerbosePrefix();1729for (; nextNode != NULL; nextNode = nextNode->getNext())1730{1731comp()->fej9()->emitNewPseudoRandomNumberVerbose(nextNode->getFrequency());1732TR_SuccessorIterator sit(nextNode);1733for (TR::CFGEdge * nextEdge = sit.getFirst(); nextEdge != NULL; nextEdge = sit.getNext())1734{1735comp()->fej9()->emitNewPseudoRandomNumberVerbose(nextEdge->getFrequency());1736if (((count++) % 50) == 0)1737{1738comp()->fej9()->emitNewPseudoRandomVerboseSuffix();1739comp()->fej9()->emitNewPseudoRandomNumberVerbosePrefix();1740}17411742edgeIndex++;1743}17441745if (((count++) % 50) == 0)1746{1747comp()->fej9()->emitNewPseudoRandomVerboseSuffix();1748comp()->fej9()->emitNewPseudoRandomNumberVerbosePrefix();1749}1750}17511752_numEdges = edgeIndex;17531754comp()->fej9()->emitNewPseudoRandomNumberVerbose(getMaxFrequency());17551756if (((count++) % 50) == 0)1757{1758comp()->fej9()->emitNewPseudoRandomVerboseSuffix();1759comp()->fej9()->emitNewPseudoRandomNumberVerbosePrefix();1760}17611762comp()->fej9()->emitNewPseudoRandomVerboseSuffix();1763return true;1764}176517661767