1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

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@polymagelabs.com>

Differential Revision: https://reviews.llvm.org/D76970
This commit is contained in:
Uday Bondhugula 2020-03-28 11:29:52 +05:30
parent d0c820ef49
commit 336d326470
8 changed files with 53 additions and 6 deletions

View File

@ -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,

View File

@ -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")

View File

@ -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

View File

@ -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,

View File

@ -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() &&

View File

@ -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);

View File

@ -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

View File

@ -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"