r247494 - Always_inline codegen rewrite.

Evgenii Stepanov via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 14 12:01:16 PDT 2015


Thanks!

On Mon, Sep 14, 2015 at 10:50 AM, Samuel F Antao <sfantao at us.ibm.com> wrote:
> Hi Evgeniy,
>
> I commit a small change to one of the regression tests to allow a signext to
> be generated: http://reviews.llvm.org/rL247584.
>
> 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.
>
> Thanks!
> Samuel
>
> 2015-09-11 21:07 GMT-04:00 Evgeniy Stepanov via cfe-commits
> <cfe-commits at lists.llvm.org>:
>>
>> Author: eugenis
>> Date: Fri Sep 11 20:07:37 2015
>> New Revision: 247494
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=247494&view=rev
>> Log:
>> Always_inline codegen rewrite.
>>
>> Current implementation may end up emitting an undefined reference for
>> an "inline __attribute__((always_inline))" function by generating an
>> "available_externally alwaysinline" IR function for it and then failing to
>> inline all the calls. This happens when a call to such function is in dead
>> code. As the inliner is an SCC pass, it does not process dead code.
>>
>> Libc++ relies on the compiler never emitting such undefined reference.
>>
>> With this patch, we emit a pair of
>> 1. internal alwaysinline definition (called F.alwaysinline)
>> 2a. A stub F() { musttail call F.alwaysinline }
>>   -- or, depending on the linkage --
>> 2b. A declaration of F.
>>
>> The frontend ensures that F.inlinefunction is only used for direct
>> calls, and the stub is used for everything else (taking the address of
>> the function, really). Declaration (2b) is emitted in the case when
>> "inline" is meant for inlining only (like __gnu_inline__ and some
>> other cases).
>>
>> This approach, among other nice properties, ensures that alwaysinline
>> functions are always internal, making it impossible for a direct call
>> to such function to produce an undefined symbol reference.
>>
>> This patch is based on ideas by Chandler Carruth and Richard Smith.
>>
>> Added:
>>     cfe/trunk/test/CodeGen/always_inline-unused.c
>>     cfe/trunk/test/CodeGen/always_inline-wrappers.c
>>     cfe/trunk/test/CodeGenCXX/alwaysinline.cpp
>> Modified:
>>     cfe/trunk/lib/CodeGen/CGCXX.cpp
>>     cfe/trunk/lib/CodeGen/CGClass.cpp
>>     cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
>>     cfe/trunk/lib/CodeGen/CodeGenModule.cpp
>>     cfe/trunk/lib/CodeGen/CodeGenModule.h
>>     cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
>>     cfe/trunk/test/CodeGen/always-inline.c
>>     cfe/trunk/test/CodeGen/always_inline.c
>>     cfe/trunk/test/CodeGen/function-attributes.c
>>     cfe/trunk/test/CodeGen/pr9614.c
>>     cfe/trunk/test/Frontend/optimization-remark-line-directive.c
>>     cfe/trunk/test/Frontend/optimization-remark.c
>>     cfe/trunk/test/Modules/cxx-irgen.cpp
>>
>> Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=247494&r1=247493&r2=247494&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CGCXX.cpp Fri Sep 11 20:07:37 2015
>> @@ -109,6 +109,9 @@ bool CodeGenModule::TryEmitBaseDestructo
>>        D->getType()->getAs<FunctionType>()->getCallConv())
>>      return true;
>>
>> +  if (BaseD->hasAttr<AlwaysInlineAttr>())
>> +    return true;
>> +
>>    return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),
>>                                    GlobalDecl(BaseD, Dtor_Base),
>>                                    false);
>> @@ -161,14 +164,7 @@ bool CodeGenModule::TryEmitDefinitionAsA
>>
>>    // 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;
>>    }
>>
>> Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=247494&r1=247493&r2=247494&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CGClass.cpp Fri Sep 11 20:07:37 2015
>> @@ -1557,7 +1557,7 @@ void CodeGenFunction::EmitDestructorBody
>>      // -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;
>>    }
>>
>> Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=247494&r1=247493&r2=247494&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp Fri Sep 11 20:07:37 2015
>> @@ -2114,7 +2114,7 @@ emitTaskPrivateMappingFunction(CodeGenMo
>>        ".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,
>>
>> Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=247494&r1=247493&r2=247494&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Fri Sep 11 20:07:37 2015
>> @@ -448,6 +448,109 @@ void CodeGenModule::Release() {
>>    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) {
>> @@ -772,7 +875,7 @@ void CodeGenModule::SetLLVMFunctionAttri
>>
>> !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>()) {
>>
>> Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=247494&r1=247493&r2=247494&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
>> +++ cfe/trunk/lib/CodeGen/CodeGenModule.h Fri Sep 11 20:07:37 2015
>> @@ -489,6 +489,8 @@ private:
>>    /// MDNodes.
>>    llvm::DenseMap<QualType, llvm::Metadata *> MetadataIdMap;
>>
>> +  llvm::SmallVector<llvm::Function*, 8> AlwaysInlineFunctions;
>> +
>>  public:
>>    CodeGenModule(ASTContext &C, const HeaderSearchOptions
>> &headersearchopts,
>>                  const PreprocessorOptions &ppopts,
>> @@ -1131,6 +1133,8 @@ public:
>>    /// \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,
>> @@ -1226,6 +1230,12 @@ private:
>>    /// 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();
>>
>> Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=247494&r1=247493&r2=247494&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Fri Sep 11 20:07:37 2015
>> @@ -3311,6 +3311,9 @@ static StructorCodegen getCodegenToUse(C
>>    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);
>>
>> Modified: cfe/trunk/test/CodeGen/always-inline.c
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/always-inline.c?rev=247494&r1=247493&r2=247494&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/test/CodeGen/always-inline.c (original)
>> +++ cfe/trunk/test/CodeGen/always-inline.c Fri Sep 11 20:07:37 2015
>> @@ -1,7 +1,9 @@
>>  // 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() {
>>  }
>>
>> Added: cfe/trunk/test/CodeGen/always_inline-unused.c
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/always_inline-unused.c?rev=247494&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/test/CodeGen/always_inline-unused.c (added)
>> +++ cfe/trunk/test/CodeGen/always_inline-unused.c Fri Sep 11 20:07:37 2015
>> @@ -0,0 +1,31 @@
>> +// 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()
>>
>> Added: cfe/trunk/test/CodeGen/always_inline-wrappers.c
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/always_inline-wrappers.c?rev=247494&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/test/CodeGen/always_inline-wrappers.c (added)
>> +++ cfe/trunk/test/CodeGen/always_inline-wrappers.c Fri Sep 11 20:07:37
>> 2015
>> @@ -0,0 +1,108 @@
>> +// 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
>>
>> Modified: cfe/trunk/test/CodeGen/always_inline.c
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/always_inline.c?rev=247494&r1=247493&r2=247494&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/test/CodeGen/always_inline.c (original)
>> +++ cfe/trunk/test/CodeGen/always_inline.c Fri Sep 11 20:07:37 2015
>> @@ -1,8 +1,5 @@
>> -// 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() {
>> @@ -18,3 +15,14 @@ inline int f2() __attribute__((always_in
>>  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
>>
>> Modified: cfe/trunk/test/CodeGen/function-attributes.c
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/function-attributes.c?rev=247494&r1=247493&r2=247494&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/test/CodeGen/function-attributes.c (original)
>> +++ cfe/trunk/test/CodeGen/function-attributes.c Fri Sep 11 20:07:37 2015
>> @@ -25,8 +25,8 @@ void f6(signed short x) { }
>>
>>  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) { }
>>
>> @@ -129,7 +129,6 @@ void f20(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 }
>>
>> Modified: cfe/trunk/test/CodeGen/pr9614.c
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/pr9614.c?rev=247494&r1=247493&r2=247494&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/test/CodeGen/pr9614.c (original)
>> +++ cfe/trunk/test/CodeGen/pr9614.c Fri Sep 11 20:07:37 2015
>> @@ -1,4 +1,5 @@
>> -// 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) {
>> @@ -24,7 +25,7 @@ extern inline __attribute__((__always_in
>>
>>  void f(void) {
>>    foo();
>> -  abs(0);
>> +  int x = abs(0);
>>    strrchr_foo("", '.');
>>    prefetch();
>>    memchr("", '.', 0);
>> @@ -32,9 +33,10 @@ void f(void) {
>>
>>  // 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
>>
>>
>> Added: cfe/trunk/test/CodeGenCXX/alwaysinline.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/alwaysinline.cpp?rev=247494&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/test/CodeGenCXX/alwaysinline.cpp (added)
>> +++ cfe/trunk/test/CodeGenCXX/alwaysinline.cpp Fri Sep 11 20:07:37 2015
>> @@ -0,0 +1,68 @@
>> +// 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
>>
>> Modified: cfe/trunk/test/Frontend/optimization-remark-line-directive.c
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/optimization-remark-line-directive.c?rev=247494&r1=247493&r2=247494&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/test/Frontend/optimization-remark-line-directive.c
>> (original)
>> +++ cfe/trunk/test/Frontend/optimization-remark-line-directive.c Fri Sep
>> 11 20:07:37 2015
>> @@ -5,8 +5,9 @@
>>  // 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 at +1 {{foo.alwaysinline inlined into foo}}
>>  int foo(int x, int y) { return x + y; }
>>
>> -// expected-remark at +2 {{foo inlined into bar}} expected-note at +2 {{could
>> not determine the original source location for
>> /bad/path/to/original.c:1230:25}}
>> +// expected-remark at +2 {{foo.alwaysinline inlined into bar}}
>> expected-note at +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); }
>>
>> Modified: cfe/trunk/test/Frontend/optimization-remark.c
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/optimization-remark.c?rev=247494&r1=247493&r2=247494&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/test/Frontend/optimization-remark.c (original)
>> +++ cfe/trunk/test/Frontend/optimization-remark.c Fri Sep 11 20:07:37 2015
>> @@ -32,6 +32,8 @@
>>  // CHECK-NOT: !llvm.dbg.cu = !{
>>
>>  int foo(int x, int y) __attribute__((always_inline));
>> +// expected-remark at +2 {{foo.alwaysinline should always be inlined}}
>> +// expected-remark at +1 {{foo.alwaysinline inlined into foo}}
>>  int foo(int x, int y) { return x + y; }
>>
>>  float foz(int x, int y) __attribute__((noinline));
>> @@ -45,7 +47,7 @@ int bar(int j) {
>>  // expected-remark at +5 {{foz will not be inlined into bar}}
>>  // expected-remark at +4 {{foz should never be inlined}}
>>  // expected-remark at +3 {{foz will not be inlined into bar}}
>> -// expected-remark at +2 {{foo should always be inlined}}
>> -// expected-remark at +1 {{foo inlined into bar}}
>> +// expected-remark at +2 {{foo.alwaysinline should always be inlined}}
>> +// expected-remark at +1 {{foo.alwaysinline inlined into bar}}
>>    return foo(j, j - 2) * foz(j - 2, j);
>>  }
>>
>> Modified: cfe/trunk/test/Modules/cxx-irgen.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/cxx-irgen.cpp?rev=247494&r1=247493&r2=247494&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/test/Modules/cxx-irgen.cpp (original)
>> +++ cfe/trunk/test/Modules/cxx-irgen.cpp Fri Sep 11 20:07:37 2015
>> @@ -26,14 +26,14 @@ namespace EmitInlineMethods {
>>    };
>>  }
>>
>> -// 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_(
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
>


More information about the cfe-commits mailing list