diff options
author | Gabor Greif <ggreif@gmail.com> | 2009-03-12 18:34:49 +0000 |
---|---|---|
committer | Gabor Greif <ggreif@gmail.com> | 2009-03-12 18:34:49 +0000 |
commit | ae5a20a9177650525b40ed88c8326a398e6caa8a (patch) | |
tree | a9a55d209febc8db93b45efd3be22850d744366b /lib/VMCore | |
parent | a065200eaf71248133470caf03eefea449fff7b4 (diff) | |
download | external_llvm-ae5a20a9177650525b40ed88c8326a398e6caa8a.zip external_llvm-ae5a20a9177650525b40ed88c8326a398e6caa8a.tar.gz external_llvm-ae5a20a9177650525b40ed88c8326a398e6caa8a.tar.bz2 |
Rearrange operands of the BranchInst, to be able to
access each with a fixed negative index from op_end().
This has two important implications:
- getUser() will work faster, because there are less iterations
for the waymarking algorithm to perform. This is important
when running various analyses that want to determine callers
of basic blocks.
- getSuccessor() now runs faster, because the indirection via OperandList
is not necessary: Uses corresponding to the successors are at fixed
offset to "this".
The price we pay is the slightly more complicated logic in the operator
User::delete, as it has to pick up the information whether it has to free
the memory of an original unconditional BranchInst or a BranchInst that
was originally conditional, but has been shortened to unconditional.
I was not able to come up with a nicer solution to this problem. (And
rest assured, I tried *a lot*).
Similar reorderings will follow for InvokeInst and CallInst. After that
some optimizations to pred_iterator and CallSite will fall out naturally.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@66815 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore')
-rw-r--r-- | lib/VMCore/Instructions.cpp | 50 | ||||
-rw-r--r-- | lib/VMCore/Use.cpp | 67 | ||||
-rw-r--r-- | lib/VMCore/Value.cpp | 18 |
3 files changed, 105 insertions, 30 deletions
diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 7f5d461..fe30271 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -612,16 +612,16 @@ BranchInst::BranchInst(BasicBlock *IfTrue, Instruction *InsertBefore) OperandTraits<BranchInst>::op_end(this) - 1, 1, InsertBefore) { assert(IfTrue != 0 && "Branch destination may not be null!"); - Op<0>() = IfTrue; + Op<-1>() = IfTrue; } BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, Instruction *InsertBefore) : TerminatorInst(Type::VoidTy, Instruction::Br, OperandTraits<BranchInst>::op_end(this) - 3, 3, InsertBefore) { - Op<0>() = IfTrue; - Op<1>() = IfFalse; - Op<2>() = Cond; + Op<-1>() = IfTrue; + Op<-2>() = IfFalse; + Op<-3>() = Cond; #ifndef NDEBUG AssertOK(); #endif @@ -632,7 +632,7 @@ BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *InsertAtEnd) OperandTraits<BranchInst>::op_end(this) - 1, 1, InsertAtEnd) { assert(IfTrue != 0 && "Branch destination may not be null!"); - Op<0>() = IfTrue; + Op<-1>() = IfTrue; } BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, @@ -640,9 +640,9 @@ BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, : TerminatorInst(Type::VoidTy, Instruction::Br, OperandTraits<BranchInst>::op_end(this) - 3, 3, InsertAtEnd) { - Op<0>() = IfTrue; - Op<1>() = IfFalse; - Op<2>() = Cond; + Op<-1>() = IfTrue; + Op<-2>() = IfFalse; + Op<-3>() = Cond; #ifndef NDEBUG AssertOK(); #endif @@ -653,14 +653,39 @@ BranchInst::BranchInst(const BranchInst &BI) : TerminatorInst(Type::VoidTy, Instruction::Br, OperandTraits<BranchInst>::op_end(this) - BI.getNumOperands(), BI.getNumOperands()) { - OperandList[0] = BI.getOperand(0); + Op<-1>() = BI.Op<-1>(); if (BI.getNumOperands() != 1) { assert(BI.getNumOperands() == 3 && "BR can have 1 or 3 operands!"); - OperandList[1] = BI.getOperand(1); - OperandList[2] = BI.getOperand(2); + Op<-3>() = BI.Op<-3>(); + Op<-2>() = BI.Op<-2>(); } } + +Use* Use::getPrefix() { + PointerIntPair<Use**, 2, PrevPtrTag> &PotentialPrefix(this[-1].Prev); + if (PotentialPrefix.getOpaqueValue()) + return 0; + + return reinterpret_cast<Use*>((char*)&PotentialPrefix + 1); +} + +BranchInst::~BranchInst() { + if (NumOperands == 1) { + if (Use *Prefix = OperandList->getPrefix()) { + Op<-1>() = 0; + // + // mark OperandList to have a special value for scrutiny + // by baseclass destructors and operator delete + OperandList = Prefix; + } else { + NumOperands = 3; + OperandList = op_begin(); + } + } +} + + BasicBlock *BranchInst::getSuccessorV(unsigned idx) const { return getSuccessor(idx); } @@ -2927,7 +2952,8 @@ ReturnInst *ReturnInst::clone() const { return new(getNumOperands()) ReturnInst(*this); } BranchInst *BranchInst::clone() const { - return new(getNumOperands()) BranchInst(*this); + unsigned Ops(getNumOperands()); + return new(Ops, Ops == 1) BranchInst(*this); } SwitchInst *SwitchInst::clone() const { return new SwitchInst(*this); } InvokeInst *InvokeInst::clone() const { diff --git a/lib/VMCore/Use.cpp b/lib/VMCore/Use.cpp index 0c566a9..b25415a 100644 --- a/lib/VMCore/Use.cpp +++ b/lib/VMCore/Use.cpp @@ -163,4 +163,71 @@ Use *User::allocHungoffUses(unsigned N) const { return Use::initTags(Begin, End); } +//===----------------------------------------------------------------------===// +// User operator new Implementations +//===----------------------------------------------------------------------===// + +void *User::operator new(size_t s, unsigned Us) { + void *Storage = ::operator new(s + sizeof(Use) * Us); + Use *Start = static_cast<Use*>(Storage); + Use *End = Start + Us; + User *Obj = reinterpret_cast<User*>(End); + Obj->OperandList = Start; + Obj->NumOperands = Us; + Use::initTags(Start, End); + return Obj; +} + +/// Prefixed allocation - just before the first Use, allocate a NULL pointer. +/// The destructor can detect its presence and readjust the OperandList +/// for deletition. +/// +void *User::operator new(size_t s, unsigned Us, bool Prefix) { + // currently prefixed allocation only admissible for + // unconditional branch instructions + if (!Prefix) + return operator new(s, Us); + + assert(Us == 1 && "Other than one Use allocated?"); + typedef PointerIntPair<void*, 2, Use::PrevPtrTag> TaggedPrefix; + void *Raw = ::operator new(s + sizeof(TaggedPrefix) + sizeof(Use) * Us); + TaggedPrefix *Pre = static_cast<TaggedPrefix*>(Raw); + Pre->setFromOpaqueValue(0); + void *Storage = Pre + 1; // skip over prefix + Use *Start = static_cast<Use*>(Storage); + Use *End = Start + Us; + User *Obj = reinterpret_cast<User*>(End); + Obj->OperandList = Start; + Obj->NumOperands = Us; + Use::initTags(Start, End); + return Obj; +} + +//===----------------------------------------------------------------------===// +// User operator delete Implementation +//===----------------------------------------------------------------------===// + +void User::operator delete(void *Usr) { + User *Start = static_cast<User*>(Usr); + Use *Storage = static_cast<Use*>(Usr) - Start->NumOperands; + // + // look for a variadic User + if (Storage == Start->OperandList) { + ::operator delete(Storage); + return; + } + // + // check for the flag whether the destructor has detected a prefixed + // allocation, in which case we remove the flag and delete starting + // at OperandList + if (reinterpret_cast<intptr_t>(Start->OperandList) & 1) { + ::operator delete(reinterpret_cast<char*>(Start->OperandList) - 1); + return; + } + // + // in all other cases just delete the nullary User (covers hung-off + // uses also + ::operator delete(Usr); +} + } // End llvm namespace diff --git a/lib/VMCore/Value.cpp b/lib/VMCore/Value.cpp index ab7e044..0aa2db4 100644 --- a/lib/VMCore/Value.cpp +++ b/lib/VMCore/Value.cpp @@ -406,21 +406,3 @@ void User::replaceUsesOfWith(Value *From, Value *To) { } } -void *User::operator new(size_t s, unsigned Us) { - void *Storage = ::operator new(s + sizeof(Use) * Us); - Use *Start = static_cast<Use*>(Storage); - Use *End = Start + Us; - User *Obj = reinterpret_cast<User*>(End); - Obj->OperandList = Start; - Obj->NumOperands = Us; - Use::initTags(Start, End); - return Obj; -} - -void User::operator delete(void *Usr) { - User *Start = static_cast<User*>(Usr); - Use *Storage = static_cast<Use*>(Usr) - Start->NumOperands; - ::operator delete(Storage == Start->OperandList - ? Storage - : Usr); -} |