[llvm] c0955ed - Introduce support for lib function aligned_alloc in TLI / memory builtins
Uday Bondhugula via llvm-commits
llvm-commits at lists.llvm.org
Sun Mar 29 11:07:53 PDT 2020
Author: Uday Bondhugula
Date: 2020-03-29T23:36:24+05:30
New Revision: c0955edfd6ec51e9a3720f9bfc90bac2e511c06d
URL: https://github.com/llvm/llvm-project/commit/c0955edfd6ec51e9a3720f9bfc90bac2e511c06d
DIFF: https://github.com/llvm/llvm-project/commit/c0955edfd6ec51e9a3720f9bfc90bac2e511c06d.diff
LOG: Introduce support for lib function aligned_alloc in TLI / memory builtins
Aligned_alloc is a standard lib function and has been in glibc since
2.16 and in the C11 standard. It has semantics similar to malloc/calloc
for several analyses/transforms. This patch introduces aligned_alloc
in target library info and memory builtins. Subsequent ones will
make other passes aware and fix https://bugs.llvm.org/show_bug.cgi?id=44062
This change will also be useful to LLVM generators that need to allocate
buffers of vector elements larger than 16 bytes (for eg. 256-bit ones),
element boundary alignment for which is not typically provided by glibc malloc.
Signed-off-by: Uday Bondhugula <uday at polymagelabs.com>
Differential Revision: https://reviews.llvm.org/D76970
Added:
Modified:
llvm/include/llvm/Analysis/MemoryBuiltins.h
llvm/include/llvm/Analysis/TargetLibraryInfo.def
llvm/lib/Analysis/BasicAliasAnalysis.cpp
llvm/lib/Analysis/MemoryBuiltins.cpp
llvm/lib/Analysis/TargetLibraryInfo.cpp
llvm/lib/Transforms/Utils/BuildLibCalls.cpp
llvm/test/Transforms/DeadStoreElimination/simple.ll
llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h
index a89d76b9e5bd..a674a3a65f47 100644
--- a/llvm/include/llvm/Analysis/MemoryBuiltins.h
+++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h
@@ -75,6 +75,14 @@ bool isMallocLikeFn(const Value *V,
function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
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<const TargetLibraryInfo &(Function &)> 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,
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
index ed0e12528228..b5688cecc4ad 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
@@ -481,6 +481,9 @@ TLI_DEFINE_STRING_INTERNAL("acoshl")
/// 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
index 0cc28efd4489..9ab056f4bb3e 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -960,7 +960,7 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call,
}
}
- // 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
index be0feeb9237e..ac72bda4eb63 100644
--- a/llvm/lib/Analysis/MemoryBuiltins.cpp
+++ b/llvm/lib/Analysis/MemoryBuiltins.cpp
@@ -52,11 +52,12 @@ using namespace llvm;
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 @@ static const std::pair<LibFunc, AllocFnsTy> AllocationFnData[] = {
{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}},
@@ -265,6 +267,20 @@ bool llvm::isMallocLikeFn(
.hasValue();
}
+/// 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<const TargetLibraryInfo &(Function &)> 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,
diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp
index fa4deea632d8..ffa6921c51be 100644
--- a/llvm/lib/Analysis/TargetLibraryInfo.cpp
+++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp
@@ -901,6 +901,8 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
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
index a385b08d17a9..c64ad147fdfe 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -378,6 +378,10 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
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
index 84034caee55f..7efd3953937f 100644
--- a/llvm/test/Transforms/DeadStoreElimination/simple.ll
+++ b/llvm/test/Transforms/DeadStoreElimination/simple.ll
@@ -259,6 +259,8 @@ define i32 addrspace(1)* @test13_addrspacecast() {
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 @@ define void @test14(i32* %Q) {
}
+; 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
index af0ee631ee12..f21081467c1e 100644
--- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
+++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
@@ -96,6 +96,7 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
"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"
More information about the llvm-commits
mailing list