Skip to content

Commit 2dd17ff

Browse files
committed
[CodeGen] only add nobuiltin to inline builtins if we'll emit them
There are some inline builtin definitions that we can't emit (isTriviallyRecursive & callers go into why). Marking these nobuiltin is only useful if we actually emit the body, so don't mark these as such unless we _do_ plan on emitting that. This suboptimality was encountered in Linux (see some discussion on D71082, and ClangBuiltLinux/linux#979). Differential Revision: https://reviews.llvm.org/D78162
1 parent f42baaa commit 2dd17ff

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1908,7 +1908,8 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
19081908
else if (const auto *SA = FD->getAttr<SectionAttr>())
19091909
F->setSection(SA->getName());
19101910

1911-
if (FD->isInlineBuiltinDeclaration()) {
1911+
// If we plan on emitting this inline builtin, we can't treat it as a builtin.
1912+
if (FD->isInlineBuiltinDeclaration() && shouldEmitFunction(FD)) {
19121913
F->addAttribute(llvm::AttributeList::FunctionIndex,
19131914
llvm::Attribute::NoBuiltin);
19141915
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -S -emit-llvm -o - %s | FileCheck %s
2+
//
3+
// Verifies that clang doesn't mark an inline builtin definition as `nobuiltin`
4+
// if the builtin isn't emittable.
5+
6+
typedef unsigned long size_t;
7+
8+
// always_inline is used so clang will emit this body. Otherwise, we need >=
9+
// -O1.
10+
#define AVAILABLE_EXTERNALLY extern inline __attribute__((always_inline)) \
11+
__attribute__((gnu_inline))
12+
13+
AVAILABLE_EXTERNALLY void *memcpy(void *a, const void *b, size_t c) {
14+
return __builtin_memcpy(a, b, c);
15+
}
16+
17+
// CHECK-LABEL: define void @foo
18+
void foo(void *a, const void *b, size_t c) {
19+
// Clang will always _emit_ this as memcpy. LLVM turns it into @llvm.memcpy
20+
// later on if optimizations are enabled.
21+
// CHECK: call i8* @memcpy
22+
memcpy(a, b, c);
23+
}
24+
25+
// CHECK-NOT: nobuiltin

0 commit comments

Comments
 (0)