diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-04-02 08:54:30 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-04-02 08:54:30 +0000 |
commit | 20e856b2a58d12231aa42d5d13888b15ac03e5a4 (patch) | |
tree | cf5763d092b81cecc168fa28032247ee495d06e2 /include/llvm/Support | |
parent | 2f2afc1aae898651e26987a5c71f3febb19bca98 (diff) | |
download | FreeBSD-src-20e856b2a58d12231aa42d5d13888b15ac03e5a4.zip FreeBSD-src-20e856b2a58d12231aa42d5d13888b15ac03e5a4.tar.gz |
Update LLVM to r100181.
Diffstat (limited to 'include/llvm/Support')
-rw-r--r-- | include/llvm/Support/Allocator.h | 40 | ||||
-rw-r--r-- | include/llvm/Support/CFG.h | 12 | ||||
-rw-r--r-- | include/llvm/Support/CallSite.h | 279 | ||||
-rw-r--r-- | include/llvm/Support/Casting.h | 20 | ||||
-rw-r--r-- | include/llvm/Support/DebugLoc.h | 65 | ||||
-rw-r--r-- | include/llvm/Support/FileUtilities.h | 13 | ||||
-rw-r--r-- | include/llvm/Support/IRBuilder.h | 22 | ||||
-rw-r--r-- | include/llvm/Support/MathExtras.h | 50 | ||||
-rw-r--r-- | include/llvm/Support/Timer.h | 179 | ||||
-rw-r--r-- | include/llvm/Support/ValueHandle.h | 5 | ||||
-rw-r--r-- | include/llvm/Support/raw_ostream.h | 1 |
11 files changed, 447 insertions, 239 deletions
diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index b1f59dc..bd38180 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -133,6 +133,7 @@ class BumpPtrAllocator { static MallocSlabAllocator DefaultSlabAllocator; + template<typename T> friend class SpecificBumpPtrAllocator; public: BumpPtrAllocator(size_t size = 4096, size_t threshold = 4096, SlabAllocator &allocator = DefaultSlabAllocator); @@ -176,6 +177,45 @@ public: void PrintStats() const; }; +/// SpecificBumpPtrAllocator - Same as BumpPtrAllocator but allows only +/// elements of one type to be allocated. This allows calling the destructor +/// in DestroyAll() and when the allocator is destroyed. +template <typename T> +class SpecificBumpPtrAllocator { + BumpPtrAllocator Allocator; +public: + SpecificBumpPtrAllocator(size_t size = 4096, size_t threshold = 4096, + SlabAllocator &allocator = BumpPtrAllocator::DefaultSlabAllocator) + : Allocator(size, threshold, allocator) {} + + ~SpecificBumpPtrAllocator() { + DestroyAll(); + } + + /// Call the destructor of each allocated object and deallocate all but the + /// current slab and reset the current pointer to the beginning of it, freeing + /// all memory allocated so far. + void DestroyAll() { + MemSlab *Slab = Allocator.CurSlab; + while (Slab) { + char *End = Slab == Allocator.CurSlab ? Allocator.CurPtr : + (char *)Slab + Slab->Size; + for (char *Ptr = (char*)Slab+1; Ptr < End; Ptr += sizeof(T)) { + Ptr = Allocator.AlignPtr(Ptr, alignof<T>()); + if (Ptr + sizeof(T) <= End) + reinterpret_cast<T*>(Ptr)->~T(); + } + Slab = Slab->NextPtr; + } + Allocator.Reset(); + } + + /// Allocate space for a specific count of elements. + T *Allocate(size_t num = 1) { + return Allocator.Allocate<T>(num); + } +}; + } // end namespace llvm inline void *operator new(size_t Size, llvm::BumpPtrAllocator &Allocator) { diff --git a/include/llvm/Support/CFG.h b/include/llvm/Support/CFG.h index 3875f0b..57699c7 100644 --- a/include/llvm/Support/CFG.h +++ b/include/llvm/Support/CFG.h @@ -67,15 +67,15 @@ public: typedef PredIterator<BasicBlock, Value::use_iterator> pred_iterator; typedef PredIterator<const BasicBlock, - Value::use_const_iterator> pred_const_iterator; + Value::const_use_iterator> const_pred_iterator; inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); } -inline pred_const_iterator pred_begin(const BasicBlock *BB) { - return pred_const_iterator(BB); +inline const_pred_iterator pred_begin(const BasicBlock *BB) { + return const_pred_iterator(BB); } inline pred_iterator pred_end(BasicBlock *BB) { return pred_iterator(BB, true);} -inline pred_const_iterator pred_end(const BasicBlock *BB) { - return pred_const_iterator(BB, true); +inline const_pred_iterator pred_end(const BasicBlock *BB) { + return const_pred_iterator(BB, true); } @@ -268,7 +268,7 @@ template <> struct GraphTraits<Inverse<BasicBlock*> > { template <> struct GraphTraits<Inverse<const BasicBlock*> > { typedef const BasicBlock NodeType; - typedef pred_const_iterator ChildIteratorType; + typedef const_pred_iterator ChildIteratorType; static NodeType *getEntryNode(Inverse<const BasicBlock*> G) { return G.Graph; } diff --git a/include/llvm/Support/CallSite.h b/include/llvm/Support/CallSite.h index 285b558..9f527e2 100644 --- a/include/llvm/Support/CallSite.h +++ b/include/llvm/Support/CallSite.h @@ -8,15 +8,18 @@ //===----------------------------------------------------------------------===// // // This file defines the CallSite class, which is a handy wrapper for code that -// wants to treat Call and Invoke instructions in a generic way. +// wants to treat Call and Invoke instructions in a generic way. When in non- +// mutation context (e.g. an analysis) ImmutableCallSite should be used. +// Finally, when some degree of customization is necessary between these two +// extremes, CallSiteBase<> can be supplied with fine-tuned parameters. // -// NOTE: This class is supposed to have "value semantics". So it should be -// passed by value, not by reference; it should not be "new"ed or "delete"d. It -// is efficiently copyable, assignable and constructable, with cost equivalent -// to copying a pointer (notice that it has only a single data member). -// The internal representation carries a flag which indicates which of the two -// variants is enclosed. This allows for cheaper checks when various accessors -// of CallSite are employed. +// NOTE: These classes are supposed to have "value semantics". So they should be +// passed by value, not by reference; they should not be "new"ed or "delete"d. +// They are efficiently copyable, assignable and constructable, with cost +// equivalent to copying a pointer (notice that they have only a single data +// member). The internal representation carries a flag which indicates which of +// the two variants is enclosed. This allows for cheaper checks when various +// accessors of CallSite are employed. // //===----------------------------------------------------------------------===// @@ -34,68 +37,42 @@ namespace llvm { class CallInst; class InvokeInst; -class CallSite { - PointerIntPair<Instruction*, 1, bool> I; +template <typename FunTy = const Function, + typename ValTy = const Value, + typename UserTy = const User, + typename InstrTy = const Instruction, + typename CallTy = const CallInst, + typename InvokeTy = const InvokeInst, + typename IterTy = User::const_op_iterator> +class CallSiteBase { +protected: + PointerIntPair<InstrTy*, 1, bool> I; public: - CallSite() : I(0, false) {} - CallSite(CallInst *CI) : I(reinterpret_cast<Instruction*>(CI), true) {} - CallSite(InvokeInst *II) : I(reinterpret_cast<Instruction*>(II), false) {} - CallSite(Instruction *C); - - bool operator==(const CallSite &CS) const { return I == CS.I; } - bool operator!=(const CallSite &CS) const { return I != CS.I; } + CallSiteBase() : I(0, false) {} + CallSiteBase(CallTy *CI) : I(reinterpret_cast<InstrTy*>(CI), true) {} + CallSiteBase(InvokeTy *II) : I(reinterpret_cast<InstrTy*>(II), false) {} + CallSiteBase(ValTy *II) { *this = get(II); } + CallSiteBase(InstrTy *II) { + assert(II && "Null instruction given?"); + *this = get(II); + assert(I.getPointer()); + } - /// CallSite::get - This static method is sort of like a constructor. It will - /// create an appropriate call site for a Call or Invoke instruction, but it - /// can also create a null initialized CallSite object for something which is - /// NOT a call site. + /// CallSiteBase::get - This static method is sort of like a constructor. It + /// will create an appropriate call site for a Call or Invoke instruction, but + /// it can also create a null initialized CallSiteBase object for something + /// which is NOT a call site. /// - static CallSite get(Value *V) { - if (Instruction *I = dyn_cast<Instruction>(V)) { - if (I->getOpcode() == Instruction::Call) - return CallSite(reinterpret_cast<CallInst*>(I)); - else if (I->getOpcode() == Instruction::Invoke) - return CallSite(reinterpret_cast<InvokeInst*>(I)); + static CallSiteBase get(ValTy *V) { + if (InstrTy *II = dyn_cast<InstrTy>(V)) { + if (II->getOpcode() == Instruction::Call) + return CallSiteBase(reinterpret_cast<CallTy*>(II)); + else if (II->getOpcode() == Instruction::Invoke) + return CallSiteBase(reinterpret_cast<InvokeTy*>(II)); } - return CallSite(); + return CallSiteBase(); } - /// getCallingConv/setCallingConv - get or set the calling convention of the - /// call. - CallingConv::ID getCallingConv() const; - void setCallingConv(CallingConv::ID CC); - - /// getAttributes/setAttributes - get or set the parameter attributes of - /// the call. - const AttrListPtr &getAttributes() const; - void setAttributes(const AttrListPtr &PAL); - - /// paramHasAttr - whether the call or the callee has the given attribute. - bool paramHasAttr(uint16_t i, Attributes attr) const; - - /// @brief Extract the alignment for a call or parameter (0=unknown). - uint16_t getParamAlignment(uint16_t i) const; - - /// @brief Determine if the call does not access memory. - bool doesNotAccessMemory() const; - void setDoesNotAccessMemory(bool doesNotAccessMemory = true); - - /// @brief Determine if the call does not access or only reads memory. - bool onlyReadsMemory() const; - void setOnlyReadsMemory(bool onlyReadsMemory = true); - - /// @brief Determine if the call cannot return. - bool doesNotReturn() const; - void setDoesNotReturn(bool doesNotReturn = true); - - /// @brief Determine if the call cannot unwind. - bool doesNotThrow() const; - void setDoesNotThrow(bool doesNotThrow = true); - - /// getType - Return the type of the instruction that generated this call site - /// - const Type *getType() const { return getInstruction()->getType(); } - /// isCall - true if a CallInst is enclosed. /// Note that !isCall() does not mean it is an InvokeInst enclosed, /// it also could signify a NULL Instruction pointer. @@ -105,37 +82,39 @@ public: /// bool isInvoke() const { return getInstruction() && !I.getInt(); } - /// getInstruction - Return the instruction this call site corresponds to - /// - Instruction *getInstruction() const { return I.getPointer(); } - - /// getCaller - Return the caller function for this call site - /// - Function *getCaller() const { return getInstruction() - ->getParent()->getParent(); } + InstrTy *getInstruction() const { return I.getPointer(); } + InstrTy *operator->() const { return I.getPointer(); } + operator bool() const { return I.getPointer(); } /// getCalledValue - Return the pointer to function that is being called... /// - Value *getCalledValue() const { + ValTy *getCalledValue() const { assert(getInstruction() && "Not a call or invoke instruction!"); - return getInstruction()->getOperand(0); + return *getCallee(); } /// getCalledFunction - Return the function being called if this is a direct /// call, otherwise return null (if it's an indirect call). /// - Function *getCalledFunction() const { - return dyn_cast<Function>(getCalledValue()); + FunTy *getCalledFunction() const { + return dyn_cast<FunTy>(getCalledValue()); } /// setCalledFunction - Set the callee to the specified value... /// void setCalledFunction(Value *V) { assert(getInstruction() && "Not a call or invoke instruction!"); - getInstruction()->setOperand(0, V); + *getCallee() = V; + } + + /// isCallee - Determine whether the passed iterator points to the + /// callee operand's Use. + /// + bool isCallee(value_use_iterator<UserTy> UI) const { + return getCallee() == &UI.getUse(); } - Value *getArgument(unsigned ArgNo) const { + ValTy *getArgument(unsigned ArgNo) const { assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!"); return *(arg_begin()+ArgNo); } @@ -146,51 +125,145 @@ public: getInstruction()->setOperand(getArgumentOffset() + ArgNo, newVal); } - /// Given an operand number, returns the argument that corresponds to it. - /// OperandNo must be a valid operand number that actually corresponds to an - /// argument. - unsigned getArgumentNo(unsigned OperandNo) const { - assert(OperandNo >= getArgumentOffset() && "Operand number passed was not " - "a valid argument"); - return OperandNo - getArgumentOffset(); + /// Given a value use iterator, returns the argument that corresponds to it. + /// Iterator must actually correspond to an argument. + unsigned getArgumentNo(value_use_iterator<UserTy> I) const { + assert(getInstruction() && "Not a call or invoke instruction!"); + assert(arg_begin() <= &I.getUse() && &I.getUse() < arg_end() + && "Argument # out of range!"); + return &I.getUse() - arg_begin(); } - /// hasArgument - Returns true if this CallSite passes the given Value* as an - /// argument to the called function. - bool hasArgument(const Value *Arg) const; - /// arg_iterator - The type of iterator to use when looping over actual /// arguments at this call site... - typedef User::op_iterator arg_iterator; + typedef IterTy arg_iterator; /// arg_begin/arg_end - Return iterators corresponding to the actual argument /// list for a call site. - arg_iterator arg_begin() const { + IterTy arg_begin() const { assert(getInstruction() && "Not a call or invoke instruction!"); // Skip non-arguments - return getInstruction()->op_begin() + getArgumentOffset(); + return (*this)->op_begin() + getArgumentOffset(); } - arg_iterator arg_end() const { return getInstruction()->op_end(); } + IterTy arg_end() const { return (*this)->op_end() - getArgumentEndOffset(); } bool arg_empty() const { return arg_end() == arg_begin(); } unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); } - - bool operator<(const CallSite &CS) const { - return getInstruction() < CS.getInstruction(); + +private: + /// Returns the operand number of the first argument + unsigned getArgumentOffset() const { + if (isCall()) + return 1; // Skip Function (ATM) + else + return 0; // Args are at the front } - bool isCallee(Value::use_iterator UI) const { - return getInstruction()->op_begin() == &UI.getUse(); + unsigned getArgumentEndOffset() const { + if (isCall()) + return 0; // Unchanged (ATM) + else + return 3; // Skip BB, BB, Function } -private: - /// Returns the operand number of the first argument - unsigned getArgumentOffset() const { + IterTy getCallee() const { + // FIXME: this is slow, since we do not have the fast versions + // of the op_*() functions here. See CallSite::getCallee. + // if (isCall()) - return 1; // Skip Function + return getInstruction()->op_begin(); // Unchanged (ATM) else - return 3; // Skip Function, BB, BB + return getInstruction()->op_end() - 3; // Skip BB, BB, Function + } +}; + +/// ImmutableCallSite - establish a view to a call site for examination +class ImmutableCallSite : public CallSiteBase<> { + typedef CallSiteBase<> _Base; +public: + ImmutableCallSite(const Value* V) : _Base(V) {} + ImmutableCallSite(const CallInst *CI) : _Base(CI) {} + ImmutableCallSite(const InvokeInst *II) : _Base(II) {} + ImmutableCallSite(const Instruction *II) : _Base(II) {} +}; + +class CallSite : public CallSiteBase<Function, Value, User, Instruction, + CallInst, InvokeInst, User::op_iterator> { + typedef CallSiteBase<Function, Value, User, Instruction, + CallInst, InvokeInst, User::op_iterator> _Base; +public: + CallSite() {} + CallSite(_Base B) : _Base(B) {} + CallSite(CallInst *CI) : _Base(CI) {} + CallSite(InvokeInst *II) : _Base(II) {} + CallSite(Instruction *II) : _Base(II) {} + + bool operator==(const CallSite &CS) const { return I == CS.I; } + bool operator!=(const CallSite &CS) const { return I != CS.I; } + + /// CallSite::get - This static method is sort of like a constructor. It will + /// create an appropriate call site for a Call or Invoke instruction, but it + /// can also create a null initialized CallSite object for something which is + /// NOT a call site. + /// + static CallSite get(Value *V) { + return _Base::get(V); } + + /// getCallingConv/setCallingConv - get or set the calling convention of the + /// call. + CallingConv::ID getCallingConv() const; + void setCallingConv(CallingConv::ID CC); + + /// getAttributes/setAttributes - get or set the parameter attributes of + /// the call. + const AttrListPtr &getAttributes() const; + void setAttributes(const AttrListPtr &PAL); + + /// paramHasAttr - whether the call or the callee has the given attribute. + bool paramHasAttr(uint16_t i, Attributes attr) const; + + /// @brief Extract the alignment for a call or parameter (0=unknown). + uint16_t getParamAlignment(uint16_t i) const; + + /// @brief Return true if the call should not be inlined. + bool isNoInline() const; + void setIsNoInline(bool Value = true); + + /// @brief Determine if the call does not access memory. + bool doesNotAccessMemory() const; + void setDoesNotAccessMemory(bool doesNotAccessMemory = true); + + /// @brief Determine if the call does not access or only reads memory. + bool onlyReadsMemory() const; + void setOnlyReadsMemory(bool onlyReadsMemory = true); + + /// @brief Determine if the call cannot return. + bool doesNotReturn() const; + void setDoesNotReturn(bool doesNotReturn = true); + + /// @brief Determine if the call cannot unwind. + bool doesNotThrow() const; + void setDoesNotThrow(bool doesNotThrow = true); + + /// getType - Return the type of the instruction that generated this call site + /// + const Type *getType() const { return (*this)->getType(); } + + /// getCaller - Return the caller function for this call site + /// + Function *getCaller() const { return (*this)->getParent()->getParent(); } + + /// hasArgument - Returns true if this CallSite passes the given Value* as an + /// argument to the called function. + bool hasArgument(const Value *Arg) const; + + bool operator<(const CallSite &CS) const { + return getInstruction() < CS.getInstruction(); + } + +private: + User::op_iterator getCallee() const; }; } // End llvm namespace diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h index 17bcb59..dccbfad 100644 --- a/include/llvm/Support/Casting.h +++ b/include/llvm/Support/Casting.h @@ -50,9 +50,11 @@ template<typename From> struct simplify_type<const From> { // if (isa<Type*>(myVal)) { ... } // template <typename To, typename From> -inline bool isa_impl(const From &Val) { - return To::classof(&Val); -} +struct isa_impl { + static inline bool doit(const From &Val) { + return To::classof(&Val); + } +}; template<typename To, typename From, typename SimpleType> struct isa_impl_wrap { @@ -68,7 +70,7 @@ template<typename To, typename FromTy> struct isa_impl_wrap<To, const FromTy, const FromTy> { // When From == SimpleType, we are as simple as we are going to get. static bool doit(const FromTy &Val) { - return isa_impl<To,FromTy>(Val); + return isa_impl<To,FromTy>::doit(Val); } }; @@ -251,10 +253,12 @@ struct foo { }*/ }; -template <> inline bool isa_impl<foo,bar>(const bar &Val) { - dbgs() << "Classof: " << &Val << "\n"; - return true; -} +template <> struct isa_impl<foo,bar> { + static inline bool doit(const bar &Val) { + dbgs() << "Classof: " << &Val << "\n"; + return true; + } +}; bar *fub(); diff --git a/include/llvm/Support/DebugLoc.h b/include/llvm/Support/DebugLoc.h index 32631fc..ede1ed3 100644 --- a/include/llvm/Support/DebugLoc.h +++ b/include/llvm/Support/DebugLoc.h @@ -1,4 +1,4 @@ -//===---- llvm/DebugLoc.h - Debug Location Information ----------*- C++ -*-===// +//===---- llvm/Support/DebugLoc.h - Debug Location Information --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -20,12 +20,71 @@ namespace llvm { class MDNode; + class LLVMContext; + + /// DebugLoc - Debug location id. This is carried by Instruction, SDNode, + /// and MachineInstr to compactly encode file/line/scope information for an + /// operation. + class NewDebugLoc { + /// LineCol - This 32-bit value encodes the line and column number for the + /// location, encoded as 24-bits for line and 8 bits for col. A value of 0 + /// for either means unknown. + unsigned LineCol; + + /// ScopeIdx - This is an opaque ID# for Scope/InlinedAt information, + /// decoded by LLVMContext. 0 is unknown. + int ScopeIdx; + public: + NewDebugLoc() : LineCol(0), ScopeIdx(0) {} // Defaults to unknown. + + /// get - Get a new DebugLoc that corresponds to the specified line/col + /// scope/inline location. + static NewDebugLoc get(unsigned Line, unsigned Col, + MDNode *Scope, MDNode *InlinedAt = 0); + + /// getFromDILocation - Translate the DILocation quad into a NewDebugLoc. + static NewDebugLoc getFromDILocation(MDNode *N); + + /// isUnknown - Return true if this is an unknown location. + bool isUnknown() const { return ScopeIdx == 0; } + + unsigned getLine() const { + return (LineCol << 8) >> 8; // Mask out column. + } + + unsigned getCol() const { + return LineCol >> 24; + } + + /// getScope - This returns the scope pointer for this DebugLoc, or null if + /// invalid. + MDNode *getScope(const LLVMContext &Ctx) const; + + /// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or + /// null if invalid or not present. + MDNode *getInlinedAt(const LLVMContext &Ctx) const; + + /// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values. + void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, + const LLVMContext &Ctx) const; + + + /// getAsMDNode - This method converts the compressed DebugLoc node into a + /// DILocation compatible MDNode. + MDNode *getAsMDNode(const LLVMContext &Ctx) const; + + bool operator==(const NewDebugLoc &DL) const { + return LineCol == DL.LineCol && ScopeIdx == DL.ScopeIdx; + } + bool operator!=(const NewDebugLoc &DL) const { return !(*this == DL); } + }; + + /// DebugLoc - Debug location id. This is carried by SDNode and MachineInstr /// to index into a vector of unique debug location tuples. class DebugLoc { unsigned Idx; - public: DebugLoc() : Idx(~0U) {} // Defaults to invalid. @@ -42,7 +101,7 @@ namespace llvm { bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } }; - /// DebugLocTracker - This class tracks debug location information. + /// DebugLocTracker - This class tracks debug location information. /// struct DebugLocTracker { /// DebugLocations - A vector of unique DebugLocTuple's. diff --git a/include/llvm/Support/FileUtilities.h b/include/llvm/Support/FileUtilities.h index cc8f953..d0dd4a7 100644 --- a/include/llvm/Support/FileUtilities.h +++ b/include/llvm/Support/FileUtilities.h @@ -40,6 +40,8 @@ namespace llvm { sys::Path Filename; bool DeleteIt; public: + FileRemover() : DeleteIt(false) {} + explicit FileRemover(const sys::Path &filename, bool deleteIt = true) : Filename(filename), DeleteIt(deleteIt) {} @@ -50,6 +52,17 @@ namespace llvm { } } + /// setFile - Give ownership of the file to the FileRemover so it will + /// be removed when the object is destroyed. If the FileRemover already + /// had ownership of a file, remove it first. + void setFile(const sys::Path &filename, bool deleteIt = true) { + if (DeleteIt) + Filename.eraseFromDisk(); + + Filename = filename; + DeleteIt = deleteIt; + } + /// releaseFile - Take ownership of the file away from the FileRemover so it /// will not be removed when the object is destroyed. void releaseFile() { DeleteIt = false; } diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h index 1f4e598..c352625 100644 --- a/include/llvm/Support/IRBuilder.h +++ b/include/llvm/Support/IRBuilder.h @@ -40,8 +40,7 @@ protected: /// IRBuilderBase - Common base class shared among various IRBuilders. class IRBuilderBase { - unsigned DbgMDKind; - MDNode *CurDbgLocation; + NewDebugLoc CurDbgLocation; protected: BasicBlock *BB; BasicBlock::iterator InsertPt; @@ -49,7 +48,7 @@ protected: public: IRBuilderBase(LLVMContext &context) - : DbgMDKind(0), CurDbgLocation(0), Context(context) { + : Context(context) { ClearInsertionPoint(); } @@ -65,6 +64,7 @@ public: BasicBlock *GetInsertBlock() const { return BB; } BasicBlock::iterator GetInsertPoint() const { return InsertPt; } + LLVMContext &getContext() const { return Context; } /// SetInsertPoint - This specifies that created instructions should be /// appended to the end of the specified block. @@ -82,12 +82,20 @@ public: /// SetCurrentDebugLocation - Set location information used by debugging /// information. - void SetCurrentDebugLocation(MDNode *L); - MDNode *getCurrentDebugLocation() const { return CurDbgLocation; } + void SetCurrentDebugLocation(const NewDebugLoc &L) { + CurDbgLocation = L; + } + + /// getCurrentDebugLocation - Get location information used by debugging + /// information. + const NewDebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; } /// SetInstDebugLocation - If this builder has a current debug location, set /// it on the specified instruction. - void SetInstDebugLocation(Instruction *I) const; + void SetInstDebugLocation(Instruction *I) const { + if (!CurDbgLocation.isUnknown()) + I->setDebugLoc(CurDbgLocation); + } //===--------------------------------------------------------------------===// // Miscellaneous creation methods. @@ -208,7 +216,7 @@ public: template<typename InstTy> InstTy *Insert(InstTy *I, const Twine &Name = "") const { this->InsertHelper(I, Name, BB, InsertPt); - if (getCurrentDebugLocation() != 0) + if (!getCurrentDebugLocation().isUnknown()) this->SetInstDebugLocation(I); return I; } diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index fa12416..9c5f32c 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -32,35 +32,43 @@ inline uint32_t Lo_32(uint64_t Value) { return static_cast<uint32_t>(Value); } -/// is?Type - these functions produce optimal testing for integer data types. -inline bool isInt8 (int64_t Value) { - return static_cast<int8_t>(Value) == Value; -} -inline bool isUInt8 (int64_t Value) { - return static_cast<uint8_t>(Value) == Value; -} -inline bool isInt16 (int64_t Value) { - return static_cast<int16_t>(Value) == Value; -} -inline bool isUInt16(int64_t Value) { - return static_cast<uint16_t>(Value) == Value; -} -inline bool isInt32 (int64_t Value) { - return static_cast<int32_t>(Value) == Value; -} -inline bool isUInt32(int64_t Value) { - return static_cast<uint32_t>(Value) == Value; -} - +/// isInt - Checks if an integer fits into the given bit width. template<unsigned N> inline bool isInt(int64_t x) { return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); } +// Template specializations to get better code for common cases. +template<> +inline bool isInt<8>(int64_t x) { + return static_cast<int8_t>(x) == x; +} +template<> +inline bool isInt<16>(int64_t x) { + return static_cast<int16_t>(x) == x; +} +template<> +inline bool isInt<32>(int64_t x) { + return static_cast<int32_t>(x) == x; +} +/// isUInt - Checks if an unsigned integer fits into the given bit width. template<unsigned N> -inline bool isUint(uint64_t x) { +inline bool isUInt(uint64_t x) { return N >= 64 || x < (UINT64_C(1)<<N); } +// Template specializations to get better code for common cases. +template<> +inline bool isUInt<8>(uint64_t x) { + return static_cast<uint8_t>(x) == x; +} +template<> +inline bool isUInt<16>(uint64_t x) { + return static_cast<uint16_t>(x) == x; +} +template<> +inline bool isUInt<32>(uint64_t x) { + return static_cast<uint32_t>(x) == x; +} /// isMask_32 - This function returns true if the argument is a sequence of ones /// starting at the least significant bit with the remainder zero (32 bit diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h index 8a0f55d..00dfeaa 100644 --- a/include/llvm/Support/Timer.h +++ b/include/llvm/Support/Timer.h @@ -16,16 +16,63 @@ #define LLVM_SUPPORT_TIMER_H #include "llvm/System/DataTypes.h" -#include "llvm/System/Mutex.h" +#include "llvm/ADT/StringRef.h" +#include <cassert> #include <string> #include <vector> -#include <cassert> +#include <utility> namespace llvm { +class Timer; class TimerGroup; class raw_ostream; +class TimeRecord { + double WallTime; // Wall clock time elapsed in seconds + double UserTime; // User time elapsed + double SystemTime; // System time elapsed + ssize_t MemUsed; // Memory allocated (in bytes) +public: + TimeRecord() : WallTime(0), UserTime(0), SystemTime(0), MemUsed(0) {} + + /// getCurrentTime - Get the current time and memory usage. If Start is true + /// we get the memory usage before the time, otherwise we get time before + /// memory usage. This matters if the time to get the memory usage is + /// significant and shouldn't be counted as part of a duration. + static TimeRecord getCurrentTime(bool Start = true); + + double getProcessTime() const { return UserTime+SystemTime; } + double getUserTime() const { return UserTime; } + double getSystemTime() const { return SystemTime; } + double getWallTime() const { return WallTime; } + ssize_t getMemUsed() const { return MemUsed; } + + + // operator< - Allow sorting. + bool operator<(const TimeRecord &T) const { + // Sort by Wall Time elapsed, as it is the only thing really accurate + return WallTime < T.WallTime; + } + + void operator+=(const TimeRecord &RHS) { + WallTime += RHS.WallTime; + UserTime += RHS.UserTime; + SystemTime += RHS.SystemTime; + MemUsed += RHS.MemUsed; + } + void operator-=(const TimeRecord &RHS) { + WallTime -= RHS.WallTime; + UserTime -= RHS.UserTime; + SystemTime -= RHS.SystemTime; + MemUsed -= RHS.MemUsed; + } + + /// print - Print the current timer to standard error, and reset the "Started" + /// flag. + void print(const TimeRecord &Total, raw_ostream &OS) const; +}; + /// Timer - This class is used to track the amount of time spent between /// invocations of its startTimer()/stopTimer() methods. Given appropriate OS /// support it can also keep track of the RSS of the program at various points. @@ -35,65 +82,32 @@ class raw_ostream; /// if they are never started. /// class Timer { - double Elapsed; // Wall clock time elapsed in seconds - double UserTime; // User time elapsed - double SystemTime; // System time elapsed - ssize_t MemUsed; // Memory allocated (in bytes) - size_t PeakMem; // Peak memory used - size_t PeakMemBase; // Temporary for peak calculation... - std::string Name; // The name of this time variable + TimeRecord Time; + std::string Name; // The name of this time variable. bool Started; // Has this time variable ever been started? TimerGroup *TG; // The TimerGroup this Timer is in. - mutable sys::SmartMutex<true> Lock; // Mutex for the contents of this Timer. + + Timer **Prev, *Next; // Doubly linked list of timers in the group. public: - explicit Timer(const std::string &N); - Timer(const std::string &N, TimerGroup &tg); - Timer(const Timer &T); - ~Timer(); - - double getProcessTime() const { return UserTime+SystemTime; } - double getWallTime() const { return Elapsed; } - ssize_t getMemUsed() const { return MemUsed; } - size_t getPeakMem() const { return PeakMem; } - std::string getName() const { return Name; } - + explicit Timer(StringRef N) : TG(0) { init(N); } + Timer(StringRef N, TimerGroup &tg) : TG(0) { init(N, tg); } + Timer(const Timer &RHS) : TG(0) { + assert(RHS.TG == 0 && "Can only copy uninitialized timers"); + } const Timer &operator=(const Timer &T) { - if (&T < this) { - T.Lock.acquire(); - Lock.acquire(); - } else { - Lock.acquire(); - T.Lock.acquire(); - } - - Elapsed = T.Elapsed; - UserTime = T.UserTime; - SystemTime = T.SystemTime; - MemUsed = T.MemUsed; - PeakMem = T.PeakMem; - PeakMemBase = T.PeakMemBase; - Name = T.Name; - Started = T.Started; - assert(TG == T.TG && "Can only assign timers in the same TimerGroup!"); - - if (&T < this) { - T.Lock.release(); - Lock.release(); - } else { - Lock.release(); - T.Lock.release(); - } - + assert(TG == 0 && T.TG == 0 && "Can only assign uninit timers"); return *this; } + ~Timer(); - // operator< - Allow sorting... - bool operator<(const Timer &T) const { - // Sort by Wall Time elapsed, as it is the only thing really accurate - return Elapsed < T.Elapsed; - } - bool operator>(const Timer &T) const { return T.operator<(*this); } - + // Create an uninitialized timer, client must use 'init'. + explicit Timer() : TG(0) {} + void init(StringRef N); + void init(StringRef N, TimerGroup &tg); + + const std::string &getName() const { return Name; } + bool isInitialized() const { return TG != 0; } + /// startTimer - Start the timer running. Time between calls to /// startTimer/stopTimer is counted by the Timer class. Note that these calls /// must be correctly paired. @@ -104,25 +118,8 @@ public: /// void stopTimer(); - /// addPeakMemoryMeasurement - This method should be called whenever memory - /// usage needs to be checked. It adds a peak memory measurement to the - /// currently active timers, which will be printed when the timer group prints - /// - static void addPeakMemoryMeasurement(); - - /// print - Print the current timer to standard error, and reset the "Started" - /// flag. - void print(const Timer &Total, raw_ostream &OS); - private: friend class TimerGroup; - - // Copy ctor, initialize with no TG member. - Timer(bool, const Timer &T); - - /// sum - Add the time accumulated in the specified timer into this timer. - /// - void sum(const Timer &T); }; @@ -139,12 +136,10 @@ public: T->startTimer(); } explicit TimeRegion(Timer *t) : T(t) { - if (T) - T->startTimer(); + if (T) T->startTimer(); } ~TimeRegion() { - if (T) - T->stopTimer(); + if (T) T->stopTimer(); } }; @@ -155,9 +150,8 @@ public: /// is primarily used for debugging and for hunting performance problems. /// struct NamedRegionTimer : public TimeRegion { - explicit NamedRegionTimer(const std::string &Name); - explicit NamedRegionTimer(const std::string &Name, - const std::string &GroupName); + explicit NamedRegionTimer(StringRef Name); + explicit NamedRegionTimer(StringRef Name, StringRef GroupName); }; @@ -168,20 +162,29 @@ struct NamedRegionTimer : public TimeRegion { /// class TimerGroup { std::string Name; - unsigned NumTimers; - std::vector<Timer> TimersToPrint; + Timer *FirstTimer; // First timer in the group. + std::vector<std::pair<TimeRecord, std::string> > TimersToPrint; + + TimerGroup **Prev, *Next; // Doubly linked list of TimerGroup's. + TimerGroup(const TimerGroup &TG); // DO NOT IMPLEMENT + void operator=(const TimerGroup &TG); // DO NOT IMPLEMENT public: - explicit TimerGroup(const std::string &name) : Name(name), NumTimers(0) {} - ~TimerGroup() { - assert(NumTimers == 0 && - "TimerGroup destroyed before all contained timers!"); - } + explicit TimerGroup(StringRef name); + ~TimerGroup(); + + void setName(StringRef name) { Name.assign(name.begin(), name.end()); } + /// print - Print any started timers in this group and zero them. + void print(raw_ostream &OS); + + /// printAll - This static method prints all timers and clears them all out. + static void printAll(raw_ostream &OS); + private: friend class Timer; - void addTimer(); - void removeTimer(); - void addTimerToPrint(const Timer &T); + void addTimer(Timer &T); + void removeTimer(Timer &T); + void PrintQueuedTimers(raw_ostream &OS); }; } // End llvm namespace diff --git a/include/llvm/Support/ValueHandle.h b/include/llvm/Support/ValueHandle.h index 82c3cae..130a620 100644 --- a/include/llvm/Support/ValueHandle.h +++ b/include/llvm/Support/ValueHandle.h @@ -284,8 +284,7 @@ class TrackingVH : public ValueHandleBase { Value *VP = ValueHandleBase::getValPtr(); // Null is always ok. - if (!VP) - return; + if (!VP) return; // Check that this value is valid (i.e., it hasn't been deleted). We // explicitly delay this check until access to avoid requiring clients to be @@ -302,7 +301,7 @@ class TrackingVH : public ValueHandleBase { ValueTy *getValPtr() const { CheckValidity(); - return static_cast<ValueTy*>(ValueHandleBase::getValPtr()); + return (ValueTy*)ValueHandleBase::getValPtr(); } void setValPtr(ValueTy *P) { CheckValidity(); diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index 0f227cc..e0de80f 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -89,6 +89,7 @@ public: /// has_error - Return the value of the flag in this raw_ostream indicating /// whether an output error has been encountered. + /// This doesn't implicitly flush any pending output. bool has_error() const { return Error; } |