diff options
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 79 |
1 files changed, 54 insertions, 25 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 64c2bd673cc..f66cfef7766 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -875,6 +875,13 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, B.addAttribute(llvm::Attribute::StackProtectReq); if (!D) { + // If we don't have a declaration to control inlining, the function isn't + // explicitly marked as alwaysinline for semantic reasons, and inlining is + // disabled, mark the function as noinline. + if (!F->hasFnAttribute(llvm::Attribute::AlwaysInline) && + CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) + B.addAttribute(llvm::Attribute::NoInline); + F->addAttributes(llvm::AttributeSet::FunctionIndex, llvm::AttributeSet::get( F->getContext(), @@ -882,7 +889,23 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, return; } - if (D->hasAttr<NakedAttr>()) { + if (D->hasAttr<OptimizeNoneAttr>()) { + B.addAttribute(llvm::Attribute::OptimizeNone); + + // OptimizeNone implies noinline; we should not be inlining such functions. + B.addAttribute(llvm::Attribute::NoInline); + assert(!F->hasFnAttribute(llvm::Attribute::AlwaysInline) && + "OptimizeNone and AlwaysInline on same function!"); + + // We still need to handle naked functions even though optnone subsumes + // much of their semantics. + if (D->hasAttr<NakedAttr>()) + B.addAttribute(llvm::Attribute::Naked); + + // OptimizeNone wins over OptimizeForSize and MinSize. + F->removeFnAttr(llvm::Attribute::OptimizeForSize); + F->removeFnAttr(llvm::Attribute::MinSize); + } else if (D->hasAttr<NakedAttr>()) { // Naked implies noinline: we should not be inlining such functions. B.addAttribute(llvm::Attribute::Naked); B.addAttribute(llvm::Attribute::NoInline); @@ -891,41 +914,47 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, } else if (D->hasAttr<NoInlineAttr>()) { B.addAttribute(llvm::Attribute::NoInline); } else if (D->hasAttr<AlwaysInlineAttr>() && - !F->getAttributes().hasAttribute(llvm::AttributeSet::FunctionIndex, - llvm::Attribute::NoInline)) { + !F->hasFnAttribute(llvm::Attribute::NoInline)) { // (noinline wins over always_inline, and we can't specify both in IR) B.addAttribute(llvm::Attribute::AlwaysInline); + } else if (CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) { + // If we're not inlining, then force everything that isn't always_inline to + // carry an explicit noinline attribute. + if (!F->hasFnAttribute(llvm::Attribute::AlwaysInline)) + B.addAttribute(llvm::Attribute::NoInline); + } else { + // Otherwise, propagate the inline hint attribute and potentially use its + // absence to mark things as noinline. + if (auto *FD = dyn_cast<FunctionDecl>(D)) { + if (any_of(FD->redecls(), [&](const FunctionDecl *Redecl) { + return Redecl->isInlineSpecified(); + })) { + B.addAttribute(llvm::Attribute::InlineHint); + } else if (CodeGenOpts.getInlining() == + CodeGenOptions::OnlyHintInlining && + !FD->isInlined() && + !F->hasFnAttribute(llvm::Attribute::AlwaysInline)) { + B.addAttribute(llvm::Attribute::NoInline); + } + } } - if (D->hasAttr<ColdAttr>()) { - if (!D->hasAttr<OptimizeNoneAttr>()) + // Add other optimization related attributes if we are optimizing this + // function. + if (!D->hasAttr<OptimizeNoneAttr>()) { + if (D->hasAttr<ColdAttr>()) { B.addAttribute(llvm::Attribute::OptimizeForSize); - B.addAttribute(llvm::Attribute::Cold); - } + B.addAttribute(llvm::Attribute::Cold); + } - if (D->hasAttr<MinSizeAttr>()) - B.addAttribute(llvm::Attribute::MinSize); + if (D->hasAttr<MinSizeAttr>()) + B.addAttribute(llvm::Attribute::MinSize); + } F->addAttributes(llvm::AttributeSet::FunctionIndex, llvm::AttributeSet::get( F->getContext(), llvm::AttributeSet::FunctionIndex, B)); - if (D->hasAttr<OptimizeNoneAttr>()) { - // OptimizeNone implies noinline; we should not be inlining such functions. - F->addFnAttr(llvm::Attribute::OptimizeNone); - F->addFnAttr(llvm::Attribute::NoInline); - - // OptimizeNone wins over OptimizeForSize, MinSize, AlwaysInline. - F->removeFnAttr(llvm::Attribute::OptimizeForSize); - F->removeFnAttr(llvm::Attribute::MinSize); - assert(!F->hasFnAttribute(llvm::Attribute::AlwaysInline) && - "OptimizeNone and AlwaysInline on same function!"); - - // Attribute 'inlinehint' has no effect on 'optnone' functions. - // Explicitly remove it from the set of function attributes. - F->removeFnAttr(llvm::Attribute::InlineHint); - } - unsigned alignment = D->getMaxAlignment() / Context.getCharWidth(); if (alignment) F->setAlignment(alignment); |