Commit 607e9f0e by Jim Stichnoth

Subzero: Implement InstList in terms of llvm::ilist<> .

Use LLVM's intrusive list ADT template to implement instruction lists. This embeds prev/next pointers into the instruction, and as such, iterators essentially double as instruction pointers. This means stripping off one level of indirection when dereferencing, and also the range-based for loop can't be used. The performance difference in translation time seems to be 1-2%. I tried to also do this for the much less used PhiList and AssignList, but ran into SFINAE problems. BUG= none R=jvoung@chromium.org Review URL: https://codereview.chromium.org/709533002
parent 6fcbdddb
...@@ -318,7 +318,8 @@ bool Cfg::validateLiveness() const { ...@@ -318,7 +318,8 @@ bool Cfg::validateLiveness() const {
Ostream &Str = Ctx->getStrDump(); Ostream &Str = Ctx->getStrDump();
for (CfgNode *Node : Nodes) { for (CfgNode *Node : Nodes) {
Inst *FirstInst = NULL; Inst *FirstInst = NULL;
for (Inst *Inst : Node->getInsts()) { for (auto Inst = Node->getInsts().begin(), E = Node->getInsts().end();
Inst != E; ++Inst) {
if (Inst->isDeleted()) if (Inst->isDeleted())
continue; continue;
if (FirstInst == NULL) if (FirstInst == NULL)
...@@ -337,7 +338,8 @@ bool Cfg::validateLiveness() const { ...@@ -337,7 +338,8 @@ bool Cfg::validateLiveness() const {
// temporary may be live at the end of the previous block, // temporary may be live at the end of the previous block,
// and if it is also assigned in the first instruction of // and if it is also assigned in the first instruction of
// this block, the adjacent live ranges get merged. // this block, the adjacent live ranges get merged.
if (Inst != FirstInst && !Inst->isDestNonKillable() && if (static_cast<class Inst *>(Inst) != FirstInst &&
!Inst->isDestNonKillable() &&
Dest->getLiveRange().containsValue(InstNumber - 1, IsDest)) Dest->getLiveRange().containsValue(InstNumber - 1, IsDest))
Invalid = true; Invalid = true;
if (Invalid) { if (Invalid) {
......
...@@ -59,7 +59,7 @@ void CfgNode::renumberInstructions() { ...@@ -59,7 +59,7 @@ void CfgNode::renumberInstructions() {
InstNumberT FirstNumber = Func->getNextInstNumber(); InstNumberT FirstNumber = Func->getNextInstNumber();
for (InstPhi *I : Phis) for (InstPhi *I : Phis)
I->renumber(Func); I->renumber(Func);
for (Inst *I : Insts) for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I)
I->renumber(Func); I->renumber(Func);
InstCountEstimate = Func->getNextInstNumber() - FirstNumber; InstCountEstimate = Func->getNextInstNumber() - FirstNumber;
} }
...@@ -69,7 +69,7 @@ void CfgNode::renumberInstructions() { ...@@ -69,7 +69,7 @@ void CfgNode::renumberInstructions() {
// constructed, the computePredecessors() pass finalizes it by // constructed, the computePredecessors() pass finalizes it by
// creating the InEdges list. // creating the InEdges list.
void CfgNode::computePredecessors() { void CfgNode::computePredecessors() {
OutEdges = (*Insts.rbegin())->getTerminatorEdges(); OutEdges = Insts.rbegin()->getTerminatorEdges();
for (CfgNode *Succ : OutEdges) for (CfgNode *Succ : OutEdges)
Succ->InEdges.push_back(this); Succ->InEdges.push_back(this);
} }
...@@ -117,7 +117,7 @@ void CfgNode::placePhiStores() { ...@@ -117,7 +117,7 @@ void CfgNode::placePhiStores() {
// Confirm that InsertionPoint is a terminator instruction. Calling // Confirm that InsertionPoint is a terminator instruction. Calling
// getTerminatorEdges() on a non-terminator instruction will cause // getTerminatorEdges() on a non-terminator instruction will cause
// an llvm_unreachable(). // an llvm_unreachable().
(void)(*InsertionPoint)->getTerminatorEdges(); (void)InsertionPoint->getTerminatorEdges();
// SafeInsertionPoint is always immediately before the terminator // SafeInsertionPoint is always immediately before the terminator
// instruction. If the block ends in a compare and conditional // instruction. If the block ends in a compare and conditional
// branch, it's better to place the Phi store before the compare so // branch, it's better to place the Phi store before the compare so
...@@ -167,13 +167,13 @@ void CfgNode::placePhiStores() { ...@@ -167,13 +167,13 @@ void CfgNode::placePhiStores() {
// instruction, and the previous instruction is a compare // instruction, and the previous instruction is a compare
// instruction, then we move the insertion point before the compare // instruction, then we move the insertion point before the compare
// instruction so as not to interfere with compare/branch fusing. // instruction so as not to interfere with compare/branch fusing.
if (InstBr *Branch = llvm::dyn_cast<InstBr>(*InsertionPoint)) { if (InstBr *Branch = llvm::dyn_cast<InstBr>(InsertionPoint)) {
if (!Branch->isUnconditional()) { if (!Branch->isUnconditional()) {
if (InsertionPoint != Insts.begin()) { if (InsertionPoint != Insts.begin()) {
--InsertionPoint; --InsertionPoint;
if (llvm::isa<InstIcmp>(*InsertionPoint) || if (llvm::isa<InstIcmp>(InsertionPoint) ||
llvm::isa<InstFcmp>(*InsertionPoint)) { llvm::isa<InstFcmp>(InsertionPoint)) {
CmpInstDest = (*InsertionPoint)->getDest(); CmpInstDest = InsertionPoint->getDest();
} else { } else {
++InsertionPoint; ++InsertionPoint;
} }
...@@ -250,8 +250,8 @@ CfgNode *CfgNode::splitIncomingEdge(CfgNode *Pred, SizeT EdgeIndex) { ...@@ -250,8 +250,8 @@ CfgNode *CfgNode::splitIncomingEdge(CfgNode *Pred, SizeT EdgeIndex) {
Found = false; Found = false;
for (auto I = Pred->getInsts().rbegin(), E = Pred->getInsts().rend(); for (auto I = Pred->getInsts().rbegin(), E = Pred->getInsts().rend();
!Found && I != E; ++I) { !Found && I != E; ++I) {
if (!(*I)->isDeleted()) { if (!I->isDeleted()) {
Found = (*I)->repointEdge(this, NewNode); Found = I->repointEdge(this, NewNode);
} }
} }
assert(Found); assert(Found);
...@@ -530,9 +530,9 @@ void CfgNode::livenessLightweight() { ...@@ -530,9 +530,9 @@ void CfgNode::livenessLightweight() {
// Process regular instructions in reverse order. // Process regular instructions in reverse order.
// TODO(stichnot): Use llvm::make_range with LLVM 3.5. // TODO(stichnot): Use llvm::make_range with LLVM 3.5.
for (auto I = Insts.rbegin(), E = Insts.rend(); I != E; ++I) { for (auto I = Insts.rbegin(), E = Insts.rend(); I != E; ++I) {
if ((*I)->isDeleted()) if (I->isDeleted())
continue; continue;
(*I)->livenessLightweight(Func, Live); I->livenessLightweight(Func, Live);
} }
for (InstPhi *I : Phis) { for (InstPhi *I : Phis) {
if (I->isDeleted()) if (I->isDeleted())
...@@ -573,9 +573,9 @@ bool CfgNode::liveness(Liveness *Liveness) { ...@@ -573,9 +573,9 @@ bool CfgNode::liveness(Liveness *Liveness) {
// Process regular instructions in reverse order. // Process regular instructions in reverse order.
for (auto I = Insts.rbegin(), E = Insts.rend(); I != E; ++I) { for (auto I = Insts.rbegin(), E = Insts.rend(); I != E; ++I) {
if ((*I)->isDeleted()) if (I->isDeleted())
continue; continue;
(*I)->liveness((*I)->getNumber(), Live, Liveness, LiveBegin, LiveEnd); I->liveness(I->getNumber(), Live, Liveness, LiveBegin, LiveEnd);
} }
// Process phis in forward order so that we can override the // Process phis in forward order so that we can override the
// instruction number to be that of the earliest phi instruction in // instruction number to be that of the earliest phi instruction in
...@@ -654,7 +654,7 @@ void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) { ...@@ -654,7 +654,7 @@ void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) {
LastInstNum = I->getNumber(); LastInstNum = I->getNumber();
} }
// Process instructions // Process instructions
for (Inst *I : Insts) { for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) {
I->deleteIfDead(); I->deleteIfDead();
if (I->isDeleted()) if (I->isDeleted())
continue; continue;
...@@ -753,7 +753,7 @@ void CfgNode::contractIfEmpty() { ...@@ -753,7 +753,7 @@ void CfgNode::contractIfEmpty() {
if (InEdges.empty()) if (InEdges.empty())
return; return;
Inst *Branch = NULL; Inst *Branch = NULL;
for (Inst *I : Insts) { for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) {
if (I->isDeleted()) if (I->isDeleted())
continue; continue;
if (I->isUnconditionalBranch()) if (I->isUnconditionalBranch())
...@@ -776,7 +776,8 @@ void CfgNode::contractIfEmpty() { ...@@ -776,7 +776,8 @@ void CfgNode::contractIfEmpty() {
OutEdges.front()->InEdges.push_back(Pred); OutEdges.front()->InEdges.push_back(Pred);
} }
} }
for (Inst *I : Pred->getInsts()) { for (auto I = Pred->getInsts().begin(), E = Pred->getInsts().end();
I != E; ++I) {
if (!I->isDeleted()) if (!I->isDeleted())
I->repointEdge(this, OutEdges.front()); I->repointEdge(this, OutEdges.front());
} }
...@@ -795,7 +796,7 @@ void CfgNode::doBranchOpt(const CfgNode *NextNode) { ...@@ -795,7 +796,7 @@ void CfgNode::doBranchOpt(const CfgNode *NextNode) {
// first opportunity, unless there is some target lowering where we // first opportunity, unless there is some target lowering where we
// have the possibility of multiple such optimizations per block // have the possibility of multiple such optimizations per block
// (currently not the case for x86 lowering). // (currently not the case for x86 lowering).
for (Inst *I : Insts) { for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) {
if (!I->isDeleted()) { if (!I->isDeleted()) {
Target->doBranchOpt(I, NextNode); Target->doBranchOpt(I, NextNode);
} }
...@@ -901,7 +902,7 @@ void CfgNode::emit(Cfg *Func) const { ...@@ -901,7 +902,7 @@ void CfgNode::emit(Cfg *Func) const {
Inst *Instr = Phi; Inst *Instr = Phi;
Instr->emit(Func); Instr->emit(Func);
} }
for (Inst *I : Insts) { for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) {
if (I->isDeleted()) if (I->isDeleted())
continue; continue;
if (I->isRedundantAssign()) { if (I->isRedundantAssign()) {
...@@ -931,7 +932,7 @@ void CfgNode::emitIAS(Cfg *Func) const { ...@@ -931,7 +932,7 @@ void CfgNode::emitIAS(Cfg *Func) const {
Inst *Instr = Phi; Inst *Instr = Phi;
Instr->emitIAS(Func); Instr->emitIAS(Func);
} }
for (Inst *I : Insts) { for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) {
if (I->isDeleted()) if (I->isDeleted())
continue; continue;
if (I->isRedundantAssign()) if (I->isRedundantAssign())
...@@ -982,7 +983,7 @@ void CfgNode::dump(Cfg *Func) const { ...@@ -982,7 +983,7 @@ void CfgNode::dump(Cfg *Func) const {
if (Func->getContext()->isVerbose(IceV_Instructions)) { if (Func->getContext()->isVerbose(IceV_Instructions)) {
for (InstPhi *I : Phis) for (InstPhi *I : Phis)
I->dumpDecorated(Func); I->dumpDecorated(Func);
for (Inst *I : Insts) for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I)
I->dumpDecorated(Func); I->dumpDecorated(Func);
} }
// Dump the live-out variables. // Dump the live-out variables.
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#define SUBZERO_SRC_ICECFGNODE_H #define SUBZERO_SRC_ICECFGNODE_H
#include "IceDefs.h" #include "IceDefs.h"
#include "IceInst.h" // InstList traits
namespace Ice { namespace Ice {
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include <vector> #include <vector>
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h" #include "llvm/ADT/BitVector.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Casting.h" #include "llvm/Support/Casting.h"
...@@ -56,7 +58,7 @@ class VariablesMetadata; ...@@ -56,7 +58,7 @@ class VariablesMetadata;
// TODO: Switch over to LLVM's ADT container classes. // TODO: Switch over to LLVM's ADT container classes.
// http://llvm.org/docs/ProgrammersManual.html#picking-the-right-data-structure-for-a-task // http://llvm.org/docs/ProgrammersManual.html#picking-the-right-data-structure-for-a-task
typedef std::string IceString; typedef std::string IceString;
typedef std::list<Inst *> InstList; typedef llvm::ilist<Inst> InstList;
typedef std::list<InstAssign *> AssignList; typedef std::list<InstAssign *> AssignList;
typedef std::list<InstPhi *> PhiList; typedef std::list<InstPhi *> PhiList;
typedef std::vector<Variable *> VarList; typedef std::vector<Variable *> VarList;
......
...@@ -34,7 +34,7 @@ namespace Ice { ...@@ -34,7 +34,7 @@ namespace Ice {
// InstHighLevel and InstTarget. High-level ICE instructions inherit // InstHighLevel and InstTarget. High-level ICE instructions inherit
// from InstHighLevel, and low-level (target-specific) ICE // from InstHighLevel, and low-level (target-specific) ICE
// instructions inherit from InstTarget. // instructions inherit from InstTarget.
class Inst { class Inst : public llvm::ilist_node<Inst> {
Inst(const Inst &) = delete; Inst(const Inst &) = delete;
Inst &operator=(const Inst &) = delete; Inst &operator=(const Inst &) = delete;
...@@ -838,4 +838,22 @@ protected: ...@@ -838,4 +838,22 @@ protected:
} // end of namespace Ice } // end of namespace Ice
// Override the default ilist traits so that Inst's private ctor and
// deleted dtor aren't invoked.
template <>
struct llvm::ilist_traits<Ice::Inst> : public llvm::ilist_default_traits<
Ice::Inst> {
Ice::Inst *createSentinel() const {
return static_cast<Ice::Inst *>(&Sentinel);
}
static void destroySentinel(Ice::Inst *) {}
Ice::Inst *provideInitialHead() const { return createSentinel(); }
Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
static void noteHead(Ice::Inst *, Ice::Inst *) {}
void deleteNode(Ice::Inst *) {}
private:
mutable ilist_half_node<Ice::Inst> Sentinel;
};
#endif // SUBZERO_SRC_ICEINST_H #endif // SUBZERO_SRC_ICEINST_H
...@@ -347,7 +347,8 @@ void VariablesMetadata::addNode(CfgNode *Node) { ...@@ -347,7 +347,8 @@ void VariablesMetadata::addNode(CfgNode *Node) {
} }
} }
for (Inst *I : Node->getInsts()) { for (auto I = Node->getInsts().begin(), E = Node->getInsts().end(); I != E;
++I) {
if (I->isDeleted()) if (I->isDeleted())
continue; continue;
// Note: The implicit definitions (and uses) from InstFakeKill are // Note: The implicit definitions (and uses) from InstFakeKill are
......
...@@ -62,7 +62,7 @@ void LoweringContext::insert(Inst *Inst) { ...@@ -62,7 +62,7 @@ void LoweringContext::insert(Inst *Inst) {
} }
void LoweringContext::skipDeleted(InstList::iterator &I) const { void LoweringContext::skipDeleted(InstList::iterator &I) const {
while (I != End && (*I)->isDeleted()) while (I != End && I->isDeleted())
++I; ++I;
} }
...@@ -116,7 +116,7 @@ void TargetLowering::doAddressOpt() { ...@@ -116,7 +116,7 @@ void TargetLowering::doAddressOpt() {
bool TargetLowering::shouldDoNopInsertion() const { return DoNopInsertion; } bool TargetLowering::shouldDoNopInsertion() const { return DoNopInsertion; }
void TargetLowering::doNopInsertion() { void TargetLowering::doNopInsertion() {
Inst *I = *Context.getCur(); Inst *I = Context.getCur();
bool ShouldSkip = llvm::isa<InstFakeUse>(I) || llvm::isa<InstFakeDef>(I) || bool ShouldSkip = llvm::isa<InstFakeUse>(I) || llvm::isa<InstFakeDef>(I) ||
llvm::isa<InstFakeKill>(I) || I->isRedundantAssign() || llvm::isa<InstFakeKill>(I) || I->isRedundantAssign() ||
I->isDeleted(); I->isDeleted();
...@@ -141,7 +141,7 @@ void TargetLowering::doNopInsertion() { ...@@ -141,7 +141,7 @@ void TargetLowering::doNopInsertion() {
// instructions it consumes. // instructions it consumes.
void TargetLowering::lower() { void TargetLowering::lower() {
assert(!Context.atEnd()); assert(!Context.atEnd());
Inst *Inst = *Context.getCur(); Inst *Inst = Context.getCur();
// Mark the current instruction as deleted before lowering, // Mark the current instruction as deleted before lowering,
// otherwise the Dest variable will likely get marked as non-SSA. // otherwise the Dest variable will likely get marked as non-SSA.
// See Variable::setDefinition(). // See Variable::setDefinition().
......
...@@ -45,13 +45,13 @@ public: ...@@ -45,13 +45,13 @@ public:
Inst *getNextInst() const { Inst *getNextInst() const {
if (Next == End) if (Next == End)
return NULL; return NULL;
return *Next; return Next;
} }
Inst *getNextInst(InstList::iterator &Iter) const { Inst *getNextInst(InstList::iterator &Iter) const {
advanceForward(Iter); advanceForward(Iter);
if (Iter == End) if (Iter == End)
return NULL; return NULL;
return *Iter; return Iter;
} }
CfgNode *getNode() const { return Node; } CfgNode *getNode() const { return Node; }
bool atEnd() const { return Cur == End; } bool atEnd() const { return Cur == End; }
......
...@@ -3826,7 +3826,7 @@ void TargetX8632::lowerLoad(const InstLoad *Inst) { ...@@ -3826,7 +3826,7 @@ void TargetX8632::lowerLoad(const InstLoad *Inst) {
} }
void TargetX8632::doAddressOptLoad() { void TargetX8632::doAddressOptLoad() {
Inst *Inst = *Context.getCur(); Inst *Inst = Context.getCur();
Variable *Dest = Inst->getDest(); Variable *Dest = Inst->getDest();
Operand *Addr = Inst->getSrc(0); Operand *Addr = Inst->getSrc(0);
Variable *Index = NULL; Variable *Index = NULL;
...@@ -4004,7 +4004,7 @@ void TargetX8632::lowerStore(const InstStore *Inst) { ...@@ -4004,7 +4004,7 @@ void TargetX8632::lowerStore(const InstStore *Inst) {
} }
void TargetX8632::doAddressOptStore() { void TargetX8632::doAddressOptStore() {
InstStore *Inst = llvm::cast<InstStore>(*Context.getCur()); InstStore *Inst = llvm::cast<InstStore>(Context.getCur());
Operand *Data = Inst->getData(); Operand *Data = Inst->getData();
Operand *Addr = Inst->getAddr(); Operand *Addr = Inst->getAddr();
Variable *Index = NULL; Variable *Index = NULL;
...@@ -4502,7 +4502,7 @@ void TargetX8632::postLower() { ...@@ -4502,7 +4502,7 @@ void TargetX8632::postLower() {
if (Ctx->getOptLevel() != Opt_m1) { if (Ctx->getOptLevel() != Opt_m1) {
// Find two-address non-SSA instructions where Dest==Src0, and set // Find two-address non-SSA instructions where Dest==Src0, and set
// the DestNonKillable flag to keep liveness analysis consistent. // the DestNonKillable flag to keep liveness analysis consistent.
for (Inst *Inst : Context) { for (auto Inst = Context.begin(), E = Context.end(); Inst != E; ++Inst) {
if (Inst->isDeleted()) if (Inst->isDeleted())
continue; continue;
if (Variable *Dest = Inst->getDest()) { if (Variable *Dest = Inst->getDest()) {
...@@ -4529,7 +4529,7 @@ void TargetX8632::postLower() { ...@@ -4529,7 +4529,7 @@ void TargetX8632::postLower() {
// The first pass also keeps track of which instruction is the last // The first pass also keeps track of which instruction is the last
// use for each infinite-weight variable. After the last use, the // use for each infinite-weight variable. After the last use, the
// variable is released to the free list. // variable is released to the free list.
for (Inst *Inst : Context) { for (auto Inst = Context.begin(), E = Context.end(); Inst != E; ++Inst) {
if (Inst->isDeleted()) if (Inst->isDeleted())
continue; continue;
// Don't consider a FakeKill instruction, because (currently) it // Don't consider a FakeKill instruction, because (currently) it
...@@ -4560,7 +4560,7 @@ void TargetX8632::postLower() { ...@@ -4560,7 +4560,7 @@ void TargetX8632::postLower() {
// The second pass colors infinite-weight variables. // The second pass colors infinite-weight variables.
llvm::SmallBitVector AvailableRegisters = WhiteList; llvm::SmallBitVector AvailableRegisters = WhiteList;
llvm::SmallBitVector FreedRegisters(WhiteList.size()); llvm::SmallBitVector FreedRegisters(WhiteList.size());
for (Inst *Inst : Context) { for (auto Inst = Context.begin(), E = Context.end(); Inst != E; ++Inst) {
FreedRegisters.reset(); FreedRegisters.reset();
if (Inst->isDeleted()) if (Inst->isDeleted())
continue; continue;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment