<div dir="ltr">Hi Evgeniy,<div><br></div><div>I commit a small change to one of the regression tests to allow a signext to be generated: <a href="http://reviews.llvm.org/rL247584">http://reviews.llvm.org/rL247584</a>.</div><div><br></div><div>It was causing an error in Power8 targets. In my view is an harmless change but you may want to take a look and see if that is fine by you.</div><div><br></div><div>Thanks!</div><div>Samuel</div>







</div><div class="gmail_extra"><br><div class="gmail_quote">2015-09-11 21:07 GMT-04:00 Evgeniy Stepanov via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: eugenis<br>
Date: Fri Sep 11 20:07:37 2015<br>
New Revision: 247494<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=247494&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=247494&view=rev</a><br>
Log:<br>
Always_inline codegen rewrite.<br>
<br>
Current implementation may end up emitting an undefined reference for<br>
an "inline __attribute__((always_inline))" function by generating an<br>
"available_externally alwaysinline" IR function for it and then failing to<br>
inline all the calls. This happens when a call to such function is in dead<br>
code. As the inliner is an SCC pass, it does not process dead code.<br>
<br>
Libc++ relies on the compiler never emitting such undefined reference.<br>
<br>
With this patch, we emit a pair of<br>
1. internal alwaysinline definition (called F.alwaysinline)<br>
2a. A stub F() { musttail call F.alwaysinline }<br>
  -- or, depending on the linkage --<br>
2b. A declaration of F.<br>
<br>
The frontend ensures that F.inlinefunction is only used for direct<br>
calls, and the stub is used for everything else (taking the address of<br>
the function, really). Declaration (2b) is emitted in the case when<br>
"inline" is meant for inlining only (like __gnu_inline__ and some<br>
other cases).<br>
<br>
This approach, among other nice properties, ensures that alwaysinline<br>
functions are always internal, making it impossible for a direct call<br>
to such function to produce an undefined symbol reference.<br>
<br>
This patch is based on ideas by Chandler Carruth and Richard Smith.<br>
<br>
Added:<br>
    cfe/trunk/test/CodeGen/always_inline-unused.c<br>
    cfe/trunk/test/CodeGen/always_inline-wrappers.c<br>
    cfe/trunk/test/CodeGenCXX/alwaysinline.cpp<br>
Modified:<br>
    cfe/trunk/lib/CodeGen/CGCXX.cpp<br>
    cfe/trunk/lib/CodeGen/CGClass.cpp<br>
    cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp<br>
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp<br>
    cfe/trunk/lib/CodeGen/CodeGenModule.h<br>
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp<br>
    cfe/trunk/test/CodeGen/always-inline.c<br>
    cfe/trunk/test/CodeGen/always_inline.c<br>
    cfe/trunk/test/CodeGen/function-attributes.c<br>
    cfe/trunk/test/CodeGen/pr9614.c<br>
    cfe/trunk/test/Frontend/optimization-remark-line-directive.c<br>
    cfe/trunk/test/Frontend/optimization-remark.c<br>
    cfe/trunk/test/Modules/cxx-irgen.cpp<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=247494&r1=247493&r2=247494&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=247494&r1=247493&r2=247494&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Fri Sep 11 20:07:37 2015<br>
@@ -109,6 +109,9 @@ bool CodeGenModule::TryEmitBaseDestructo<br>
       D->getType()->getAs<FunctionType>()->getCallConv())<br>
     return true;<br>
<br>
+  if (BaseD->hasAttr<AlwaysInlineAttr>())<br>
+    return true;<br>
+<br>
   return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),<br>
                                   GlobalDecl(BaseD, Dtor_Base),<br>
                                   false);<br>
@@ -161,14 +164,7 @@ bool CodeGenModule::TryEmitDefinitionAsA<br>
<br>
   // Instead of creating as alias to a linkonce_odr, replace all of the uses<br>
   // of the aliasee.<br>
-  if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) &&<br>
-     (TargetLinkage != llvm::GlobalValue::AvailableExternallyLinkage ||<br>
-      !TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>())) {<br>
-    // FIXME: An extern template instantiation will create functions with<br>
-    // linkage "AvailableExternally". In libc++, some classes also define<br>
-    // members with attribute "AlwaysInline" and expect no reference to<br>
-    // be generated. It is desirable to reenable this optimisation after<br>
-    // corresponding LLVM changes.<br>
+  if (llvm::GlobalValue::isDiscardableIfUnused(Linkage)) {<br>
     Replacements[MangledName] = Aliasee;<br>
     return false;<br>
   }<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGClass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=247494&r1=247493&r2=247494&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=247494&r1=247493&r2=247494&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Fri Sep 11 20:07:37 2015<br>
@@ -1557,7 +1557,7 @@ void CodeGenFunction::EmitDestructorBody<br>
     // -fapple-kext must inline any call to this dtor into<br>
     // the caller's body.<br>
     if (getLangOpts().AppleKext)<br>
-      CurFn->addFnAttr(llvm::Attribute::AlwaysInline);<br>
+      CGM.AddAlwaysInlineFunction(CurFn);<br>
<br>
     break;<br>
   }<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=247494&r1=247493&r2=247494&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=247494&r1=247493&r2=247494&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp Fri Sep 11 20:07:37 2015<br>
