Skip to content

Commit c229754

Browse files
[Clang] Propagate guaranteed alignment for malloc and others
LLVM should be smarter about *known* malloc's alignment and this knowledge may enable other optimizations. Originally started as LLVM patch - https://reviews.llvm.org/D100862 but this logic should be really in Clang. Reviewed By: rjmccall Differential Revision: https://reviews.llvm.org/D100879
1 parent a819e73 commit c229754

File tree

3 files changed

+55
-2
lines changed

3 files changed

+55
-2
lines changed

clang/include/clang/Basic/TargetInfo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -612,8 +612,8 @@ class TargetInfo : public virtual TransferrableTargetInfo,
612612
}
613613

614614
/// Return the largest alignment for which a suitably-sized allocation with
615-
/// '::operator new(size_t)' is guaranteed to produce a correctly-aligned
616-
/// pointer.
615+
/// '::operator new(size_t)' or 'malloc' is guaranteed to produce a
616+
/// correctly-aligned pointer.
617617
unsigned getNewAlign() const {
618618
return NewAlign ? NewAlign : std::max(LongDoubleAlign, LongLongAlign);
619619
}

clang/lib/CodeGen/CGCall.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2048,6 +2048,24 @@ void CodeGenModule::ConstructAttributeList(
20482048
// allows it to work on indirect virtual function calls.
20492049
if (AttrOnCallSite && TargetDecl->hasAttr<NoMergeAttr>())
20502050
FuncAttrs.addAttribute(llvm::Attribute::NoMerge);
2051+
2052+
// Add known guaranteed alignment for allocation functions.
2053+
if (unsigned BuiltinID = Fn->getBuiltinID()) {
2054+
switch (BuiltinID) {
2055+
case Builtin::BIaligned_alloc:
2056+
case Builtin::BIcalloc:
2057+
case Builtin::BImalloc:
2058+
case Builtin::BImemalign:
2059+
case Builtin::BIrealloc:
2060+
case Builtin::BIstrdup:
2061+
case Builtin::BIstrndup:
2062+
RetAttrs.addAlignmentAttr(Context.getTargetInfo().getNewAlign() /
2063+
Context.getTargetInfo().getCharWidth());
2064+
break;
2065+
default:
2066+
break;
2067+
}
2068+
}
20512069
}
20522070

20532071
// 'const', 'pure' and 'noalias' attributed functions are also nounwind.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm < %s | FileCheck %s --check-prefix=ALIGN16
2+
// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm < %s | FileCheck %s --check-prefix=ALIGN16
3+
// RUN: %clang_cc1 -triple i386-apple-darwin -emit-llvm < %s | FileCheck %s --check-prefix=ALIGN16
4+
// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -emit-llvm < %s | FileCheck %s --check-prefix=ALIGN8
5+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fno-builtin-malloc -emit-llvm < %s | FileCheck %s --check-prefix=NOBUILTIN-MALLOC
6+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fno-builtin-calloc -emit-llvm < %s | FileCheck %s --check-prefix=NOBUILTIN-CALLOC
7+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fno-builtin-realloc -emit-llvm < %s | FileCheck %s --check-prefix=NOBUILTIN-REALLOC
8+
9+
typedef __SIZE_TYPE__ size_t;
10+
11+
void *malloc(size_t);
12+
void *calloc(size_t, size_t);
13+
void *realloc(void *, size_t);
14+
15+
void *malloc_test(size_t n) {
16+
return malloc(n);
17+
}
18+
19+
void *calloc_test(size_t n) {
20+
return calloc(1, n);
21+
}
22+
23+
void *raalloc_test(void *p, size_t n) {
24+
return realloc(p, n);
25+
}
26+
27+
// ALIGN16: align 16 i8* @malloc
28+
// ALIGN16: align 16 i8* @calloc
29+
// ALIGN16: align 16 i8* @realloc
30+
// ALIGN8: align 8 i8* @malloc
31+
// ALIGN8: align 8 i8* @calloc
32+
// ALIGN8: align 8 i8* @realloc
33+
// NOBUILTIN-MALLOC: declare i8* @malloc
34+
// NOBUILTIN-CALLOC: declare i8* @calloc
35+
// NOBUILTIN-REALLOC: declare i8* @realloc

0 commit comments

Comments
 (0)