D->getType()->getAs<FunctionType>()->getCallConv())
return true;
+ if (BaseD->hasAttr<AlwaysInlineAttr>())
+ return true;
+
return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),
GlobalDecl(BaseD, Dtor_Base),
false);
// Instead of creating as alias to a linkonce_odr, replace all of the uses
// of the aliasee.
- if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) &&
- (TargetLinkage != llvm::GlobalValue::AvailableExternallyLinkage ||
- !TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>())) {
- // FIXME: An extern template instantiation will create functions with
- // linkage "AvailableExternally". In libc++, some classes also define
- // members with attribute "AlwaysInline" and expect no reference to
- // be generated. It is desirable to reenable this optimisation after
- // corresponding LLVM changes.
+ if (llvm::GlobalValue::isDiscardableIfUnused(Linkage)) {
Replacements[MangledName] = Aliasee;
return false;
}
// -fapple-kext must inline any call to this dtor into
// the caller's body.
if (getLangOpts().AppleKext)
- CurFn->addFnAttr(llvm::Attribute::AlwaysInline);
+ CGM.AddAlwaysInlineFunction(CurFn);
break;
}
".omp_task_privates_map.", &CGM.getModule());
CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, TaskPrivatesMapFnInfo,
TaskPrivatesMap);
- TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
+ CGM.AddAlwaysInlineFunction(TaskPrivatesMap);
CodeGenFunction CGF(CGM);
CGF.disableDebugInfo();
CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
EmitVersionIdentMetadata();
EmitTargetMetadata();
+
+ RewriteAlwaysInlineFunctions();
+}
+
+void CodeGenModule::AddAlwaysInlineFunction(llvm::Function *Fn) {
+ AlwaysInlineFunctions.push_back(Fn);
+}
+
+/// Find all uses of GV that are not direct calls or invokes.
+static void FindNonDirectCallUses(llvm::GlobalValue *GV,
+ llvm::SmallVectorImpl<llvm::Use *> *Uses) {
+ llvm::GlobalValue::use_iterator UI = GV->use_begin(), E = GV->use_end();
+ for (; UI != E;) {
+ llvm::Use &U = *UI;
+ ++UI;
+
+ llvm::CallSite CS(U.getUser());
+ bool isDirectCall = (CS.isCall() || CS.isInvoke()) && CS.isCallee(&U);
+ if (!isDirectCall)
+ Uses->push_back(&U);
+ }
+}
+
+/// Replace a list of uses.
+static void ReplaceUsesWith(const llvm::SmallVectorImpl<llvm::Use *> &Uses,
+ llvm::GlobalValue *V,
+ llvm::GlobalValue *Replacement) {
+ for (llvm::Use *U : Uses) {
+ auto *C = dyn_cast<llvm::Constant>(U->getUser());
+ if (C && !isa<llvm::GlobalValue>(C))
+ C->handleOperandChange(V, Replacement, U);
+ else
+ U->set(Replacement);
+ }
+}
+
+void CodeGenModule::RewriteAlwaysInlineFunction(llvm::Function *Fn) {
+ std::string Name = Fn->getName();
+ std::string InlineName = Name + ".alwaysinline";
+ Fn->setName(InlineName);
+
+ llvm::SmallVector<llvm::Use *, 8> NonDirectCallUses;
+ Fn->removeDeadConstantUsers();
+ FindNonDirectCallUses(Fn, &NonDirectCallUses);
+ // Do not create the wrapper if there are no non-direct call uses, and we are
+ // not required to emit an external definition.
+ if (NonDirectCallUses.empty() && Fn->isDiscardableIfUnused())
+ return;
+
+ llvm::FunctionType *FT = Fn->getFunctionType();
+ llvm::LLVMContext &Ctx = getModule().getContext();
+ llvm::Function *StubFn =
+ llvm::Function::Create(FT, Fn->getLinkage(), Name, &getModule());
+ assert(StubFn->getName() == Name && "name was uniqued!");
+
+ // Insert the stub immediately after the original function. Helps with the
+ // fragile tests, among other things.
+ StubFn->removeFromParent();
+ TheModule.getFunctionList().insertAfter(Fn, StubFn);
+
+ StubFn->copyAttributesFrom(Fn);
+ StubFn->setPersonalityFn(nullptr);
+
+ // AvailableExternally functions are replaced with a declaration.
+ // Everyone else gets a wrapper that musttail-calls the original function.
+ if (Fn->hasAvailableExternallyLinkage()) {
+ StubFn->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ } else {
+ llvm::BasicBlock *BB = llvm::BasicBlock::Create(Ctx, "entry", StubFn);
+ std::vector<llvm::Value *> Args;
+ for (llvm::Function::arg_iterator ai = StubFn->arg_begin();
+ ai != StubFn->arg_end(); ++ai)
+ Args.push_back(&*ai);
+ llvm::CallInst *CI = llvm::CallInst::Create(Fn, Args, "", BB);
+ CI->setCallingConv(Fn->getCallingConv());
+ CI->setTailCallKind(llvm::CallInst::TCK_MustTail);
+ CI->setAttributes(Fn->getAttributes());
+ if (FT->getReturnType()->isVoidTy())
+ llvm::ReturnInst::Create(Ctx, BB);
+ else
+ llvm::ReturnInst::Create(Ctx, CI, BB);
+ }
+
+ if (Fn->hasComdat())
+ StubFn->setComdat(Fn->getComdat());
+
+ ReplaceUsesWith(NonDirectCallUses, Fn, StubFn);
+
+ // Replace all metadata uses with the stub. This is primarily to reattach
+ // DISubprogram metadata to the stub, because that's what will be emitted in
+ // the object file.
+ if (Fn->isUsedByMetadata())
+ llvm::ValueAsMetadata::handleRAUW(Fn, StubFn);
+}
+
+void CodeGenModule::RewriteAlwaysInlineFunctions() {
+ for (llvm::Function *Fn : AlwaysInlineFunctions) {
+ RewriteAlwaysInlineFunction(Fn);
+ Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
+ Fn->addFnAttr(llvm::Attribute::AlwaysInline);
+ Fn->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass);
+ Fn->setVisibility(llvm::GlobalValue::DefaultVisibility);
+ }
}
void CodeGenModule::UpdateCompletedType(const TagDecl *TD) {
!F->getAttributes().hasAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::NoInline)) {
// (noinline wins over always_inline, and we can't specify both in IR)
- B.addAttribute(llvm::Attribute::AlwaysInline);
+ AddAlwaysInlineFunction(F);
}
if (D->hasAttr<ColdAttr>()) {
/// MDNodes.
llvm::DenseMap<QualType, llvm::Metadata *> MetadataIdMap;
+ llvm::SmallVector<llvm::Function*, 8> AlwaysInlineFunctions;
+
public:
CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts,
const PreprocessorOptions &ppopts,
/// \breif Get the declaration of std::terminate for the platform.
llvm::Constant *getTerminateFn();
+ void AddAlwaysInlineFunction(llvm::Function *Fn);
+
private:
llvm::Constant *
GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty, GlobalDecl D,
/// Emits target specific Metadata for global declarations.
void EmitTargetMetadata();
+ /// Replaces alwaysinline functions with a pair of internal xxx.inlinefunction
+ /// for direct calls, and a stub for indirect calls, and rewrites all uses of
+ /// those.
+ void RewriteAlwaysInlineFunctions();
+ void RewriteAlwaysInlineFunction(llvm::Function *Fn);
+
/// Emit the llvm.gcov metadata used to tell LLVM where to emit the .gcno and
/// .gcda files in a way that persists in .bc files.
void EmitCoverageFile();
if (MD->getParent()->getNumVBases())
return StructorCodegen::Emit;
+ if (MD->hasAttr<AlwaysInlineAttr>())
+ return StructorCodegen::Emit;
+
GlobalDecl AliasDecl;
if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
AliasDecl = GlobalDecl(DD, Dtor_Complete);
// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fno-inline -emit-llvm %s -o - | FileCheck %s
+// CHECK-LABEL: define void @i_want_bar()
// CHECK-NOT: foo
+// CHECK: ret void
void bar() {
}
--- /dev/null
+// Test alwaysinline definitions w/o any non-direct-call uses.
+// None of the declarations are emitted. Stub are only emitted when the original
+// function can not be discarded.
+
+// RUN: %clang_cc1 -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s
+
+void __attribute__((__always_inline__)) f1() {}
+inline void __attribute__((__always_inline__)) f2() {}
+static inline void __attribute__((__always_inline__)) f3() {}
+inline void __attribute__((gnu_inline, __always_inline__)) f4() {}
+static inline void __attribute__((gnu_inline, __always_inline__)) f5() {}
+inline void __attribute__((visibility("hidden"), __always_inline__)) f6() {}
+inline void __attribute__((visibility("hidden"), gnu_inline, __always_inline__)) f7() {}
+
+void g() {
+ f1();
+ f2();
+ f3();
+ f4();
+ f5();
+ f6();
+ f7();
+}
+
+// CHECK: define void @f1()
+// CHECK-NOT: void @f2()
+// CHECK-NOT: void @f3()
+// CHECK: define void @f4()
+// CHECK-NOT: void @f5()
+// CHECK-NOT: void @f6()
+// CHECK: define hidden void @f7()
--- /dev/null
+// Test different kinds of alwaysinline definitions.
+
+// RUN: %clang_cc1 -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-INLINE
+// RUN: %clang_cc1 -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-USE
+// RUN: %clang_cc1 -disable-llvm-optzns -fno-inline -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 -disable-llvm-optzns -fno-inline -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-USE
+
+void __attribute__((__always_inline__)) f1() {}
+inline void __attribute__((__always_inline__)) f2() {}
+static inline void __attribute__((__always_inline__)) f3() {}
+inline void __attribute__((gnu_inline, __always_inline__)) f4() {}
+static inline void __attribute__((gnu_inline, __always_inline__)) f5() {}
+inline void __attribute__((visibility("hidden"), __always_inline__)) f6() {}
+inline void __attribute__((visibility("hidden"), gnu_inline, __always_inline__)) f7() {}
+
+void g() {
+ f1();
+ f2();
+ f3();
+ f4();
+ f5();
+ f6();
+ f7();
+}
+
+void (*p)(void);
+void h() {
+ p = f1;
+ p = f2;
+ p = f3;
+ p = f4;
+ p = f5;
+ p = f6;
+ p = f7;
+}
+
+void (*const cp1)(void) = f1;
+void (*p1)(void) = f1;
+void (*p2)(int) = (void (*)(int))f1;
+
+void __attribute__((__always_inline__)) f8(void(*f)(void)) {}
+
+void call() {
+ f8(f1);
+}
+
+// CHECK-DAG: define internal void @f1.alwaysinline() #[[AI:[0-9]+]]
+// CHECK-DAG: define internal void @f2.alwaysinline() #[[AI_IH:[0-9]+]]
+// CHECK-DAG: define internal void @f3.alwaysinline() #[[AI_IH]]
+// CHECK-DAG: define internal void @f4.alwaysinline() #[[AI_IH]]
+// CHECK-DAG: define internal void @f5.alwaysinline() #[[AI_IH]]
+// CHECK-DAG: define internal void @f6.alwaysinline() #[[AI_IH]]
+// CHECK-DAG: define internal void @f7.alwaysinline() #[[AI_IH]]
+
+
+// CHECK-DAG: define void @f1() #[[NOAI:[01-9]+]]
+// CHECK-DAG: musttail call void @f1.alwaysinline()
+
+// CHECK-DAG: declare void @f2() #[[NOAI:[01-9]+]]
+
+// CHECK-DAG: define internal void @f3() #[[NOAI:[01-9]+]]
+// CHECK-DAG: musttail call void @f3.alwaysinline()
+
+// CHECK-DAG: define void @f4() #[[NOAI:[01-9]+]]
+// CHECK-DAG: musttail call void @f4.alwaysinline()
+
+// CHECK-DAG: define internal void @f5() #[[NOAI:[01-9]+]]
+// CHECK-DAG: musttail call void @f5.alwaysinline()
+
+// CHECK-DAG: declare hidden void @f6() #[[NOAI:[01-9]+]]
+
+// CHECK-DAG: define hidden void @f7() #[[NOAI:[01-9]+]]
+// CHECK-DAG: musttail call void @f7.alwaysinline()
+
+
+// CHECK-DAG: @cp1 = constant void ()* @f1, align
+// CHECK-DAG: @p1 = global void ()* @f1, align
+// CHECK-DAG: @p2 = global void (i32)* bitcast (void ()* @f1 to void (i32)*), align
+
+// CHECK: attributes #[[AI]] = {{.*alwaysinline.*}}
+// CHECK-INLINE: attributes #[[AI_IH]] = {{.*alwaysinline.*inlinehint.*}}
+// CHECK-NOT: attributes #[[NOAI]] = {{.*alwaysinline.*}}
+
+// CHECK-USE-LABEL: define void @g()
+// CHECK-USE-NOT: ret void
+// CHECK-USE: call void @f1.alwaysinline()
+// CHECK-USE-NEXT: call void @f2.alwaysinline()
+// CHECK-USE-NEXT: call void @f3.alwaysinline()
+// CHECK-USE-NEXT: call void @f4.alwaysinline()
+// CHECK-USE-NEXT: call void @f5.alwaysinline()
+// CHECK-USE-NEXT: call void @f6.alwaysinline()
+// CHECK-USE-NEXT: call void @f7.alwaysinline()
+// CHECK-USE-NEXT: ret void
+
+// CHECK-USE-LABEL: define void @h()
+// CHECK-USE-NOT: ret void
+// CHECK-USE: store void ()* @f1,
+// CHECK-USE-NEXT: store void ()* @f2,
+// CHECK-USE-NEXT: store void ()* @f3,
+// CHECK-USE-NEXT: store void ()* @f4,
+// CHECK-USE-NEXT: store void ()* @f5,
+// CHECK-USE-NEXT: store void ()* @f6,
+// CHECK-USE-NEXT: store void ()* @f7,
+// CHECK-USE-NEXT: ret void
+
+// CHECK-USE-LABEL: define void @call()
+// CHECK-USE: call void @f8.alwaysinline(void ()* @f1)
+// CHECK-USE: ret void
-// RUN: %clang -emit-llvm -S -o %t %s
-// RUN: not grep '@f0' %t
-// RUN: not grep 'call ' %t
-// RUN: %clang -mllvm -disable-llvm-optzns -emit-llvm -S -o %t %s
-// RUN: grep '@f0' %t | count 2
+// RUN: %clang -target x86_64-pc-linux-gnu -emit-llvm -S -o - %s | FileCheck %s
+// RUN: %clang -target x86_64-pc-linux-gnu -mllvm -disable-llvm-optzns -emit-llvm -S -o - %s | FileCheck %s --check-prefix=CHECK-NO-OPTZNS
//static int f0() {
static int __attribute__((always_inline)) f0() {
int f2() { return 7; }
int f3(void) { return f2(); }
+// CHECK-LABEL: define i32 @f1()
+// CHECK: ret i32 1
+// CHECK-LABEL: define i32 @f2()
+// CHECK: ret i32 7
+// CHECK-LABEL: define i32 @f3()
+// CHECK: ret i32 7
+
+// CHECK-NO-OPTZNS: define i32 @f3()
+// CHECK-NO-OPTZNS-NOT: ret i32
+// CHECK-NO-OPTZNS: call i32 @f2.alwaysinline()
+// CHECK-NO-OPTZNS-NEXT: ret i32
void f7(unsigned short x) { }
-// CHECK-LABEL: define void @f8()
-// CHECK: [[AI:#[0-9]+]]
+// CHECK: define void @f8()
+// CHECK: [[NUW:#[0-9]+]]
// CHECK: {
void __attribute__((always_inline)) f8(void) { }
}
// CHECK: attributes [[NUW]] = { nounwind optsize readnone{{.*}} }
-// CHECK: attributes [[AI]] = { alwaysinline nounwind optsize readnone{{.*}} }
// CHECK: attributes [[ALIGN]] = { nounwind optsize readnone alignstack=16{{.*}} }
// CHECK: attributes [[RT]] = { nounwind optsize returns_twice{{.*}} }
// CHECK: attributes [[NR]] = { noreturn nounwind optsize }
-// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK0
+// RUN: %clang_cc1 -triple x86_64-pc-linux -O1 -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK1
extern void foo_alias (void) __asm ("foo");
inline void foo (void) {
void f(void) {
foo();
- abs(0);
+ int x = abs(0);
strrchr_foo("", '.');
prefetch();
memchr("", '.', 0);
// CHECK-LABEL: define void @f()
// CHECK: call void @foo()
-// CHECK: call i32 @abs(i32 0)
+// CHECK: call i32 @abs(
// CHECK: call i8* @strrchr(
-// CHECK: call void @llvm.prefetch(
+// CHECK0: call void @llvm.prefetch(
+// CHECK1: call void @prefetch.alwaysinline(
// CHECK: call i8* @memchr(
// CHECK: ret void
--- /dev/null
+// Test different kinds of alwaysinline *structor definitions.
+
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-CALL
+
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -mconstructor-aliases -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -mconstructor-aliases -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-CALL
+
+struct A1 {
+ __attribute__((__always_inline__)) A1() {}
+ __attribute__((__always_inline__)) ~A1() {}
+};
+
+void g1() {
+ A1 a1;
+}
+
+struct A2 {
+ inline __attribute__((__always_inline__)) A2() {}
+ inline __attribute__((__always_inline__)) ~A2() {}
+};
+
+void g2() {
+ A2 a2;
+}
+
+struct A3 {
+ inline __attribute__((gnu_inline, __always_inline__)) A3() {}
+ inline __attribute__((gnu_inline, __always_inline__)) ~A3() {}
+};
+
+void g3() {
+ A3 a3;
+}
+
+// CHECK-DAG: define internal void @_ZN2A1C1Ev.alwaysinline(%struct.A1* %this) unnamed_addr #[[AI:[01-9]+]]
+// CHECK-DAG: define internal void @_ZN2A1C2Ev.alwaysinline(%struct.A1* %this) unnamed_addr #[[AI]]
+// CHECK-DAG: define internal void @_ZN2A1D1Ev.alwaysinline(%struct.A1* %this) unnamed_addr #[[AI]]
+// CHECK-DAG: define internal void @_ZN2A1D2Ev.alwaysinline(%struct.A1* %this) unnamed_addr #[[AI]]
+
+// CHECK-DAG: define internal void @_ZN2A2C1Ev.alwaysinline(%struct.A2* %this) unnamed_addr #[[AIIH:[01-9]+]]
+// CHECK-DAG: define internal void @_ZN2A2C2Ev.alwaysinline(%struct.A2* %this) unnamed_addr #[[AIIH]]
+// CHECK-DAG: define internal void @_ZN2A2D1Ev.alwaysinline(%struct.A2* %this) unnamed_addr #[[AIIH]]
+// CHECK-DAG: define internal void @_ZN2A2D2Ev.alwaysinline(%struct.A2* %this) unnamed_addr #[[AIIH]]
+
+// CHECK-DAG: define internal void @_ZN2A3C1Ev.alwaysinline(%struct.A3* %this) unnamed_addr #[[AIIH]]
+// CHECK-DAG: define internal void @_ZN2A3C2Ev.alwaysinline(%struct.A3* %this) unnamed_addr #[[AIIH]]
+// CHECK-DAG: define internal void @_ZN2A3D1Ev.alwaysinline(%struct.A3* %this) unnamed_addr #[[AIIH]]
+// CHECK-DAG: define internal void @_ZN2A3D2Ev.alwaysinline(%struct.A3* %this) unnamed_addr #[[AIIH]]
+
+// CHECK-DAG: attributes #[[AI]] = {{.*alwaysinline.*}}
+// CHECK-DAG: attributes #[[AIIH]] = {{.*alwaysinline.*inlinehint.*}}
+// CHECK-NOT: attributes #[[NOAI]] = {{.*alwaysinline.*}}
+
+// CHECK-CALL-LABEL: define void @_Z2g1v()
+// CHECK-CALL: call void @_ZN2A1C1Ev.alwaysinline
+// CHECK-CALL: call void @_ZN2A1D1Ev.alwaysinline
+// CHECK-CALL: ret void
+
+// CHECK-CALL-LABEL: define void @_Z2g2v()
+// CHECK-CALL: call void @_ZN2A2C1Ev.alwaysinline
+// CHECK-CALL: call void @_ZN2A2D1Ev.alwaysinline
+// CHECK-CALL: ret void
+
+// CHECK-CALL-LABEL: define void @_Z2g3v()
+// CHECK-CALL: call void @_ZN2A3C1Ev.alwaysinline
+// CHECK-CALL: call void @_ZN2A3D1Ev.alwaysinline
+// CHECK-CALL: ret void
// RUN: %clang_cc1 %s -Rpass=inline -gline-tables-only -dwarf-column-info -emit-llvm-only -verify
int foo(int x, int y) __attribute__((always_inline));
+// expected-remark@+1 {{foo.alwaysinline inlined into foo}}
int foo(int x, int y) { return x + y; }
-// expected-remark@+2 {{foo inlined into bar}} expected-note@+2 {{could not determine the original source location for /bad/path/to/original.c:1230:25}}
+// expected-remark@+2 {{foo.alwaysinline inlined into bar}} expected-note@+2 {{could not determine the original source location for /bad/path/to/original.c:1230:25}}
#line 1230 "/bad/path/to/original.c"
int bar(int j) { return foo(j, j - 2); }
// CHECK-NOT: !llvm.dbg.cu = !{
int foo(int x, int y) __attribute__((always_inline));
+// expected-remark@+2 {{foo.alwaysinline should always be inlined}}
+// expected-remark@+1 {{foo.alwaysinline inlined into foo}}
int foo(int x, int y) { return x + y; }
float foz(int x, int y) __attribute__((noinline));
// expected-remark@+5 {{foz will not be inlined into bar}}
// expected-remark@+4 {{foz should never be inlined}}
// expected-remark@+3 {{foz will not be inlined into bar}}
-// expected-remark@+2 {{foo should always be inlined}}
-// expected-remark@+1 {{foo inlined into bar}}
+// expected-remark@+2 {{foo.alwaysinline should always be inlined}}
+// expected-remark@+1 {{foo.alwaysinline inlined into bar}}
return foo(j, j - 2) * foz(j - 2, j);
}
};
}
-// CHECK-DAG: define available_externally hidden {{.*}}{{signext i32|i32}} @_ZN1SIiE1gEv({{.*}} #[[ALWAYS_INLINE:.*]] align
+// CHECK-DAG: define internal i32 @_ZN1SIiE1gEv.alwaysinline() #[[ALWAYS_INLINE:.*]] align
int a = S<int>::g();
int b = h();
// CHECK-DAG: define linkonce_odr {{.*}}{{signext i32|i32}} @_Z3minIiET_S0_S0_(i32
int c = min(1, 2);
-// CHECK: define available_externally {{.*}}{{signext i32|i32}} @_ZN1SIiE1fEv({{.*}} #[[ALWAYS_INLINE]] align
+// CHECK-DAG: define internal {{.*}}{{signext i32|i32}} @_ZN1SIiE1fEv.alwaysinline() #[[ALWAYS_INLINE]] align
namespace ImplicitSpecialMembers {
// CHECK-LABEL: define {{.*}} @_ZN22ImplicitSpecialMembers1BC2ERKS0_(