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:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
/*
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário