blob: df9014d57b2e6b5222fc974d689c89205eda1c8a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Intel, Mikhail Y. Fursov
*/
#ifndef HYX86CODE_LAYOUT_TOP_DOWN
#define HYX86CODE_LAYOUT_TOP_DOWN
#include "Ia32CodeLayout.h"
namespace Jitrino
{
namespace Ia32 {
/**
* Class to perform top-down block layout.
* The layout algorithm is similar to the one described in the paper
* "Profile Guided Code Positioning" by Hansen & Pettis.
*/
class TopDownLayout : public Linearizer {
friend class Linearizer;
// To choose a candidate for layout the choice is made from one of two
// sources. The first source is a control flow successor of the last block
// to be laid-out assuming this successor can be a fall through successor.
// The second source is a map containing blocks that have not yet been laid
// out but have an immediate predecessor that has been laid out.
// LayoutValue is used to order blocks in this map of blocks yet to be
// laid-out but that are successors of already laid-out blocks (i.e.
// only blocks which are directly connected to already placed blocks
// are kept in the set). Hence the set will start out empty before block
// layout. During layout when we choose one successor of a block with
// multiple successors that have yet to be placed, the successors that
// are not chosen will be inserted into the map which is presumed to be
// implemented as a RedBlack tree and is hence O(lgN) for insertion,
// deletion, and search operations. Two methods to compute the LayoutValue
// are described below:
// Option 1:
// LayoutValue is a measure of the connectivity of a block to already
// placed blocks. Connectivity is measured as the sum of the execution
// counts on direct OUT edges from one or more blocks already placed,
// to the block in question.
// Option 2:
// LayoutValue is a measure of the cache locality benefit of placing the
// block, and a measure of any opportunity lost from not placing the block
// after its most likely predecessor that is yet to be laid-out.
//
class TopDownLayoutBlockInfo {
public:
BasicBlock* block;
enum State { NOT_ESTIMATED, LAYOUT_NEIGHBOUR, LAYOUTED} state;
double layoutValue;
TopDownLayoutBlockInfo(BasicBlock* b = NULL) : block(b), state(NOT_ESTIMATED), layoutValue(0){};
struct compare {
bool operator() (const TopDownLayoutBlockInfo* c1, const TopDownLayoutBlockInfo* c2) const { //c1 is first
return less(c2, c1);
}
};
bool isLayouted() const {return state == LAYOUTED;}
bool isLayoutNeighbour() const {return state == LAYOUT_NEIGHBOUR;}
bool isNotEstimated() const {return state == NOT_ESTIMATED;}
static bool less(const TopDownLayoutBlockInfo* c1, const TopDownLayoutBlockInfo* c2) {
assert(c1->isLayoutNeighbour() && c2->isLayoutNeighbour());
double v1 = c1->layoutValue, v2 = c2->layoutValue;
//topological if ==, Nan,Inf
return v1 < v2 ? true: (v1 > v2 ? false: c1->block->getId() < c2->block->getId());
}
};
typedef StlSet<TopDownLayoutBlockInfo*, TopDownLayoutBlockInfo::compare> SortedBlockInfoSet;//type constructor
typedef StlVector<TopDownLayoutBlockInfo*> TDBlockInfos;
protected:
TopDownLayout(IRManager* irManager);
virtual ~TopDownLayout() {}
void linearizeCfgImpl();
private:
BasicBlock * pickLayoutCandidate();
void layoutBlock(BasicBlock *blk);
void processSuccLayoutValue(Node *node, BasicBlock *layoutSucc);
void printConnectedBlkMap(::std::ostream & os);
/* for use in doing top down layout */
MemoryManager memManager;
/** Last block that was laid out*/
BasicBlock* lastBlk;
/**Set of blocks with TopDownLayoutBlockInfo::state==LAYOUT_NEIGHBOUR */
SortedBlockInfoSet neighboursBlocks;
/** Array indexed by block id*/
TDBlockInfos blockInfos;
};
#endif
}
}