[llvm-commits] [llvm] r158919 - in /llvm/trunk: include/llvm/Analysis/MemoryBuiltins.h lib/Analysis/BasicAliasAnalysis.cpp lib/Analysis/IPA/GlobalsModRef.cpp lib/Analysis/MemoryBuiltins.cpp lib/Analysis/MemoryDependenceAnalysis.cpp lib/Transforms/I...
Nuno Lopes
nunoplopes at sapo.pt
Wed Jun 27 13:34:12 PDT 2012
All right; I'll commit a fix to ignore extractvalue.
Thanks,
Nuno
Quoting "Rotem, Nadav" <nadav.rotem at intel.com>:
> I don't think that MemoryBuiltin can detect anything interesting
> that uses vectors of pointers.
>
> -----Original Message-----
> From: Hal Finkel [mailto:hfinkel at anl.gov]
> Sent: Wednesday, June 27, 2012 22:52
> To: Nuno Lopes
> Cc: llvm-commits at cs.uiuc.edu; Rotem, Nadav
> Subject: Re: [llvm-commits] [llvm] r158919 - in /llvm/trunk:
> include/llvm/Analysis/MemoryBuiltins.h
> lib/Analysis/BasicAliasAnalysis.cpp
> lib/Analysis/IPA/GlobalsModRef.cpp lib/Analysis/MemoryBuiltins.cpp
> lib/Analysis/MemoryDependenceAnalysis.cpp lib/Transforms/I...
>
> On Wed, 27 Jun 2012 20:42:22 +0100
> Nuno Lopes <nunoplopes at sapo.pt> wrote:
>
>> Hi,
>>
>> Well, it's not broken. It's just saying it doesn't know how to deal
>> with that instruction.
>> Is there any thing we can do about this instruction, or should we
>> just ignore it?
>
> Probably ignore it. Nadav, do you have any thoughts on this?
>
> -Hal
>
>>
>> Nuno
>>
>>
>> Quoting Hal Finkel <hfinkel at anl.gov>:
>>
>> > Nuno,
>> >
>> > I think that something here is broken w.r.t. pointer vectors.
>> > When testing the vectorizer I see errors in the debug output
>> > like this:
>> >
>> > ObjectSizeOffsetVisitor unknown instruction: %arrayidx7.v.r1 =
>> > extractelement <2 x double*> %arrayidx7, i32 0
>> >
>> > -Hal
>> >
>> > On Thu, 21 Jun 2012 15:45:29 -0000
>> > Nuno Lopes <nunoplopes at sapo.pt> wrote:
>> >
>> >> Author: nlopes
>> >> Date: Thu Jun 21 10:45:28 2012
>> >> New Revision: 158919
>> >>
>> >> URL: http://llvm.org/viewvc/llvm-project?rev=158919&view=rev
>> >> Log:
>> >> refactor the MemoryBuiltin analysis:
>> >> - provide more extensive set of functions to detect library
>> >> allocation functions (e.g., malloc, calloc, strdup, etc)
>> >> - provide an API to compute the size and offset of an object
>> >> pointed by
>> >>
>> >> Move a few clients (GVN, AA, instcombine, ...) to the new API.
>> >> This implementation is a lot more aggressive than each of the
>> >> custom implementations being replaced.
>> >>
>> >> Patch reviewed by Nick Lewycky and Chandler Carruth, thanks.
>> >>
>> >> Modified:
>> >> llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h
>> >> llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
>> >> llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp
>> >> llvm/trunk/lib/Analysis/MemoryBuiltins.cpp
>> >> llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp
>> >> llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
>> >> llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
>> >> llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp
>> >> llvm/trunk/lib/Transforms/Scalar/GVN.cpp
>> >> llvm/trunk/lib/Transforms/Utils/Local.cpp
>> >> llvm/trunk/test/Transforms/InstCombine/objsize.ll
>> >>
>> >> Modified: llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h
>> >> URL:
>> >>
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h?rev=158919&r1=158918&r2=158919&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h (original)
>> >> +++ llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h Thu Jun 21
>> >> 10:45:28 2012 @@ -15,6 +15,14 @@ #ifndef
>> >> LLVM_ANALYSIS_MEMORYBUILTINS_H #define
>> >> LLVM_ANALYSIS_MEMORYBUILTINS_H
>> >>
>> >> +#include "llvm/ADT/DenseMap.h"
>> >> +#include "llvm/ADT/SmallPtrSet.h"
>> >> +#include "llvm/Operator.h"
>> >> +#include "llvm/Support/DataTypes.h"
>> >> +#include "llvm/Support/InstVisitor.h"
>> >> +#include "llvm/Support/IRBuilder.h"
>> >> +#include "llvm/Support/TargetFolder.h"
>> >> +
>> >> namespace llvm {
>> >> class CallInst;
>> >> class PointerType;
>> >> @@ -22,24 +30,50 @@
>> >> class Type;
>> >> class Value;
>> >>
>> >> +
>> >> +/// \brief Tests if a value is a call to a library function that
>> >> allocates or +/// reallocates memory (either malloc, calloc,
>> >> realloc, or strdup like). +bool isAllocationFn(const Value *V, bool
>> >> LookThroughBitCast = false); +
>> >> +/// \brief Tests if a value is a call to a function that returns a
>> >> NoAlias +/// pointer (including malloc/calloc/strdup-like
>> >> functions). +bool isNoAliasFn(const Value *V, bool
>> >> LookThroughBitCast = false); +
>> >> +/// \brief Tests if a value is a call to a library function that
>> >> allocates +/// uninitialized memory (such as malloc).
>> >> +bool isMallocLikeFn(const Value *V, bool LookThroughBitCast =
>> >> false); +
>> >> +/// \brief Tests if a value is a call to a library function that
>> >> allocates +/// zero-filled memory (such as calloc).
>> >> +bool isCallocLikeFn(const Value *V, bool LookThroughBitCast =
>> >> false); +
>> >> +/// \brief Tests if a value is a call to a library function that
>> >> allocates +/// memory (either malloc, calloc, or strdup like).
>> >> +bool isAllocLikeFn(const Value *V, bool LookThroughBitCast =
>> >> false); +
>> >> +/// \brief Tests if a value is a call to a library function that
>> >> reallocates +/// memory (such as realloc).
>> >> +bool isReallocLikeFn(const Value *V, bool LookThroughBitCast =
>> >> false); +
>> >> +
>> >>
>> >>
>> //===----------------------------------------------------------------------===//
>> >> // malloc Call Utility Functions.
>> >> //
>> >>
>> >> -/// isMalloc - Returns true if the value is either a malloc call
>> >> or a bitcast of -/// the result of a malloc call
>> >> -bool isMalloc(const Value *I);
>> >> -
>> >> /// extractMallocCall - Returns the corresponding CallInst if the
>> >> instruction /// is a malloc call. Since CallInst::CreateMalloc()
>> >> only creates calls, we /// ignore InvokeInst here.
>> >> const CallInst *extractMallocCall(const Value *I);
>> >> -CallInst *extractMallocCall(Value *I);
>> >> +static inline CallInst *extractMallocCall(Value *I) {
>> >> + return const_cast<CallInst*>(extractMallocCall((const
>> >> Value*)I)); +}
>> >>
>> >> /// extractMallocCallFromBitCast - Returns the corresponding
>> >> CallInst if the /// instruction is a bitcast of the result of a
>> >> malloc call. const CallInst *extractMallocCallFromBitCast(const
>> >> Value *I); -CallInst *extractMallocCallFromBitCast(Value *I);
>> >> +static inline CallInst *extractMallocCallFromBitCast(Value *I) {
>> >> + return const_cast<CallInst*>(extractMallocCallFromBitCast((const
>> >> Value*)I)); +}
>> >>
>> >> /// isArrayMalloc - Returns the corresponding CallInst if the
>> >> instruction /// is a call to malloc whose array size can be
>> >> determined and the array size @@ -67,7 +101,7 @@
>> >> /// determined.
>> >> Value *getMallocArraySize(CallInst *CI, const TargetData *TD,
>> >> bool LookThroughSExt = false);
>> >> -
>> >> +
>> >>
>> >>
>> >>
>> //===----------------------------------------------------------------------===//
>> >> // calloc Call Utility Functions.
>> >> @@ -76,7 +110,9 @@
>> >> /// extractCallocCall - Returns the corresponding CallInst if the
>> >> instruction /// is a calloc call.
>> >> const CallInst *extractCallocCall(const Value *I);
>> >> -CallInst *extractCallocCall(Value *I);
>> >> +static inline CallInst *extractCallocCall(Value *I) {
>> >> + return const_cast<CallInst*>(extractCallocCall((const
>> >> Value*)I)); +}
>> >>
>> >>
>> >>
>> >>
>> //===----------------------------------------------------------------------===//
>> >> @@ -90,6 +126,126 @@
>> >> return const_cast<CallInst*>(isFreeCall((const Value*)I));
>> >> }
>> >>
>> >> +
>> >>
>> +//===----------------------------------------------------------------------===//
>> >> +// Utility functions to compute size of objects.
>> >> +//
>> >> +
>> >> +/// \brief Compute the size of the object pointed by Ptr. Returns
>> >> true and the +/// object size in Size if successful, and false
>> >> otherwise. +/// If RoundToAlign is true, then Size is rounded up to
>> >> the aligment of allocas, +/// byval arguments, and global
>> >> variables. +bool getObjectSize(const Value *Ptr, uint64_t &Size,
>> >> const TargetData *TD,
>> >> + bool RoundToAlign = false);
>> >> +
>> >> +
>> >> +
>> >> +typedef std::pair<APInt, APInt> SizeOffsetType;
>> >> +
>> >> +/// \brief Evaluate the size and offset of an object ponted by a
>> >> Value* +/// statically. Fails if size or offset are not known at
>> >> compile time. +class ObjectSizeOffsetVisitor
>> >> + : public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> {
>> >> +
>> >> + const TargetData *TD;
>> >> + bool RoundToAlign;
>> >> + unsigned IntTyBits;
>> >> + APInt Zero;
>> >> +
>> >> + APInt align(APInt Size, uint64_t Align);
>> >> +
>> >> + SizeOffsetType unknown() {
>> >> + return std::make_pair(APInt(), APInt());
>> >> + }
>> >> +
>> >> +public:
>> >> + ObjectSizeOffsetVisitor(const TargetData *TD, LLVMContext
>> >> &Context,
>> >> + bool RoundToAlign = false);
>> >> +
>> >> + SizeOffsetType compute(Value *V);
>> >> +
>> >> + bool knownSize(SizeOffsetType &SizeOffset) {
>> >> + return SizeOffset.first.getBitWidth() > 1;
>> >> + }
>> >> +
>> >> + bool knownOffset(SizeOffsetType &SizeOffset) {
>> >> + return SizeOffset.second.getBitWidth() > 1;
>> >> + }
>> >> +
>> >> + bool bothKnown(SizeOffsetType &SizeOffset) {
>> >> + return knownSize(SizeOffset) && knownOffset(SizeOffset);
>> >> + }
>> >> +
>> >> + SizeOffsetType visitAllocaInst(AllocaInst &I);
>> >> + SizeOffsetType visitArgument(Argument &A);
>> >> + SizeOffsetType visitCallSite(CallSite CS);
>> >> + SizeOffsetType visitConstantPointerNull(ConstantPointerNull&);
>> >> + SizeOffsetType visitExtractValueInst(ExtractValueInst &I);
>> >> + SizeOffsetType visitGEPOperator(GEPOperator &GEP);
>> >> + SizeOffsetType visitGlobalVariable(GlobalVariable &GV);
>> >> + SizeOffsetType visitIntToPtrInst(IntToPtrInst&);
>> >> + SizeOffsetType visitLoadInst(LoadInst &I);
>> >> + SizeOffsetType visitPHINode(PHINode&);
>> >> + SizeOffsetType visitSelectInst(SelectInst &I);
>> >> + SizeOffsetType visitUndefValue(UndefValue&);
>> >> + SizeOffsetType visitInstruction(Instruction &I);
>> >> +};
>> >> +
>> >> +typedef std::pair<Value*, Value*> SizeOffsetEvalType;
>> >> +typedef IRBuilder<true, TargetFolder> BuilderTy;
>> >> +typedef DenseMap<const Value*, SizeOffsetEvalType> CacheMapTy;
>> >> +typedef SmallPtrSet<const Value*, 8> PtrSetTy;
>> >> +
>> >> +
>> >> +/// \brief Evaluate the size and offset of an object ponted by a
>> >> Value*. +/// May create code to compute the result at run-time.
>> >> +class ObjectSizeOffsetEvaluator
>> >> + : public InstVisitor<ObjectSizeOffsetEvaluator,
>> >> SizeOffsetEvalType> { +
>> >> + const TargetData *TD;
>> >> + LLVMContext &Context;
>> >> + BuilderTy Builder;
>> >> + ObjectSizeOffsetVisitor Visitor;
>> >> + IntegerType *IntTy;
>> >> + Value *Zero;
>> >> + CacheMapTy CacheMap;
>> >> + PtrSetTy SeenVals;
>> >> +
>> >> + SizeOffsetEvalType unknown() {
>> >> + return std::make_pair((Value*)0, (Value*)0);
>> >> + }
>> >> + SizeOffsetEvalType compute_(Value *V);
>> >> +
>> >> +public:
>> >> + ObjectSizeOffsetEvaluator(const TargetData *TD, LLVMContext
>> >> &Context);
>> >> + SizeOffsetEvalType compute(Value *V);
>> >> +
>> >> + bool knownSize(SizeOffsetEvalType &SizeOffset) {
>> >> + return SizeOffset.first;
>> >> + }
>> >> +
>> >> + bool knownOffset(SizeOffsetEvalType &SizeOffset) {
>> >> + return SizeOffset.second;
>> >> + }
>> >> +
>> >> + bool anyKnown(SizeOffsetEvalType &SizeOffset) {
>> >> + return knownSize(SizeOffset) || knownOffset(SizeOffset);
>> >> + }
>> >> +
>> >> + bool bothKnown(SizeOffsetEvalType &SizeOffset) {
>> >> + return knownSize(SizeOffset) && knownOffset(SizeOffset);
>> >> + }
>> >> +
>> >> + SizeOffsetEvalType visitAllocaInst(AllocaInst &I);
>> >> + SizeOffsetEvalType visitCallSite(CallSite CS);
>> >> + SizeOffsetEvalType visitGEPOperator(GEPOperator &GEP);
>> >> + SizeOffsetEvalType visitIntToPtrInst(IntToPtrInst&);
>> >> + SizeOffsetEvalType visitLoadInst(LoadInst &I);
>> >> + SizeOffsetEvalType visitPHINode(PHINode &PHI);
>> >> + SizeOffsetEvalType visitSelectInst(SelectInst &I);
>> >> + SizeOffsetEvalType visitInstruction(Instruction &I);
>> >> +};
>> >> +
>> >> } // End llvm namespace
>> >>
>> >> #endif
>> >>
>> >> Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
>> >> URL:
>> >>
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=158919&r1=158918&r2=158919&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original) +++
>> >> llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Thu Jun 21 10:45:28
>> >> 2012 @@ -86,47 +86,10 @@ /// UnknownSize if unknown.
>> >> static uint64_t getObjectSize(const Value *V, const TargetData
>> >> &TD, bool RoundToAlign = false) {
>> >> - Type *AccessTy;
>> >> - unsigned Align;
>> >> - if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
>> >> - if (!GV->hasDefinitiveInitializer())
>> >> - return AliasAnalysis::UnknownSize;
>> >> - AccessTy = GV->getType()->getElementType();
>> >> - Align = GV->getAlignment();
>> >> - } else if (const AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
>> >> - if (!AI->isArrayAllocation())
>> >> - AccessTy = AI->getType()->getElementType();
>> >> - else
>> >> - return AliasAnalysis::UnknownSize;
>> >> - Align = AI->getAlignment();
>> >> - } else if (const CallInst* CI = extractMallocCall(V)) {
>> >> - if (!RoundToAlign && !isArrayMalloc(V, &TD))
>> >> - // The size is the argument to the malloc call.
>> >> - if (const ConstantInt* C =
>> >> dyn_cast<ConstantInt>(CI->getArgOperand(0)))
>> >> - return C->getZExtValue();
>> >> - return AliasAnalysis::UnknownSize;
>> >> - } else if (const Argument *A = dyn_cast<Argument>(V)) {
>> >> - if (A->hasByValAttr()) {
>> >> - AccessTy =
>> >> cast<PointerType>(A->getType())->getElementType();
>> >> - Align = A->getParamAlignment();
>> >> - } else {
>> >> - return AliasAnalysis::UnknownSize;
>> >> - }
>> >> - } else {
>> >> - return AliasAnalysis::UnknownSize;
>> >> - }
>> >> -
>> >> - if (!AccessTy->isSized())
>> >> - return AliasAnalysis::UnknownSize;
>> >> -
>> >> - uint64_t Size = TD.getTypeAllocSize(AccessTy);
>> >> - // If there is an explicitly specified alignment, and we need to
>> >> - // take alignment into account, round up the size. (If the
>> >> alignment
>> >> - // is implicit, getTypeAllocSize is sufficient.)
>> >> - if (RoundToAlign && Align)
>> >> - Size = RoundUpToAlignment(Size, Align);
>> >> -
>> >> - return Size;
>> >> + uint64_t Size;
>> >> + if (getObjectSize(V, Size, &TD, RoundToAlign))
>> >> + return Size;
>> >> + return AliasAnalysis::UnknownSize;
>> >> }
>> >>
>> >> /// isObjectSmallerThan - Return true if we can prove that the
>> >> object specified
>> >>
>> >> Modified: llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp
>> >> URL:
>> >>
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp?rev=158919&r1=158918&r2=158919&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp (original) +++
>> >> llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp Thu Jun 21 10:45:28
>> >> 2012 @@ -329,15 +329,8 @@ // Check the value being stored.
>> >> Value *Ptr = GetUnderlyingObject(SI->getOperand(0));
>> >>
>> >> - if (isMalloc(Ptr)) {
>> >> - // Okay, easy case.
>> >> - } else if (CallInst *CI = dyn_cast<CallInst>(Ptr)) {
>> >> - Function *F = CI->getCalledFunction();
>> >> - if (!F || !F->isDeclaration()) return false; // Too
>> >> hard to analyze.
>> >> - if (F->getName() != "calloc") return false; // Not
>> >> calloc.
>> >> - } else {
>> >> + if (!isAllocLikeFn(Ptr))
>> >> return false; // Too hard to analyze.
>> >> - }
>> >>
>> >> // Analyze all uses of the allocation. If any of them are
>> >> used in a // non-simple way (e.g. stored to another global) bail
>> >> out. @@ -454,19 +447,18 @@
>> >> for (inst_iterator II = inst_begin(SCC[i]->getFunction()),
>> >> E = inst_end(SCC[i]->getFunction());
>> >> II != E && FunctionEffect != ModRef; ++II)
>> >> - if (isa<LoadInst>(*II)) {
>> >> + if (LoadInst *LI = dyn_cast<LoadInst>(&*II)) {
>> >> FunctionEffect |= Ref;
>> >> - if (cast<LoadInst>(*II).isVolatile())
>> >> + if (LI->isVolatile())
>> >> // Volatile loads may have side-effects, so mark them
>> >> as writing // memory (for example, a flag inside the processor).
>> >> FunctionEffect |= Mod;
>> >> - } else if (isa<StoreInst>(*II)) {
>> >> + } else if (StoreInst *SI = dyn_cast<StoreInst>(&*II)) {
>> >> FunctionEffect |= Mod;
>> >> - if (cast<StoreInst>(*II).isVolatile())
>> >> + if (SI->isVolatile())
>> >> // Treat volatile stores as reading memory somewhere.
>> >> FunctionEffect |= Ref;
>> >> - } else if (isMalloc(&cast<Instruction>(*II)) ||
>> >> - isFreeCall(&cast<Instruction>(*II))) {
>> >> + } else if (isAllocationFn(&*II) || isFreeCall(&*II)) {
>> >> FunctionEffect |= ModRef;
>> >> } else if (IntrinsicInst *Intrinsic =
>> >> dyn_cast<IntrinsicInst>(&*II)) { // The callgraph doesn't include
>> >> intrinsic calls.
>> >>
>> >> Modified: llvm/trunk/lib/Analysis/MemoryBuiltins.cpp
>> >> URL:
>> >>
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MemoryBuiltins.cpp?rev=158919&r1=158918&r2=158919&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Analysis/MemoryBuiltins.cpp (original) +++
>> >> llvm/trunk/lib/Analysis/MemoryBuiltins.cpp Thu Jun 21 10:45:28 2012
>> >> @@ -12,80 +12,165 @@ //
>> >>
>> >>
>> //===----------------------------------------------------------------------===//
>> >>
>> >> +#define DEBUG_TYPE "memory-builtins"
>> >> +#include "llvm/ADT/Statistic.h"
>> >> +#include "llvm/ADT/STLExtras.h"
>> >> #include "llvm/Analysis/MemoryBuiltins.h"
>> >> -#include "llvm/Constants.h"
>> >> +#include "llvm/GlobalVariable.h"
>> >> #include "llvm/Instructions.h"
>> >> +#include "llvm/Intrinsics.h"
>> >> +#include "llvm/Metadata.h"
>> >> #include "llvm/Module.h"
>> >> #include "llvm/Analysis/ValueTracking.h"
>> >> +#include "llvm/Support/Debug.h"
>> >> +#include "llvm/Support/MathExtras.h"
>> >> +#include "llvm/Support/raw_ostream.h"
>> >> #include "llvm/Target/TargetData.h"
>> >> +#include "llvm/Transforms/Utils/Local.h"
>> >> using namespace llvm;
>> >>
>> >>
>> -//===----------------------------------------------------------------------===//
>> >> -// malloc Call Utility Functions.
>> >> -//
>> >> +enum AllocType {
>> >> + MallocLike = 1<<0, // allocates
>> >> + CallocLike = 1<<1, // allocates + bzero
>> >> + ReallocLike = 1<<2, // reallocates
>> >> + StrDupLike = 1<<3,
>> >> + AllocLike = MallocLike | CallocLike | StrDupLike,
>> >> + AnyAlloc = MallocLike | CallocLike | ReallocLike |
>> >> StrDupLike +};
>> >> +
>> >> +struct AllocFnsTy {
>> >> + const char *Name;
>> >> + AllocType AllocTy;
>> >> + unsigned char NumParams;
>> >> + // First and Second size parameters (or -1 if unused)
>> >> + unsigned char FstParam, SndParam;
>> >> +};
>> >> +
>> >> +static const AllocFnsTy AllocationFnData[] = {
>> >> + {"malloc", MallocLike, 1, 0, -1},
>> >> + {"valloc", MallocLike, 1, 0, -1},
>> >> + {"_Znwj", MallocLike, 1, 0, -1}, // operator
>> >> new(unsigned int)
>> >> + {"_Znwm", MallocLike, 1, 0, -1}, // operator
>> >> new(unsigned long)
>> >> + {"_Znaj", MallocLike, 1, 0, -1}, // operator
>> >> new[](unsigned int)
>> >> + {"_Znam", MallocLike, 1, 0, -1}, // operator
>> >> new[](unsigned long)
>> >> + {"posix_memalign", MallocLike, 3, 2, -1},
>> >> + {"calloc", CallocLike, 2, 0, 1},
>> >> + {"realloc", ReallocLike, 2, 1, -1},
>> >> + {"reallocf", ReallocLike, 2, 1, -1},
>> >> + {"strdup", StrDupLike, 1, -1, -1},
>> >> + {"strndup", StrDupLike, 2, -1, -1}
>> >> +};
>> >> +
>> >> +
>> >> +static Function *getCalledFunction(const Value *V, bool
>> >> LookThroughBitCast) {
>> >> + if (LookThroughBitCast)
>> >> + V = V->stripPointerCasts();
>> >> + const CallInst *CI = dyn_cast<CallInst>(V);
>> >> + if (!CI)
>> >> + return 0;
>> >>
>> >> -/// isMalloc - Returns true if the value is either a malloc call
>> >> or a -/// bitcast of the result of a malloc call.
>> >> -bool llvm::isMalloc(const Value *I) {
>> >> - return extractMallocCall(I) || extractMallocCallFromBitCast(I);
>> >> + Function *Callee = CI->getCalledFunction();
>> >> + if (!Callee || !Callee->isDeclaration())
>> >> + return 0;
>> >> + return Callee;
>> >> }
>> >>
>> >> -static bool isMallocCall(const CallInst *CI) {
>> >> - if (!CI)
>> >> - return false;
>> >> +/// \brief Returns the allocation data for the given value if it
>> >> is a call to a +/// known allocation function, and NULL otherwise.
>> >> +static const AllocFnsTy *getAllocationData(const Value *V,
>> >> AllocType AllocTy,
>> >> + bool
>> >> LookThroughBitCast = false) {
>> >> + Function *Callee = getCalledFunction(V, LookThroughBitCast);
>> >> + if (!Callee)
>> >> + return 0;
>> >>
>> >> - Function *Callee = CI->getCalledFunction();
>> >> - if (Callee == 0 || !Callee->isDeclaration())
>> >> - return false;
>> >> - if (Callee->getName() != "malloc" &&
>> >> - Callee->getName() != "_Znwj" && // operator new(unsigned
>> >> int)
>> >> - Callee->getName() != "_Znwm" && // operator new(unsigned
>> >> long)
>> >> - Callee->getName() != "_Znaj" && // operator new[](unsigned
>> >> int)
>> >> - Callee->getName() != "_Znam") // operator new[](unsigned
>> >> long)
>> >> - return false;
>> >> + unsigned i = 0;
>> >> + bool found = false;
>> >> + for ( ; i < array_lengthof(AllocationFnData); ++i) {
>> >> + if (Callee->getName() == AllocationFnData[i].Name) {
>> >> + found = true;
>> >> + break;
>> >> + }
>> >> + }
>> >> + if (!found)
>> >> + return 0;
>> >>
>> >> - // Check malloc prototype.
>> >> - // FIXME: workaround for PR5130, this will be obsolete when a
>> >> nobuiltin
>> >> - // attribute will exist.
>> >> + const AllocFnsTy *FnData = &AllocationFnData[i];
>> >> + if ((FnData->AllocTy & AllocTy) == 0)
>> >> + return 0;
>> >> +
>> >> + // Check function prototype.
>> >> + // FIXME: Check the nobuiltin metadata?? (PR5130)
>> >> + unsigned FstParam = FnData->FstParam;
>> >> + unsigned SndParam = FnData->SndParam;
>> >> FunctionType *FTy = Callee->getFunctionType();
>> >> - return FTy->getReturnType() ==
>> >> Type::getInt8PtrTy(FTy->getContext()) &&
>> >> - FTy->getNumParams() == 1 &&
>> >> - (FTy->getParamType(0)->isIntegerTy(32) ||
>> >> - FTy->getParamType(0)->isIntegerTy(64));
>> >> +
>> >> + if (FTy->getReturnType() ==
>> >> Type::getInt8PtrTy(FTy->getContext()) &&
>> >> + FTy->getNumParams() == FnData->NumParams &&
>> >> + (FstParam == (unsigned char)-1 ||
>> >> + (FTy->getParamType(FstParam)->isIntegerTy(32) ||
>> >> + FTy->getParamType(FstParam)->isIntegerTy(64))) &&
>> >> + (SndParam == (unsigned char)-1 ||
>> >> + FTy->getParamType(SndParam)->isIntegerTy(32) ||
>> >> + FTy->getParamType(SndParam)->isIntegerTy(64)))
>> >> + return FnData;
>> >> + return 0;
>> >> }
>> >>
>> >> -/// extractMallocCall - Returns the corresponding CallInst if the
>> >> instruction -/// is a malloc call. Since CallInst::CreateMalloc()
>> >> only creates calls, we -/// ignore InvokeInst here.
>> >> -const CallInst *llvm::extractMallocCall(const Value *I) {
>> >> - const CallInst *CI = dyn_cast<CallInst>(I);
>> >> - return (isMallocCall(CI)) ? CI : NULL;
>> >> +static bool hasNoAliasAttr(const Value *V, bool
>> >> LookThroughBitCast) {
>> >> + Function *Callee = getCalledFunction(V, LookThroughBitCast);
>> >> + return Callee && Callee->hasFnAttr(Attribute::NoAlias);
>> >> }
>> >>
>> >> -CallInst *llvm::extractMallocCall(Value *I) {
>> >> - CallInst *CI = dyn_cast<CallInst>(I);
>> >> - return (isMallocCall(CI)) ? CI : NULL;
>> >> +
>> >> +/// \brief Tests if a value is a call to a library function that
>> >> allocates or +/// reallocates memory (either malloc, calloc,
>> >> realloc, or strdup like). +bool llvm::isAllocationFn(const Value
>> >> *V, bool LookThroughBitCast) {
>> >> + return getAllocationData(V, AnyAlloc, LookThroughBitCast);
>> >> }
>> >>
>> >> -static bool isBitCastOfMallocCall(const BitCastInst *BCI) {
>> >> - if (!BCI)
>> >> - return false;
>> >> -
>> >> - return isMallocCall(dyn_cast<CallInst>(BCI->getOperand(0)));
>> >> +/// \brief Tests if a value is a call to a function that returns a
>> >> NoAlias +/// pointer (including malloc/calloc/strdup-like
>> >> functions). +bool llvm::isNoAliasFn(const Value *V, bool
>> >> LookThroughBitCast) {
>> >> + return isAllocLikeFn(V, LookThroughBitCast) ||
>> >> + hasNoAliasAttr(V, LookThroughBitCast);
>> >> }
>> >>
>> >> -/// extractMallocCallFromBitCast - Returns the corresponding
>> >> CallInst if the -/// instruction is a bitcast of the result of a
>> >> malloc call. -CallInst *llvm::extractMallocCallFromBitCast(Value
>> >> *I) {
>> >> - BitCastInst *BCI = dyn_cast<BitCastInst>(I);
>> >> - return (isBitCastOfMallocCall(BCI)) ?
>> >> cast<CallInst>(BCI->getOperand(0))
>> >> - : NULL;
>> >> +/// \brief Tests if a value is a call to a library function that
>> >> allocates +/// uninitialized memory (such as malloc).
>> >> +bool llvm::isMallocLikeFn(const Value *V, bool
>> >> LookThroughBitCast) {
>> >> + return getAllocationData(V, MallocLike, LookThroughBitCast);
>> >> +}
>> >> +
>> >> +/// \brief Tests if a value is a call to a library function that
>> >> allocates +/// zero-filled memory (such as calloc).
>> >> +bool llvm::isCallocLikeFn(const Value *V, bool
>> >> LookThroughBitCast) {
>> >> + return getAllocationData(V, CallocLike, LookThroughBitCast);
>> >> +}
>> >> +
>> >> +/// \brief Tests if a value is a call to a library function that
>> >> allocates +/// memory (either malloc, calloc, or strdup like).
>> >> +bool llvm::isAllocLikeFn(const Value *V, bool LookThroughBitCast)
>> >> {
>> >> + return getAllocationData(V, AllocLike, LookThroughBitCast);
>> >> }
>> >>
>> >> +/// \brief Tests if a value is a call to a library function that
>> >> reallocates +/// memory (such as realloc).
>> >> +bool llvm::isReallocLikeFn(const Value *V, bool
>> >> LookThroughBitCast) {
>> >> + return getAllocationData(V, ReallocLike, LookThroughBitCast);
>> >> +}
>> >> +
>> >> +/// extractMallocCall - Returns the corresponding CallInst if the
>> >> instruction +/// is a malloc call. Since CallInst::CreateMalloc()
>> >> only creates calls, we +/// ignore InvokeInst here.
>> >> +const CallInst *llvm::extractMallocCall(const Value *I) {
>> >> + return isMallocLikeFn(I) ? cast<CallInst>(I) : 0;
>> >> +}
>> >> +
>> >> +/// extractMallocCallFromBitCast - Returns the corresponding
>> >> CallInst if the +/// instruction is a bitcast of the result of a
>> >> malloc call. const CallInst
>> >> *llvm::extractMallocCallFromBitCast(const Value *I) { const
>> >> BitCastInst *BCI = dyn_cast<BitCastInst>(I);
>> >> - return (isBitCastOfMallocCall(BCI)) ?
>> >> cast<CallInst>(BCI->getOperand(0))
>> >> - : NULL;
>> >> + return BCI ? extractMallocCall(BCI->getOperand(0)) : 0;
>> >> }
>> >>
>> >> static Value *computeArraySize(const CallInst *CI, const
>> >> TargetData *TD, @@ -134,7 +219,7 @@
>> >> /// 1: PointerType is the bitcast's result type.
>> >> /// >1: Unique PointerType cannot be determined, return NULL.
>> >> PointerType *llvm::getMallocType(const CallInst *CI) {
>> >> - assert(isMalloc(CI) && "getMallocType and not malloc call");
>> >> + assert(isMallocLikeFn(CI) && "getMallocType and not malloc
>> >> call");
>> >>
>> >> PointerType *MallocType = NULL;
>> >> unsigned NumOfBitCastUses = 0;
>> >> @@ -176,53 +261,17 @@
>> >> /// determined.
>> >> Value *llvm::getMallocArraySize(CallInst *CI, const TargetData
>> >> *TD, bool LookThroughSExt) {
>> >> - assert(isMalloc(CI) && "getMallocArraySize and not malloc
>> >> call");
>> >> + assert(isMallocLikeFn(CI) && "getMallocArraySize and not malloc
>> >> call"); return computeArraySize(CI, TD, LookThroughSExt);
>> >> }
>> >>
>> >>
>> >>
>> -//===----------------------------------------------------------------------===//
>> >> -// calloc Call Utility Functions.
>> >> -//
>> >> -
>> >> -static bool isCallocCall(const CallInst *CI) {
>> >> - if (!CI)
>> >> - return false;
>> >> -
>> >> - Function *Callee = CI->getCalledFunction();
>> >> - if (Callee == 0 || !Callee->isDeclaration())
>> >> - return false;
>> >> - if (Callee->getName() != "calloc")
>> >> - return false;
>> >> -
>> >> - // Check malloc prototype.
>> >> - // FIXME: workaround for PR5130, this will be obsolete when a
>> >> nobuiltin
>> >> - // attribute exists.
>> >> - FunctionType *FTy = Callee->getFunctionType();
>> >> - return FTy->getReturnType() ==
>> >> Type::getInt8PtrTy(FTy->getContext()) &&
>> >> - FTy->getNumParams() == 2 &&
>> >> - ((FTy->getParamType(0)->isIntegerTy(32) &&
>> >> - FTy->getParamType(1)->isIntegerTy(32)) ||
>> >> - (FTy->getParamType(0)->isIntegerTy(64) &&
>> >> - FTy->getParamType(1)->isIntegerTy(64)));
>> >> -}
>> >> -
>> >> /// extractCallocCall - Returns the corresponding CallInst if the
>> >> instruction /// is a calloc call.
>> >> const CallInst *llvm::extractCallocCall(const Value *I) {
>> >> - const CallInst *CI = dyn_cast<CallInst>(I);
>> >> - return isCallocCall(CI) ? CI : 0;
>> >> + return isCallocLikeFn(I) ? cast<CallInst>(I) : 0;
>> >> }
>> >>
>> >> -CallInst *llvm::extractCallocCall(Value *I) {
>> >> - CallInst *CI = dyn_cast<CallInst>(I);
>> >> - return isCallocCall(CI) ? CI : 0;
>> >> -}
>> >> -
>> >> -
>> >>
>> -//===----------------------------------------------------------------------===//
>> >> -// free Call Utility Functions.
>> >> -//
>> >>
>> >> /// isFreeCall - Returns non-null if the value is a call to the
>> >> builtin free() const CallInst *llvm::isFreeCall(const Value *I) {
>> >> @@ -251,3 +300,388 @@
>> >>
>> >> return CI;
>> >> }
>> >> +
>> >> +
>> >> +
>> >>
>> +//===----------------------------------------------------------------------===//
>> >> +// Utility functions to compute size of objects.
>> >> +//
>> >> +
>> >> +
>> >> +/// \brief Compute the size of the object pointed by Ptr. Returns
>> >> true and the +/// object size in Size if successful, and false
>> >> otherwise. +/// If RoundToAlign is true, then Size is rounded up to
>> >> the aligment of allocas, +/// byval arguments, and global
>> >> variables. +bool llvm::getObjectSize(const Value *Ptr, uint64_t
>> >> &Size, const TargetData *TD,
>> >> + bool RoundToAlign) {
>> >> + if (!TD)
>> >> + return false;
>> >> +
>> >> + ObjectSizeOffsetVisitor Visitor(TD, Ptr->getContext(),
>> >> RoundToAlign);
>> >> + SizeOffsetType Data = Visitor.compute(const_cast<Value*>(Ptr));
>> >> + if (!Visitor.bothKnown(Data))
>> >> + return false;
>> >> +
>> >> + APInt ObjSize = Data.first, Offset = Data.second;
>> >> + // check for overflow
>> >> + if (Offset.slt(0) || ObjSize.ult(Offset))
>> >> + Size = 0;
>> >> + else
>> >> + Size = (ObjSize - Offset).getZExtValue();
>> >> + return true;
>> >> +}
>> >> +
>> >> +
>> >> +STATISTIC(ObjectVisitorArgument,
>> >> + "Number of arguments with unsolved size and offset");
>> >> +STATISTIC(ObjectVisitorLoad,
>> >> + "Number of load instructions with unsolved size and
>> >> offset"); +
>> >> +
>> >> +APInt ObjectSizeOffsetVisitor::align(APInt Size, uint64_t Align) {
>> >> + if (RoundToAlign && Align)
>> >> + return APInt(IntTyBits,
>> >> RoundUpToAlignment(Size.getZExtValue(), Align));
>> >> + return Size;
>> >> +}
>> >> +
>> >> +ObjectSizeOffsetVisitor::ObjectSizeOffsetVisitor(const TargetData
>> >> *TD,
>> >> + LLVMContext
>> >> &Context,
>> >> + bool
>> >> RoundToAlign) +: TD(TD), RoundToAlign(RoundToAlign) {
>> >> + IntegerType *IntTy = TD->getIntPtrType(Context);
>> >> + IntTyBits = IntTy->getBitWidth();
>> >> + Zero = APInt::getNullValue(IntTyBits);
>> >> +}
>> >> +
>> >> +SizeOffsetType ObjectSizeOffsetVisitor::compute(Value *V) {
>> >> + V = V->stripPointerCasts();
>> >> +
>> >> + if (GEPOperator *GEP = dyn_cast<GEPOperator>(V))
>> >> + return visitGEPOperator(*GEP);
>> >> + if (Instruction *I = dyn_cast<Instruction>(V))
>> >> + return visit(*I);
>> >> + if (Argument *A = dyn_cast<Argument>(V))
>> >> + return visitArgument(*A);
>> >> + if (ConstantPointerNull *P = dyn_cast<ConstantPointerNull>(V))
>> >> + return visitConstantPointerNull(*P);
>> >> + if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
>> >> + return visitGlobalVariable(*GV);
>> >> + if (UndefValue *UV = dyn_cast<UndefValue>(V))
>> >> + return visitUndefValue(*UV);
>> >> + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
>> >> + if (CE->getOpcode() == Instruction::IntToPtr)
>> >> + return unknown(); // clueless
>> >> +
>> >> + DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled
>> >> value: " << *V
>> >> + << '\n');
>> >> + return unknown();
>> >> +}
>> >> +
>> >> +SizeOffsetType ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst
>> >> &I) {
>> >> + if (!I.getAllocatedType()->isSized())
>> >> + return unknown();
>> >> +
>> >> + APInt Size(IntTyBits,
>> >> TD->getTypeAllocSize(I.getAllocatedType()));
>> >> + if (!I.isArrayAllocation())
>> >> + return std::make_pair(align(Size, I.getAlignment()), Zero);
>> >> +
>> >> + Value *ArraySize = I.getArraySize();
>> >> + if (const ConstantInt *C = dyn_cast<ConstantInt>(ArraySize)) {
>> >> + Size *= C->getValue().zextOrSelf(IntTyBits);
>> >> + return std::make_pair(align(Size, I.getAlignment()), Zero);
>> >> + }
>> >> + return unknown();
>> >> +}
>> >> +
>> >> +SizeOffsetType ObjectSizeOffsetVisitor::visitArgument(Argument
>> >> &A) {
>> >> + // no interprocedural analysis is done at the moment
>> >> + if (!A.hasByValAttr()) {
>> >> + ++ObjectVisitorArgument;
>> >> + return unknown();
>> >> + }
>> >> + PointerType *PT = cast<PointerType>(A.getType());
>> >> + APInt Size(IntTyBits,
>> >> TD->getTypeAllocSize(PT->getElementType()));
>> >> + return std::make_pair(align(Size, A.getParamAlignment()), Zero);
>> >> +}
>> >> +
>> >> +SizeOffsetType ObjectSizeOffsetVisitor::visitCallSite(CallSite
>> >> CS) {
>> >> + const AllocFnsTy *FnData =
>> >> getAllocationData(CS.getInstruction(), AnyAlloc);
>> >> + if (!FnData)
>> >> + return unknown();
>> >> +
>> >> + // handle strdup-like functions separately
>> >> + if (FnData->AllocTy == StrDupLike) {
>> >> + // TODO
>> >> + return unknown();
>> >> + }
>> >> +
>> >> + ConstantInt *Arg =
>> >> dyn_cast<ConstantInt>(CS.getArgument(FnData->FstParam));
>> >> + if (!Arg)
>> >> + return unknown();
>> >> +
>> >> + APInt Size = Arg->getValue();
>> >> + // size determined by just 1 parameter
>> >> + if (FnData->SndParam == (unsigned char)-1)
>> >> + return std::make_pair(Size, Zero);
>> >> +
>> >> + Arg = dyn_cast<ConstantInt>(CS.getArgument(FnData->SndParam));
>> >> + if (!Arg)
>> >> + return unknown();
>> >> +
>> >> + Size *= Arg->getValue();
>> >> + return std::make_pair(Size, Zero);
>> >> +
>> >> + // TODO: handle more standard functions (+ wchar cousins):
>> >> + // - strdup / strndup
>> >> + // - strcpy / strncpy
>> >> + // - strcat / strncat
>> >> + // - memcpy / memmove
>> >> + // - strcat / strncat
>> >> + // - memset
>> >> +}
>> >> +
>> >> +SizeOffsetType
>> >> +ObjectSizeOffsetVisitor::visitConstantPointerNull(ConstantPointerNull&)
>> >> {
>> >> + return std::make_pair(Zero, Zero);
>> >> +}
>> >> +
>> >> +SizeOffsetType
>> >> +ObjectSizeOffsetVisitor::visitExtractValueInst(ExtractValueInst&)
>> >> {
>> >> + // Easy cases were already folded by previous passes.
>> >> + return unknown();
>> >> +}
>> >> +
>> >> +SizeOffsetType
>> >> ObjectSizeOffsetVisitor::visitGEPOperator(GEPOperator &GEP) {
>> >> + SizeOffsetType PtrData = compute(GEP.getPointerOperand());
>> >> + if (!bothKnown(PtrData) || !GEP.hasAllConstantIndices())
>> >> + return unknown();
>> >> +
>> >> + SmallVector<Value*, 8> Ops(GEP.idx_begin(), GEP.idx_end());
>> >> + APInt
>> >> Offset(IntTyBits,TD->getIndexedOffset(GEP.getPointerOperandType(),Ops));
>> >> + return std::make_pair(PtrData.first, PtrData.second + Offset);
>> >> +}
>> >> +
>> >> +SizeOffsetType
>> >> ObjectSizeOffsetVisitor::visitGlobalVariable(GlobalVariable &GV){
>> >> + if (!GV.hasDefinitiveInitializer())
>> >> + return unknown();
>> >> +
>> >> + APInt Size(IntTyBits,
>> >> TD->getTypeAllocSize(GV.getType()->getElementType()));
>> >> + return std::make_pair(align(Size, GV.getAlignment()), Zero);
>> >> +}
>> >> +
>> >> +SizeOffsetType
>> >> ObjectSizeOffsetVisitor::visitIntToPtrInst(IntToPtrInst&) {
>> >> + // clueless
>> >> + return unknown();
>> >> +}
>> >> +
>> >> +SizeOffsetType ObjectSizeOffsetVisitor::visitLoadInst(LoadInst&) {
>> >> + ++ObjectVisitorLoad;
>> >> + return unknown();
>> >> +}
>> >> +
>> >> +SizeOffsetType ObjectSizeOffsetVisitor::visitPHINode(PHINode&) {
>> >> + // too complex to analyze statically.
>> >> + return unknown();
>> >> +}
>> >> +
>> >> +SizeOffsetType ObjectSizeOffsetVisitor::visitSelectInst(SelectInst
>> >> &I) {
>> >> + SizeOffsetType TrueSide = compute(I.getTrueValue());
>> >> + SizeOffsetType FalseSide = compute(I.getFalseValue());
>> >> + if (bothKnown(TrueSide) && bothKnown(FalseSide) && TrueSide ==
>> >> FalseSide)
>> >> + return TrueSide;
>> >> + return unknown();
>> >> +}
>> >> +
>> >> +SizeOffsetType
>> >> ObjectSizeOffsetVisitor::visitUndefValue(UndefValue&) {
>> >> + return std::make_pair(Zero, Zero);
>> >> +}
>> >> +
>> >> +SizeOffsetType
>> >> ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) {
>> >> + DEBUG(dbgs() << "ObjectSizeOffsetVisitor unknown instruction:"
>> >> << I << '\n');
>> >> + return unknown();
>> >> +}
>> >> +
>> >> +
>> >> +ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator(const
>> >> TargetData *TD,
>> >> + LLVMContext
>> >> &Context) +: TD(TD), Context(Context), Builder(Context,
>> >> TargetFolder(TD)), +Visitor(TD, Context) {
>> >> + IntTy = TD->getIntPtrType(Context);
>> >> + Zero = ConstantInt::get(IntTy, 0);
>> >> +}
>> >> +
>> >> +SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute(Value *V) {
>> >> + SizeOffsetEvalType Result = compute_(V);
>> >> +
>> >> + if (!bothKnown(Result)) {
>> >> + // erase everything that was computed in this iteration from
>> >> the cache, so
>> >> + // that no dangling references are left behind. We could be a
>> >> bit smarter if
>> >> + // we kept a dependency graph. It's probably not worth the
>> >> complexity.
>> >> + for (PtrSetTy::iterator I=SeenVals.begin(), E=SeenVals.end();
>> >> I != E; ++I) {
>> >> + CacheMapTy::iterator CacheIt = CacheMap.find(*I);
>> >> + // non-computable results can be safely cached
>> >> + if (CacheIt != CacheMap.end() && anyKnown(CacheIt->second))
>> >> + CacheMap.erase(CacheIt);
>> >> + }
>> >> + }
>> >> +
>> >> + SeenVals.clear();
>> >> + return Result;
>> >> +}
>> >> +
>> >> +SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) {
>> >> + SizeOffsetType Const = Visitor.compute(V);
>> >> + if (Visitor.bothKnown(Const))
>> >> + return std::make_pair(ConstantInt::get(Context, Const.first),
>> >> + ConstantInt::get(Context,
>> >> Const.second)); +
>> >> + V = V->stripPointerCasts();
>> >> +
>> >> + // check cache
>> >> + CacheMapTy::iterator CacheIt = CacheMap.find(V);
>> >> + if (CacheIt != CacheMap.end())
>> >> + return CacheIt->second;
>> >> +
>> >> + // always generate code immediately before the instruction being
>> >> + // processed, so that the generated code dominates the same BBs
>> >> + Instruction *PrevInsertPoint = Builder.GetInsertPoint();
>> >> + if (Instruction *I = dyn_cast<Instruction>(V))
>> >> + Builder.SetInsertPoint(I);
>> >> +
>> >> + // record the pointers that were handled in this run, so that
>> >> they can be
>> >> + // cleaned later if something fails
>> >> + SeenVals.insert(V);
>> >> +
>> >> + // now compute the size and offset
>> >> + SizeOffsetEvalType Result;
>> >> + if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
>> >> + Result = visitGEPOperator(*GEP);
>> >> + } else if (Instruction *I = dyn_cast<Instruction>(V)) {
>> >> + Result = visit(*I);
>> >> + } else if (isa<Argument>(V) ||
>> >> + (isa<ConstantExpr>(V) &&
>> >> + cast<ConstantExpr>(V)->getOpcode() ==
>> >> Instruction::IntToPtr) ||
>> >> + isa<GlobalVariable>(V)) {
>> >> + // ignore values where we cannot do more than what
>> >> ObjectSizeVisitor can
>> >> + Result = unknown();
>> >> + } else {
>> >> + DEBUG(dbgs() << "ObjectSizeOffsetEvaluator::compute()
>> >> unhandled value: "
>> >> + << *V << '\n');
>> >> + Result = unknown();
>> >> + }
>> >> +
>> >> + if (PrevInsertPoint)
>> >> + Builder.SetInsertPoint(PrevInsertPoint);
>> >> +
>> >> + // Don't reuse CacheIt since it may be invalid at this point.
>> >> + CacheMap[V] = Result;
>> >> + return Result;
>> >> +}
>> >> +
>> >> +SizeOffsetEvalType
>> >> ObjectSizeOffsetEvaluator::visitAllocaInst(AllocaInst &I) {
>> >> + if (!I.getAllocatedType()->isSized())
>> >> + return unknown();
>> >> +
>> >> + // must be a VLA
>> >> + assert(I.isArrayAllocation());
>> >> + Value *ArraySize = I.getArraySize();
>> >> + Value *Size = ConstantInt::get(ArraySize->getType(),
>> >> +
>> >> TD->getTypeAllocSize(I.getAllocatedType()));
>> >> + Size = Builder.CreateMul(Size, ArraySize);
>> >> + return std::make_pair(Size, Zero);
>> >> +}
>> >> +
>> >> +SizeOffsetEvalType
>> >> ObjectSizeOffsetEvaluator::visitCallSite(CallSite CS) {
>> >> + const AllocFnsTy *FnData =
>> >> getAllocationData(CS.getInstruction(), AnyAlloc);
>> >> + if (!FnData)
>> >> + return unknown();
>> >> +
>> >> + // handle strdup-like functions separately
>> >> + if (FnData->AllocTy == StrDupLike) {
>> >> + // TODO
>> >> + return unknown();
>> >> + }
>> >> +
>> >> + Value *FirstArg = CS.getArgument(FnData->FstParam);
>> >> + if (FnData->SndParam == (unsigned char)-1)
>> >> + return std::make_pair(FirstArg, Zero);
>> >> +
>> >> + Value *SecondArg = CS.getArgument(FnData->SndParam);
>> >> + Value *Size = Builder.CreateMul(FirstArg, SecondArg);
>> >> + return std::make_pair(Size, Zero);
>> >> +
>> >> + // TODO: handle more standard functions (+ wchar cousins):
>> >> + // - strdup / strndup
>> >> + // - strcpy / strncpy
>> >> + // - strcat / strncat
>> >> + // - memcpy / memmove
>> >> + // - strcat / strncat
>> >> + // - memset
>> >> +}
>> >> +
>> >> +SizeOffsetEvalType
>> >> +ObjectSizeOffsetEvaluator::visitGEPOperator(GEPOperator &GEP) {
>> >> + SizeOffsetEvalType PtrData = compute_(GEP.getPointerOperand());
>> >> + if (!bothKnown(PtrData))
>> >> + return unknown();
>> >> +
>> >> + Value *Offset = EmitGEPOffset(&Builder, *TD, &GEP);
>> >> + Offset = Builder.CreateAdd(PtrData.second, Offset);
>> >> + return std::make_pair(PtrData.first, Offset);
>> >> +}
>> >> +
>> >> +SizeOffsetEvalType
>> >> ObjectSizeOffsetEvaluator::visitIntToPtrInst(IntToPtrInst&) {
>> >> + // clueless
>> >> + return unknown();
>> >> +}
>> >> +
>> >> +SizeOffsetEvalType
>> >> ObjectSizeOffsetEvaluator::visitLoadInst(LoadInst&) {
>> >> + return unknown();
>> >> +}
>> >> +
>> >> +SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitPHINode(PHINode
>> >> &PHI) {
>> >> + // create 2 PHIs: one for size and another for offset
>> >> + PHINode *SizePHI = Builder.CreatePHI(IntTy,
>> >> PHI.getNumIncomingValues());
>> >> + PHINode *OffsetPHI = Builder.CreatePHI(IntTy,
>> >> PHI.getNumIncomingValues()); +
>> >> + // insert right away in the cache to handle recursive PHIs
>> >> + CacheMap[&PHI] = std::make_pair(SizePHI, OffsetPHI);
>> >> +
>> >> + // compute offset/size for each PHI incoming pointer
>> >> + for (unsigned i = 0, e = PHI.getNumIncomingValues(); i != e;
>> >> ++i) { +
>> >> Builder.SetInsertPoint(PHI.getIncomingBlock(i)->getFirstInsertionPt());
>> >> + SizeOffsetEvalType EdgeData =
>> >> compute_(PHI.getIncomingValue(i)); +
>> >> + if (!bothKnown(EdgeData)) {
>> >> + OffsetPHI->replaceAllUsesWith(UndefValue::get(IntTy));
>> >> + OffsetPHI->eraseFromParent();
>> >> + SizePHI->replaceAllUsesWith(UndefValue::get(IntTy));
>> >> + SizePHI->eraseFromParent();
>> >> + return unknown();
>> >> + }
>> >> + SizePHI->addIncoming(EdgeData.first, PHI.getIncomingBlock(i));
>> >> + OffsetPHI->addIncoming(EdgeData.second,
>> >> PHI.getIncomingBlock(i));
>> >> + }
>> >> + return std::make_pair(SizePHI, OffsetPHI);
>> >> +}
>> >> +
>> >> +SizeOffsetEvalType
>> >> ObjectSizeOffsetEvaluator::visitSelectInst(SelectInst &I) {
>> >> + SizeOffsetEvalType TrueSide = compute_(I.getTrueValue());
>> >> + SizeOffsetEvalType FalseSide = compute_(I.getFalseValue());
>> >> +
>> >> + if (!bothKnown(TrueSide) || !bothKnown(FalseSide))
>> >> + return unknown();
>> >> + if (TrueSide == FalseSide)
>> >> + return TrueSide;
>> >> +
>> >> + Value *Size = Builder.CreateSelect(I.getCondition(),
>> >> TrueSide.first,
>> >> + FalseSide.first);
>> >> + Value *Offset = Builder.CreateSelect(I.getCondition(),
>> >> TrueSide.second,
>> >> + FalseSide.second);
>> >> + return std::make_pair(Size, Offset);
>> >> +}
>> >> +
>> >> +SizeOffsetEvalType
>> >> ObjectSizeOffsetEvaluator::visitInstruction(Instruction &I) {
>> >> + DEBUG(dbgs() << "ObjectSizeOffsetEvaluator unknown instruction:"
>> >> << I <<'\n');
>> >> + return unknown();
>> >> +}
>> >>
>> >> Modified: llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp
>> >> URL:
>> >>
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp?rev=158919&r1=158918&r2=158919&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp (original)
>> >> +++ llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp Thu Jun 21
>> >> 10:45:28 2012 @@ -474,8 +474,7 @@ // a subsequent bitcast of the
>> >> malloc call result. There can be stores to // the malloced memory
>> >> between the malloc call and its bitcast uses, and we // need to
>> >> continue scanning until the malloc call.
>> >> - if (isa<AllocaInst>(Inst) ||
>> >> - (isa<CallInst>(Inst) && extractMallocCall(Inst))) {
>> >> + if (isa<AllocaInst>(Inst) || isNoAliasFn(Inst)) {
>> >> const Value *AccessPtr = GetUnderlyingObject(MemLoc.Ptr,
>> >> TD);
>> >>
>> >> if (AccessPtr == Inst || AA->isMustAlias(Inst, AccessPtr))
>> >>
>> >> Modified:
>> >> llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp URL:
>> >>
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=158919&r1=158918&r2=158919&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
>> >> (original) +++
>> >> llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Thu Jun
>> >> 21 10:45:28 2012 @@ -172,7 +172,7 @@ Instruction
>> >> *InstCombiner::visitCallInst(CallInst &CI) { if (isFreeCall(&CI))
>> >> return visitFree(CI);
>> >> - if (extractMallocCall(&CI) || extractCallocCall(&CI))
>> >> + if (isAllocLikeFn(&CI))
>> >> return visitMalloc(CI);
>> >>
>> >> // If the caller function is nounwind, mark the call as
>> >> nounwind, even if the @@ -246,84 +246,10 @@
>> >> switch (II->getIntrinsicID()) {
>> >> default: break;
>> >> case Intrinsic::objectsize: {
>> >> - // We need target data for just about everything so depend on
>> >> it.
>> >> - if (!TD) return 0;
>> >> -
>> >> - Type *ReturnTy = CI.getType();
>> >> - uint64_t DontKnow = II->getArgOperand(1) ==
>> >> Builder->getTrue() ? 0 : -1ULL; -
>> >> - // Get to the real allocated thing and offset as fast as
>> >> possible.
>> >> - Value *Op1 = II->getArgOperand(0)->stripPointerCasts();
>> >> -
>> >> - uint64_t Offset = 0;
>> >> - uint64_t Size = -1ULL;
>> >> -
>> >> - // Try to look through constant GEPs.
>> >> - if (GEPOperator *GEP = dyn_cast<GEPOperator>(Op1)) {
>> >> - if (!GEP->hasAllConstantIndices()) return 0;
>> >> -
>> >> - // Get the current byte offset into the thing. Use the
>> >> original
>> >> - // operand in case we're looking through a bitcast.
>> >> - SmallVector<Value*, 8> Ops(GEP->idx_begin(),
>> >> GEP->idx_end());
>> >> - if (!GEP->getPointerOperandType()->isPointerTy())
>> >> - return 0;
>> >> - Offset = TD->getIndexedOffset(GEP->getPointerOperandType(),
>> >> Ops); -
>> >> - Op1 = GEP->getPointerOperand()->stripPointerCasts();
>> >> -
>> >> - // Make sure we're not a constant offset from an external
>> >> - // global.
>> >> - if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Op1))
>> >> - if (!GV->hasDefinitiveInitializer()) return 0;
>> >> - }
>> >> -
>> >> - // If we've stripped down to a single global variable that we
>> >> - // can know the size of then just return that.
>> >> - if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Op1)) {
>> >> - if (GV->hasDefinitiveInitializer()) {
>> >> - Constant *C = GV->getInitializer();
>> >> - Size = TD->getTypeAllocSize(C->getType());
>> >> - } else {
>> >> - // Can't determine size of the GV.
>> >> - Constant *RetVal = ConstantInt::get(ReturnTy, DontKnow);
>> >> - return ReplaceInstUsesWith(CI, RetVal);
>> >> - }
>> >> - } else if (AllocaInst *AI = dyn_cast<AllocaInst>(Op1)) {
>> >> - // Get alloca size.
>> >> - if (AI->getAllocatedType()->isSized()) {
>> >> - Size = TD->getTypeAllocSize(AI->getAllocatedType());
>> >> - if (AI->isArrayAllocation()) {
>> >> - const ConstantInt *C =
>> >> dyn_cast<ConstantInt>(AI->getArraySize());
>> >> - if (!C) return 0;
>> >> - Size *= C->getZExtValue();
>> >> - }
>> >> - }
>> >> - } else if (CallInst *MI = extractMallocCall(Op1)) {
>> >> - // Get allocation size.
>> >> - Value *Arg = MI->getArgOperand(0);
>> >> - if (ConstantInt *CI = dyn_cast<ConstantInt>(Arg))
>> >> - Size = CI->getZExtValue();
>> >> -
>> >> - } else if (CallInst *MI = extractCallocCall(Op1)) {
>> >> - // Get allocation size.
>> >> - Value *Arg1 = MI->getArgOperand(0);
>> >> - Value *Arg2 = MI->getArgOperand(1);
>> >> - if (ConstantInt *CI1 = dyn_cast<ConstantInt>(Arg1))
>> >> - if (ConstantInt *CI2 = dyn_cast<ConstantInt>(Arg2))
>> >> - Size = (CI1->getValue() *
>> >> CI2->getValue()).getZExtValue();
>> >> - }
>> >> -
>> >> - // Do not return "I don't know" here. Later optimization
>> >> passes could
>> >> - // make it possible to evaluate objectsize to a constant.
>> >> - if (Size == -1ULL)
>> >> - return 0;
>> >> -
>> >> - if (Size < Offset) {
>> >> - // Out of bound reference? Negative index normalized to
>> >> large
>> >> - // index? Just return "I don't know".
>> >> - return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy,
>> >> DontKnow));
>> >> - }
>> >> - return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy,
>> >> Size-Offset));
>> >> + uint64_t Size;
>> >> + if (getObjectSize(II->getArgOperand(0), Size, TD))
>> >> + return ReplaceInstUsesWith(CI,
>> >> ConstantInt::get(CI.getType(), Size));
>> >> + return 0;
>> >> }
>> >> case Intrinsic::bswap:
>> >> // bswap(bswap(x)) -> x
>> >> @@ -768,7 +694,7 @@
>> >> TerminatorInst *TI = II->getParent()->getTerminator();
>> >> bool CannotRemove = false;
>> >> for (++BI; &*BI != TI; ++BI) {
>> >> - if (isa<AllocaInst>(BI) || isMalloc(BI)) {
>> >> + if (isa<AllocaInst>(BI)) {
>> >> CannotRemove = true;
>> >> break;
>> >> }
>> >>
>> >> Modified:
>> >> llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp URL:
>> >>
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp?rev=158919&r1=158918&r2=158919&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
>> >> (original) +++
>> >> llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp Thu
>> >> Jun 21 10:45:28 2012 @@ -1068,7 +1068,7 @@ // If the bitcast is of
>> >> an allocation, and the allocation will be // converted to match
>> >> the type of the cast, don't touch this. if
>> >> (isa<AllocaInst>(BCI->getOperand(0)) ||
>> >> - isMalloc(BCI->getOperand(0))) {
>> >> + isAllocationFn(BCI->getOperand(0))) {
>> >> // See if the bitcast simplifies, if so, don't nuke this
>> >> GEP yet. if (Instruction *I = visitBitCast(*BCI)) {
>> >> if (I != BCI) {
>> >>
>> >> Modified: llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp
>> >> URL:
>> >>
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp?rev=158919&r1=158918&r2=158919&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp
>> >> (original) +++
>> >> llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp Thu Jun
>> >> 21 10:45:28 2012 @@ -275,39 +275,9 @@ }
>> >> static uint64_t getPointerSize(const Value *V, AliasAnalysis &AA)
>> >> {
>> >> - const TargetData *TD = AA.getTargetData();
>> >> -
>> >> - if (const CallInst *CI = extractMallocCall(V)) {
>> >> - if (const ConstantInt *C =
>> >> dyn_cast<ConstantInt>(CI->getArgOperand(0)))
>> >> - return C->getZExtValue();
>> >> - }
>> >> -
>> >> - if (const CallInst *CI = extractCallocCall(V)) {
>> >> - if (const ConstantInt *C1 =
>> >> dyn_cast<ConstantInt>(CI->getArgOperand(0)))
>> >> - if (const ConstantInt *C2 =
>> >> dyn_cast<ConstantInt>(CI->getArgOperand(1)))
>> >> - return (C1->getValue() * C2->getValue()).getZExtValue();
>> >> - }
>> >> -
>> >> - if (TD == 0)
>> >> - return AliasAnalysis::UnknownSize;
>> >> -
>> >> - if (const AllocaInst *A = dyn_cast<AllocaInst>(V)) {
>> >> - // Get size information for the alloca
>> >> - if (const ConstantInt *C =
>> >> dyn_cast<ConstantInt>(A->getArraySize()))
>> >> - return C->getZExtValue() *
>> >> TD->getTypeAllocSize(A->getAllocatedType());
>> >> - }
>> >> -
>> >> - if (const Argument *A = dyn_cast<Argument>(V)) {
>> >> - if (A->hasByValAttr())
>> >> - if (PointerType *PT = dyn_cast<PointerType>(A->getType()))
>> >> - return TD->getTypeAllocSize(PT->getElementType());
>> >> - }
>> >> -
>> >> - if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
>> >> - if (!GV->mayBeOverridden())
>> >> - return
>> >> TD->getTypeAllocSize(GV->getType()->getElementType());
>> >> - }
>> >> -
>> >> + uint64_t Size;
>> >> + if (getObjectSize(V, Size, AA.getTargetData()))
>> >> + return Size;
>> >> return AliasAnalysis::UnknownSize;
>> >> }
>> >>
>> >> @@ -705,16 +675,13 @@
>> >> // Find all of the alloca'd pointers in the entry block.
>> >> BasicBlock *Entry = BB.getParent()->begin();
>> >> for (BasicBlock::iterator I = Entry->begin(), E = Entry->end();
>> >> I != E; ++I) {
>> >> - if (AllocaInst *AI = dyn_cast<AllocaInst>(I))
>> >> - DeadStackObjects.insert(AI);
>> >> + if (isa<AllocaInst>(I))
>> >> + DeadStackObjects.insert(I);
>> >>
>> >> // Okay, so these are dead heap objects, but if the pointer
>> >> never escapes // then it's leaked by this function anyways.
>> >> - CallInst *CI = extractMallocCall(I);
>> >> - if (!CI)
>> >> - CI = extractCallocCall(I);
>> >> - if (CI && !PointerMayBeCaptured(CI, true, true))
>> >> - DeadStackObjects.insert(CI);
>> >> + else if (isAllocLikeFn(I) && !PointerMayBeCaptured(I, true,
>> >> true))
>> >> + DeadStackObjects.insert(I);
>> >> }
>> >>
>> >> // Treat byval arguments the same, stores to them are dead at
>> >> the end of the @@ -773,18 +740,8 @@
>> >> continue;
>> >> }
>> >>
>> >> - if (AllocaInst *A = dyn_cast<AllocaInst>(BBI)) {
>> >> - DeadStackObjects.remove(A);
>> >> - continue;
>> >> - }
>> >> -
>> >> - if (CallInst *CI = extractMallocCall(BBI)) {
>> >> - DeadStackObjects.remove(CI);
>> >> - continue;
>> >> - }
>> >> -
>> >> - if (CallInst *CI = extractCallocCall(BBI)) {
>> >> - DeadStackObjects.remove(CI);
>> >> + if (isa<AllocaInst>(BBI) || isAllocLikeFn(BBI)) {
>> >> + DeadStackObjects.remove(BBI);
>> >> continue;
>> >> }
>> >>
>> >>
>> >> Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp
>> >> URL:
>> >>
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=158919&r1=158918&r2=158919&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) +++
>> >> llvm/trunk/lib/Transforms/Scalar/GVN.cpp Thu Jun 21 10:45:28 2012
>> >> @@ -1436,7 +1436,7 @@ Instruction *DepInst = DepInfo.getInst();
>> >>
>> >> // Loading the allocation -> undef.
>> >> - if (isa<AllocaInst>(DepInst) || isMalloc(DepInst) ||
>> >> + if (isa<AllocaInst>(DepInst) || isMallocLikeFn(DepInst) ||
>> >> // Loading immediately after lifetime begin -> undef.
>> >> isLifetimeStart(DepInst)) {
>> >> ValuesPerBlock.push_back(AvailableValueInBlock::get(DepBB,
>> >> @@ -1951,7 +1951,7 @@
>> >> // If this load really doesn't depend on anything, then we must
>> >> be loading an // undef value. This can happen when loading for a
>> >> fresh allocation with no // intervening stores, for example.
>> >> - if (isa<AllocaInst>(DepInst) || isMalloc(DepInst)) {
>> >> + if (isa<AllocaInst>(DepInst) || isMallocLikeFn(DepInst)) {
>> >> L->replaceAllUsesWith(UndefValue::get(L->getType()));
>> >> markInstructionForDeletion(L);
>> >> ++NumGVNLoad;
>> >>
>> >> Modified: llvm/trunk/lib/Transforms/Utils/Local.cpp
>> >> URL:
>> >>
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=158919&r1=158918&r2=158919&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/Utils/Local.cpp (original) +++
>> >> llvm/trunk/lib/Transforms/Utils/Local.cpp Thu Jun 21 10:45:28 2012
>> >> @@ -266,7 +266,7 @@ return isa<UndefValue>(II->getArgOperand(1));
>> >> }
>> >>
>> >> - if (extractMallocCall(I) || extractCallocCall(I)) return true;
>> >> + if (isAllocLikeFn(I)) return true;
>> >>
>> >> if (CallInst *CI = isFreeCall(I))
>> >> if (Constant *C = dyn_cast<Constant>(CI->getArgOperand(0)))
>> >>
>> >> Modified: llvm/trunk/test/Transforms/InstCombine/objsize.ll
>> >> URL:
>> >>
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/objsize.ll?rev=158919&r1=158918&r2=158919&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Transforms/InstCombine/objsize.ll (original)
>> >> +++ llvm/trunk/test/Transforms/InstCombine/objsize.ll Thu Jun 21
>> >> 10:45:28 2012 @@ -42,7 +42,7 @@
>> >> define i1 @baz() nounwind {
>> >> ; CHECK: @baz
>> >> -; CHECK-NEXT: ret i1 true
>> >> +; CHECK-NEXT: objectsize
>> >> %1 = tail call i32 @llvm.objectsize.i32(i8* getelementptr
>> >> inbounds ([0 x i8]* @window, i32 0, i32 0), i1 false) %2 = icmp eq
>> >> i32 %1, -1 ret i1 %2
>> >>
>> >>
>> >> _______________________________________________
>> >> llvm-commits mailing list
>> >> llvm-commits at cs.uiuc.edu
>> >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>> >
>> >
>> >
>> > --
>> > Hal Finkel
>> > Postdoctoral Appointee
>> > Leadership Computing Facility
>> > Argonne National Laboratory
>
>
>
> --
> Hal Finkel
> Postdoctoral Appointee
> Leadership Computing Facility
> Argonne National Laboratory
> ---------------------------------------------------------------------
> Intel Israel (74) Limited
>
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.
More information about the llvm-commits
mailing list