mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[attrs] Split off the forced attributes utility into its own pass that
is (by default) run much earlier than FuncitonAttrs proper. This allows forcing optnone or other widely impactful attributes. It is also a bit simpler as the force attribute behavior needs no specific iteration order. I've added the pass into the default module pass pipeline and LTO pass pipeline which mirrors where function attrs itself was being run. Differential Revision: http://reviews.llvm.org/D15668 llvm-svn: 256465
This commit is contained in:
parent
c79efd26f5
commit
cf6f5436f5
@ -131,6 +131,7 @@ void initializeScalarizerPass(PassRegistry&);
|
||||
void initializeEarlyCSELegacyPassPass(PassRegistry &);
|
||||
void initializeEliminateAvailableExternallyPass(PassRegistry&);
|
||||
void initializeExpandISelPseudosPass(PassRegistry&);
|
||||
void initializeForceFunctionAttrsLegacyPassPass(PassRegistry&);
|
||||
void initializeFunctionAttrsPass(PassRegistry&);
|
||||
void initializeGCMachineCodeAnalysisPass(PassRegistry&);
|
||||
void initializeGCModuleInfoPass(PassRegistry&);
|
||||
|
35
include/llvm/Transforms/IPO/ForceFunctionAttrs.h
Normal file
35
include/llvm/Transforms/IPO/ForceFunctionAttrs.h
Normal file
@ -0,0 +1,35 @@
|
||||
//===-- ForceFunctionAttrs.h - Force function attrs for debugging ---------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// \file
|
||||
/// Super simple passes to force specific function attrs from the commandline
|
||||
/// into the IR for debugging purposes.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TRANSFORMS_IPO_FORCEFUNCTIONATTRS_H
|
||||
#define LLVM_TRANSFORMS_IPO_FORCEFUNCTIONATTRS_H
|
||||
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// Pass which forces specific function attributes into the IR, primarily as
|
||||
/// a debugging tool.
|
||||
class ForceFunctionAttrsPass {
|
||||
public:
|
||||
static StringRef name() { return "ForceFunctionAttrsPass"; }
|
||||
PreservedAnalyses run(Module &M);
|
||||
};
|
||||
|
||||
/// Create a legacy pass manager instance of a pass to force function attrs.
|
||||
Pass *createForceFunctionAttrsLegacyPass();
|
||||
|
||||
}
|
||||
|
||||
#endif // LLVM_TRANSFORMS_IPO_FORCEFUNCTIONATTRS_H
|
@ -29,13 +29,14 @@
|
||||
#include "llvm/IR/Verifier.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Transforms/InstCombine/InstCombine.h"
|
||||
#include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
|
||||
#include "llvm/Transforms/IPO/StripDeadPrototypes.h"
|
||||
#include "llvm/Transforms/InstCombine/InstCombine.h"
|
||||
#include "llvm/Transforms/Scalar/ADCE.h"
|
||||
#include "llvm/Transforms/Scalar/EarlyCSE.h"
|
||||
#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
|
||||
#include "llvm/Transforms/Scalar/SimplifyCFG.h"
|
||||
#include "llvm/Transforms/Scalar/SROA.h"
|
||||
#include "llvm/Transforms/Scalar/SimplifyCFG.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
|
@ -27,6 +27,7 @@ MODULE_ANALYSIS("targetlibinfo", TargetLibraryAnalysis())
|
||||
#ifndef MODULE_PASS
|
||||
#define MODULE_PASS(NAME, CREATE_PASS)
|
||||
#endif
|
||||
MODULE_PASS("forceattrs", ForceFunctionAttrsPass())
|
||||
MODULE_PASS("invalidate<all>", InvalidateAllAnalysesPass())
|
||||
MODULE_PASS("no-op-module", NoOpModulePass())
|
||||
MODULE_PASS("print", PrintModulePass(dbgs()))
|
||||
|
@ -6,6 +6,7 @@ add_llvm_library(LLVMipo
|
||||
DeadArgumentElimination.cpp
|
||||
ElimAvailExtern.cpp
|
||||
ExtractGV.cpp
|
||||
ForceFunctionAttrs.cpp
|
||||
FunctionAttrs.cpp
|
||||
FunctionImport.cpp
|
||||
GlobalDCE.cpp
|
||||
|
121
lib/Transforms/IPO/ForceFunctionAttrs.cpp
Normal file
121
lib/Transforms/IPO/ForceFunctionAttrs.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
//===- ForceFunctionAttrs.cpp - Force function attrs for debugging --------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "forceattrs"
|
||||
|
||||
static cl::list<std::string>
|
||||
ForceAttributes("force-attribute", cl::Hidden,
|
||||
cl::desc("Add an attribute to a function. This should be a "
|
||||
"pair of 'function-name:attribute-name', for "
|
||||
"example -force-add-attribute=foo:noinline. This "
|
||||
"option can be specified multiple times."));
|
||||
|
||||
static Attribute::AttrKind parseAttrKind(StringRef Kind) {
|
||||
return StringSwitch<Attribute::AttrKind>(Kind)
|
||||
.Case("alwaysinline", Attribute::AlwaysInline)
|
||||
.Case("builtin", Attribute::Builtin)
|
||||
.Case("cold", Attribute::Cold)
|
||||
.Case("convergent", Attribute::Convergent)
|
||||
.Case("inlinehint", Attribute::InlineHint)
|
||||
.Case("jumptable", Attribute::JumpTable)
|
||||
.Case("minsize", Attribute::MinSize)
|
||||
.Case("naked", Attribute::Naked)
|
||||
.Case("nobuiltin", Attribute::NoBuiltin)
|
||||
.Case("noduplicate", Attribute::NoDuplicate)
|
||||
.Case("noimplicitfloat", Attribute::NoImplicitFloat)
|
||||
.Case("noinline", Attribute::NoInline)
|
||||
.Case("nonlazybind", Attribute::NonLazyBind)
|
||||
.Case("noredzone", Attribute::NoRedZone)
|
||||
.Case("noreturn", Attribute::NoReturn)
|
||||
.Case("norecurse", Attribute::NoRecurse)
|
||||
.Case("nounwind", Attribute::NoUnwind)
|
||||
.Case("optnone", Attribute::OptimizeNone)
|
||||
.Case("optsize", Attribute::OptimizeForSize)
|
||||
.Case("readnone", Attribute::ReadNone)
|
||||
.Case("readonly", Attribute::ReadOnly)
|
||||
.Case("argmemonly", Attribute::ArgMemOnly)
|
||||
.Case("returns_twice", Attribute::ReturnsTwice)
|
||||
.Case("safestack", Attribute::SafeStack)
|
||||
.Case("sanitize_address", Attribute::SanitizeAddress)
|
||||
.Case("sanitize_memory", Attribute::SanitizeMemory)
|
||||
.Case("sanitize_thread", Attribute::SanitizeThread)
|
||||
.Case("ssp", Attribute::StackProtect)
|
||||
.Case("sspreq", Attribute::StackProtectReq)
|
||||
.Case("sspstrong", Attribute::StackProtectStrong)
|
||||
.Case("uwtable", Attribute::UWTable)
|
||||
.Default(Attribute::None);
|
||||
}
|
||||
|
||||
/// If F has any forced attributes given on the command line, add them.
|
||||
static void addForcedAttributes(Function &F) {
|
||||
for (auto &S : ForceAttributes) {
|
||||
auto KV = StringRef(S).split(':');
|
||||
if (KV.first != F.getName())
|
||||
continue;
|
||||
|
||||
auto Kind = parseAttrKind(KV.second);
|
||||
if (Kind == Attribute::None) {
|
||||
DEBUG(dbgs() << "ForcedAttribute: " << KV.second
|
||||
<< " unknown or not handled!\n");
|
||||
continue;
|
||||
}
|
||||
if (F.hasFnAttribute(Kind))
|
||||
continue;
|
||||
F.addFnAttr(Kind);
|
||||
}
|
||||
}
|
||||
|
||||
PreservedAnalyses ForceFunctionAttrsPass::run(Module &M) {
|
||||
if (ForceAttributes.empty())
|
||||
return PreservedAnalyses::all();
|
||||
|
||||
for (Function &F : M.functions())
|
||||
addForcedAttributes(F);
|
||||
|
||||
// Just conservatively invalidate analyses, this isn't likely to be important.
|
||||
return PreservedAnalyses::none();
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct ForceFunctionAttrsLegacyPass : public ModulePass {
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
ForceFunctionAttrsLegacyPass() : ModulePass(ID) {
|
||||
initializeForceFunctionAttrsLegacyPassPass(
|
||||
*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
bool runOnModule(Module &M) override {
|
||||
if (ForceAttributes.empty())
|
||||
return false;
|
||||
|
||||
for (Function &F : M.functions())
|
||||
addForcedAttributes(F);
|
||||
|
||||
// Conservatively assume we changed something.
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
char ForceFunctionAttrsLegacyPass::ID = 0;
|
||||
INITIALIZE_PASS(ForceFunctionAttrsLegacyPass, "forceattrs",
|
||||
"Force set function attributes", false, false)
|
||||
|
||||
Pass *llvm::createForceFunctionAttrsLegacyPass() {
|
||||
return new ForceFunctionAttrsLegacyPass();
|
||||
}
|
@ -53,13 +53,6 @@ STATISTIC(NumNonNullReturn, "Number of function returns marked nonnull");
|
||||
STATISTIC(NumAnnotated, "Number of attributes added to library functions");
|
||||
STATISTIC(NumNoRecurse, "Number of functions marked as norecurse");
|
||||
|
||||
static cl::list<std::string>
|
||||
ForceAttributes("force-attribute", cl::Hidden,
|
||||
cl::desc("Add an attribute to a function. This should be a "
|
||||
"pair of 'function-name:attribute-name', for "
|
||||
"example -force-add-attribute=foo:noinline. This "
|
||||
"option can be specified multiple times."));
|
||||
|
||||
namespace {
|
||||
typedef SmallSetVector<Function *, 8> SCCNodeSet;
|
||||
}
|
||||
@ -1851,64 +1844,6 @@ static bool addNoRecurseAttrsTopDownOnly(Function *F) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static Attribute::AttrKind parseAttrKind(StringRef Kind) {
|
||||
return StringSwitch<Attribute::AttrKind>(Kind)
|
||||
.Case("alwaysinline", Attribute::AlwaysInline)
|
||||
.Case("builtin", Attribute::Builtin)
|
||||
.Case("cold", Attribute::Cold)
|
||||
.Case("convergent", Attribute::Convergent)
|
||||
.Case("inlinehint", Attribute::InlineHint)
|
||||
.Case("jumptable", Attribute::JumpTable)
|
||||
.Case("minsize", Attribute::MinSize)
|
||||
.Case("naked", Attribute::Naked)
|
||||
.Case("nobuiltin", Attribute::NoBuiltin)
|
||||
.Case("noduplicate", Attribute::NoDuplicate)
|
||||
.Case("noimplicitfloat", Attribute::NoImplicitFloat)
|
||||
.Case("noinline", Attribute::NoInline)
|
||||
.Case("nonlazybind", Attribute::NonLazyBind)
|
||||
.Case("noredzone", Attribute::NoRedZone)
|
||||
.Case("noreturn", Attribute::NoReturn)
|
||||
.Case("norecurse", Attribute::NoRecurse)
|
||||
.Case("nounwind", Attribute::NoUnwind)
|
||||
.Case("optnone", Attribute::OptimizeNone)
|
||||
.Case("optsize", Attribute::OptimizeForSize)
|
||||
.Case("readnone", Attribute::ReadNone)
|
||||
.Case("readonly", Attribute::ReadOnly)
|
||||
.Case("argmemonly", Attribute::ArgMemOnly)
|
||||
.Case("returns_twice", Attribute::ReturnsTwice)
|
||||
.Case("safestack", Attribute::SafeStack)
|
||||
.Case("sanitize_address", Attribute::SanitizeAddress)
|
||||
.Case("sanitize_memory", Attribute::SanitizeMemory)
|
||||
.Case("sanitize_thread", Attribute::SanitizeThread)
|
||||
.Case("ssp", Attribute::StackProtect)
|
||||
.Case("sspreq", Attribute::StackProtectReq)
|
||||
.Case("sspstrong", Attribute::StackProtectStrong)
|
||||
.Case("uwtable", Attribute::UWTable)
|
||||
.Default(Attribute::None);
|
||||
}
|
||||
|
||||
/// If F has any forced attributes given on the command line, add them.
|
||||
static bool addForcedAttributes(Function *F) {
|
||||
bool Changed = false;
|
||||
for (auto &S : ForceAttributes) {
|
||||
auto KV = StringRef(S).split(':');
|
||||
if (KV.first != F->getName())
|
||||
continue;
|
||||
|
||||
auto Kind = parseAttrKind(KV.second);
|
||||
if (Kind == Attribute::None) {
|
||||
DEBUG(dbgs() << "ForcedAttribute: " << KV.second
|
||||
<< " unknown or not handled!\n");
|
||||
continue;
|
||||
}
|
||||
if (F->hasFnAttribute(Kind))
|
||||
continue;
|
||||
Changed = true;
|
||||
F->addFnAttr(Kind);
|
||||
}
|
||||
return Changed;
|
||||
}
|
||||
|
||||
bool FunctionAttrs::runOnSCC(CallGraphSCC &SCC) {
|
||||
TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
|
||||
bool Changed = false;
|
||||
@ -1944,7 +1879,6 @@ bool FunctionAttrs::runOnSCC(CallGraphSCC &SCC) {
|
||||
if (F->isDeclaration())
|
||||
Changed |= inferPrototypeAttributes(*F, *TLI);
|
||||
|
||||
Changed |= addForcedAttributes(F);
|
||||
SCCNodes.insert(F);
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ void llvm::initializeIPO(PassRegistry &Registry) {
|
||||
initializeCrossDSOCFIPass(Registry);
|
||||
initializeDAEPass(Registry);
|
||||
initializeDAHPass(Registry);
|
||||
initializeForceFunctionAttrsLegacyPassPass(Registry);
|
||||
initializeFunctionAttrsPass(Registry);
|
||||
initializeGlobalDCEPass(Registry);
|
||||
initializeGlobalOptPass(Registry);
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "llvm/Analysis/TypeBasedAliasAnalysis.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Transforms/IPO.h"
|
||||
#include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Transforms/Vectorize.h"
|
||||
|
||||
@ -187,6 +188,9 @@ void PassManagerBuilder::populateFunctionPassManager(
|
||||
|
||||
void PassManagerBuilder::populateModulePassManager(
|
||||
legacy::PassManagerBase &MPM) {
|
||||
// Allow forcing function attributes as a debugging and tuning aid.
|
||||
MPM.add(createForceFunctionAttrsLegacyPass());
|
||||
|
||||
// If all optimizations are disabled, just run the always-inline pass and,
|
||||
// if enabled, the function merging pass.
|
||||
if (OptLevel == 0) {
|
||||
@ -483,6 +487,9 @@ void PassManagerBuilder::addLTOOptimizationPasses(legacy::PassManagerBase &PM) {
|
||||
if (FunctionIndex)
|
||||
PM.add(createFunctionImportPass(FunctionIndex));
|
||||
|
||||
// Allow forcing function attributes as a debugging and tuning aid.
|
||||
PM.add(createForceFunctionAttrsLegacyPass());
|
||||
|
||||
// Propagate constants at call sites into the functions they call. This
|
||||
// opens opportunities for globalopt (and inlining) by substituting function
|
||||
// pointers passed as arguments to direct uses of functions.
|
||||
|
12
test/Transforms/ForcedFunctionAttrs/forced.ll
Normal file
12
test/Transforms/ForcedFunctionAttrs/forced.ll
Normal file
@ -0,0 +1,12 @@
|
||||
; RUN: opt < %s -S -forceattrs | FileCheck %s --check-prefix=CHECK-CONTROL
|
||||
; RUN: opt < %s -S -forceattrs -force-attribute foo:noinline | FileCheck %s --check-prefix=CHECK-FOO
|
||||
; RUN: opt < %s -S -passes=forceattrs -force-attribute foo:noinline | FileCheck %s --check-prefix=CHECK-FOO
|
||||
|
||||
; CHECK-CONTROL: define void @foo() {
|
||||
; CHECK-FOO: define void @foo() #0 {
|
||||
define void @foo() {
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
; CHECK-FOO: attributes #0 = { noinline }
|
@ -1,12 +0,0 @@
|
||||
; RUN: opt < %s -S -functionattrs | FileCheck %s --check-prefix=CHECK-CONTROL
|
||||
; RUN: opt < %s -S -functionattrs -force-attribute foo:noinline | FileCheck %s --check-prefix=CHECK-FOO
|
||||
|
||||
; CHECK-CONTROL: define void @foo() #0 {
|
||||
; CHECK-FOO: define void @foo() #0 {
|
||||
define void @foo() {
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
; CHECK-CONTROL: attributes #0 = { norecurse readnone }
|
||||
; CHECK-FOO: attributes #0 = { noinline norecurse readnone }
|
Loading…
x
Reference in New Issue
Block a user