[llvm-commits] [llvm] r66815 - in /llvm/trunk: include/llvm/Instructions.h include/llvm/Use.h include/llvm/User.h lib/VMCore/Instructions.cpp lib/VMCore/Use.cpp lib/VMCore/Value.cpp
Gabor Greif
ggreif at gmail.com
Thu Mar 12 11:34:49 PDT 2009
Author: ggreif
Date: Thu Mar 12 13:34:49 2009
New Revision: 66815
URL: http://llvm.org/viewvc/llvm-project?rev=66815&view=rev
Log:
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.
Modified:
llvm/trunk/include/llvm/Instructions.h
llvm/trunk/include/llvm/Use.h
llvm/trunk/include/llvm/User.h
llvm/trunk/lib/VMCore/Instructions.cpp
llvm/trunk/lib/VMCore/Use.cpp
llvm/trunk/lib/VMCore/Value.cpp
Modified: llvm/trunk/include/llvm/Instructions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Instructions.h?rev=66815&r1=66814&r2=66815&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Instructions.h (original)
+++ llvm/trunk/include/llvm/Instructions.h Thu Mar 12 13:34:49 2009
@@ -2117,8 +2117,9 @@
///
class BranchInst : public TerminatorInst {
/// Ops list - Branches are strange. The operands are ordered:
- /// TrueDest, FalseDest, Cond. This makes some accessors faster because
- /// they don't have to check for cond/uncond branchness.
+ /// [Cond, FalseDest,] TrueDest. This makes some accessors faster because
+ /// they don't have to check for cond/uncond branchness. These are mostly
+ /// accessed relative from op_end().
BranchInst(const BranchInst &BI);
void AssertOK();
// BranchInst constructors (where {B, T, F} are blocks, and C is a condition):
@@ -2136,24 +2137,21 @@
BasicBlock *InsertAtEnd);
public:
static BranchInst *Create(BasicBlock *IfTrue, Instruction *InsertBefore = 0) {
- return new(1) BranchInst(IfTrue, InsertBefore);
+ return new(1, true) BranchInst(IfTrue, InsertBefore);
}
static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse,
Value *Cond, Instruction *InsertBefore = 0) {
return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertBefore);
}
static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *InsertAtEnd) {
- return new(1) BranchInst(IfTrue, InsertAtEnd);
+ return new(1, true) BranchInst(IfTrue, InsertAtEnd);
}
static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse,
Value *Cond, BasicBlock *InsertAtEnd) {
return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertAtEnd);
}
- ~BranchInst() {
- if (NumOperands == 1)
- NumOperands = (unsigned)((Use*)this - OperandList);
- }
+ ~BranchInst();
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -2165,23 +2163,24 @@
Value *getCondition() const {
assert(isConditional() && "Cannot get condition of an uncond branch!");
- return getOperand(2);
+ return Op<-3>();
}
void setCondition(Value *V) {
assert(isConditional() && "Cannot set condition of unconditional branch!");
- setOperand(2, V);
+ Op<-3>() = V;
}
// setUnconditionalDest - Change the current branch to an unconditional branch
// targeting the specified block.
// FIXME: Eliminate this ugly method.
void setUnconditionalDest(BasicBlock *Dest) {
- Op<0>() = Dest;
+ Op<-1>() = Dest;
if (isConditional()) { // Convert this to an uncond branch.
- Op<1>().set(0);
- Op<2>().set(0);
+ Op<-2>() = 0;
+ Op<-3>() = 0;
NumOperands = 1;
+ OperandList = op_begin();
}
}
@@ -2189,12 +2188,12 @@
BasicBlock *getSuccessor(unsigned i) const {
assert(i < getNumSuccessors() && "Successor # out of range for Branch!");
- return cast_or_null<BasicBlock>(getOperand(i));
+ return cast_or_null<BasicBlock>((&Op<-1>() - i)->get());
}
void setSuccessor(unsigned idx, BasicBlock *NewSucc) {
assert(idx < getNumSuccessors() && "Successor # out of range for Branch!");
- setOperand(idx, NewSucc);
+ *(&Op<-1>() - idx) = NewSucc;
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -2212,11 +2211,7 @@
};
template <>
-struct OperandTraits<BranchInst> : HungoffOperandTraits<> {
- // we need to access operands via OperandList, since
- // the NumOperands may change from 3 to 1
- static inline void *allocate(unsigned); // FIXME
-};
+struct OperandTraits<BranchInst> : VariadicOperandTraits<1> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value)
Modified: llvm/trunk/include/llvm/Use.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Use.h?rev=66815&r1=66814&r2=66815&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Use.h (original)
+++ llvm/trunk/include/llvm/Use.h Thu Mar 12 13:34:49 2009
@@ -92,6 +92,8 @@
/// a User changes.
static void zap(Use *Start, const Use *Stop, bool del = false);
+ /// getPrefix - Return deletable pointer if appropriate
+ Use *getPrefix();
private:
const Use* getImpliedUser() const;
static Use *initTags(Use *Start, Use *Stop, ptrdiff_t Done = 0);
Modified: llvm/trunk/include/llvm/User.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/User.h?rev=66815&r1=66814&r2=66815&view=diff
==============================================================================
--- llvm/trunk/include/llvm/User.h (original)
+++ llvm/trunk/include/llvm/User.h Thu Mar 12 13:34:49 2009
@@ -62,6 +62,7 @@
unsigned NumOperands;
void *operator new(size_t s, unsigned Us);
+ void *operator new(size_t s, unsigned Us, bool Prefix);
User(const Type *ty, unsigned vty, Use *OpList, unsigned NumOps)
: Value(ty, vty), OperandList(OpList), NumOperands(NumOps) {}
Use *allocHungoffUses(unsigned) const;
@@ -74,7 +75,8 @@
}
public:
~User() {
- Use::zap(OperandList, OperandList + NumOperands);
+ if ((intptr_t(OperandList) & 1) == 0)
+ Use::zap(OperandList, OperandList + NumOperands);
}
/// operator delete - free memory allocated for User and Use objects
void operator delete(void *Usr);
Modified: llvm/trunk/lib/VMCore/Instructions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instructions.cpp?rev=66815&r1=66814&r2=66815&view=diff
==============================================================================
--- llvm/trunk/lib/VMCore/Instructions.cpp (original)
+++ llvm/trunk/lib/VMCore/Instructions.cpp Thu Mar 12 13:34:49 2009
@@ -612,16 +612,16 @@
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 @@
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 @@
: 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 @@
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 @@
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 {
Modified: llvm/trunk/lib/VMCore/Use.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Use.cpp?rev=66815&r1=66814&r2=66815&view=diff
==============================================================================
--- llvm/trunk/lib/VMCore/Use.cpp (original)
+++ llvm/trunk/lib/VMCore/Use.cpp Thu Mar 12 13:34:49 2009
@@ -163,4 +163,71 @@
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
Modified: llvm/trunk/lib/VMCore/Value.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Value.cpp?rev=66815&r1=66814&r2=66815&view=diff
==============================================================================
--- llvm/trunk/lib/VMCore/Value.cpp (original)
+++ llvm/trunk/lib/VMCore/Value.cpp Thu Mar 12 13:34:49 2009
@@ -406,21 +406,3 @@
}
}
-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);
-}
More information about the llvm-commits
mailing list