@@ -2114,7 +2114,7 @@ emitTaskPrivateMappingFunction(CodeGenMo<br>
       ".omp_task_privates_map.", &CGM.getModule());<br>
   CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, TaskPrivatesMapFnInfo,<br>
                                 TaskPrivatesMap);<br>
-  TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);<br>
+  CGM.AddAlwaysInlineFunction(TaskPrivatesMap);<br>
   CodeGenFunction CGF(CGM);<br>
   CGF.disableDebugInfo();<br>
   CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=247494&r1=247493&r2=247494&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=247494&r1=247493&r2=247494&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Fri Sep 11 20:07:37 2015<br>
@@ -448,6 +448,109 @@ void CodeGenModule::Release() {<br>
   EmitVersionIdentMetadata();<br>
<br>
   EmitTargetMetadata();<br>
+<br>
+  RewriteAlwaysInlineFunctions();<br>
+}<br>
+<br>
+void CodeGenModule::AddAlwaysInlineFunction(llvm::Function *Fn) {<br>
+  AlwaysInlineFunctions.push_back(Fn);<br>
+}<br>
+<br>
+/// Find all uses of GV that are not direct calls or invokes.<br>
+static void FindNonDirectCallUses(llvm::GlobalValue *GV,<br>
+                                  llvm::SmallVectorImpl<llvm::Use *> *Uses) {<br>
+  llvm::GlobalValue::use_iterator UI = GV->use_begin(), E = GV->use_end();<br>
+  for (; UI != E;) {<br>
+    llvm::Use &U = *UI;<br>
+    ++UI;<br>
+<br>
+    llvm::CallSite CS(U.getUser());<br>
+    bool isDirectCall = (CS.isCall() || CS.isInvoke()) && CS.isCallee(&U);<br>
+    if (!isDirectCall)<br>
+      Uses->push_back(&U);<br>
+  }<br>
+}<br>
+<br>
+/// Replace a list of uses.<br>
+static void ReplaceUsesWith(const llvm::SmallVectorImpl<llvm::Use *> &Uses,<br>
+                            llvm::GlobalValue *V,<br>
+                            llvm::GlobalValue *Replacement) {<br>
+  for (llvm::Use *U : Uses) {<br>
+    auto *C = dyn_cast<llvm::Constant>(U->getUser());<br>
+    if (C && !isa<llvm::GlobalValue>(C))<br>
+      C->handleOperandChange(V, Replacement, U);<br>
+    else<br>
+      U->set(Replacement);<br>
+  }<br>
+}<br>
+<br>
+void CodeGenModule::RewriteAlwaysInlineFunction(llvm::Function *Fn) {<br>
+  std::string Name = Fn->getName();<br>
+  std::string InlineName = Name + ".alwaysinline";<br>
+  Fn->setName(InlineName);<br>
+<br>
+  llvm::SmallVector<llvm::Use *, 8> NonDirectCallUses;<br>
+  Fn->removeDeadConstantUsers();<br>
+  FindNonDirectCallUses(Fn, &NonDirectCallUses);<br>
+  // Do not create the wrapper if there are no non-direct call uses, and we are<br>
+  // not required to emit an external definition.<br>
+  if (NonDirectCallUses.empty() && Fn->isDiscardableIfUnused())<br>
+    return;<br>
+<br>
+  llvm::FunctionType *FT = Fn->getFunctionType();<br>
+  llvm::LLVMContext &Ctx = getModule().getContext();<br>
+  llvm::Function *StubFn =<br>
+      llvm::Function::Create(FT, Fn->getLinkage(), Name, &getModule());<br>
+  assert(StubFn->getName() == Name && "name was uniqued!");<br>
+<br>
+  // Insert the stub immediately after the original function. Helps with the<br>
+  // fragile tests, among other things.<br>
+  StubFn->removeFromParent();<br>
+  TheModule.getFunctionList().insertAfter(Fn, StubFn);<br>
+<br>
+  StubFn->copyAttributesFrom(Fn);<br>
+  StubFn->setPersonalityFn(nullptr);<br>
+<br>
+  // AvailableExternally functions are replaced with a declaration.<br>
+  // Everyone else gets a wrapper that musttail-calls the original function.<br>
+  if (Fn->hasAvailableExternallyLinkage()) {<br>
+    StubFn->setLinkage(llvm::GlobalValue::ExternalLinkage);<br>
+  } else {<br>
+    llvm::BasicBlock *BB = llvm::BasicBlock::Create(Ctx, "entry", StubFn);<br>
+    std::vector<llvm::Value *> Args;<br>
+    for (llvm::Function::arg_iterator ai = StubFn->arg_begin();<br>
+         ai != StubFn->arg_end(); ++ai)<br>
+      Args.push_back(&*ai);<br>
+    llvm::CallInst *CI = llvm::CallInst::Create(Fn, Args, "", BB);<br>
+    CI->setCallingConv(Fn->getCallingConv());<br>
+    CI->setTailCallKind(llvm::CallInst::TCK_MustTail);<br>
+    CI->setAttributes(Fn->getAttributes());<br>
+    if (FT->getReturnType()->isVoidTy())<br>
+      llvm::ReturnInst::Create(Ctx, BB);<br>
+    else<br>
+      llvm::ReturnInst::Create(Ctx, CI, BB);<br>
+  }<br>
+<br>
+  if (Fn->hasComdat())<br>
+    StubFn->setComdat(Fn->getComdat());<br>
+<br>
+  ReplaceUsesWith(NonDirectCallUses, Fn, StubFn);<br>
+<br>
+  // Replace all metadata uses with the stub. This is primarily to reattach<br>
+  // DISubprogram metadata to the stub, because that's what will be emitted in<br>
+  // the object file.<br>
+  if (Fn->isUsedByMetadata())<br>
+    llvm::ValueAsMetadata::handleRAUW(Fn, StubFn);<br>
+}<br>
+<br>
+void CodeGenModule::RewriteAlwaysInlineFunctions() {<br>
+  for (llvm::Function *Fn : AlwaysInlineFunctions) {<br>
+    RewriteAlwaysInlineFunction(Fn);<br>
+    Fn->setLinkage(llvm::GlobalValue::InternalLinkage);<br>
+    Fn->addFnAttr(llvm::Attribute::AlwaysInline);<br>
+    Fn->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass);<br>
+    Fn->setVisibility(llvm::GlobalValue::DefaultVisibility);<br>
+  }<br>
 }<br>
