[llvm-commits] [llvm] r162841 - in /llvm/trunk: include/llvm/Analysis/ include/llvm/Target/ include/llvm/Transforms/Utils/ lib/Analysis/ lib/Analysis/IPA/ lib/Target/ lib/Transforms/IPO/ lib/Transforms/InstCombine/ lib/Transforms/Instrumentation/ lib/T
Nuno Lopes
nunoplopes at sapo.pt
Sun Sep 2 07:07:02 PDT 2012
cool!
AFAICT, this patch closes the last big loophole we had in detecting (and
emitting calls to) library functions :)
Nuno
----- Original Message -----
From: "Benjamin Kramer" <benny.kra at googlemail.com>
Sent: Wednesday, August 29, 2012 4:32 PM
> Author: d0k
> Date: Wed Aug 29 10:32:21 2012
> New Revision: 162841
>
> URL: http://llvm.org/viewvc/llvm-project?rev=162841&view=rev
> Log:
> Make MemoryBuiltins aware of TargetLibraryInfo.
>
> This disables malloc-specific optimization when -fno-builtin
> (or -ffreestanding)
> is specified. This has been a problem for a long time but became more
> severe
> with the recent memory builtin improvements.
>
> Since the memory builtin functions are used everywhere, this required
> passing
> TLI in many places. This means that functions that now have an optional
> TLI
> argument, like RecursivelyDeleteTriviallyDeadFunctions, won't remove dead
> mallocs anymore if the TLI argument is missing. I've updated most passes
> to do
> the right thing.
>
> Fixes PR13694 and probably others.
>
> Added:
> llvm/trunk/test/Transforms/GVN/malloc-load-removal.ll
> Modified:
> llvm/trunk/include/llvm/Analysis/AliasAnalysis.h
> llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h
> llvm/trunk/include/llvm/Target/TargetLibraryInfo.h
> llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h
> llvm/trunk/include/llvm/Transforms/Utils/Local.h
> llvm/trunk/lib/Analysis/AliasAnalysis.cpp
> 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/Target/TargetLibraryInfo.cpp
> llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
> llvm/trunk/lib/Transforms/IPO/Inliner.cpp
> llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
> llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
> llvm/trunk/lib/Transforms/Instrumentation/BoundsChecking.cpp
> llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp
> llvm/trunk/lib/Transforms/Scalar/DCE.cpp
> llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp
> llvm/trunk/lib/Transforms/Scalar/EarlyCSE.cpp
> llvm/trunk/lib/Transforms/Scalar/GVN.cpp
> llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
> llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
> llvm/trunk/lib/Transforms/Scalar/LICM.cpp
> llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
> llvm/trunk/lib/Transforms/Scalar/LoopInstSimplify.cpp
> llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp
> llvm/trunk/lib/Transforms/Utils/Local.cpp
> llvm/trunk/lib/Transforms/Utils/SimplifyInstructions.cpp
> llvm/trunk/lib/Transforms/Vectorize/BBVectorize.cpp
>
> Modified: llvm/trunk/include/llvm/Analysis/AliasAnalysis.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/AliasAnalysis.h?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Analysis/AliasAnalysis.h (original)
> +++ llvm/trunk/include/llvm/Analysis/AliasAnalysis.h Wed Aug 29 10:32:21
> 2012
> @@ -46,6 +46,7 @@
> class StoreInst;
> class VAArgInst;
> class TargetData;
> +class TargetLibraryInfo;
> class Pass;
> class AnalysisUsage;
> class MemTransferInst;
> @@ -55,6 +56,7 @@
> class AliasAnalysis {
> protected:
> const TargetData *TD;
> + const TargetLibraryInfo *TLI;
>
> private:
> AliasAnalysis *AA; // Previous Alias Analysis to chain to.
> @@ -73,7 +75,7 @@
>
> public:
> static char ID; // Class identification, replacement for typeinfo
> - AliasAnalysis() : TD(0), AA(0) {}
> + AliasAnalysis() : TD(0), TLI(0), AA(0) {}
> virtual ~AliasAnalysis(); // We want to be subclassed
>
> /// UnknownSize - This is a special value which can be used with the
> @@ -86,6 +88,11 @@
> ///
> const TargetData *getTargetData() const { return TD; }
>
> + /// getTargetLibraryInfo - Return a pointer to the current
> TargetLibraryInfo
> + /// object, or null if no TargetLibraryInfo object is available.
> + ///
> + const TargetLibraryInfo *getTargetLibraryInfo() const { return TLI; }
> +
> /// getTypeStoreSize - Return the TargetData store size for the given
> type,
> /// if known, or a conservative value otherwise.
> ///
>
> Modified: llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h (original)
> +++ llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h Wed Aug 29 10:32:21
> 2012
> @@ -28,6 +28,7 @@
> class CallInst;
> class PointerType;
> class TargetData;
> +class TargetLibraryInfo;
> class Type;
> class Value;
>
> @@ -35,27 +36,33 @@
> /// \brief Tests if a value is a call or invoke to a library function that
> /// allocates or reallocates memory (either malloc, calloc, realloc, or
> strdup
> /// like).
> -bool isAllocationFn(const Value *V, bool LookThroughBitCast = false);
> +bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI,
> + bool LookThroughBitCast = false);
>
> /// \brief Tests if a value is a call or invoke to a function that returns
> a
> /// NoAlias pointer (including malloc/calloc/realloc/strdup-like
> functions).
> -bool isNoAliasFn(const Value *V, bool LookThroughBitCast = false);
> +bool isNoAliasFn(const Value *V, const TargetLibraryInfo *TLI,
> + bool LookThroughBitCast = false);
>
> /// \brief Tests if a value is a call or invoke to a library function that
> /// allocates uninitialized memory (such as malloc).
> -bool isMallocLikeFn(const Value *V, bool LookThroughBitCast = false);
> +bool isMallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
> + bool LookThroughBitCast = false);
>
> /// \brief Tests if a value is a call or invoke to a library function that
> /// allocates zero-filled memory (such as calloc).
> -bool isCallocLikeFn(const Value *V, bool LookThroughBitCast = false);
> +bool isCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
> + bool LookThroughBitCast = false);
>
> /// \brief Tests if a value is a call or invoke to a library function that
> /// allocates memory (either malloc, calloc, or strdup like).
> -bool isAllocLikeFn(const Value *V, bool LookThroughBitCast = false);
> +bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
> + bool LookThroughBitCast = false);
>
> /// \brief Tests if a value is a call or invoke to a library function that
> /// reallocates memory (such as realloc).
> -bool isReallocLikeFn(const Value *V, bool LookThroughBitCast = false);
> +bool isReallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
> + bool LookThroughBitCast = false);
>
>
> //===----------------------------------------------------------------------===//
> @@ -65,29 +72,31 @@
> /// 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);
> -static inline CallInst *extractMallocCall(Value *I) {
> - return const_cast<CallInst*>(extractMallocCall((const Value*)I));
> +const CallInst *extractMallocCall(const Value *I, const TargetLibraryInfo
> *TLI);
> +static inline CallInst *extractMallocCall(Value *I,
> + const TargetLibraryInfo *TLI) {
> + return const_cast<CallInst*>(extractMallocCall((const Value*)I, TLI));
> }
>
> /// isArrayMalloc - Returns the corresponding CallInst if the instruction
> /// is a call to malloc whose array size can be determined and the array
> size
> /// is not constant 1. Otherwise, return NULL.
> -const CallInst *isArrayMalloc(const Value *I, const TargetData *TD);
> +const CallInst *isArrayMalloc(const Value *I, const TargetData *TD,
> + const TargetLibraryInfo *TLI);
>
> /// getMallocType - Returns the PointerType resulting from the malloc
> call.
> /// The PointerType depends on the number of bitcast uses of the malloc
> call:
> /// 0: PointerType is the malloc calls' return type.
> /// 1: PointerType is the bitcast's result type.
> /// >1: Unique PointerType cannot be determined, return NULL.
> -PointerType *getMallocType(const CallInst *CI);
> +PointerType *getMallocType(const CallInst *CI, const TargetLibraryInfo
> *TLI);
>
> /// getMallocAllocatedType - Returns the Type allocated by malloc call.
> /// The Type depends on the number of bitcast uses of the malloc call:
> /// 0: PointerType is the malloc calls' return type.
> /// 1: PointerType is the bitcast's result type.
> /// >1: Unique PointerType cannot be determined, return NULL.
> -Type *getMallocAllocatedType(const CallInst *CI);
> +Type *getMallocAllocatedType(const CallInst *CI, const TargetLibraryInfo
> *TLI);
>
> /// getMallocArraySize - Returns the array size of a malloc call. If the
> /// argument passed to malloc is a multiple of the size of the malloced
> type,
> @@ -95,6 +104,7 @@
> /// constant 1. Otherwise, return NULL for mallocs whose array size
> cannot be
> /// determined.
> Value *getMallocArraySize(CallInst *CI, const TargetData *TD,
> + const TargetLibraryInfo *TLI,
> bool LookThroughSExt = false);
>
>
> @@ -104,9 +114,10 @@
>
> /// extractCallocCall - Returns the corresponding CallInst if the
> instruction
> /// is a calloc call.
> -const CallInst *extractCallocCall(const Value *I);
> -static inline CallInst *extractCallocCall(Value *I) {
> - return const_cast<CallInst*>(extractCallocCall((const Value*)I));
> +const CallInst *extractCallocCall(const Value *I, const TargetLibraryInfo
> *TLI);
> +static inline CallInst *extractCallocCall(Value *I,
> + const TargetLibraryInfo *TLI) {
> + return const_cast<CallInst*>(extractCallocCall((const Value*)I, TLI));
> }
>
>
> @@ -115,10 +126,10 @@
> //
>
> /// isFreeCall - Returns non-null if the value is a call to the builtin
> free()
> -const CallInst *isFreeCall(const Value *I);
> +const CallInst *isFreeCall(const Value *I, const TargetLibraryInfo *TLI);
>
> -static inline CallInst *isFreeCall(Value *I) {
> - return const_cast<CallInst*>(isFreeCall((const Value*)I));
> +static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo
> *TLI) {
> + return const_cast<CallInst*>(isFreeCall((const Value*)I, TLI));
> }
>
>
> @@ -131,7 +142,7 @@
> /// 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);
> + const TargetLibraryInfo *TLI, bool RoundToAlign =
> false);
>
>
>
> @@ -143,6 +154,7 @@
> : public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> {
>
> const TargetData *TD;
> + const TargetLibraryInfo *TLI;
> bool RoundToAlign;
> unsigned IntTyBits;
> APInt Zero;
> @@ -155,8 +167,8 @@
> }
>
> public:
> - ObjectSizeOffsetVisitor(const TargetData *TD, LLVMContext &Context,
> - bool RoundToAlign = false);
> + ObjectSizeOffsetVisitor(const TargetData *TD, const TargetLibraryInfo
> *TLI,
> + LLVMContext &Context, bool RoundToAlign =
> false);
>
> SizeOffsetType compute(Value *V);
>
> @@ -202,6 +214,7 @@
> typedef SmallPtrSet<const Value*, 8> PtrSetTy;
>
> const TargetData *TD;
> + const TargetLibraryInfo *TLI;
> LLVMContext &Context;
> BuilderTy Builder;
> IntegerType *IntTy;
> @@ -215,7 +228,8 @@
> SizeOffsetEvalType compute_(Value *V);
>
> public:
> - ObjectSizeOffsetEvaluator(const TargetData *TD, LLVMContext &Context);
> + ObjectSizeOffsetEvaluator(const TargetData *TD, const TargetLibraryInfo
> *TLI,
> + LLVMContext &Context);
> SizeOffsetEvalType compute(Value *V);
>
> bool knownSize(SizeOffsetEvalType SizeOffset) {
>
> Modified: llvm/trunk/include/llvm/Target/TargetLibraryInfo.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLibraryInfo.h?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Target/TargetLibraryInfo.h (original)
> +++ llvm/trunk/include/llvm/Target/TargetLibraryInfo.h Wed Aug 29 10:32:21
> 2012
> @@ -18,6 +18,26 @@
>
> namespace LibFunc {
> enum Func {
> + /// void operator delete[](void*);
> + ZdaPv,
> + /// void operator delete(void*);
> + ZdlPv,
> + /// void *new[](unsigned int);
> + Znaj,
> + /// void *new[](unsigned int, nothrow);
> + ZnajRKSt9nothrow_t,
> + /// void *new[](unsigned long);
> + Znam,
> + /// void *new[](unsigned long, nothrow);
> + ZnamRKSt9nothrow_t,
> + /// void *new(unsigned int);
> + Znwj,
> + /// void *new(unsigned int, nothrow);
> + ZnwjRKSt9nothrow_t,
> + /// void *new(unsigned long);
> + Znwm,
> + /// void *new(unsigned long, nothrow);
> + ZnwmRKSt9nothrow_t,
> /// int __cxa_atexit(void (*f)(void *), void *p, void *d);
> cxa_atexit,
> /// void __cxa_guard_abort(guard_t *guard);
> @@ -71,6 +91,8 @@
> atanhl,
> /// long double atanl(long double x);
> atanl,
> + /// void *calloc(size_t count, size_t size);
> + calloc,
> /// double cbrt(double x);
> cbrt,
> /// float cbrtf(float x);
> @@ -149,6 +171,8 @@
> fputc,
> /// int fputs(const char *s, FILE *stream);
> fputs,
> + /// void free(void *ptr);
> + free,
> /// size_t fwrite(const void *ptr, size_t size, size_t nitems,
> /// FILE *stream);
> fwrite,
> @@ -184,6 +208,8 @@
> logf,
> /// long double logl(long double x);
> logl,
> + /// void *malloc(size_t size);
> + malloc,
> /// void *memchr(const void *s, int c, size_t n);
> memchr,
> /// int memcmp(const void *s1, const void *s2, size_t n);
> @@ -202,6 +228,8 @@
> nearbyintf,
> /// long double nearbyintl(long double x);
> nearbyintl,
> + /// int posix_memalign(void **memptr, size_t alignment, size_t
> size);
> + posix_memalign,
> /// double pow(double x, double y);
> pow,
> /// float powf(float x, float y);
> @@ -212,6 +240,10 @@
> putchar,
> /// int puts(const char *s);
> puts,
> + /// void *realloc(void *ptr, size_t size);
> + realloc,
> + /// void *reallocf(void *ptr, size_t size);
> + reallocf,
> /// double rint(double x);
> rint,
> /// float rintf(float x);
> @@ -250,6 +282,8 @@
> strchr,
> /// char *strcpy(char *s1, const char *s2);
> strcpy,
> + /// char *strdup(const char *s1);
> + strdup,
> /// size_t strlen(const char *s);
> strlen,
> /// char *strncat(char *s1, const char *s2, size_t n);
> @@ -258,6 +292,8 @@
> strncmp,
> /// char *strncpy(char *s1, const char *s2, size_t n);
> strncpy,
> + /// char *strndup(const char *s1, size_t n);
> + strndup,
> /// size_t strnlen(const char *s, size_t maxlen);
> strnlen,
> /// double tan(double x);
> @@ -278,6 +314,8 @@
> truncf,
> /// long double truncl(long double x);
> truncl,
> + /// void *valloc(size_t size);
> + valloc,
>
> NumLibFuncs
> };
>
> Modified: llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h Wed Aug 29
> 10:32:21 2012
> @@ -27,6 +27,7 @@
> class Instruction;
> class Pass;
> class ReturnInst;
> +class TargetLibraryInfo;
>
> /// DeleteDeadBlock - Delete the specified block, which must have no
> /// predecessors.
> @@ -44,7 +45,7 @@
> /// a result. This includes tracing the def-use list from the PHI to see
> if
> /// it is ultimately unused or if it reaches an unused cycle. Return true
> /// if any PHIs were deleted.
> -bool DeleteDeadPHIs(BasicBlock *BB);
> +bool DeleteDeadPHIs(BasicBlock *BB, const TargetLibraryInfo *TLI = 0);
>
> /// MergeBlockIntoPredecessor - Attempts to merge a block into its
> predecessor,
> /// if possible. The return value indicates success or failure.
>
> Modified: llvm/trunk/include/llvm/Transforms/Utils/Local.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Local.h?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Utils/Local.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Utils/Local.h Wed Aug 29 10:32:21
> 2012
> @@ -36,6 +36,7 @@
> class AllocaInst;
> class ConstantExpr;
> class TargetData;
> +class TargetLibraryInfo;
> class DIBuilder;
>
> template<typename T> class SmallVectorImpl;
> @@ -51,7 +52,8 @@
> /// Also calls RecursivelyDeleteTriviallyDeadInstructions() on any
> branch/switch
> /// conditions and indirectbr addresses this might make dead if
> /// DeleteDeadConditions is true.
> -bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions =
> false);
> +bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions =
> false,
> + const TargetLibraryInfo *TLI = 0);
>
> //===----------------------------------------------------------------------===//
> // Local dead code elimination.
> @@ -60,20 +62,21 @@
> /// isInstructionTriviallyDead - Return true if the result produced by the
> /// instruction is not used, and the instruction has no side effects.
> ///
> -bool isInstructionTriviallyDead(Instruction *I);
> +bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo
> *TLI=0);
>
> /// RecursivelyDeleteTriviallyDeadInstructions - If the specified value is
> a
> /// trivially dead instruction, delete it. If that makes any of its
> operands
> /// trivially dead, delete them too, recursively. Return true if any
> /// instructions were deleted.
> -bool RecursivelyDeleteTriviallyDeadInstructions(Value *V);
> +bool RecursivelyDeleteTriviallyDeadInstructions(Value *V,
> + const TargetLibraryInfo
> *TLI=0);
>
> /// RecursivelyDeleteDeadPHINode - If the specified value is an
> effectively
> /// dead PHI node, due to being a def-use chain of single-use nodes that
> /// either forms a cycle or is terminated by a trivially dead instruction,
> /// delete it. If that makes any of its operands trivially dead, delete
> them
> /// too, recursively. Return true if a change was made.
> -bool RecursivelyDeleteDeadPHINode(PHINode *PN);
> +bool RecursivelyDeleteDeadPHINode(PHINode *PN, const TargetLibraryInfo
> *TLI=0);
>
>
> /// SimplifyInstructionsInBlock - Scan the specified basic block and try
> to
> @@ -81,7 +84,8 @@
> ///
> /// This returns true if it changed the code, note that it can delete
> /// instructions in other blocks as well in this block.
> -bool SimplifyInstructionsInBlock(BasicBlock *BB, const TargetData *TD =
> 0);
> +bool SimplifyInstructionsInBlock(BasicBlock *BB, const TargetData *TD =
> 0,
> + const TargetLibraryInfo *TLI = 0);
>
> //===----------------------------------------------------------------------===//
> // Control Flow Graph Restructuring.
>
> Modified: llvm/trunk/lib/Analysis/AliasAnalysis.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/AliasAnalysis.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Analysis/AliasAnalysis.cpp (original)
> +++ llvm/trunk/lib/Analysis/AliasAnalysis.cpp Wed Aug 29 10:32:21 2012
> @@ -36,6 +36,7 @@
> #include "llvm/LLVMContext.h"
> #include "llvm/Type.h"
> #include "llvm/Target/TargetData.h"
> +#include "llvm/Target/TargetLibraryInfo.h"
> using namespace llvm;
>
> // Register the AliasAnalysis interface, providing a nice name to refer
> to.
> @@ -452,6 +453,7 @@
> ///
> void AliasAnalysis::InitializeAliasAnalysis(Pass *P) {
> TD = P->getAnalysisIfAvailable<TargetData>();
> + TLI = P->getAnalysisIfAvailable<TargetLibraryInfo>();
> AA = &P->getAnalysis<AliasAnalysis>();
> }
>
>
> Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original)
> +++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Wed Aug 29 10:32:21
> 2012
> @@ -85,9 +85,10 @@
> /// getObjectSize - Return the size of the object specified by V, or
> /// UnknownSize if unknown.
> static uint64_t getObjectSize(const Value *V, const TargetData &TD,
> + const TargetLibraryInfo &TLI,
> bool RoundToAlign = false) {
> uint64_t Size;
> - if (getObjectSize(V, Size, &TD, RoundToAlign))
> + if (getObjectSize(V, Size, &TD, &TLI, RoundToAlign))
> return Size;
> return AliasAnalysis::UnknownSize;
> }
> @@ -95,10 +96,11 @@
> /// isObjectSmallerThan - Return true if we can prove that the object
> specified
> /// by V is smaller than Size.
> static bool isObjectSmallerThan(const Value *V, uint64_t Size,
> - const TargetData &TD) {
> + const TargetData &TD,
> + const TargetLibraryInfo &TLI) {
> // This function needs to use the aligned object size because we allow
> // reads a bit past the end given sufficient alignment.
> - uint64_t ObjectSize = getObjectSize(V, TD, /*RoundToAlign*/true);
> + uint64_t ObjectSize = getObjectSize(V, TD, TLI, /*RoundToAlign*/true);
>
> return ObjectSize != AliasAnalysis::UnknownSize && ObjectSize < Size;
> }
> @@ -106,8 +108,8 @@
> /// isObjectSize - Return true if we can prove that the object specified
> /// by V has size Size.
> static bool isObjectSize(const Value *V, uint64_t Size,
> - const TargetData &TD) {
> - uint64_t ObjectSize = getObjectSize(V, TD);
> + const TargetData &TD, const TargetLibraryInfo
> &TLI) {
> + uint64_t ObjectSize = getObjectSize(V, TD, TLI);
> return ObjectSize != AliasAnalysis::UnknownSize && ObjectSize == Size;
> }
>
> @@ -1133,8 +1135,8 @@
> // If the size of one access is larger than the entire object on the
> other
> // side, then we know such behavior is undefined and can assume no
> alias.
> if (TD)
> - if ((V1Size != UnknownSize && isObjectSmallerThan(O2, V1Size, *TD))
> ||
> - (V2Size != UnknownSize && isObjectSmallerThan(O1, V2Size, *TD)))
> + if ((V1Size != UnknownSize && isObjectSmallerThan(O2, V1Size, *TD,
> *TLI)) ||
> + (V2Size != UnknownSize && isObjectSmallerThan(O1, V2Size, *TD,
> *TLI)))
> return NoAlias;
>
> // Check the cache before climbing up use-def chains. This also
> terminates
> @@ -1184,8 +1186,8 @@
> // accesses is accessing the entire object, then the accesses must
> // overlap in some way.
> if (TD && O1 == O2)
> - if ((V1Size != UnknownSize && isObjectSize(O1, V1Size, *TD)) ||
> - (V2Size != UnknownSize && isObjectSize(O2, V2Size, *TD)))
> + if ((V1Size != UnknownSize && isObjectSize(O1, V1Size, *TD, *TLI)) ||
> + (V2Size != UnknownSize && isObjectSize(O2, V2Size, *TD, *TLI)))
> return AliasCache[Locs] = PartialAlias;
>
> AliasResult Result =
>
> Modified: llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp (original)
> +++ llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp Wed Aug 29 10:32:21 2012
> @@ -263,7 +263,7 @@
> } else if (BitCastInst *BCI = dyn_cast<BitCastInst>(U)) {
> if (AnalyzeUsesOfPointer(BCI, Readers, Writers, OkayStoreDest))
> return true;
> - } else if (isFreeCall(U)) {
> + } else if (isFreeCall(U, TLI)) {
> Writers.push_back(cast<Instruction>(U)->getParent()->getParent());
> } else if (CallInst *CI = dyn_cast<CallInst>(U)) {
> // Make sure that this is just the function being called, not that
> it is
> @@ -329,7 +329,7 @@
> // Check the value being stored.
> Value *Ptr = GetUnderlyingObject(SI->getOperand(0));
>
> - if (!isAllocLikeFn(Ptr))
> + if (!isAllocLikeFn(Ptr, TLI))
> return false; // Too hard to analyze.
>
> // Analyze all uses of the allocation. If any of them are used in a
> @@ -458,7 +458,7 @@
> if (SI->isVolatile())
> // Treat volatile stores as reading memory somewhere.
> FunctionEffect |= Ref;
> - } else if (isAllocationFn(&*II) || isFreeCall(&*II)) {
> + } else if (isAllocationFn(&*II, TLI) || isFreeCall(&*II, TLI)) {
> 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=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Analysis/MemoryBuiltins.cpp (original)
> +++ llvm/trunk/lib/Analysis/MemoryBuiltins.cpp Wed Aug 29 10:32:21 2012
> @@ -26,6 +26,7 @@
> #include "llvm/Support/MathExtras.h"
> #include "llvm/Support/raw_ostream.h"
> #include "llvm/Target/TargetData.h"
> +#include "llvm/Target/TargetLibraryInfo.h"
> #include "llvm/Transforms/Utils/Local.h"
> using namespace llvm;
>
> @@ -39,7 +40,7 @@
> };
>
> struct AllocFnsTy {
> - const char *Name;
> + LibFunc::Func Func;
> AllocType AllocTy;
> unsigned char NumParams;
> // First and Second size parameters (or -1 if unused)
> @@ -49,22 +50,22 @@
> // FIXME: certain users need more information. E.g., SimplifyLibCalls
> needs to
> // know which functions are nounwind, noalias, nocapture parameters, etc.
> static const AllocFnsTy AllocationFnData[] = {
> - {"malloc", MallocLike, 1, 0, -1},
> - {"valloc", MallocLike, 1, 0, -1},
> - {"_Znwj", MallocLike, 1, 0, -1}, // new(unsigned int)
> - {"_ZnwjRKSt9nothrow_t", MallocLike, 2, 0, -1}, // new(unsigned int,
> nothrow)
> - {"_Znwm", MallocLike, 1, 0, -1}, // new(unsigned long)
> - {"_ZnwmRKSt9nothrow_t", MallocLike, 2, 0, -1}, // new(unsigned long,
> nothrow)
> - {"_Znaj", MallocLike, 1, 0, -1}, // new[](unsigned int)
> - {"_ZnajRKSt9nothrow_t", MallocLike, 2, 0, -1}, // new[](unsigned int,
> nothrow)
> - {"_Znam", MallocLike, 1, 0, -1}, // new[](unsigned
> long)
> - {"_ZnamRKSt9nothrow_t", MallocLike, 2, 0, -1}, // new[](unsigned
> long, nothrow)
> - {"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}
> + {LibFunc::malloc, MallocLike, 1, 0, -1},
> + {LibFunc::valloc, MallocLike, 1, 0, -1},
> + {LibFunc::Znwj, MallocLike, 1, 0, -1}, // new(unsigned
> int)
> + {LibFunc::ZnwjRKSt9nothrow_t, MallocLike, 2, 0, -1}, // new(unsigned
> int, nothrow)
> + {LibFunc::Znwm, MallocLike, 1, 0, -1}, // new(unsigned
> long)
> + {LibFunc::ZnwmRKSt9nothrow_t, MallocLike, 2, 0, -1}, // new(unsigned
> long, nothrow)
> + {LibFunc::Znaj, MallocLike, 1, 0, -1}, //
> new[](unsigned int)
> + {LibFunc::ZnajRKSt9nothrow_t, MallocLike, 2, 0, -1}, //
> new[](unsigned int, nothrow)
> + {LibFunc::Znam, MallocLike, 1, 0, -1}, //
> new[](unsigned long)
> + {LibFunc::ZnamRKSt9nothrow_t, MallocLike, 2, 0, -1}, //
> new[](unsigned long, nothrow)
> + {LibFunc::posix_memalign, MallocLike, 3, 2, -1},
> + {LibFunc::calloc, CallocLike, 2, 0, 1},
> + {LibFunc::realloc, ReallocLike, 2, 1, -1},
> + {LibFunc::reallocf, ReallocLike, 2, 1, -1},
> + {LibFunc::strdup, StrDupLike, 1, -1, -1},
> + {LibFunc::strndup, StrDupLike, 2, 1, -1}
> };
>
>
> @@ -85,15 +86,22 @@
> /// \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,
> + const TargetLibraryInfo *TLI,
> bool LookThroughBitCast =
> false) {
> Function *Callee = getCalledFunction(V, LookThroughBitCast);
> if (!Callee)
> return 0;
>
> + // Make sure that the function is available.
> + StringRef FnName = Callee->getName();
> + LibFunc::Func TLIFn;
> + if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
> + return 0;
> +
> unsigned i = 0;
> bool found = false;
> for ( ; i < array_lengthof(AllocationFnData); ++i) {
> - if (Callee->getName() == AllocationFnData[i].Name) {
> + if (AllocationFnData[i].Func == TLIFn) {
> found = true;
> break;
> }
> @@ -106,7 +114,6 @@
> return 0;
>
> // Check function prototype.
> - // FIXME: Check the nobuiltin metadata?? (PR5130)
> int FstParam = FnData->FstParam;
> int SndParam = FnData->SndParam;
> FunctionType *FTy = Callee->getFunctionType();
> @@ -132,57 +139,65 @@
> /// \brief Tests if a value is a call or invoke 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);
> +bool llvm::isAllocationFn(const Value *V, const TargetLibraryInfo *TLI,
> + bool LookThroughBitCast) {
> + return getAllocationData(V, AnyAlloc, TLI, LookThroughBitCast);
> }
>
> /// \brief Tests if a value is a call or invoke to a function that returns
> a
> /// NoAlias pointer (including malloc/calloc/realloc/strdup-like
> functions).
> -bool llvm::isNoAliasFn(const Value *V, bool LookThroughBitCast) {
> +bool llvm::isNoAliasFn(const Value *V, const TargetLibraryInfo *TLI,
> + bool LookThroughBitCast) {
> // it's safe to consider realloc as noalias since accessing the original
> // pointer is undefined behavior
> - return isAllocationFn(V, LookThroughBitCast) ||
> + return isAllocationFn(V, TLI, LookThroughBitCast) ||
> hasNoAliasAttr(V, LookThroughBitCast);
> }
>
> /// \brief Tests if a value is a call or invoke to a library function that
> /// allocates uninitialized memory (such as malloc).
> -bool llvm::isMallocLikeFn(const Value *V, bool LookThroughBitCast) {
> - return getAllocationData(V, MallocLike, LookThroughBitCast);
> +bool llvm::isMallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
> + bool LookThroughBitCast) {
> + return getAllocationData(V, MallocLike, TLI, LookThroughBitCast);
> }
>
> /// \brief Tests if a value is a call or invoke 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);
> +bool llvm::isCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
> + bool LookThroughBitCast) {
> + return getAllocationData(V, CallocLike, TLI, LookThroughBitCast);
> }
>
> /// \brief Tests if a value is a call or invoke 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);
> +bool llvm::isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
> + bool LookThroughBitCast) {
> + return getAllocationData(V, AllocLike, TLI, LookThroughBitCast);
> }
>
> /// \brief Tests if a value is a call or invoke to a library function that
> /// reallocates memory (such as realloc).
> -bool llvm::isReallocLikeFn(const Value *V, bool LookThroughBitCast) {
> - return getAllocationData(V, ReallocLike, LookThroughBitCast);
> +bool llvm::isReallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
> + bool LookThroughBitCast) {
> + return getAllocationData(V, ReallocLike, TLI, 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) ? dyn_cast<CallInst>(I) : 0;
> +const CallInst *llvm::extractMallocCall(const Value *I,
> + const TargetLibraryInfo *TLI) {
> + return isMallocLikeFn(I, TLI) ? dyn_cast<CallInst>(I) : 0;
> }
>
> static Value *computeArraySize(const CallInst *CI, const TargetData *TD,
> + const TargetLibraryInfo *TLI,
> bool LookThroughSExt = false) {
> if (!CI)
> return NULL;
>
> // The size of the malloc's result type must be known to determine array
> size.
> - Type *T = getMallocAllocatedType(CI);
> + Type *T = getMallocAllocatedType(CI, TLI);
> if (!T || !T->isSized() || !TD)
> return NULL;
>
> @@ -204,9 +219,11 @@
> /// isArrayMalloc - Returns the corresponding CallInst if the instruction
> /// is a call to malloc whose array size can be determined and the array
> size
> /// is not constant 1. Otherwise, return NULL.
> -const CallInst *llvm::isArrayMalloc(const Value *I, const TargetData *TD)
> {
> - const CallInst *CI = extractMallocCall(I);
> - Value *ArraySize = computeArraySize(CI, TD);
> +const CallInst *llvm::isArrayMalloc(const Value *I,
> + const TargetData *TD,
> + const TargetLibraryInfo *TLI) {
> + const CallInst *CI = extractMallocCall(I, TLI);
> + Value *ArraySize = computeArraySize(CI, TD, TLI);
>
> if (ArraySize &&
> ArraySize != ConstantInt::get(CI->getArgOperand(0)->getType(), 1))
> @@ -221,8 +238,9 @@
> /// 0: PointerType is the calls' return type.
> /// 1: PointerType is the bitcast's result type.
> /// >1: Unique PointerType cannot be determined, return NULL.
> -PointerType *llvm::getMallocType(const CallInst *CI) {
> - assert(isMallocLikeFn(CI) && "getMallocType and not malloc call");
> +PointerType *llvm::getMallocType(const CallInst *CI,
> + const TargetLibraryInfo *TLI) {
> + assert(isMallocLikeFn(CI, TLI) && "getMallocType and not malloc call");
>
> PointerType *MallocType = NULL;
> unsigned NumOfBitCastUses = 0;
> @@ -252,8 +270,9 @@
> /// 0: PointerType is the malloc calls' return type.
> /// 1: PointerType is the bitcast's result type.
> /// >1: Unique PointerType cannot be determined, return NULL.
> -Type *llvm::getMallocAllocatedType(const CallInst *CI) {
> - PointerType *PT = getMallocType(CI);
> +Type *llvm::getMallocAllocatedType(const CallInst *CI,
> + const TargetLibraryInfo *TLI) {
> + PointerType *PT = getMallocType(CI, TLI);
> return PT ? PT->getElementType() : NULL;
> }
>
> @@ -263,21 +282,23 @@
> /// constant 1. Otherwise, return NULL for mallocs whose array size
> cannot be
> /// determined.
> Value *llvm::getMallocArraySize(CallInst *CI, const TargetData *TD,
> + const TargetLibraryInfo *TLI,
> bool LookThroughSExt) {
> - assert(isMallocLikeFn(CI) && "getMallocArraySize and not malloc call");
> - return computeArraySize(CI, TD, LookThroughSExt);
> + assert(isMallocLikeFn(CI, TLI) && "getMallocArraySize and not malloc
> call");
> + return computeArraySize(CI, TD, TLI, LookThroughSExt);
> }
>
>
> /// extractCallocCall - Returns the corresponding CallInst if the
> instruction
> /// is a calloc call.
> -const CallInst *llvm::extractCallocCall(const Value *I) {
> - return isCallocLikeFn(I) ? cast<CallInst>(I) : 0;
> +const CallInst *llvm::extractCallocCall(const Value *I,
> + const TargetLibraryInfo *TLI) {
> + return isCallocLikeFn(I, TLI) ? cast<CallInst>(I) : 0;
> }
>
>
> /// isFreeCall - Returns non-null if the value is a call to the builtin
> free()
> -const CallInst *llvm::isFreeCall(const Value *I) {
> +const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo
> *TLI) {
> const CallInst *CI = dyn_cast<CallInst>(I);
> if (!CI)
> return 0;
> @@ -285,9 +306,14 @@
> if (Callee == 0 || !Callee->isDeclaration())
> return 0;
>
> - if (Callee->getName() != "free" &&
> - Callee->getName() != "_ZdlPv" && // operator delete(void*)
> - Callee->getName() != "_ZdaPv") // operator delete[](void*)
> + StringRef FnName = Callee->getName();
> + LibFunc::Func TLIFn;
> + if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
> + return 0;
> +
> + if (TLIFn != LibFunc::free &&
> + TLIFn != LibFunc::ZdlPv && // operator delete(void*)
> + TLIFn != LibFunc::ZdaPv) // operator delete[](void*)
> return 0;
>
> // Check free prototype.
> @@ -316,11 +342,11 @@
> /// 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) {
> + const TargetLibraryInfo *TLI, bool RoundToAlign)
> {
> if (!TD)
> return false;
>
> - ObjectSizeOffsetVisitor Visitor(TD, Ptr->getContext(), RoundToAlign);
> + ObjectSizeOffsetVisitor Visitor(TD, TLI, Ptr->getContext(),
> RoundToAlign);
> SizeOffsetType Data = Visitor.compute(const_cast<Value*>(Ptr));
> if (!Visitor.bothKnown(Data))
> return false;
> @@ -348,9 +374,10 @@
> }
>
> ObjectSizeOffsetVisitor::ObjectSizeOffsetVisitor(const TargetData *TD,
> + const TargetLibraryInfo
> *TLI,
> LLVMContext &Context,
> bool RoundToAlign)
> -: TD(TD), RoundToAlign(RoundToAlign) {
> +: TD(TD), TLI(TLI), RoundToAlign(RoundToAlign) {
> IntegerType *IntTy = TD->getIntPtrType(Context);
> IntTyBits = IntTy->getBitWidth();
> Zero = APInt::getNullValue(IntTyBits);
> @@ -416,7 +443,8 @@
> }
>
> SizeOffsetType ObjectSizeOffsetVisitor::visitCallSite(CallSite CS) {
> - const AllocFnsTy *FnData = getAllocationData(CS.getInstruction(),
> AnyAlloc);
> + const AllocFnsTy *FnData = getAllocationData(CS.getInstruction(),
> AnyAlloc,
> + TLI);
> if (!FnData)
> return unknown();
>
> @@ -532,8 +560,9 @@
>
>
> ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator(const TargetData *TD,
> + const
> TargetLibraryInfo *TLI,
> LLVMContext &Context)
> -: TD(TD), Context(Context), Builder(Context, TargetFolder(TD)) {
> +: TD(TD), TLI(TLI), Context(Context), Builder(Context, TargetFolder(TD))
> {
> IntTy = TD->getIntPtrType(Context);
> Zero = ConstantInt::get(IntTy, 0);
> }
> @@ -558,7 +587,7 @@
> }
>
> SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) {
> - ObjectSizeOffsetVisitor Visitor(TD, Context);
> + ObjectSizeOffsetVisitor Visitor(TD, TLI, Context);
> SizeOffsetType Const = Visitor.compute(V);
> if (Visitor.bothKnown(Const))
> return std::make_pair(ConstantInt::get(Context, Const.first),
> @@ -621,7 +650,8 @@
> }
>
> SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitCallSite(CallSite CS) {
> - const AllocFnsTy *FnData = getAllocationData(CS.getInstruction(),
> AnyAlloc);
> + const AllocFnsTy *FnData = getAllocationData(CS.getInstruction(),
> AnyAlloc,
> + TLI);
> if (!FnData)
> return unknown();
>
>
> Modified: llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp (original)
> +++ llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp Wed Aug 29
> 10:32:21 2012
> @@ -148,7 +148,7 @@
> return AliasAnalysis::ModRef;
> }
>
> - if (const CallInst *CI = isFreeCall(Inst)) {
> + if (const CallInst *CI = isFreeCall(Inst, AA->getTargetLibraryInfo()))
> {
> // calls to free() deallocate the entire structure
> Loc = AliasAnalysis::Location(CI->getArgOperand(0));
> return AliasAnalysis::Mod;
> @@ -479,7 +479,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) || isNoAliasFn(Inst)) {
> + if (isa<AllocaInst>(Inst) || isNoAliasFn(Inst,
> AA->getTargetLibraryInfo())){
> const Value *AccessPtr = GetUnderlyingObject(MemLoc.Ptr, TD);
>
> if (AccessPtr == Inst || AA->isMustAlias(Inst, AccessPtr))
>
> Modified: llvm/trunk/lib/Target/TargetLibraryInfo.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/TargetLibraryInfo.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/TargetLibraryInfo.cpp (original)
> +++ llvm/trunk/lib/Target/TargetLibraryInfo.cpp Wed Aug 29 10:32:21 2012
> @@ -24,6 +24,16 @@
>
> const char* TargetLibraryInfo::StandardNames[LibFunc::NumLibFuncs] =
> {
> + "_ZdaPv",
> + "_ZdlPv",
> + "_Znaj",
> + "_ZnajRKSt9nothrow_t",
> + "_Znam",
> + "_ZnamRKSt9nothrow_t",
> + "_Znwj",
> + "_ZnwjRKSt9nothrow_t",
> + "_Znwm",
> + "_ZnwmRKSt9nothrow_t",
> "__cxa_atexit",
> "__cxa_guard_abort",
> "__cxa_guard_acquire",
> @@ -50,6 +60,7 @@
> "atanhf",
> "atanhl",
> "atanl",
> + "calloc",
> "cbrt",
> "cbrtf",
> "cbrtl",
> @@ -89,6 +100,7 @@
> "fmodl",
> "fputc",
> "fputs",
> + "free",
> "fwrite",
> "iprintf",
> "log",
> @@ -106,6 +118,7 @@
> "logbl",
> "logf",
> "logl",
> + "malloc",
> "memchr",
> "memcmp",
> "memcpy",
> @@ -115,11 +128,14 @@
> "nearbyint",
> "nearbyintf",
> "nearbyintl",
> + "posix_memalign",
> "pow",
> "powf",
> "powl",
> "putchar",
> "puts",
> + "realloc",
> + "reallocf",
> "rint",
> "rintf",
> "rintl",
> @@ -139,10 +155,12 @@
> "strcat",
> "strchr",
> "strcpy",
> + "strdup",
> "strlen",
> "strncat",
> "strncmp",
> "strncpy",
> + "strndup",
> "strnlen",
> "tan",
> "tanf",
> @@ -152,7 +170,8 @@
> "tanl",
> "trunc",
> "truncf",
> - "truncl"
> + "truncl",
> + "valloc"
> };
>
> /// initialize - Initialize the set of available library functions based
> on the
>
> Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Wed Aug 29 10:32:21 2012
> @@ -346,7 +346,7 @@
> /// Given a value that is stored to a global but never read, determine
> whether
> /// it's safe to remove the store and the chain of computation that feeds
> the
> /// store.
> -static bool IsSafeComputationToRemove(Value *V) {
> +static bool IsSafeComputationToRemove(Value *V, const TargetLibraryInfo
> *TLI) {
> do {
> if (isa<Constant>(V))
> return true;
> @@ -355,7 +355,7 @@
> if (isa<LoadInst>(V) || isa<InvokeInst>(V) || isa<Argument>(V) ||
> isa<GlobalValue>(V))
> return false;
> - if (isAllocationFn(V))
> + if (isAllocationFn(V, TLI))
> return true;
>
> Instruction *I = cast<Instruction>(V);
> @@ -376,7 +376,8 @@
> /// of the global and clean up any that obviously don't assign the global
> a
> /// value that isn't dynamically allocated.
> ///
> -static bool CleanupPointerRootUsers(GlobalVariable *GV) {
> +static bool CleanupPointerRootUsers(GlobalVariable *GV,
> + const TargetLibraryInfo *TLI) {
> // A brief explanation of leak checkers. The goal is to find bugs where
> // pointers are forgotten, causing an accumulating growth in memory
> // usage over time. The common strategy for leak checkers is to
> whitelist the
> @@ -432,18 +433,18 @@
> C->destroyConstant();
> // This could have invalidated UI, start over from scratch.
> Dead.clear();
> - CleanupPointerRootUsers(GV);
> + CleanupPointerRootUsers(GV, TLI);
> return true;
> }
> }
> }
>
> for (int i = 0, e = Dead.size(); i != e; ++i) {
> - if (IsSafeComputationToRemove(Dead[i].first)) {
> + if (IsSafeComputationToRemove(Dead[i].first, TLI)) {
> Dead[i].second->eraseFromParent();
> Instruction *I = Dead[i].first;
> do {
> - if (isAllocationFn(I))
> + if (isAllocationFn(I, TLI))
> break;
> Instruction *J = dyn_cast<Instruction>(I->getOperand(0));
> if (!J)
> @@ -975,7 +976,7 @@
> // nor is the global.
> if (AllNonStoreUsesGone) {
> if (isLeakCheckerRoot(GV)) {
> - Changed |= CleanupPointerRootUsers(GV);
> + Changed |= CleanupPointerRootUsers(GV, TLI);
> } else {
> Changed = true;
> CleanupConstantGlobalUsers(GV, 0, TD, TLI);
> @@ -1465,9 +1466,10 @@
> /// PerformHeapAllocSRoA - CI is an allocation of an array of structures.
> Break
> /// it up into multiple allocations of arrays of the fields.
> static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, CallInst
> *CI,
> - Value *NElems, TargetData
> *TD) {
> + Value *NElems, TargetData
> *TD,
> + const TargetLibraryInfo *TLI)
> {
> DEBUG(dbgs() << "SROA HEAP ALLOC: " << *GV << " MALLOC = " << *CI <<
> '\n');
> - Type *MAT = getMallocAllocatedType(CI);
> + Type *MAT = getMallocAllocatedType(CI, TLI);
> StructType *STy = cast<StructType>(MAT);
>
> // There is guaranteed to be at least one use of the malloc (storing
> @@ -1688,7 +1690,7 @@
> // This eliminates dynamic allocation, avoids an indirection accessing
> the
> // data, and exposes the resultant global to further GlobalOpt.
> // We cannot optimize the malloc if we cannot determine malloc array
> size.
> - Value *NElems = getMallocArraySize(CI, TD, true);
> + Value *NElems = getMallocArraySize(CI, TD, TLI, true);
> if (!NElems)
> return false;
>
> @@ -1725,7 +1727,7 @@
>
> // If this is a fixed size array, transform the Malloc to be an alloc
> of
> // structs. malloc [100 x struct],1 -> malloc struct, 100
> - if (ArrayType *AT = dyn_cast<ArrayType>(getMallocAllocatedType(CI)))
> {
> + if (ArrayType *AT = dyn_cast<ArrayType>(getMallocAllocatedType(CI,
> TLI))) {
> Type *IntPtrTy = TD->getIntPtrType(CI->getContext());
> unsigned TypeSize = TD->getStructLayout(AllocSTy)->getSizeInBytes();
> Value *AllocSize = ConstantInt::get(IntPtrTy, TypeSize);
> @@ -1742,7 +1744,8 @@
> CI = cast<CallInst>(Malloc);
> }
>
> - GVI = PerformHeapAllocSRoA(GV, CI, getMallocArraySize(CI, TD, true),
> TD);
> + GVI = PerformHeapAllocSRoA(GV, CI, getMallocArraySize(CI, TD, TLI,
> true),
> + TD, TLI);
> return true;
> }
>
> @@ -1771,8 +1774,8 @@
> // Optimize away any trapping uses of the loaded value.
> if (OptimizeAwayTrappingUsesOfLoads(GV, SOVC, TD, TLI))
> return true;
> - } else if (CallInst *CI = extractMallocCall(StoredOnceVal)) {
> - Type *MallocType = getMallocAllocatedType(CI);
> + } else if (CallInst *CI = extractMallocCall(StoredOnceVal, TLI)) {
> + Type *MallocType = getMallocAllocatedType(CI, TLI);
> if (MallocType &&
> TryToOptimizeStoreOfMallocToGlobal(GV, CI, MallocType, Ordering,
> GVI,
> TD, TLI))
> @@ -1964,7 +1967,7 @@
> bool Changed;
> if (isLeakCheckerRoot(GV)) {
> // Delete any constant stores to the global.
> - Changed = CleanupPointerRootUsers(GV);
> + Changed = CleanupPointerRootUsers(GV, TLI);
> } else {
> // Delete any stores we can find to the global. We may not be able
> to
> // make it completely dead though.
>
> Modified: llvm/trunk/lib/Transforms/IPO/Inliner.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Inliner.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/Inliner.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/Inliner.cpp Wed Aug 29 10:32:21 2012
> @@ -20,6 +20,7 @@
> #include "llvm/Analysis/CallGraph.h"
> #include "llvm/Analysis/InlineCost.h"
> #include "llvm/Target/TargetData.h"
> +#include "llvm/Target/TargetLibraryInfo.h"
> #include "llvm/Transforms/IPO/InlinerPass.h"
> #include "llvm/Transforms/Utils/Cloning.h"
> #include "llvm/Transforms/Utils/Local.h"
> @@ -339,6 +340,7 @@
> bool Inliner::runOnSCC(CallGraphSCC &SCC) {
> CallGraph &CG = getAnalysis<CallGraph>();
> const TargetData *TD = getAnalysisIfAvailable<TargetData>();
> + const TargetLibraryInfo *TLI =
> getAnalysisIfAvailable<TargetLibraryInfo>();
>
> SmallPtrSet<Function*, 8> SCCFunctions;
> DEBUG(dbgs() << "Inliner visiting SCC:");
> @@ -417,7 +419,7 @@
> // just delete the call instead of trying to inline it, regardless
> of
> // size. This happens because IPSCCP propagates the result out of
> the
> // call and then we're left with the dead call.
> - if (isInstructionTriviallyDead(CS.getInstruction())) {
> + if (isInstructionTriviallyDead(CS.getInstruction(), TLI)) {
> DEBUG(dbgs() << " -> Deleting dead call: "
> << *CS.getInstruction() << "\n");
> // Update the call graph by deleting the edge from Callee to
> Caller.
>
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Wed Aug 29
> 10:32:21 2012
> @@ -168,7 +168,7 @@
> /// the heavy lifting.
> ///
> Instruction *InstCombiner::visitCallInst(CallInst &CI) {
> - if (isFreeCall(&CI))
> + if (isFreeCall(&CI, TLI))
> return visitFree(CI);
>
> // If the caller function is nounwind, mark the call as nounwind, even
> if the
> @@ -243,7 +243,7 @@
> default: break;
> case Intrinsic::objectsize: {
> uint64_t Size;
> - if (getObjectSize(II->getArgOperand(0), Size, TD))
> + if (getObjectSize(II->getArgOperand(0), Size, TD, TLI))
> return ReplaceInstUsesWith(CI, ConstantInt::get(CI.getType(),
> Size));
> return 0;
> }
> @@ -877,7 +877,7 @@
> // visitCallSite - Improvements for call and invoke instructions.
> //
> Instruction *InstCombiner::visitCallSite(CallSite CS) {
> - if (isAllocLikeFn(CS.getInstruction()))
> + if (isAllocLikeFn(CS.getInstruction(), TLI))
> return visitAllocSite(*CS.getInstruction());
>
> bool Changed = false;
>
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
> (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp Wed Aug
> 29 10:32:21 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)) ||
> - isAllocationFn(BCI->getOperand(0))) {
> + isAllocationFn(BCI->getOperand(0), TLI)) {
> // See if the bitcast simplifies, if so, don't nuke this GEP
> yet.
> if (Instruction *I = visitBitCast(*BCI)) {
> if (I != BCI) {
> @@ -1107,7 +1107,8 @@
>
>
> static bool
> -isAllocSiteRemovable(Instruction *AI, SmallVectorImpl<WeakVH> &Users) {
> +isAllocSiteRemovable(Instruction *AI, SmallVectorImpl<WeakVH> &Users,
> + const TargetLibraryInfo *TLI) {
> SmallVector<Instruction*, 4> Worklist;
> Worklist.push_back(AI);
>
> @@ -1163,7 +1164,7 @@
> }
> }
>
> - if (isFreeCall(I)) {
> + if (isFreeCall(I, TLI)) {
> Users.push_back(I);
> continue;
> }
> @@ -1188,7 +1189,7 @@
> // to null and free calls, delete the calls and replace the comparisons
> with
> // true or false as appropriate.
> SmallVector<WeakVH, 64> Users;
> - if (isAllocSiteRemovable(&MI, Users)) {
> + if (isAllocSiteRemovable(&MI, Users, TLI)) {
> for (unsigned i = 0, e = Users.size(); i != e; ++i) {
> Instruction *I = cast_or_null<Instruction>(&*Users[i]);
> if (!I) continue;
> @@ -1872,7 +1873,7 @@
> Instruction *Inst = BBI++;
>
> // DCE instruction if trivially dead.
> - if (isInstructionTriviallyDead(Inst)) {
> + if (isInstructionTriviallyDead(Inst, TLI)) {
> ++NumDeadInst;
> DEBUG(errs() << "IC: DCE: " << *Inst << '\n');
> Inst->eraseFromParent();
> @@ -2002,7 +2003,7 @@
> if (I == 0) continue; // skip null values.
>
> // Check to see if we can DCE the instruction.
> - if (isInstructionTriviallyDead(I)) {
> + if (isInstructionTriviallyDead(I, TLI)) {
> DEBUG(errs() << "IC: DCE: " << *I << '\n');
> EraseInstFromFunction(*I);
> ++NumDeadInst;
> @@ -2102,7 +2103,7 @@
>
> // If the instruction was modified, it's possible that it is now
> dead.
> // if so, remove it.
> - if (isInstructionTriviallyDead(I)) {
> + if (isInstructionTriviallyDead(I, TLI)) {
> EraseInstFromFunction(*I);
> } else {
> Worklist.Add(I);
>
> Modified: llvm/trunk/lib/Transforms/Instrumentation/BoundsChecking.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/BoundsChecking.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Instrumentation/BoundsChecking.cpp
> (original)
> +++ llvm/trunk/lib/Transforms/Instrumentation/BoundsChecking.cpp Wed Aug
> 29 10:32:21 2012
> @@ -24,6 +24,7 @@
> #include "llvm/Support/TargetFolder.h"
> #include "llvm/Support/raw_ostream.h"
> #include "llvm/Target/TargetData.h"
> +#include "llvm/Target/TargetLibraryInfo.h"
> #include "llvm/Transforms/Instrumentation.h"
> using namespace llvm;
>
> @@ -48,10 +49,12 @@
>
> virtual void getAnalysisUsage(AnalysisUsage &AU) const {
> AU.addRequired<TargetData>();
> + AU.addRequired<TargetLibraryInfo>();
> }
>
> private:
> const TargetData *TD;
> + const TargetLibraryInfo *TLI;
> ObjectSizeOffsetEvaluator *ObjSizeEval;
> BuilderTy *Builder;
> Instruction *Inst;
> @@ -166,11 +169,12 @@
>
> bool BoundsChecking::runOnFunction(Function &F) {
> TD = &getAnalysis<TargetData>();
> + TLI = &getAnalysis<TargetLibraryInfo>();
>
> TrapBB = 0;
> BuilderTy TheBuilder(F.getContext(), TargetFolder(TD));
> Builder = &TheBuilder;
> - ObjectSizeOffsetEvaluator TheObjSizeEval(TD, F.getContext());
> + ObjectSizeOffsetEvaluator TheObjSizeEval(TD, TLI, F.getContext());
> ObjSizeEval = &TheObjSizeEval;
>
> // check HANDLE_MEMORY_INST in include/llvm/Instruction.def for memory
>
> Modified: llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp Wed Aug 29
> 10:32:21 2012
> @@ -988,7 +988,7 @@
> WeakVH IterHandle(CurInstIterator);
> BasicBlock *BB = CurInstIterator->getParent();
>
> - RecursivelyDeleteTriviallyDeadInstructions(Repl);
> + RecursivelyDeleteTriviallyDeadInstructions(Repl, TLInfo);
>
> if (IterHandle != CurInstIterator) {
> // If the iterator instruction was recursively deleted, start over
> at the
>
> Modified: llvm/trunk/lib/Transforms/Scalar/DCE.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/DCE.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/DCE.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/DCE.cpp Wed Aug 29 10:32:21 2012
> @@ -22,6 +22,7 @@
> #include "llvm/Instruction.h"
> #include "llvm/Pass.h"
> #include "llvm/Support/InstIterator.h"
> +#include "llvm/Target/TargetLibraryInfo.h"
> #include "llvm/ADT/Statistic.h"
> using namespace llvm;
>
> @@ -38,10 +39,11 @@
> initializeDeadInstEliminationPass(*PassRegistry::getPassRegistry());
> }
> virtual bool runOnBasicBlock(BasicBlock &BB) {
> + TargetLibraryInfo *TLI =
> getAnalysisIfAvailable<TargetLibraryInfo>();
> bool Changed = false;
> for (BasicBlock::iterator DI = BB.begin(); DI != BB.end(); ) {
> Instruction *Inst = DI++;
> - if (isInstructionTriviallyDead(Inst)) {
> + if (isInstructionTriviallyDead(Inst, TLI)) {
> Inst->eraseFromParent();
> Changed = true;
> ++DIEEliminated;
> @@ -87,6 +89,8 @@
> INITIALIZE_PASS(DCE, "dce", "Dead Code Elimination", false, false)
>
> bool DCE::runOnFunction(Function &F) {
> + TargetLibraryInfo *TLI = getAnalysisIfAvailable<TargetLibraryInfo>();
> +
> // Start out with all of the instructions in the worklist...
> std::vector<Instruction*> WorkList;
> for (inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i)
> @@ -101,7 +105,7 @@
> Instruction *I = WorkList.back();
> WorkList.pop_back();
>
> - if (isInstructionTriviallyDead(I)) { // If the instruction is
> dead.
> + if (isInstructionTriviallyDead(I, TLI)) { // If the instruction is
> dead.
> // Loop over all of the values that the instruction uses, if there
> are
> // instructions being used, add them to the worklist, because they
> might
> // go dead after this one is removed.
>
> Modified: llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp Wed Aug 29
> 10:32:21 2012
> @@ -106,6 +106,7 @@
> ///
> static void DeleteDeadInstruction(Instruction *I,
> MemoryDependenceAnalysis &MD,
> + const TargetLibraryInfo *TLI,
> SmallSetVector<Value*, 16> *ValueSet =
> 0) {
> SmallVector<Instruction*, 32> NowDeadInsts;
>
> @@ -130,7 +131,7 @@
> if (!Op->use_empty()) continue;
>
> if (Instruction *OpI = dyn_cast<Instruction>(Op))
> - if (isInstructionTriviallyDead(OpI))
> + if (isInstructionTriviallyDead(OpI, TLI))
> NowDeadInsts.push_back(OpI);
> }
>
> @@ -276,7 +277,7 @@
>
> static uint64_t getPointerSize(const Value *V, AliasAnalysis &AA) {
> uint64_t Size;
> - if (getObjectSize(V, Size, AA.getTargetData()))
> + if (getObjectSize(V, Size, AA.getTargetData(),
> AA.getTargetLibraryInfo()))
> return Size;
> return AliasAnalysis::UnknownSize;
> }
> @@ -454,7 +455,7 @@
> Instruction *Inst = BBI++;
>
> // Handle 'free' calls specially.
> - if (CallInst *F = isFreeCall(Inst)) {
> + if (CallInst *F = isFreeCall(Inst, AA->getTargetLibraryInfo())) {
> MadeChange |= HandleFree(F);
> continue;
> }
> @@ -483,7 +484,7 @@
> // in case we need it.
> WeakVH NextInst(BBI);
>
> - DeleteDeadInstruction(SI, *MD);
> + DeleteDeadInstruction(SI, *MD, AA->getTargetLibraryInfo());
>
> if (NextInst == 0) // Next instruction deleted.
> BBI = BB.begin();
> @@ -530,7 +531,7 @@
> << *DepWrite << "\n KILLER: " << *Inst << '\n');
>
> // Delete the store and now-dead instructions that feed it.
> - DeleteDeadInstruction(DepWrite, *MD);
> + DeleteDeadInstruction(DepWrite, *MD,
> AA->getTargetLibraryInfo());
> ++NumFastStores;
> MadeChange = true;
>
> @@ -640,7 +641,7 @@
> Instruction *Next = llvm::next(BasicBlock::iterator(Dependency));
>
> // DCE instructions only used to calculate that store
> - DeleteDeadInstruction(Dependency, *MD);
> + DeleteDeadInstruction(Dependency, *MD, AA->getTargetLibraryInfo());
> ++NumFastStores;
> MadeChange = true;
>
> @@ -680,7 +681,8 @@
>
> // Okay, so these are dead heap objects, but if the pointer never
> escapes
> // then it's leaked by this function anyways.
> - else if (isAllocLikeFn(I) && !PointerMayBeCaptured(I, true, true))
> + else if (isAllocLikeFn(I, AA->getTargetLibraryInfo()) &&
> + !PointerMayBeCaptured(I, true, true))
> DeadStackObjects.insert(I);
> }
>
> @@ -724,7 +726,8 @@
> dbgs() << '\n');
>
> // DCE instructions only used to calculate that store.
> - DeleteDeadInstruction(Dead, *MD, &DeadStackObjects);
> + DeleteDeadInstruction(Dead, *MD, AA->getTargetLibraryInfo(),
> + &DeadStackObjects);
> ++NumFastStores;
> MadeChange = true;
> continue;
> @@ -732,9 +735,10 @@
> }
>
> // Remove any dead non-memory-mutating instructions.
> - if (isInstructionTriviallyDead(BBI)) {
> + if (isInstructionTriviallyDead(BBI, AA->getTargetLibraryInfo())) {
> Instruction *Inst = BBI++;
> - DeleteDeadInstruction(Inst, *MD, &DeadStackObjects);
> + DeleteDeadInstruction(Inst, *MD, AA->getTargetLibraryInfo(),
> + &DeadStackObjects);
> ++NumFastOther;
> MadeChange = true;
> continue;
> @@ -750,7 +754,7 @@
> if (CallSite CS = cast<Value>(BBI)) {
> // Remove allocation function calls from the list of dead stack
> objects;
> // there can't be any references before the definition.
> - if (isAllocLikeFn(BBI))
> + if (isAllocLikeFn(BBI, AA->getTargetLibraryInfo()))
> DeadStackObjects.remove(BBI);
>
> // If this call does not access memory, it can't be loading any of
> our
>
> Modified: llvm/trunk/lib/Transforms/Scalar/EarlyCSE.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/EarlyCSE.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/EarlyCSE.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/EarlyCSE.cpp Wed Aug 29 10:32:21 2012
> @@ -374,7 +374,7 @@
> Instruction *Inst = I++;
>
> // Dead instructions should just be removed.
> - if (isInstructionTriviallyDead(Inst)) {
> + if (isInstructionTriviallyDead(Inst, TLI)) {
> DEBUG(dbgs() << "EarlyCSE DCE: " << *Inst << '\n');
> Inst->eraseFromParent();
> Changed = true;
>
> Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Wed Aug 29 10:32:21 2012
> @@ -1436,7 +1436,7 @@
> Instruction *DepInst = DepInfo.getInst();
>
> // Loading the allocation -> undef.
> - if (isa<AllocaInst>(DepInst) || isMallocLikeFn(DepInst) ||
> + if (isa<AllocaInst>(DepInst) || isMallocLikeFn(DepInst, TLI) ||
> // 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) || isMallocLikeFn(DepInst)) {
> + if (isa<AllocaInst>(DepInst) || isMallocLikeFn(DepInst, TLI)) {
> L->replaceAllUsesWith(UndefValue::get(L->getType()));
> markInstructionForDeletion(L);
> ++NumGVNLoad;
>
> Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Wed Aug 29
> 10:32:21 2012
> @@ -44,6 +44,7 @@
> #include "llvm/Transforms/Utils/BasicBlockUtils.h"
> #include "llvm/Transforms/Utils/SimplifyIndVar.h"
> #include "llvm/Target/TargetData.h"
> +#include "llvm/Target/TargetLibraryInfo.h"
> #include "llvm/ADT/DenseMap.h"
> #include "llvm/ADT/SmallVector.h"
> #include "llvm/ADT/Statistic.h"
> @@ -68,6 +69,7 @@
> ScalarEvolution *SE;
> DominatorTree *DT;
> TargetData *TD;
> + TargetLibraryInfo *TLI;
>
> SmallVector<WeakVH, 16> DeadInsts;
> bool Changed;
> @@ -414,11 +416,11 @@
> // new comparison.
> NewCompare->takeName(Compare);
> Compare->replaceAllUsesWith(NewCompare);
> - RecursivelyDeleteTriviallyDeadInstructions(Compare);
> + RecursivelyDeleteTriviallyDeadInstructions(Compare, TLI);
>
> // Delete the old floating point increment.
> Incr->replaceAllUsesWith(UndefValue::get(Incr->getType()));
> - RecursivelyDeleteTriviallyDeadInstructions(Incr);
> + RecursivelyDeleteTriviallyDeadInstructions(Incr, TLI);
>
> // If the FP induction variable still has uses, this is because
> something else
> // in the loop uses its value. In order to canonicalize the induction
> @@ -431,7 +433,7 @@
> Value *Conv = new SIToFPInst(NewPHI, PN->getType(), "indvar.conv",
> PN->getParent()->getFirstInsertionPt());
> PN->replaceAllUsesWith(Conv);
> - RecursivelyDeleteTriviallyDeadInstructions(PN);
> + RecursivelyDeleteTriviallyDeadInstructions(PN, TLI);
> }
> Changed = true;
> }
> @@ -550,14 +552,14 @@
> PN->setIncomingValue(i, ExitVal);
>
> // If this instruction is dead now, delete it.
> - RecursivelyDeleteTriviallyDeadInstructions(Inst);
> + RecursivelyDeleteTriviallyDeadInstructions(Inst, TLI);
>
> if (NumPreds == 1) {
> // Completely replace a single-pred PHI. This is safe, because
> the
> // NewVal won't be variant in the loop, so we don't need an
> LCSSA phi
> // node anymore.
> PN->replaceAllUsesWith(ExitVal);
> - RecursivelyDeleteTriviallyDeadInstructions(PN);
> + RecursivelyDeleteTriviallyDeadInstructions(PN, TLI);
> }
> }
> if (NumPreds != 1) {
> @@ -1697,6 +1699,7 @@
> SE = &getAnalysis<ScalarEvolution>();
> DT = &getAnalysis<DominatorTree>();
> TD = getAnalysisIfAvailable<TargetData>();
> + TLI = getAnalysisIfAvailable<TargetLibraryInfo>();
>
> DeadInsts.clear();
> Changed = false;
> @@ -1763,7 +1766,7 @@
> while (!DeadInsts.empty())
> if (Instruction *Inst =
> dyn_cast_or_null<Instruction>(&*DeadInsts.pop_back_val()))
> - RecursivelyDeleteTriviallyDeadInstructions(Inst);
> + RecursivelyDeleteTriviallyDeadInstructions(Inst, TLI);
>
> // The Rewriter may not be used from this point on.
>
> @@ -1772,7 +1775,7 @@
> SinkUnusedInvariants(L);
>
> // Clean up dead instructions.
> - Changed |= DeleteDeadPHIs(L->getHeader());
> + Changed |= DeleteDeadPHIs(L->getHeader(), TLI);
> // Check a post-condition.
> assert(L->isLCSSAForm(*DT) &&
> "Indvars did not leave the loop in lcssa form!");
>
> Modified: llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp Wed Aug 29 10:32:21
> 2012
> @@ -1455,7 +1455,7 @@
> // At this point, the IR is fully up to date and consistent. Do a quick
> scan
> // over the new instructions and zap any that are constants or dead.
> This
> // frequently happens because of phi translation.
> - SimplifyInstructionsInBlock(NewBB, TD);
> + SimplifyInstructionsInBlock(NewBB, TD, TLI);
>
> // Threaded an edge!
> ++NumThreads;
>
> Modified: llvm/trunk/lib/Transforms/Scalar/LICM.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LICM.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/LICM.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp Wed Aug 29 10:32:21 2012
> @@ -307,7 +307,7 @@
>
> // If the instruction is dead, we would try to sink it because it
> isn't used
> // in the loop, instead, just delete it.
> - if (isInstructionTriviallyDead(&I)) {
> + if (isInstructionTriviallyDead(&I, TLI)) {
> DEBUG(dbgs() << "LICM deleting dead inst: " << I << '\n');
> ++II;
> CurAST->deleteValue(&I);
>
> Modified: llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp Wed Aug 29
> 10:32:21 2012
> @@ -132,7 +132,8 @@
> /// and zero out all the operands of this instruction. If any of them
> become
> /// dead, delete them and the computation tree that feeds them.
> ///
> -static void deleteDeadInstruction(Instruction *I, ScalarEvolution &SE) {
> +static void deleteDeadInstruction(Instruction *I, ScalarEvolution &SE,
> + const TargetLibraryInfo *TLI) {
> SmallVector<Instruction*, 32> NowDeadInsts;
>
> NowDeadInsts.push_back(I);
> @@ -153,7 +154,7 @@
> if (!Op->use_empty()) continue;
>
> if (Instruction *OpI = dyn_cast<Instruction>(Op))
> - if (isInstructionTriviallyDead(OpI))
> + if (isInstructionTriviallyDead(OpI, TLI))
> NowDeadInsts.push_back(OpI);
> }
>
> @@ -164,10 +165,11 @@
>
> /// deleteIfDeadInstruction - If the specified value is a dead
> instruction,
> /// delete it and any recursively used instructions.
> -static void deleteIfDeadInstruction(Value *V, ScalarEvolution &SE) {
> +static void deleteIfDeadInstruction(Value *V, ScalarEvolution &SE,
> + const TargetLibraryInfo *TLI) {
> if (Instruction *I = dyn_cast<Instruction>(V))
> - if (isInstructionTriviallyDead(I))
> - deleteDeadInstruction(I, SE);
> + if (isInstructionTriviallyDead(I, TLI))
> + deleteDeadInstruction(I, SE, TLI);
> }
>
> bool LoopIdiomRecognize::runOnLoop(Loop *L, LPPassManager &LPM) {
> @@ -490,7 +492,7 @@
> StoreSize, getAnalysis<AliasAnalysis>(),
> TheStore)){
> Expander.clear();
> // If we generated new code for the base pointer, clean up.
> - deleteIfDeadInstruction(BasePtr, *SE);
> + deleteIfDeadInstruction(BasePtr, *SE, TLI);
> return false;
> }
>
> @@ -538,7 +540,7 @@
>
> // Okay, the memset has been formed. Zap the original store and
> anything that
> // feeds into it.
> - deleteDeadInstruction(TheStore, *SE);
> + deleteDeadInstruction(TheStore, *SE, TLI);
> ++NumMemSet;
> return true;
> }
> @@ -579,7 +581,7 @@
> getAnalysis<AliasAnalysis>(), SI)) {
> Expander.clear();
> // If we generated new code for the base pointer, clean up.
> - deleteIfDeadInstruction(StoreBasePtr, *SE);
> + deleteIfDeadInstruction(StoreBasePtr, *SE, TLI);
> return false;
> }
>
> @@ -594,8 +596,8 @@
> StoreSize, getAnalysis<AliasAnalysis>(), SI))
> {
> Expander.clear();
> // If we generated new code for the base pointer, clean up.
> - deleteIfDeadInstruction(LoadBasePtr, *SE);
> - deleteIfDeadInstruction(StoreBasePtr, *SE);
> + deleteIfDeadInstruction(LoadBasePtr, *SE, TLI);
> + deleteIfDeadInstruction(StoreBasePtr, *SE, TLI);
> return false;
> }
>
> @@ -628,7 +630,7 @@
>
> // Okay, the memset has been formed. Zap the original store and
> anything that
> // feeds into it.
> - deleteDeadInstruction(SI, *SE);
> + deleteDeadInstruction(SI, *SE, TLI);
> ++NumMemCpy;
> return true;
> }
>
> Modified: llvm/trunk/lib/Transforms/Scalar/LoopInstSimplify.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopInstSimplify.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/LoopInstSimplify.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/LoopInstSimplify.cpp Wed Aug 29
> 10:32:21 2012
> @@ -120,7 +120,7 @@
> ++NumSimplified;
> }
> }
> - LocalChanged |= RecursivelyDeleteTriviallyDeadInstructions(I);
> + LocalChanged |= RecursivelyDeleteTriviallyDeadInstructions(I,
> TLI);
>
> if (IsSubloopHeader && !isa<PHINode>(I))
> break;
>
> Modified: llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp Wed Aug 29
> 10:32:21 2012
> @@ -94,7 +94,7 @@
> /// is dead. Also recursively delete any operands that become dead as
> /// a result. This includes tracing the def-use list from the PHI to see
> if
> /// it is ultimately unused or if it reaches an unused cycle.
> -bool llvm::DeleteDeadPHIs(BasicBlock *BB) {
> +bool llvm::DeleteDeadPHIs(BasicBlock *BB, const TargetLibraryInfo *TLI) {
> // Recursively deleting a PHI may cause multiple PHIs to be deleted
> // or RAUW'd undef, so use an array of WeakVH for the PHIs to delete.
> SmallVector<WeakVH, 8> PHIs;
> @@ -105,7 +105,7 @@
> bool Changed = false;
> for (unsigned i = 0, e = PHIs.size(); i != e; ++i)
> if (PHINode *PN = dyn_cast_or_null<PHINode>(PHIs[i].operator
> Value*()))
> - Changed |= RecursivelyDeleteDeadPHINode(PN);
> + Changed |= RecursivelyDeleteDeadPHINode(PN, TLI);
>
> return Changed;
> }
>
> Modified: llvm/trunk/lib/Transforms/Utils/Local.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/Local.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/Local.cpp Wed Aug 29 10:32:21 2012
> @@ -52,7 +52,8 @@
> /// Also calls RecursivelyDeleteTriviallyDeadInstructions() on any
> branch/switch
> /// conditions and indirectbr addresses this might make dead if
> /// DeleteDeadConditions is true.
> -bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool
> DeleteDeadConditions) {
> +bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool
> DeleteDeadConditions,
> + const TargetLibraryInfo *TLI) {
> TerminatorInst *T = BB->getTerminator();
> IRBuilder<> Builder(T);
>
> @@ -96,7 +97,7 @@
> Value *Cond = BI->getCondition();
> BI->eraseFromParent();
> if (DeleteDeadConditions)
> - RecursivelyDeleteTriviallyDeadInstructions(Cond);
> + RecursivelyDeleteTriviallyDeadInstructions(Cond, TLI);
> return true;
> }
> return false;
> @@ -161,7 +162,7 @@
> Value *Cond = SI->getCondition();
> SI->eraseFromParent();
> if (DeleteDeadConditions)
> - RecursivelyDeleteTriviallyDeadInstructions(Cond);
> + RecursivelyDeleteTriviallyDeadInstructions(Cond, TLI);
> return true;
> }
>
> @@ -205,7 +206,7 @@
> Value *Address = IBI->getAddress();
> IBI->eraseFromParent();
> if (DeleteDeadConditions)
> - RecursivelyDeleteTriviallyDeadInstructions(Address);
> + RecursivelyDeleteTriviallyDeadInstructions(Address, TLI);
>
> // If we didn't find our destination in the IBI successor list, then
> we
> // have undefined behavior. Replace the unconditional branch with
> an
> @@ -230,7 +231,8 @@
> /// isInstructionTriviallyDead - Return true if the result produced by the
> /// instruction is not used, and the instruction has no side effects.
> ///
> -bool llvm::isInstructionTriviallyDead(Instruction *I) {
> +bool llvm::isInstructionTriviallyDead(Instruction *I,
> + const TargetLibraryInfo *TLI) {
> if (!I->use_empty() || isa<TerminatorInst>(I)) return false;
>
> // We don't want the landingpad instruction removed by anything this
> general.
> @@ -265,9 +267,9 @@
> return isa<UndefValue>(II->getArgOperand(1));
> }
>
> - if (isAllocLikeFn(I)) return true;
> + if (isAllocLikeFn(I, TLI)) return true;
>
> - if (CallInst *CI = isFreeCall(I))
> + if (CallInst *CI = isFreeCall(I, TLI))
> if (Constant *C = dyn_cast<Constant>(CI->getArgOperand(0)))
> return C->isNullValue() || isa<UndefValue>(C);
>
> @@ -278,9 +280,11 @@
> /// trivially dead instruction, delete it. If that makes any of its
> operands
> /// trivially dead, delete them too, recursively. Return true if any
> /// instructions were deleted.
> -bool llvm::RecursivelyDeleteTriviallyDeadInstructions(Value *V) {
> +bool
> +llvm::RecursivelyDeleteTriviallyDeadInstructions(Value *V,
> + const TargetLibraryInfo
> *TLI) {
> Instruction *I = dyn_cast<Instruction>(V);
> - if (!I || !I->use_empty() || !isInstructionTriviallyDead(I))
> + if (!I || !I->use_empty() || !isInstructionTriviallyDead(I, TLI))
> return false;
>
> SmallVector<Instruction*, 16> DeadInsts;
> @@ -301,7 +305,7 @@
> // operand, and if it is 'trivially' dead, delete it in a future
> loop
> // iteration.
> if (Instruction *OpI = dyn_cast<Instruction>(OpV))
> - if (isInstructionTriviallyDead(OpI))
> + if (isInstructionTriviallyDead(OpI, TLI))
> DeadInsts.push_back(OpI);
> }
>
> @@ -334,19 +338,20 @@
> /// either forms a cycle or is terminated by a trivially dead instruction,
> /// delete it. If that makes any of its operands trivially dead, delete
> them
> /// too, recursively. Return true if a change was made.
> -bool llvm::RecursivelyDeleteDeadPHINode(PHINode *PN) {
> +bool llvm::RecursivelyDeleteDeadPHINode(PHINode *PN,
> + const TargetLibraryInfo *TLI) {
> SmallPtrSet<Instruction*, 4> Visited;
> for (Instruction *I = PN; areAllUsesEqual(I) &&
> !I->mayHaveSideEffects();
> I = cast<Instruction>(*I->use_begin())) {
> if (I->use_empty())
> - return RecursivelyDeleteTriviallyDeadInstructions(I);
> + return RecursivelyDeleteTriviallyDeadInstructions(I, TLI);
>
> // If we find an instruction more than once, we're on a cycle that
> // won't prove fruitful.
> if (!Visited.insert(I)) {
> // Break the cycle and delete the instruction and its operands.
> I->replaceAllUsesWith(UndefValue::get(I->getType()));
> - (void)RecursivelyDeleteTriviallyDeadInstructions(I);
> + (void)RecursivelyDeleteTriviallyDeadInstructions(I, TLI);
> return true;
> }
> }
> @@ -358,7 +363,8 @@
> ///
> /// This returns true if it changed the code, note that it can delete
> /// instructions in other blocks as well in this block.
> -bool llvm::SimplifyInstructionsInBlock(BasicBlock *BB, const TargetData
> *TD) {
> +bool llvm::SimplifyInstructionsInBlock(BasicBlock *BB, const TargetData
> *TD,
> + const TargetLibraryInfo *TLI) {
> bool MadeChange = false;
>
> #ifndef NDEBUG
> @@ -381,7 +387,7 @@
> continue;
> }
>
> - MadeChange |= RecursivelyDeleteTriviallyDeadInstructions(Inst);
> + MadeChange |= RecursivelyDeleteTriviallyDeadInstructions(Inst, TLI);
> if (BIHandle != BI)
> BI = BB->begin();
> }
>
> Modified: llvm/trunk/lib/Transforms/Utils/SimplifyInstructions.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyInstructions.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/SimplifyInstructions.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/SimplifyInstructions.cpp Wed Aug 29
> 10:32:21 2012
> @@ -72,7 +72,7 @@
> ++NumSimplified;
> Changed = true;
> }
> - Changed |= RecursivelyDeleteTriviallyDeadInstructions(I);
> + Changed |= RecursivelyDeleteTriviallyDeadInstructions(I,
> TLI);
> }
>
> // Place the list of instructions to simplify on the next loop
> iteration
>
> Modified: llvm/trunk/lib/Transforms/Vectorize/BBVectorize.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Vectorize/BBVectorize.cpp?rev=162841&r1=162840&r2=162841&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Vectorize/BBVectorize.cpp (original)
> +++ llvm/trunk/lib/Transforms/Vectorize/BBVectorize.cpp Wed Aug 29
> 10:32:21 2012
> @@ -601,7 +601,7 @@
>
> // It is important to cleanup here so that future iterations of this
> // function have less work to do.
> - (void) SimplifyInstructionsInBlock(&BB, TD);
> + (void) SimplifyInstructionsInBlock(&BB, TD,
> AA->getTargetLibraryInfo());
> return true;
> }
>
>
> Added: llvm/trunk/test/Transforms/GVN/malloc-load-removal.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/malloc-load-removal.ll?rev=162841&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/GVN/malloc-load-removal.ll (added)
> +++ llvm/trunk/test/Transforms/GVN/malloc-load-removal.ll Wed Aug 29
> 10:32:21 2012
> @@ -0,0 +1,31 @@
> +; RUN: opt -S -basicaa -gvn < %s | FileCheck %s
> +; RUN: opt -S -basicaa -gvn -disable-simplify-libcalls < %s | FileCheck
> %s -check-prefix=CHECK_NO_LIBCALLS
> +; PR13694
> +
> +target datalayout =
> "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
> +target triple = "x86_64-apple-macosx10.8.0"
> +
> +declare i8* @malloc(i64) nounwind
> +
> +define noalias i8* @test() nounwind uwtable ssp {
> +entry:
> + %call = tail call i8* @malloc(i64 100) nounwind
> + %0 = load i8* %call, align 1
> + %tobool = icmp eq i8 %0, 0
> + br i1 %tobool, label %if.end, label %if.then
> +
> +if.then: ; preds = %entry
> + store i8 0, i8* %call, align 1
> + br label %if.end
> +
> +if.end: ; preds = %if.then,
> %entry
> + ret i8* %call
> +
> +; CHECK: @test
> +; CHECK-NOT: load
> +; CHECK-NOT: icmp
> +
> +; CHECK_NO_LIBCALLS: @test
> +; CHECK_NO_LIBCALLS: load
> +; CHECK_NO_LIBCALLS: icmp
> +}
>
More information about the llvm-commits
mailing list