Skip to content

Commit

Permalink
[CodeGen] only add nobuiltin to inline builtins if we'll emit them
Browse files Browse the repository at this point in the history
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
  • Loading branch information
gburgessiv committed Apr 15, 2020
1 parent f42baaa commit 2dd17ff
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CodeGenModule.cpp
Expand Up @@ -1908,7 +1908,8 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
else if (const auto *SA = FD->getAttr<SectionAttr>())
F->setSection(SA->getName());

if (FD->isInlineBuiltinDeclaration()) {
// If we plan on emitting this inline builtin, we can't treat it as a builtin.
if (FD->isInlineBuiltinDeclaration() && shouldEmitFunction(FD)) {
F->addAttribute(llvm::AttributeList::FunctionIndex,
llvm::Attribute::NoBuiltin);
}
Expand Down
25 changes: 25 additions & 0 deletions clang/test/CodeGen/memcpy-no-nobuiltin-if-not-emitted.c
@@ -0,0 +1,25 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -S -emit-llvm -o - %s | FileCheck %s
//
// Verifies that clang doesn't mark an inline builtin definition as `nobuiltin`
// if the builtin isn't emittable.

typedef unsigned long size_t;

// always_inline is used so clang will emit this body. Otherwise, we need >=
// -O1.
#define AVAILABLE_EXTERNALLY extern inline __attribute__((always_inline)) \
__attribute__((gnu_inline))

AVAILABLE_EXTERNALLY void *memcpy(void *a, const void *b, size_t c) {
return __builtin_memcpy(a, b, c);
}

// CHECK-LABEL: define void @foo
void foo(void *a, const void *b, size_t c) {
// Clang will always _emit_ this as memcpy. LLVM turns it into @llvm.memcpy
// later on if optimizations are enabled.
// CHECK: call i8* @memcpy
memcpy(a, b, c);
}

// CHECK-NOT: nobuiltin

0 comments on commit 2dd17ff

Please sign in to comment.