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@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@+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); } > > 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@+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)); > @@ -45,7 +47,7 @@ int bar(int j) { > // 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); > } > > 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@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits