diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h --- a/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -76,6 +76,14 @@ bool LookThroughBitCast = false); /// Tests if a value is a call or invoke to a library function that +/// allocates uninitialized memory with alignment (such as aligned_alloc). +bool isAlignedAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI, + bool LookThroughBitCast = false); +bool isAlignedAllocLikeFn( + const Value *V, function_ref GetTLI, + bool LookThroughBitCast = false); + +/// 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, const TargetLibraryInfo *TLI, bool LookThroughBitCast = false); diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def --- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def +++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def @@ -481,6 +481,9 @@ /// long double acosl(long double x); TLI_DEFINE_ENUM_INTERNAL(acosl) TLI_DEFINE_STRING_INTERNAL("acosl") +/// void *aligned_alloc(size_t alignment, size_t size); +TLI_DEFINE_ENUM_INTERNAL(aligned_alloc) +TLI_DEFINE_STRING_INTERNAL("aligned_alloc") /// double asin(double x); TLI_DEFINE_ENUM_INTERNAL(asin) TLI_DEFINE_STRING_INTERNAL("asin") diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -960,7 +960,7 @@ } } - // If the call is to malloc or calloc, we can assume that it doesn't + // If the call is malloc/calloc like, we can assume that it doesn't // modify any IR visible value. This is only valid because we assume these // routines do not read values visible in the IR. TODO: Consider special // casing realloc and strdup routines which access only their arguments as diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -52,11 +52,12 @@ enum AllocType : uint8_t { OpNewLike = 1<<0, // allocates; never returns null MallocLike = 1<<1 | OpNewLike, // allocates; may return null - CallocLike = 1<<2, // allocates + bzero - ReallocLike = 1<<3, // reallocates - StrDupLike = 1<<4, - MallocOrCallocLike = MallocLike | CallocLike, - AllocLike = MallocLike | CallocLike | StrDupLike, + AlignedAllocLike = 1<<2, // allocates with alignment; may return null + CallocLike = 1<<3, // allocates + bzero + ReallocLike = 1<<4, // reallocates + StrDupLike = 1<<5, + MallocOrCallocLike = MallocLike | CallocLike | AlignedAllocLike, + AllocLike = MallocOrCallocLike | StrDupLike, AnyAlloc = AllocLike | ReallocLike }; @@ -100,6 +101,7 @@ {LibFunc_msvc_new_array_int_nothrow, {MallocLike, 2, 0, -1}}, // new[](unsigned int, nothrow) {LibFunc_msvc_new_array_longlong, {OpNewLike, 1, 0, -1}}, // new[](unsigned long long) {LibFunc_msvc_new_array_longlong_nothrow, {MallocLike, 2, 0, -1}}, // new[](unsigned long long, nothrow) + {LibFunc_aligned_alloc, {AlignedAllocLike, 2, 1, -1}}, {LibFunc_calloc, {CallocLike, 2, 0, 1}}, {LibFunc_realloc, {ReallocLike, 2, 1, -1}}, {LibFunc_reallocf, {ReallocLike, 2, 1, -1}}, @@ -266,6 +268,20 @@ } /// Tests if a value is a call or invoke to a library function that +/// allocates uninitialized memory with alignment (such as aligned_alloc). +bool llvm::isAlignedAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI, + bool LookThroughBitCast) { + return getAllocationData(V, AlignedAllocLike, TLI, LookThroughBitCast) + .hasValue(); +} +bool llvm::isAlignedAllocLikeFn( + const Value *V, function_ref GetTLI, + bool LookThroughBitCast) { + return getAllocationData(V, AlignedAllocLike, GetTLI, LookThroughBitCast) + .hasValue(); +} + +/// 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, const TargetLibraryInfo *TLI, bool LookThroughBitCast) { diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -901,6 +901,8 @@ FTy.getParamType(1)->isPointerTy()); case LibFunc_write: return (NumParams == 3 && FTy.getParamType(1)->isPointerTy()); + case LibFunc_aligned_alloc: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy()); case LibFunc_bcopy: case LibFunc_bcmp: return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -378,6 +378,10 @@ Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 1); return Changed; + case LibFunc_aligned_alloc: + Changed |= setDoesNotThrow(F); + Changed |= setRetDoesNotAlias(F); + return Changed; case LibFunc_bcopy: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 0); diff --git a/llvm/test/Transforms/DeadStoreElimination/simple.ll b/llvm/test/Transforms/DeadStoreElimination/simple.ll --- a/llvm/test/Transforms/DeadStoreElimination/simple.ll +++ b/llvm/test/Transforms/DeadStoreElimination/simple.ll @@ -259,6 +259,8 @@ declare noalias i8* @malloc(i32) declare noalias i8* @calloc(i32, i32) +declare noalias i8* @aligned_alloc(i32, i32) +declare void @free(i8*) define void @test14(i32* %Q) { @@ -272,6 +274,17 @@ } +; Dead store on an aligned_alloc: should know that %M doesn't alias with %A. +define i32 @test14a(i8* %M, i8 %value) { +; CHECK-LABEL: @test14a( +; CHECK-NOT: store +; CHECK: ret i32 0 +; + %A = tail call i8* @aligned_alloc(i32 32, i32 1024) + store i8 %value, i8* %A + tail call void @free(i8* %A) + ret i32 0 +} ; PR8701 diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp --- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp +++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp @@ -96,6 +96,7 @@ "declare float @acoshf(float)\n" "declare x86_fp80 @acoshl(x86_fp80)\n" "declare x86_fp80 @acosl(x86_fp80)\n" + "declare i8* @aligned_alloc(i64, i64)\n" "declare double @asin(double)\n" "declare float @asinf(float)\n" "declare double @asinh(double)\n"