Revert "Simplify handling of builtin with inline redefinition"

This reverts commit 3d6f49a569.

Broke bot: https://lab.llvm.org/buildbot/#/builders/5/builds/12360
This commit is contained in:
Kevin Athey 2021-09-28 11:08:32 -07:00
parent fd582eeffe
commit 0d76d4833d
6 changed files with 28 additions and 58 deletions

View File

@ -1294,11 +1294,6 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
FunctionArgList Args;
QualType ResTy = BuildFunctionArgList(GD, Args);
// Give a different name to inline builtin to avoid conflict with actual
// builtins.
if (FD->isInlineBuiltinDeclaration() && Fn)
Fn->setName(Fn->getName() + ".inline");
// Check if we should generate debug info for this function.
if (FD->hasAttr<NoDebugAttr>()) {
// Clear non-distinct debug info that was possibly attached to the function

View File

@ -3169,11 +3169,6 @@ bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
}
}
// Inline builtins declaration must be emitted. They often are fortified
// functions.
if (F->isInlineBuiltinDeclaration())
return true;
// PR9614. Avoid cases where the source code is lying to us. An available
// externally function should have an equivalent function somewhere else,
// but a function that calls itself through asm label/`__builtin_` trickery is

View File

@ -1,44 +0,0 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -triple x86_64 -S -emit-llvm -o - %s | FileCheck %s
//
// Verifies that clang detects memcpy inline version and uses it instead of the builtin.
typedef unsigned long size_t;
// Clang requires these attributes for a function to be redefined.
#define AVAILABLE_EXTERNALLY extern inline __attribute__((always_inline)) __attribute__((gnu_inline))
// Clang recognizes an inline builtin and renames it to prevent conflict with builtins.
AVAILABLE_EXTERNALLY void *memcpy(void *a, const void *b, size_t c) {
asm("# memcpy.inline marker");
return __builtin_memcpy(a, b, c);
}
// CHECK-LABEL: @foo(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[A_ADDR_I:%.*]] = alloca i8*, align 8
// CHECK-NEXT: [[B_ADDR_I:%.*]] = alloca i8*, align 8
// CHECK-NEXT: [[C_ADDR_I:%.*]] = alloca i64, align 8
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i8*, align 8
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i8*, align 8
// CHECK-NEXT: [[C_ADDR:%.*]] = alloca i64, align 8
// CHECK-NEXT: store i8* [[A:%.*]], i8** [[A_ADDR]], align 8
// CHECK-NEXT: store i8* [[B:%.*]], i8** [[B_ADDR]], align 8
// CHECK-NEXT: store i64 [[C:%.*]], i64* [[C_ADDR]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** [[A_ADDR]], align 8
// CHECK-NEXT: [[TMP1:%.*]] = load i8*, i8** [[B_ADDR]], align 8
// CHECK-NEXT: [[TMP2:%.*]] = load i64, i64* [[C_ADDR]], align 8
// CHECK-NEXT: store i8* [[TMP0]], i8** [[A_ADDR_I]], align 8
// CHECK-NEXT: store i8* [[TMP1]], i8** [[B_ADDR_I]], align 8
// CHECK-NEXT: store i64 [[TMP2]], i64* [[C_ADDR_I]], align 8
// CHECK-NEXT: call void asm sideeffect "# memcpy.inline marker", "~{dirflag},~{fpsr},~{flags}"() #[[ATTR2:[0-9]+]], !srcloc !2
// CHECK-NEXT: [[TMP3:%.*]] = load i8*, i8** [[A_ADDR_I]], align 8
// CHECK-NEXT: [[TMP4:%.*]] = load i8*, i8** [[B_ADDR_I]], align 8
// CHECK-NEXT: [[TMP5:%.*]] = load i64, i64* [[C_ADDR_I]], align 8
// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 [[TMP3]], i8* align 1 [[TMP4]], i64 [[TMP5]], i1 false) #[[ATTR2]]
// CHECK-NEXT: ret void
//
void foo(void *a, const void *b, size_t c) {
memcpy(a, b, c);
}

View File

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

View File

@ -4,8 +4,7 @@
//
// CHECK-WITH-DECL-NOT: @llvm.memcpy
// CHECK-NO-DECL: @llvm.memcpy
// CHECK-SELF-REF-DECL-LABEL: define dso_local i8* @memcpy.inline
// CHECK-SELF-REF-DECL: @memcpy(
// CHECK-SELF-REF-DECL: @llvm.memcpy
//
#include <memcpy-nobuiltin.inc>
void test(void *dest, void const *from, size_t n) {

View File

@ -32,14 +32,14 @@ void f(void) {
// CHECK-LABEL: define{{.*}} void @f()
// CHECK: call void @foo()
// CHECK: call i32 @abs(i32 %0)
// CHECK: call i32 @abs(i32 0)
// CHECK: call i8* @strrchr(
// CHECK: call void @llvm.prefetch.p0i8(
// CHECK: call i8* @memchr(
// CHECK: ret void
// CHECK: declare void @foo()
// CHECK: declare i32 @abs(i32
// CHECK: declare i8* @strrchr(i8*, i32)
// CHECK: declare i8* @memchr(
// CHECK: declare i32 @abs(i32
// CHECK: declare void @llvm.prefetch.p0i8(