diff options
author | Jay Foad <jay.foad@gmail.com> | 2011-06-20 14:38:01 +0000 |
---|---|---|
committer | Jay Foad <jay.foad@gmail.com> | 2011-06-20 14:38:01 +0000 |
commit | 72f5f313d87558958696ce69593d82efcdfa9128 (patch) | |
tree | de93d765561f6dd605919f206871568262f09a2d /include | |
parent | c137120bb047a7017cbab21f5f9c9e6f65e2b84f (diff) |
Change how PHINodes store their operands.
Change PHINodes to store simple pointers to their incoming basic blocks,
instead of full-blown Uses.
Note that this loses an optimization in SplitCriticalEdge(), because we
can no longer walk the use list of a BasicBlock to find phi nodes. See
the comment I removed starting "However, the foreach loop is slow for
blocks with lots of predecessors".
Extend replaceAllUsesWith() on a BasicBlock to also update any phi
nodes in the block's successors. This mimics what would have happened
when PHINodes were proper Users of their incoming blocks. (Note that
this only works if OldBB->replaceAllUsesWith(NewBB) is called when
OldBB still has a terminator instruction, so it still has some
successors.)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133435 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r-- | include/llvm/BasicBlock.h | 6 | ||||
-rw-r--r-- | include/llvm/Instructions.h | 81 | ||||
-rw-r--r-- | include/llvm/Support/CFG.h | 2 | ||||
-rw-r--r-- | include/llvm/Use.h | 6 |
4 files changed, 61 insertions, 34 deletions
diff --git a/include/llvm/BasicBlock.h b/include/llvm/BasicBlock.h index 7e7c9e7694..b02c249c7e 100644 --- a/include/llvm/BasicBlock.h +++ b/include/llvm/BasicBlock.h @@ -110,7 +110,7 @@ public: Function *getParent() { return Parent; } /// use_back - Specialize the methods defined in Value, as we know that an - /// BasicBlock can only be used by Users (specifically PHI nodes, terminators, + /// BasicBlock can only be used by Users (specifically terminators /// and BlockAddress's). User *use_back() { return cast<User>(*use_begin());} const User *use_back() const { return cast<User>(*use_begin());} @@ -248,6 +248,10 @@ public: /// other than direct branches, switches, etc. to it. bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; } + /// replaceSuccessorsPhiUsesWith - Update all phi nodes in all our successors + /// to refer to basic block New instead of to us. + void replaceSuccessorsPhiUsesWith(BasicBlock *New); + private: /// AdjustBlockAddressRefCount - BasicBlock stores the number of BlockAddress /// objects using it. This is almost always 0, sometimes one, possibly but diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index 54dfe3957f..cc3801043e 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -1814,7 +1814,7 @@ class PHINode : public Instruction { explicit PHINode(const Type *Ty, unsigned NumReservedValues, const Twine &NameStr = "", Instruction *InsertBefore = 0) : Instruction(Ty, Instruction::PHI, 0, 0, InsertBefore), - ReservedSpace(NumReservedValues * 2) { + ReservedSpace(NumReservedValues) { setName(NameStr); OperandList = allocHungoffUses(ReservedSpace); } @@ -1822,11 +1822,16 @@ class PHINode : public Instruction { PHINode(const Type *Ty, unsigned NumReservedValues, const Twine &NameStr, BasicBlock *InsertAtEnd) : Instruction(Ty, Instruction::PHI, 0, 0, InsertAtEnd), - ReservedSpace(NumReservedValues * 2) { + ReservedSpace(NumReservedValues) { setName(NameStr); OperandList = allocHungoffUses(ReservedSpace); } protected: + // allocHungoffUses - this is more complicated than the generic + // User::allocHungoffUses, because we have to allocate Uses for the incoming + // values and pointers to the incoming blocks, all in one allocation. + Use *allocHungoffUses(unsigned) const; + virtual PHINode *clone_impl() const; public: /// Constructors - NumReservedValues is a hint for the number of incoming @@ -1845,32 +1850,55 @@ public: /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + // Block iterator interface. This provides access to the list of incoming + // basic blocks, which parallels the list of incoming values. + + typedef BasicBlock **block_iterator; + typedef BasicBlock * const *const_block_iterator; + + block_iterator block_begin() { + Use::UserRef *ref = + reinterpret_cast<Use::UserRef*>(op_begin() + ReservedSpace); + return reinterpret_cast<block_iterator>(ref + 1); + } + + const_block_iterator block_begin() const { + const Use::UserRef *ref = + reinterpret_cast<const Use::UserRef*>(op_begin() + ReservedSpace); + return reinterpret_cast<const_block_iterator>(ref + 1); + } + + block_iterator block_end() { + return block_begin() + getNumOperands(); + } + + const_block_iterator block_end() const { + return block_begin() + getNumOperands(); + } + /// getNumIncomingValues - Return the number of incoming edges /// - unsigned getNumIncomingValues() const { return getNumOperands()/2; } + unsigned getNumIncomingValues() const { return getNumOperands(); } /// getIncomingValue - Return incoming value number x /// Value *getIncomingValue(unsigned i) const { - assert(i*2 < getNumOperands() && "Invalid value number!"); - return getOperand(i*2); + return getOperand(i); } void setIncomingValue(unsigned i, Value *V) { - assert(i*2 < getNumOperands() && "Invalid value number!"); - setOperand(i*2, V); + setOperand(i, V); } static unsigned getOperandNumForIncomingValue(unsigned i) { - return i*2; + return i; } static unsigned getIncomingValueNumForOperand(unsigned i) { - assert(i % 2 == 0 && "Invalid incoming-value operand index!"); - return i/2; + return i; } /// getIncomingBlock - Return incoming basic block number @p i. /// BasicBlock *getIncomingBlock(unsigned i) const { - return cast<BasicBlock>(getOperand(i*2+1)); + return block_begin()[i]; } /// getIncomingBlock - Return incoming basic block corresponding @@ -1878,7 +1906,7 @@ public: /// BasicBlock *getIncomingBlock(const Use &U) const { assert(this == U.getUser() && "Iterator doesn't point to PHI's Uses?"); - return cast<BasicBlock>((&U + 1)->get()); + return getIncomingBlock(&U - op_begin()); } /// getIncomingBlock - Return incoming basic block corresponding @@ -1889,16 +1917,8 @@ public: return getIncomingBlock(I.getUse()); } - void setIncomingBlock(unsigned i, BasicBlock *BB) { - setOperand(i*2+1, (Value*)BB); - } - static unsigned getOperandNumForIncomingBlock(unsigned i) { - return i*2+1; - } - static unsigned getIncomingBlockNumForOperand(unsigned i) { - assert(i % 2 == 1 && "Invalid incoming-block operand index!"); - return i/2; + block_begin()[i] = BB; } /// addIncoming - Add an incoming value to the end of the PHI list @@ -1908,13 +1928,12 @@ public: assert(BB && "PHI node got a null basic block!"); assert(getType() == V->getType() && "All operands to PHI node must be the same type as the PHI node!"); - unsigned OpNo = NumOperands; - if (OpNo+2 > ReservedSpace) + if (NumOperands == ReservedSpace) growOperands(); // Get more space! // Initialize some new operands. - NumOperands = OpNo+2; - OperandList[OpNo] = V; - OperandList[OpNo+1] = (Value*)BB; + ++NumOperands; + setIncomingValue(NumOperands - 1, V); + setIncomingBlock(NumOperands - 1, BB); } /// removeIncomingValue - Remove an incoming value. This is useful if a @@ -1937,14 +1956,16 @@ public: /// block in the value list for this PHI. Returns -1 if no instance. /// int getBasicBlockIndex(const BasicBlock *BB) const { - Use *OL = OperandList; - for (unsigned i = 0, e = getNumOperands(); i != e; i += 2) - if (OL[i+1].get() == (const Value*)BB) return i/2; + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (block_begin()[i] == BB) + return i; return -1; } Value *getIncomingValueForBlock(const BasicBlock *BB) const { - return getIncomingValue(getBasicBlockIndex(BB)); + int Idx = getBasicBlockIndex(BB); + assert(Idx >= 0 && "Invalid basic block argument!"); + return getIncomingValue(Idx); } /// hasConstantValue - If the specified PHI node always merges together the diff --git a/include/llvm/Support/CFG.h b/include/llvm/Support/CFG.h index d2ea12364e..7e193ff15e 100644 --- a/include/llvm/Support/CFG.h +++ b/include/llvm/Support/CFG.h @@ -33,7 +33,7 @@ class PredIterator : public std::iterator<std::forward_iterator_tag, USE_iterator It; inline void advancePastNonTerminators() { - // Loop to ignore non terminator uses (for example PHI nodes). + // Loop to ignore non terminator uses (for example BlockAddresses). while (!It.atEnd() && !isa<TerminatorInst>(*It)) ++It; } diff --git a/include/llvm/Use.h b/include/llvm/Use.h index 1bdacb48f4..a496325c1f 100644 --- a/include/llvm/Use.h +++ b/include/llvm/Use.h @@ -112,13 +112,16 @@ public: Use *getNext() const { return Next; } + /// initTags - initialize the waymarking tags on an array of Uses, so that + /// getUser() can find the User from any of those Uses. + static Use *initTags(Use *Start, Use *Stop); + /// zap - This is used to destroy Use operands when the number of operands of /// a User changes. static void zap(Use *Start, const Use *Stop, bool del = false); private: const Use* getImpliedUser() const; - static Use *initTags(Use *Start, Use *Stop); Value *Val; Use *Next; @@ -140,7 +143,6 @@ private: } friend class Value; - friend class User; }; // simplify_type - Allow clients to treat uses just like values when using |