| // RUN: %clang_cc1 -O1 -disable-llvm-passes -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s |
| |
| template <typename T> |
| [[clang::noinline]] void foo(T) {} |
| |
| // Explicit specializations should not inherit noinline |
| template <> |
| [[clang::always_inline]] void foo<int>(int) {} |
| |
| template <> |
| void foo<long>(long) {} |
| |
| void caller() { |
| foo<float>(4.2f); // expect noinline on function |
| foo<int>(42); // expect alwaysinline on function |
| foo<long>(42L); // expect no noinline attribute |
| } |
| // CHECK: define {{.*}}void @_Z3fooIiEvT_({{.*}}) #[[ALWAYSINLINE:[0-9]+]] |
| // CHECK: define {{.*}}void @_Z3fooIlEvT_({{.*}}) #[[BARE:[0-9]+]] |
| // CHECK: define {{.*}}void @_Z3fooIfEvT_({{.*}}) #[[NOINLINE:[0-9]+]] |
| |
| // Inner function should not clobber non-conflicting attributes |
| void inner_fn(); |
| |
| void outer_fn() { |
| [[clang::noinline]] |
| { |
| [[clang::nomerge]] // unrelated to inlining |
| inner_fn(); |
| } |
| } |
| // CHECK: call void @_Z8inner_fnv() #[[NOINLINE_NOMERGE:[0-9]+]] |
| |
| void inner_fn2(); |
| |
| void outer_fn2() { |
| [[clang::nomerge]] |
| { |
| [[clang::noinline]] // unrelated to nomerge |
| inner_fn2(); |
| } |
| } |
| // CHECK: call void @_Z9inner_fn2v() #[[NOINLINE_NOMERGE]] |
| |
| [[clang::convergent]] |
| void inner_fn3(); |
| |
| void outer_fn3() { |
| [[clang::always_inline]] |
| { |
| [[clang::noconvergent]] // unrelated to inlining |
| inner_fn3(); |
| } |
| } |
| // CHECK: call void @_Z9inner_fn3v() #[[ALWAYSINLINE_ONLY:[0-9]+]] |
| |
| [[clang::convergent]] |
| void inner_fn4(); |
| |
| void outer_fn4() { |
| [[clang::noconvergent]] |
| { |
| [[clang::always_inline]] // unrelated to noconvergent |
| inner_fn4(); |
| } |
| } |
| // CHECK: call void @_Z9inner_fn4v() #[[ALWAYSINLINE_ONLY]] |
| |
| // Inner function should clobber a conflicting attribute |
| void inner_fn5(); |
| |
| void outer_fn5() { |
| [[clang::noinline]] |
| { |
| [[clang::always_inline]] |
| inner_fn5(); |
| } |
| } |
| // CHECK: call void @_Z9inner_fn5v() #[[ALWAYSINLINE_ONLY]] |
| |
| // CHECK: attributes #[[ALWAYSINLINE]] = { |
| // CHECK-SAME: alwaysinline |
| // CHECK-NOT: noinline |
| // CHECK: attributes #[[BARE]] = { |
| // CHECK-NOT: alwaysinline |
| // CHECK-NOT: noinline |
| // CHECK: attributes #[[NOINLINE]] = { |
| // CHECK-SAME: noinline |
| // CHECK-NOT: alwaysinline |
| |
| // CHECK: attributes #[[NOINLINE_NOMERGE]] = { noinline nomerge } |
| // CHECK: attributes #[[ALWAYSINLINE_ONLY]] = { alwaysinline } |