<br>
 void CodeGenModule::UpdateCompletedType(const TagDecl *TD) {<br>
@@ -772,7 +875,7 @@ void CodeGenModule::SetLLVMFunctionAttri<br>
              !F->getAttributes().hasAttribute(llvm::AttributeSet::FunctionIndex,<br>
                                               llvm::Attribute::NoInline)) {<br>
     // (noinline wins over always_inline, and we can't specify both in IR)<br>
-    B.addAttribute(llvm::Attribute::AlwaysInline);<br>
+    AddAlwaysInlineFunction(F);<br>
   }<br>
<br>
   if (D->hasAttr<ColdAttr>()) {<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=247494&r1=247493&r2=247494&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=247494&r1=247493&r2=247494&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Fri Sep 11 20:07:37 2015<br>
@@ -489,6 +489,8 @@ private:<br>
   /// MDNodes.<br>
   llvm::DenseMap<QualType, llvm::Metadata *> MetadataIdMap;<br>
<br>
+  llvm::SmallVector<llvm::Function*, 8> AlwaysInlineFunctions;<br>
+<br>
 public:<br>
   CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts,<br>
                 const PreprocessorOptions &ppopts,<br>
@@ -1131,6 +1133,8 @@ public:<br>
   /// \breif Get the declaration of std::terminate for the platform.<br>
   llvm::Constant *getTerminateFn();<br>
<br>
+  void AddAlwaysInlineFunction(llvm::Function *Fn);<br>
+<br>
 private:<br>
   llvm::Constant *<br>
   GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty, GlobalDecl D,<br>
@@ -1226,6 +1230,12 @@ private:<br>
   /// Emits target specific Metadata for global declarations.<br>
   void EmitTargetMetadata();<br>
<br>
+  /// Replaces alwaysinline functions with a pair of internal xxx.inlinefunction<br>
+  /// for direct calls, and a stub for indirect calls, and rewrites all uses of<br>
+  /// those.<br>
+  void RewriteAlwaysInlineFunctions();<br>
+  void RewriteAlwaysInlineFunction(llvm::Function *Fn);<br>
+<br>
   /// Emit the llvm.gcov metadata used to tell LLVM where to emit the .gcno and<br>
   /// .gcda files in a way that persists in .bc files.<br>
   void EmitCoverageFile();<br>
<br>
Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=247494&r1=247493&r2=247494&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=247494&r1=247493&r2=247494&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Fri Sep 11 20:07:37 2015<br>
@@ -3311,6 +3311,9 @@ static StructorCodegen getCodegenToUse(C<br>
   if (MD->getParent()->getNumVBases())<br>
     return StructorCodegen::Emit;<br>
<br>
+  if (MD->hasAttr<AlwaysInlineAttr>())<br>
+    return StructorCodegen::Emit;<br>
+<br>
   GlobalDecl AliasDecl;<br>
   if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {<br>
     AliasDecl = GlobalDecl(DD, Dtor_Complete);<br>
<br>
Modified: cfe/trunk/test/CodeGen/always-inline.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/always-inline.c?rev=247494&r1=247493&r2=247494&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/always-inline.c?rev=247494&r1=247493&r2=247494&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGen/always-inline.c (original)<br>
+++ cfe/trunk/test/CodeGen/always-inline.c Fri Sep 11 20:07:37 2015<br>
@@ -1,7 +1,9 @@<br>
 // RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s<br>
 // RUN: %clang_cc1 -fno-inline -emit-llvm %s -o - | FileCheck %s<br>
<br>
+// CHECK-LABEL: define void @i_want_bar()<br>
 // CHECK-NOT: foo<br>
+// CHECK: ret void<br>
<br>
 void bar() {<br>
 }<br>
<br>
Added: cfe/trunk/test/CodeGen/always_inline-unused.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/always_inline-unused.c?rev=247494&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/always_inline-unused.c?rev=247494&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGen/always_inline-unused.c (added)<br>
+++ cfe/trunk/test/CodeGen/always_inline-unused.c Fri Sep 11 20:07:37 2015<br>
@@ -0,0 +1,31 @@<br>
+// Test alwaysinline definitions w/o any non-direct-call uses.<br>
+// None of the declarations are emitted. Stub are only emitted when the original<br>
+// function can not be discarded.<br>
+<br>
+// RUN: %clang_cc1 -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s<br>
+<br>
+void __attribute__((__always_inline__)) f1() {}<br>
+inline void __attribute__((__always_inline__)) f2() {}<br>
+static inline void __attribute__((__always_inline__)) f3() {}<br>
+inline void __attribute__((gnu_inline, __always_inline__)) f4() {}<br>
+static inline void __attribute__((gnu_inline, __always_inline__)) f5() {}<br>
+inline void __attribute__((visibility("hidden"), __always_inline__)) f6() {}<br>
+inline void __attribute__((visibility("hidden"), gnu_inline, __always_inline__)) f7() {}<br>
+<br>
+void g() {<br>
+  f1();<br>
+  f2();<br>
+  f3();<br>
+  f4();<br>
+  f5();<br>
+  f6();<br>
+  f7();<br>
+}<br>
+<br>
+// CHECK: define void @f1()<br>
+// CHECK-NOT: void @f2()<br>
+// CHECK-NOT: void @f3()<br>
+// CHECK: define void @f4()<br>
+// CHECK-NOT: void @f5()<br>
+// CHECK-NOT: void @f6()<br>
+// CHECK: define hidden void @f7()<br>
<br>
Added: cfe/trunk/test/CodeGen/always_inline-wrappers.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/always_inline-wrappers.c?rev=247494&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/always_inline-wrappers.c?rev=247494&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGen/always_inline-wrappers.c (added)<br>
+++ cfe/trunk/test/CodeGen/always_inline-wrappers.c Fri Sep 11 20:07:37 2015<br>
@@ -0,0 +1,108 @@<br>
+// Test different kinds of alwaysinline definitions.<br>
+<br>
+// RUN: %clang_cc1 -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-INLINE<br>
+// RUN: %clang_cc1 -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-USE<br>
+// RUN: %clang_cc1 -disable-llvm-optzns -fno-inline -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK<br>
+// RUN: %clang_cc1 -disable-llvm-optzns -fno-inline -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-USE<br>
+<br>
+void __attribute__((__always_inline__)) f1() {}<br>
+inline void __attribute__((__always_inline__)) f2() {}<br>
+static inline void __attribute__((__always_inline__)) f3() {}<br>
+inline void __attribute__((gnu_inline, __always_inline__)) f4() {}<br>
+static inline void __attribute__((gnu_inline, __always_inline__)) f5() {}<br>
+inline void __attribute__((visibility("hidden"), __always_inline__)) f6() {}<br>
+inline void __attribute__((visibility("hidden"), gnu_inline, __always_inline__)) f7() {}<br>
+<br>
+void g() {<br>
+  f1();<br>
+  f2();<br>
+  f3();<br>
+  f4();<br>
+  f5();<br>
+  f6();<br>
+  f7();<br>
+}<br>
+<br>
+void (*p)(void);<br>
+void h() {<br>
+  p = f1;<br>
+  p = f2;<br>
+  p = f3;<br>
+  p = f4;<br>
+  p = f5;<br>
+  p = f6;<br>
+  p = f7;<br>
+}<br>
+<br>
+void (*const cp1)(void) = f1;<br>
+void (*p1)(void) = f1;<br>
+void (*p2)(int) = (void (*)(int))f1;<br>
+<br>
+void __attribute__((__always_inline__)) f8(void(*f)(void)) {}<br>
+<br>
+void call() {<br>
+  f8(f1);<br>
+}<br>
+<br>
+// CHECK-DAG: define internal void @f1.alwaysinline() #[[AI:[0-9]+]]<br>
+// CHECK-DAG: define internal void @f2.alwaysinline() #[[AI_IH:[0-9]+]]<br>
+// CHECK-DAG: define internal void @f3.alwaysinline() #[[AI_IH]]<br>
+// CHECK-DAG: define internal void @f4.alwaysinline() #[[AI_IH]]<br>
+// CHECK-DAG: define internal void @f5.alwaysinline() #[[AI_IH]]<br>
+// CHECK-DAG: define internal void @f6.alwaysinline() #[[AI_IH]]<br>
+// CHECK-DAG: define internal void @f7.alwaysinline() #[[AI_IH]]<br>
+<br>
+<br>
+// CHECK-DAG: define void @f1() #[[NOAI:[01-9]+]]<br>
+// CHECK-DAG: musttail call void @f1.alwaysinline()<br>
+<br>
+// CHECK-DAG: declare void @f2() #[[NOAI:[01-9]+]]<br>
+<br>
+// CHECK-DAG: define internal void @f3() #[[NOAI:[01-9]+]]<br>
+// CHECK-DAG: musttail call void @f3.alwaysinline()<br>
+<br>
+// CHECK-DAG: define void @f4() #[[NOAI:[01-9]+]]<br>
+// CHECK-DAG: musttail call void @f4.alwaysinline()<br>
+<br>
+// CHECK-DAG: define internal void @f5() #[[NOAI:[01-9]+]]<br>
+// CHECK-DAG: musttail call void @f5.alwaysinline()<br>
+<br>
+// CHECK-DAG: declare hidden void @f6() #[[NOAI:[01-9]+]]<br>
+<br>
+// CHECK-DAG: define hidden void @f7() #[[NOAI:[01-9]+]]<br>
+// CHECK-DAG: musttail call void @f7.alwaysinline()<br>
+<br>
+<br>
+// CHECK-DAG: @cp1 = constant void ()* @f1, align<br>
+// CHECK-DAG: @p1 = global void ()* @f1, align<br>
+// CHECK-DAG: @p2 = global void (i32)* bitcast (void ()* @f1 to void (i32)*), align<br>
+<br>
+// CHECK: attributes #[[AI]] = {{.*alwaysinline.*}}<br>
+// CHECK-INLINE: attributes #[[AI_IH]] = {{.*alwaysinline.*inlinehint.*}}<br>
+// CHECK-NOT: attributes #[[NOAI]] = {{.*alwaysinline.*}}<br>
+<br>
+// CHECK-USE-LABEL: define void @g()<br>
+// CHECK-USE-NOT:      ret void<br>
+// CHECK-USE:          call void @f1.alwaysinline()<br>
+// CHECK-USE-NEXT:     call void @f2.alwaysinline()<br>
+// CHECK-USE-NEXT:     call void @f3.alwaysinline()<br>
+// CHECK-USE-NEXT:     call void @f4.alwaysinline()<br>
+// CHECK-USE-NEXT:     call void @f5.alwaysinline()<br>
+// CHECK-USE-NEXT:     call void @f6.alwaysinline()<br>
+// CHECK-USE-NEXT:     call void @f7.alwaysinline()<br>
+// CHECK-USE-NEXT:     ret void<br>
+<br>
+// CHECK-USE-LABEL: define void @h()<br>
+// CHECK-USE-NOT:      ret void<br>
+// CHECK-USE:          store void ()* @f1,<br>
+// CHECK-USE-NEXT:     store void ()* @f2,<br>
+// CHECK-USE-NEXT:     store void ()* @f3,<br>
+// CHECK-USE-NEXT:     store void ()* @f4,<br>
+// CHECK-USE-NEXT:     store void ()* @f5,<br>
+// CHECK-USE-NEXT:     store void ()* @f6,<br>
+// CHECK-USE-NEXT:     store void ()* @f7,<br>
+// CHECK-USE-NEXT:     ret void<br>
+<br>
+// CHECK-USE-LABEL:  define void @call()<br>
+// CHECK-USE:           call void @f8.alwaysinline(void ()* @f1)<br>
+// CHECK-USE:           ret void<br>
<br>
Modified: cfe/trunk/test/CodeGen/always_inline.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/always_inline.c?rev=247494&r1=247493&r2=247494&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/always_inline.c?rev=247494&r1=247493&r2=247494&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGen/always_inline.c (original)<br>
+++ cfe/trunk/test/CodeGen/always_inline.c Fri Sep 11 20:07:37 2015<br>
@@ -1,8 +1,5 @@<br>
-// RUN: %clang -emit-llvm -S -o %t %s<br>
-// RUN: not grep '@f0' %t<br>
-// RUN: not grep 'call ' %t<br>
-// RUN: %clang -mllvm -disable-llvm-optzns -emit-llvm -S -o %t %s<br>
-// RUN: grep '@f0' %t | count 2<br>
+// RUN: %clang -target x86_64-pc-linux-gnu -emit-llvm -S -o - %s | FileCheck %s<br>
+// RUN: %clang -target x86_64-pc-linux-gnu -mllvm -disable-llvm-optzns -emit-llvm -S -o - %s | FileCheck %s --check-prefix=CHECK-NO-OPTZNS<br>
<br>
 //static int f0() {<br>
 static int __attribute__((always_inline)) f0() {<br>
@@ -18,3 +15,14 @@ inline int f2() __attribute__((always_in<br>
 int f2() { return 7; }<br>
 int f3(void) { return f2(); }<br>
<br>
+// CHECK-LABEL: define i32 @f1()<br>
+// CHECK: ret i32 1<br>
+// CHECK-LABEL: define i32 @f2()<br>
+// CHECK: ret i32 7<br>
+// CHECK-LABEL: define i32 @f3()<br>
+// CHECK: ret i32 7<br>
+<br>
+// CHECK-NO-OPTZNS: define i32 @f3()<br>
+// CHECK-NO-OPTZNS-NOT: ret i32<br>
+// CHECK-NO-OPTZNS:   call i32 @f2.alwaysinline()<br>
+// CHECK-NO-OPTZNS-NEXT:   ret i32<br>
<br>
Modified: cfe/trunk/test/CodeGen/function-attributes.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/function-attributes.c?rev=247494&r1=247493&r2=247494&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/function-attributes.c?rev=247494&r1=247493&r2=247494&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGen/function-attributes.c (original)<br>
+++ cfe/trunk/test/CodeGen/function-attributes.c Fri Sep 11 20:07:37 2015<br>
@@ -25,8 +25,8 @@ void f6(signed short x) { }<br>
<br>
 void f7(unsigned short x) { }<br>
<br>
-// CHECK-LABEL: define void @f8()<br>
-// CHECK: [[AI:#[0-9]+]]<br>
+// CHECK: define void @f8()<br>
+// CHECK: [[NUW:#[0-9]+]]<br>
 // CHECK: {<br>
 void __attribute__((always_inline)) f8(void) { }<br>
<br>
@@ -129,7 +129,6 @@ void f20(void) {<br>
 }<br>
<br>
 // CHECK: attributes [[NUW]] = { nounwind optsize readnone{{.*}} }<br>
-// CHECK: attributes [[AI]] = { alwaysinline nounwind optsize readnone{{.*}} }<br>
 // CHECK: attributes [[ALIGN]] = { nounwind optsize readnone alignstack=16{{.*}} }<br>
 // CHECK: attributes [[RT]] = { nounwind optsize returns_twice{{.*}} }<br>
 // CHECK: attributes [[NR]] = { noreturn nounwind optsize }<br>
<br>
Modified: cfe/trunk/test/CodeGen/pr9614.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/pr9614.c?rev=247494&r1=247493&r2=247494&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/pr9614.c?rev=247494&r1=247493&r2=247494&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGen/pr9614.c (original)<br>
+++ cfe/trunk/test/CodeGen/pr9614.c Fri Sep 11 20:07:37 2015<br>
@@ -1,4 +1,5 @@<br>
-// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm %s -o - | FileCheck %s<br>
+// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK0<br>
+// RUN: %clang_cc1 -triple x86_64-pc-linux -O1 -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK1<br>
<br>
 extern void foo_alias (void) __asm ("foo");<br>
 inline void foo (void) {<br>
@@ -24,7 +25,7 @@ extern inline __attribute__((__always_in<br>
<br>
 void f(void) {<br>
   foo();<br>
-  abs(0);<br>
+  int x = abs(0);<br>
   strrchr_foo("", '.');<br>
   prefetch();<br>
   memchr("", '.', 0);<br>
@@ -32,9 +33,10 @@ void f(void) {<br>
<br>
 // CHECK-LABEL: define void @f()<br>
 // CHECK: call void @foo()<br>
-// CHECK: call i32 @abs(i32 0)<br>
+// CHECK: call i32 @abs(<br>
 // CHECK: call i8* @strrchr(<br>
-// CHECK: call void @llvm.prefetch(<br>
+// CHECK0: call void @llvm.prefetch(<br>
+// CHECK1: call void @prefetch.alwaysinline(<br>
 // CHECK: call i8* @memchr(<br>
 // CHECK: ret void<br>
<br>
<br>
Added: cfe/trunk/test/CodeGenCXX/alwaysinline.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/alwaysinline.cpp?rev=247494&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/alwaysinline.cpp?rev=247494&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/alwaysinline.cpp (added)<br>
+++ cfe/trunk/test/CodeGenCXX/alwaysinline.cpp Fri Sep 11 20:07:37 2015<br>
@@ -0,0 +1,68 @@<br>
+// Test different kinds of alwaysinline *structor definitions.<br>
+<br>
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK<br>
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-CALL<br>
+<br>
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -mconstructor-aliases -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK<br>
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -mconstructor-aliases -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-CALL<br>
+<br>
+struct A1 {<br>
+  __attribute__((__always_inline__)) A1() {}<br>
+  __attribute__((__always_inline__)) ~A1() {}<br>
+};<br>
+<br>
+void g1() {<br>
+  A1 a1;<br>
+}<br>
+<br>
+struct A2 {<br>
+  inline __attribute__((__always_inline__)) A2() {}<br>
+  inline __attribute__((__always_inline__)) ~A2() {}<br>
+};<br>
+<br>
+void g2() {<br>
+  A2 a2;<br>
+}<br>
+<br>
+struct A3 {<br>
+  inline __attribute__((gnu_inline, __always_inline__)) A3() {}<br>
+  inline __attribute__((gnu_inline, __always_inline__)) ~A3() {}<br>
+};<br>
+<br>
+void g3() {<br>
+  A3 a3;<br>
+}<br>
+<br>
+// CHECK-DAG: define internal void @_ZN2A1C1Ev.alwaysinline(%struct.A1* %this) unnamed_addr #[[AI:[01-9]+]]<br>
+// CHECK-DAG: define internal void @_ZN2A1C2Ev.alwaysinline(%struct.A1* %this) unnamed_addr #[[AI]]<br>
+// CHECK-DAG: define internal void @_ZN2A1D1Ev.alwaysinline(%struct.A1* %this) unnamed_addr #[[AI]]<br>
+// CHECK-DAG: define internal void @_ZN2A1D2Ev.alwaysinline(%struct.A1* %this) unnamed_addr #[[AI]]<br>
+<br>
+// CHECK-DAG: define internal void @_ZN2A2C1Ev.alwaysinline(%struct.A2* %this) unnamed_addr #[[AIIH:[01-9]+]]<br>
+// CHECK-DAG: define internal void @_ZN2A2C2Ev.alwaysinline(%struct.A2* %this) unnamed_addr #[[AIIH]]<br>
+// CHECK-DAG: define internal void @_ZN2A2D1Ev.alwaysinline(%struct.A2* %this) unnamed_addr #[[AIIH]]<br>
+// CHECK-DAG: define internal void @_ZN2A2D2Ev.alwaysinline(%struct.A2* %this) unnamed_addr #[[AIIH]]<br>
+<br>
+// CHECK-DAG: define internal void @_ZN2A3C1Ev.alwaysinline(%struct.A3* %this) unnamed_addr #[[AIIH]]<br>
+// CHECK-DAG: define internal void @_ZN2A3C2Ev.alwaysinline(%struct.A3* %this) unnamed_addr #[[AIIH]]<br>
+// CHECK-DAG: define internal void @_ZN2A3D1Ev.alwaysinline(%struct.A3* %this) unnamed_addr #[[AIIH]]<br>
+// CHECK-DAG: define internal void @_ZN2A3D2Ev.alwaysinline(%struct.A3* %this) unnamed_addr #[[AIIH]]<br>
+<br>
+// CHECK-DAG: attributes #[[AI]] = {{.*alwaysinline.*}}<br>
+// CHECK-DAG: attributes #[[AIIH]] = {{.*alwaysinline.*inlinehint.*}}<br>
+// CHECK-NOT: attributes #[[NOAI]] = {{.*alwaysinline.*}}<br>
+<br>
+// CHECK-CALL-LABEL: define void @_Z2g1v()<br>
+// CHECK-CALL:       call void @_ZN2A1C1Ev.alwaysinline<br>
+// CHECK-CALL:       call void @_ZN2A1D1Ev.alwaysinline<br>
+// CHECK-CALL:       ret void<br>
+<br>
+// CHECK-CALL-LABEL: define void @_Z2g2v()<br>
+// CHECK-CALL:       call void @_ZN2A2C1Ev.alwaysinline<br>
+// CHECK-CALL:       call void @_ZN2A2D1Ev.alwaysinline<br>
+// CHECK-CALL:       ret void<br>
+<br>
+// CHECK-CALL-LABEL: define void @_Z2g3v()<br>
+// CHECK-CALL:       call void @_ZN2A3C1Ev.alwaysinline<br>
+// CHECK-CALL:       call void @_ZN2A3D1Ev.alwaysinline<br>
+// CHECK-CALL:       ret void<br>
<br>
Modified: cfe/trunk/test/Frontend/optimization-remark-line-directive.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/optimization-remark-line-directive.c?rev=247494&r1=247493&r2=247494&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/optimization-remark-line-directive.c?rev=247494&r1=247493&r2=247494&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Frontend/optimization-remark-line-directive.c (original)<br>
+++ cfe/trunk/test/Frontend/optimization-remark-line-directive.c Fri Sep 11 20:07:37 2015<br>
@@ -5,8 +5,9 @@<br>
 // RUN: %clang_cc1 %s -Rpass=inline -gline-tables-only -dwarf-column-info -emit-llvm-only -verify<br>
<br>
 int foo(int x, int y) __attribute__((always_inline));<br>
+// expected-remark@+1 {{foo.alwaysinline inlined into foo}}<br>
 int foo(int x, int y) { return x + y; }<br>
<br>
-// 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}}<br>
+// 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}}<br>
 #line 1230 "/bad/path/to/original.c"<br>
 int bar(int j) { return foo(j, j - 2); }<br>
<br>
Modified: cfe/trunk/test/Frontend/optimization-remark.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/optimization-remark.c?rev=247494&r1=247493&r2=247494&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/optimization-remark.c?rev=247494&r1=247493&r2=247494&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Frontend/optimization-remark.c (original)<br>
+++ cfe/trunk/test/Frontend/optimization-remark.c Fri Sep 11 20:07:37 2015<br>
@@ -32,6 +32,8 @@<br>
 // CHECK-NOT: !<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{<br>
<br>
 int foo(int x, int y) __attribute__((always_inline));<br>
+// expected-remark@+2 {{foo.alwaysinline should always be inlined}}<br>
+// expected-remark@+1 {{foo.alwaysinline inlined into foo}}<br>
 int foo(int x, int y) { return x + y; }<br>
<br>
 float foz(int x, int y) __attribute__((noinline));<br>
@@ -45,7 +47,7 @@ int bar(int j) {<br>
 // expected-remark@+5 {{foz will not be inlined into bar}}<br>
 // expected-remark@+4 {{foz should never be inlined}}<br>
 // expected-remark@+3 {{foz will not be inlined into bar}}<br>
-// expected-remark@+2 {{foo should always be inlined}}<br>
-// expected-remark@+1 {{foo inlined into bar}}<br>
+// expected-remark@+2 {{foo.alwaysinline should always be inlined}}<br>
+// expected-remark@+1 {{foo.alwaysinline inlined into bar}}<br>
   return foo(j, j - 2) * foz(j - 2, j);<br>
 }<br>
<br>
Modified: cfe/trunk/test/Modules/cxx-irgen.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/cxx-irgen.cpp?rev=247494&r1=247493&r2=247494&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/cxx-irgen.cpp?rev=247494&r1=247493&r2=247494&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/cxx-irgen.cpp (original)<br>
+++ cfe/trunk/test/Modules/cxx-irgen.cpp Fri Sep 11 20:07:37 2015<br>
@@ -26,14 +26,14 @@ namespace EmitInlineMethods {<br>
   };<br>
 }<br>
<br>
-// CHECK-DAG: define available_externally hidden {{.*}}{{signext i32|i32}} @_ZN1SIiE1gEv({{.*}} #[[ALWAYS_INLINE:.*]] align<br>
+// CHECK-DAG: define internal i32 @_ZN1SIiE1gEv.alwaysinline() #[[ALWAYS_INLINE:.*]] align<br>
 int a = S<int>::g();<br>
<br>
 int b = h();<br>
<br>
 // CHECK-DAG: define linkonce_odr {{.*}}{{signext i32|i32}} @_Z3minIiET_S0_S0_(i32<br>
 int c = min(1, 2);<br>
-// CHECK: define available_externally {{.*}}{{signext i32|i32}} @_ZN1SIiE1fEv({{.*}} #[[ALWAYS_INLINE]] align<br>
+// CHECK-DAG: define internal {{.*}}{{signext i32|i32}} @_ZN1SIiE1fEv.alwaysinline() #[[ALWAYS_INLINE]] align<br>
<br>
 namespace ImplicitSpecialMembers {<br>
   // CHECK-LABEL: define {{.*}} @_ZN22ImplicitSpecialMembers1BC2ERKS0_(<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>