Remove some linear searches; use a vector instead of a list for BlockList

Less malloc and less linear search.  Also renames sortCfg,
since @smith told me he didn't like that name very much.  This still
makes use of the postId() field on each Block, which maybe still has
us leaving some trash in the Block structure that should be on the
side.  (These functions can be changed to take indexes later instead
if we want to kill that.)
Esse commit está contido em:
Jordan DeLong
2013-05-26 12:46:03 -07:00
commit de sgolemon
commit 1c0a6c9082
11 arquivos alterados com 40 adições e 27 exclusões
+3 -2
Ver Arquivo
@@ -17,6 +17,7 @@
#ifndef incl_HPHP_VM_BLOCK_H_
#define incl_HPHP_VM_BLOCK_H_
#include "hphp/runtime/base/memory/memory_manager.h"
#include "hphp/runtime/vm/translator/hopt/ir.h"
#include "hphp/runtime/vm/translator/hopt/edge.h"
#include "hphp/runtime/vm/translator/hopt/irinstruction.h"
@@ -228,8 +229,8 @@ struct Block : boost::noncopyable {
EdgeList m_preds; // Edges that point to this block
Hint m_hint; // execution frequency hint
};
typedef std::list<Block*> BlockList;
typedef std::forward_list<Block*> BlockPtrList;
typedef smart::vector<Block*> BlockList;
inline void Edge::setTo(Block* to) {
m_to = Block::updatePreds(this, to);
+16 -4
Ver Arquivo
@@ -17,6 +17,7 @@
#ifndef incl_HPHP_VM_CFG_H_
#define incl_HPHP_VM_CFG_H_
#include "hphp/runtime/base/memory/memory_manager.h"
#include "hphp/runtime/vm/translator/hopt/block.h"
#include "hphp/runtime/vm/translator/hopt/trace.h"
@@ -70,7 +71,18 @@ void postorderWalk(Visitor visitor, unsigned num_blocks, Block* head) {
*
* Post: isRPOSorted(return value)
*/
BlockList sortCfg(Trace*, const IRFactory&);
BlockList rpoSortCfg(Trace*, const IRFactory&);
/*
* Return an iterator into an rpo-sorted BlockList for a given Block.
* Uses the postId() assigned by rpoSortCfg.
*
* Pre: isRPOSorted(cfg)
*/
inline BlockList::const_iterator
rpoIteratorTo(const BlockList& cfg, Block* b) {
return cfg.end() - (b->postId() + 1);
}
/*
* Returns: true if the supplied block list is sorted in reverse post
@@ -80,17 +92,17 @@ bool isRPOSorted(const BlockList&);
/*
* Compute the postorder number of each immediate dominator of each
* block, using a list produced by sortCfg().
* block, using a list produced by rpoSortCfg().
*
* Pre: isRPOSorted(blocks)
*/
typedef std::vector<int> IdomVector;
typedef smart::vector<int> IdomVector;
IdomVector findDominators(const BlockList& blocks);
/*
* A vector of children lists, indexed by block->postId()
*/
typedef std::vector<BlockPtrList> DomChildren;
typedef smart::vector<BlockList> DomChildren;
/*
* Compute the dominator tree, then populate a list of dominator children
+4 -4
Ver Arquivo
@@ -136,7 +136,7 @@ bool checkCfg(Trace* trace, const IRFactory& factory) {
forEachTraceBlock(trace, checkBlock);
// Check valid successor/predecessor edges.
auto const blocks = sortCfg(trace, factory);
auto const blocks = rpoSortCfg(trace, factory);
std::unordered_set<const Edge*> edges;
for (Block* b : blocks) {
auto checkEdge = [&] (const Edge* e) {
@@ -157,7 +157,7 @@ bool checkCfg(Trace* trace, const IRFactory& factory) {
}
// visit dom tree in preorder, checking all tmps
std::vector<BlockPtrList> children = findDomChildren(blocks);
auto const children = findDomChildren(blocks);
boost::dynamic_bitset<> defined0(factory.numTmps());
forPreorderDoms(blocks.front(), children, defined0,
[] (Block* block, boost::dynamic_bitset<>& defined) {
@@ -185,7 +185,7 @@ bool checkCfg(Trace* trace, const IRFactory& factory) {
}
bool checkTmpsSpanningCalls(Trace* trace, const IRFactory& irFactory) {
auto const blocks = sortCfg(trace, irFactory);
auto const blocks = rpoSortCfg(trace, irFactory);
auto const children = findDomChildren(blocks);
// CallBuiltin is ok because it is not a php-level call. (It will
@@ -236,7 +236,7 @@ bool checkRegisters(Trace* trace, const IRFactory& factory,
const RegAllocInfo& regs) {
assert(checkCfg(trace, factory));
auto blocks = sortCfg(trace, factory);
auto blocks = rpoSortCfg(trace, factory);
auto children = findDomChildren(blocks);
forPreorderDoms(blocks.front(), children, RegState(),
[&] (Block* block, RegState& state) {
+1 -1
Ver Arquivo
@@ -168,7 +168,7 @@ BlockList removeUnreachable(Trace* trace, IRFactory* factory) {
// 2. get a list of reachable blocks by sorting them, and erase any
// blocks that are unreachable.
bool needsReflow = false;
BlockList blocks = sortCfg(trace, *factory);
BlockList blocks = rpoSortCfg(trace, *factory);
StateVector<Block, bool> reachable(factory, false);
for (Block* b : blocks) reachable[b] = true;
for (Block* b : blocks) {
+6 -4
Ver Arquivo
@@ -1066,18 +1066,20 @@ bool isConvIntOrPtrToBool(IRInstruction* instr) {
}
}
BlockList sortCfg(Trace* trace, const IRFactory& factory) {
BlockList rpoSortCfg(Trace* trace, const IRFactory& factory) {
assert(trace->isMain());
BlockList blocks;
blocks.reserve(factory.numBlocks());
unsigned next_id = 0;
postorderWalk(
[&](Block* block) {
block->setPostId(next_id++);
blocks.push_front(block);
blocks.push_back(block);
},
factory.numBlocks(),
trace->front()
);
std::reverse(blocks.begin(), blocks.end());
assert(blocks.size() <= factory.numBlocks());
assert(next_id <= factory.numBlocks());
return blocks;
@@ -1154,10 +1156,10 @@ bool dominates(const Block* b1, const Block* b2, const IdomVector& idoms) {
DomChildren findDomChildren(const BlockList& blocks) {
IdomVector idom = findDominators(blocks);
DomChildren children(blocks.size(), BlockPtrList());
DomChildren children(blocks.size(), BlockList());
for (Block* block : blocks) {
int idom_id = idom[block->postId()];
if (idom_id != -1) children[idom_id].push_front(block);
if (idom_id != -1) children[idom_id].push_back(block);
}
return children;
}
+2 -2
Ver Arquivo
@@ -70,7 +70,7 @@ Block* findMainExitBlock(Trace* trace, IRFactory* irFactory) {
* something like the assert below to find the main exit.)
*/
if (debug) {
auto const sorted = sortCfg(trace, *irFactory);
auto const sorted = rpoSortCfg(trace, *irFactory);
auto it = sorted.rbegin();
while (it != sorted.rend() && !(*it)->isMain()) {
++it;
@@ -143,7 +143,7 @@ void optimizeCondTraceExit(Trace* trace, IRFactory* irFactory) {
auto const mainExit = findMainExitBlock(trace, irFactory);
if (!isNormalExit(mainExit)) return;
auto const &mainPreds = mainExit->preds();
auto const& mainPreds = mainExit->preds();
if (mainPreds.size() != 1) return;
auto const jccBlock = mainPreds.front().from();
+3 -3
Ver Arquivo
@@ -187,8 +187,8 @@ private:
smart::list<RegState*> m_allocatedRegs;
smart::vector<SlotInfo> m_slots; // Spill info indexed by slot id
BlockList m_blocks; // all basic blocks in reverse postorder
IdomVector m_idoms; // immediate dominator vector
BlockList m_blocks; // all basic blocks in reverse postorder
IdomVector m_idoms; // immediate dominator vector
// any tmp that has been spilled has an entry in this array with
// the spill-slot number, which is an index into m_slots[]. tmps that
@@ -1087,7 +1087,7 @@ RegAllocInfo LinearScan::allocRegs(Trace* trace, LifetimeInfo* lifetime) {
coalesce(trace);
}
m_blocks = sortCfg(trace, *m_irFactory);
m_blocks = rpoSortCfg(trace, *m_irFactory);
m_idoms = findDominators(m_blocks);
if (!packed_tv) {
+2 -4
Ver Arquivo
@@ -62,8 +62,7 @@ void cloneToBlock(const BlockList& rpoBlocks,
targetIt = ++target->iteratorTo(newInst);
}
// TODO(#2424504): don't use linear search
auto it = std::find(rpoBlocks.begin(), rpoBlocks.end(), target);
auto it = rpoIteratorTo(rpoBlocks, target);
for (; it != rpoBlocks.end(); ++it) {
FTRACE(5, "cloneToBlock: rewriting block {}\n", (*it)->getId());
for (auto& inst : **it) {
@@ -129,8 +128,7 @@ void reflowTypes(Block* const changed, const BlockList& blocks) {
}
};
// TODO(#2424504): don't use linear search
auto it = std::find(blocks.begin(), blocks.end(), changed);
auto it = rpoIteratorTo(blocks, changed);
assert(it != blocks.end());
for (; it != blocks.end(); ++it) {
FTRACE(5, "reflowTypes: visiting block {}\n", (*it)->getId());
@@ -66,7 +66,7 @@ void optimizePredictions(Trace* const trace, IRFactory* const irFactory) {
SCOPE_EXIT { FTRACE(5, "PredOpts:^^^^^^^^^^^^^^^^^^^^^\n"); };
auto const sortedBlocks = folly::lazy([&]{
return sortCfg(trace, *irFactory);
return rpoSortCfg(trace, *irFactory);
});
/*
+1 -1
Ver Arquivo
@@ -22,7 +22,7 @@
#include "hphp/runtime/base/memory/memory_manager.h"
#include "hphp/runtime/vm/translator/hopt/irfactory.h"
namespace HPHP { namespace JIT {
namespace HPHP { namespace JIT {
//////////////////////////////////////////////////////////////////////
@@ -840,7 +840,7 @@ void TraceBuilder::reoptimize() {
return;
}
BlockList sortedBlocks = sortCfg(m_trace.get(), m_irFactory);
BlockList sortedBlocks = rpoSortCfg(m_trace.get(), m_irFactory);
IdomVector idoms = findDominators(sortedBlocks);
clearTrackedState();