CodeGen: Refactor SetLLVMFunctionAttributesForDefinition to use an AttrBuilder.

Adding attributes to a uniqued set has become expensive, don't do it more often
than necessary. No functionality change.

llvm-svn: 181662
This commit is contained in:
Benjamin Kramer 2013-05-11 12:45:37 +00:00
parent 470b077bca
commit 2960dbddbb
1 changed files with 31 additions and 27 deletions

View File

@ -598,61 +598,65 @@ static bool hasUnwindExceptions(const LangOptions &LangOpts) {
void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
llvm::Function *F) {
llvm::AttrBuilder B;
if (CodeGenOpts.UnwindTables)
F->setHasUWTable();
B.addAttribute(llvm::Attribute::UWTable);
if (!hasUnwindExceptions(LangOpts))
F->addFnAttr(llvm::Attribute::NoUnwind);
B.addAttribute(llvm::Attribute::NoUnwind);
if (D->hasAttr<NakedAttr>()) {
// Naked implies noinline: we should not be inlining such functions.
F->addFnAttr(llvm::Attribute::Naked);
F->addFnAttr(llvm::Attribute::NoInline);
}
if (D->hasAttr<NoInlineAttr>())
F->addFnAttr(llvm::Attribute::NoInline);
// (noinline wins over always_inline, and we can't specify both in IR)
if ((D->hasAttr<AlwaysInlineAttr>() || D->hasAttr<ForceInlineAttr>()) &&
B.addAttribute(llvm::Attribute::Naked);
B.addAttribute(llvm::Attribute::NoInline);
} else if (D->hasAttr<NoInlineAttr>()) {
B.addAttribute(llvm::Attribute::NoInline);
} else if ((D->hasAttr<AlwaysInlineAttr>() ||
D->hasAttr<ForceInlineAttr>()) &&
!F->getAttributes().hasAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::NoInline))
F->addFnAttr(llvm::Attribute::AlwaysInline);
llvm::Attribute::NoInline)) {
// (noinline wins over always_inline, and we can't specify both in IR)
B.addAttribute(llvm::Attribute::AlwaysInline);
}
// FIXME: Communicate hot and cold attributes to LLVM more directly.
if (D->hasAttr<ColdAttr>())
F->addFnAttr(llvm::Attribute::OptimizeForSize);
B.addAttribute(llvm::Attribute::OptimizeForSize);
if (D->hasAttr<MinSizeAttr>())
F->addFnAttr(llvm::Attribute::MinSize);
if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D))
F->setUnnamedAddr(true);
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D))
if (MD->isVirtual())
F->setUnnamedAddr(true);
B.addAttribute(llvm::Attribute::MinSize);
if (LangOpts.getStackProtector() == LangOptions::SSPOn)
F->addFnAttr(llvm::Attribute::StackProtect);
B.addAttribute(llvm::Attribute::StackProtect);
else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
F->addFnAttr(llvm::Attribute::StackProtectReq);
B.addAttribute(llvm::Attribute::StackProtectReq);
// Add sanitizer attributes if function is not blacklisted.
if (!SanitizerBlacklist.isIn(*F)) {
// When AddressSanitizer is enabled, set SanitizeAddress attribute
// unless __attribute__((no_sanitize_address)) is used.
if (SanOpts.Address && !D->hasAttr<NoSanitizeAddressAttr>())
F->addFnAttr(llvm::Attribute::SanitizeAddress);
B.addAttribute(llvm::Attribute::SanitizeAddress);
// Same for ThreadSanitizer and __attribute__((no_sanitize_thread))
if (SanOpts.Thread && !D->hasAttr<NoSanitizeThreadAttr>()) {
F->addFnAttr(llvm::Attribute::SanitizeThread);
B.addAttribute(llvm::Attribute::SanitizeThread);
}
// Same for MemorySanitizer and __attribute__((no_sanitize_memory))
if (SanOpts.Memory && !D->hasAttr<NoSanitizeMemoryAttr>())
F->addFnAttr(llvm::Attribute::SanitizeMemory);
B.addAttribute(llvm::Attribute::SanitizeMemory);
}
F->addAttributes(llvm::AttributeSet::FunctionIndex,
llvm::AttributeSet::get(
F->getContext(), llvm::AttributeSet::FunctionIndex, B));
if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D))
F->setUnnamedAddr(true);
else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D))
if (MD->isVirtual())
F->setUnnamedAddr(true);
unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
if (alignment)
F->setAlignment(alignment);