summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorJessica Paquette <jpaquette@apple.com>2017-10-07 00:16:34 +0000
committerJessica Paquette <jpaquette@apple.com>2017-10-07 00:16:34 +0000
commit13593843f60f80a951daba92108a02ddf1c552e2 (patch)
tree88ca3322b520b1cffc0acb3ca2d821654c9dfca8 /llvm/lib
parentc1b16558717898b202015f4615eb69c01b94d5c9 (diff)
downloadbcm5719-llvm-13593843f60f80a951daba92108a02ddf1c552e2.tar.gz
bcm5719-llvm-13593843f60f80a951daba92108a02ddf1c552e2.zip
[MachineOutliner] Disable outlining from LinkOnceODRs by default
Say you have two identical linkonceodr functions, one in M1 and one in M2. Say that the outliner outlines A,B,C from one function, and D,E,F from another function (where letters are instructions). Now those functions are not identical, and cannot be deduped. Locally to M1 and M2, these outlining choices would be good-- to the whole program, however, this might not be true! To mitigate this, this commit makes it so that the outliner sees linkonceodr functions as unsafe to outline from. It also adds a flag, -enable-linkonceodr-outlining, which allows the user to specify that they want to outline from such functions when they know what they're doing. Changing this handles most code size regressions in the test suite caused by competing with linker dedupe. It also doesn't have a huge impact on the code size improvements from the outliner. There are 6 tests that regress > 5% from outlining WITH linkonceodrs to outlining WITHOUT linkonceodrs. Overall, most tests either improve or are not impacted. Not outlined vs outlined without linkonceodrs: https://hastebin.com/raw/qeguxavuda Not outlined vs outlined with linkonceodrs: https://hastebin.com/raw/edepoqoqic Outlined with linkonceodrs vs outlined without linkonceodrs: https://hastebin.com/raw/awiqifiheb Numbers generated using compare.py with -m size.__text. Tests run for AArch64 with -Oz -mllvm -enable-machine-outliner -mno-red-zone. llvm-svn: 315136
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/MachineOutliner.cpp15
-rw-r--r--llvm/lib/CodeGen/TargetPassConfig.cpp7
-rw-r--r--llvm/lib/Target/AArch64/AArch64InstrInfo.cpp25
-rw-r--r--llvm/lib/Target/AArch64/AArch64InstrInfo.h3
-rw-r--r--llvm/lib/Target/X86/X86InstrInfo.cpp18
-rw-r--r--llvm/lib/Target/X86/X86InstrInfo.h3
6 files changed, 56 insertions, 15 deletions
diff --git a/llvm/lib/CodeGen/MachineOutliner.cpp b/llvm/lib/CodeGen/MachineOutliner.cpp
index b52d3ebfeff..8e6e0b12409 100644
--- a/llvm/lib/CodeGen/MachineOutliner.cpp
+++ b/llvm/lib/CodeGen/MachineOutliner.cpp
@@ -746,6 +746,10 @@ struct MachineOutliner : public ModulePass {
static char ID;
+ /// \brief Set to true if the outliner should consider functions with
+ /// linkonceodr linkage.
+ bool OutlineFromLinkOnceODRs = false;
+
StringRef getPassName() const override { return "Machine Outliner"; }
void getAnalysisUsage(AnalysisUsage &AU) const override {
@@ -755,7 +759,8 @@ struct MachineOutliner : public ModulePass {
ModulePass::getAnalysisUsage(AU);
}
- MachineOutliner() : ModulePass(ID) {
+ MachineOutliner(bool OutlineFromLinkOnceODRs = false) :
+ ModulePass(ID), OutlineFromLinkOnceODRs(OutlineFromLinkOnceODRs) {
initializeMachineOutlinerPass(*PassRegistry::getPassRegistry());
}
@@ -844,7 +849,10 @@ struct MachineOutliner : public ModulePass {
char MachineOutliner::ID = 0;
namespace llvm {
-ModulePass *createMachineOutlinerPass() { return new MachineOutliner(); }
+ModulePass *createMachineOutlinerPass(bool OutlineFromLinkOnceODRs) {
+ return new MachineOutliner(OutlineFromLinkOnceODRs);
+}
+
} // namespace llvm
INITIALIZE_PASS(MachineOutliner, DEBUG_TYPE, "Machine Function Outliner", false,
@@ -1248,7 +1256,8 @@ bool MachineOutliner::runOnModule(Module &M) {
MachineFunction &MF = MMI.getOrCreateMachineFunction(F);
// Is the function empty? Safe to outline from?
- if (F.empty() || !TII->isFunctionSafeToOutlineFrom(MF))
+ if (F.empty() ||
+ !TII->isFunctionSafeToOutlineFrom(MF, OutlineFromLinkOnceODRs))
continue;
// If it is, look at each MachineBasicBlock in the function.
diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp
index 4584f65619c..c5101b1ecfc 100644
--- a/llvm/lib/CodeGen/TargetPassConfig.cpp
+++ b/llvm/lib/CodeGen/TargetPassConfig.cpp
@@ -111,6 +111,11 @@ static cl::opt<bool> VerifyMachineCode("verify-machineinstrs", cl::Hidden,
static cl::opt<bool> EnableMachineOutliner("enable-machine-outliner",
cl::Hidden,
cl::desc("Enable machine outliner"));
+static cl::opt<bool> EnableLinkOnceODROutlining(
+ "enable-linkonceodr-outlining",
+ cl::Hidden,
+ cl::desc("Enable the machine outliner on linkonceodr functions"),
+ cl::init(false));
// Enable or disable FastISel. Both options are needed, because
// FastISel is enabled by default with -fast, and we wish to be
// able to enable or disable fast-isel independently from -O0.
@@ -891,7 +896,7 @@ void TargetPassConfig::addMachinePasses() {
addPass(&PatchableFunctionID, false);
if (EnableMachineOutliner)
- PM->add(createMachineOutlinerPass());
+ PM->add(createMachineOutlinerPass(EnableLinkOnceODROutlining));
AddingMachinePasses = false;
}
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 1d35fb3da2b..03a358053bb 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -4646,13 +4646,24 @@ AArch64InstrInfo::getOutlininingCandidateInfo(
FrameID);
}
-bool AArch64InstrInfo::isFunctionSafeToOutlineFrom(MachineFunction &MF) const {
- // If MF has a red zone, then we ought not to outline from it, since outlined
- // functions can modify/read from the stack.
- // If MF's address is taken, then we don't want to outline from it either
- // since we don't really know what the user is doing with it.
- return MF.getFunction()->hasFnAttribute(Attribute::NoRedZone) &&
- !MF.getFunction()->hasAddressTaken();
+bool AArch64InstrInfo::isFunctionSafeToOutlineFrom(MachineFunction &MF,
+ bool OutlineFromLinkOnceODRs) const {
+ const Function *F = MF.getFunction();
+
+ // If F uses a redzone, then don't outline from it because it might mess up
+ // the stack.
+ if (!F->hasFnAttribute(Attribute::NoRedZone))
+ return false;
+
+ // If anyone is using the address of this function, don't outline from it.
+ if (F->hasAddressTaken())
+ return false;
+
+ // Can F be deduplicated by the linker? If it can, don't outline from it.
+ if (!OutlineFromLinkOnceODRs && F->hasLinkOnceODRLinkage())
+ return false;
+
+ return true;
}
AArch64GenInstrInfo::MachineOutlinerInstrType
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
index 9a338b53c7a..24758e97888 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
@@ -352,7 +352,8 @@ public:
bool
canOutlineWithoutLRSave(MachineBasicBlock::iterator &CallInsertionPt) const;
- bool isFunctionSafeToOutlineFrom(MachineFunction &MF) const override;
+ bool isFunctionSafeToOutlineFrom(MachineFunction &MF,
+ bool OutlineFromLinkOnceODRs) const override;
MachineOutlinerInfo getOutlininingCandidateInfo(
std::vector<
std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp
index 604ee1533fa..3fea891cdaf 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.cpp
+++ b/llvm/lib/Target/X86/X86InstrInfo.cpp
@@ -10763,8 +10763,22 @@ X86InstrInfo::getOutlininingCandidateInfo(
MachineOutlinerDefault);
}
-bool X86InstrInfo::isFunctionSafeToOutlineFrom(MachineFunction &MF) const {
- return MF.getFunction()->hasFnAttribute(Attribute::NoRedZone);
+bool X86InstrInfo::isFunctionSafeToOutlineFrom(MachineFunction &MF,
+ bool OutlineFromLinkOnceODRs) const {
+ const Function *F = MF.getFunction();
+
+ // Does the function use a red zone? If it does, then we can't risk messing
+ // with the stack.
+ if (!F->hasFnAttribute(Attribute::NoRedZone))
+ return false;
+
+ // If we *don't* want to outline from things that could potentially be deduped
+ // then return false.
+ if (!OutlineFromLinkOnceODRs && F->hasLinkOnceODRLinkage())
+ return false;
+
+ // This function is viable for outlining, so return true.
+ return true;
}
X86GenInstrInfo::MachineOutlinerInstrType
diff --git a/llvm/lib/Target/X86/X86InstrInfo.h b/llvm/lib/Target/X86/X86InstrInfo.h
index 8bbf7dc6d23..e665ec1f14d 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.h
+++ b/llvm/lib/Target/X86/X86InstrInfo.h
@@ -564,7 +564,8 @@ public:
std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
&RepeatedSequenceLocs) const override;
- bool isFunctionSafeToOutlineFrom(MachineFunction &MF) const override;
+ bool isFunctionSafeToOutlineFrom(MachineFunction &MF,
+ bool OutlineFromLinkOnceODRs) const override;
llvm::X86GenInstrInfo::MachineOutlinerInstrType
getOutliningType(MachineInstr &MI) const override;
OpenPOWER on IntegriCloud