summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/CodeGen/Passes.h2
-rw-r--r--llvm/include/llvm/Target/TargetInstrInfo.h3
-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
-rw-r--r--llvm/test/CodeGen/AArch64/machine-outliner.ll37
9 files changed, 88 insertions, 25 deletions
diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h
index 1377a6dd6aa..8e6b1570e4a 100644
--- a/llvm/include/llvm/CodeGen/Passes.h
+++ b/llvm/include/llvm/CodeGen/Passes.h
@@ -411,7 +411,7 @@ namespace llvm {
/// This pass performs outlining on machine instructions directly before
/// printing assembly.
- ModulePass *createMachineOutlinerPass();
+ ModulePass *createMachineOutlinerPass(bool OutlineFromLinkOnceODRs = false);
/// This pass expands the experimental reduction intrinsics into sequences of
/// shuffles.
diff --git a/llvm/include/llvm/Target/TargetInstrInfo.h b/llvm/include/llvm/Target/TargetInstrInfo.h
index 8e7e6a7fbfd..5d230d820db 100644
--- a/llvm/include/llvm/Target/TargetInstrInfo.h
+++ b/llvm/include/llvm/Target/TargetInstrInfo.h
@@ -1646,7 +1646,8 @@ public:
/// A function \p MF is considered safe for outlining if an outlined function
/// produced from instructions in F will produce a program which produces the
/// same output for any set of given inputs.
- virtual bool isFunctionSafeToOutlineFrom(MachineFunction &MF) const {
+ virtual bool isFunctionSafeToOutlineFrom(MachineFunction &MF,
+ bool OutlineFromLinkOnceODRs) const {
llvm_unreachable("Target didn't implement "
"TargetInstrInfo::isFunctionSafeToOutlineFrom!");
}
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;
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner.ll b/llvm/test/CodeGen/AArch64/machine-outliner.ll
index b5094fe4750..9b6254fb3cc 100644
--- a/llvm/test/CodeGen/AArch64/machine-outliner.ll
+++ b/llvm/test/CodeGen/AArch64/machine-outliner.ll
@@ -1,9 +1,31 @@
-; RUN: llc -enable-machine-outliner -mtriple=aarch64-apple-darwin < %s | FileCheck %s
+; RUN: llc -enable-machine-outliner -mtriple=aarch64-apple-darwin < %s | FileCheck %s -check-prefix=NoODR
+; RUN: llc -enable-machine-outliner -enable-linkonceodr-outlining -mtriple=aarch64-apple-darwin < %s | FileCheck %s -check-prefix=ODR
+
+define linkonce_odr void @fish() #0 {
+ ; CHECK-LABEL: _fish:
+ ; NoODR: orr w8, wzr, #0x1
+ ; NoODR-NEXT: stp w8, wzr, [sp, #8]
+ ; NoODR-NEXT: orr w8, wzr, #0x2
+ ; NoODR-NEXT: str w8, [sp, #4]
+ ; NoODR-NEXT: orr w8, wzr, #0x3
+ ; NoODR-NEXT: str w8, [sp], #16
+ ; NoODR-NEXT: ret
+ ; ODR: b l_OUTLINED_FUNCTION_0
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ store i32 0, i32* %1, align 4
+ store i32 1, i32* %2, align 4
+ store i32 2, i32* %3, align 4
+ store i32 3, i32* %4, align 4
+ ret void
+}
define void @cat() #0 {
-; CHECK-LABEL: _cat:
-; CHECK: b l_OUTLINED_FUNCTION_0
-; CHECK-NOT: ret
+ ; CHECK-LABEL: _cat:
+ ; CHECK: b l_OUTLINED_FUNCTION_0
+ ; CHECK-NOT: ret
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
@@ -16,9 +38,9 @@ define void @cat() #0 {
}
define void @dog() #0 {
-; CHECK-LABEL: _dog:
-; CHECK: b l_OUTLINED_FUNCTION_0
-; CHECK-NOT: ret
+ ; CHECK-LABEL: _dog:
+ ; CHECK: b l_OUTLINED_FUNCTION_0
+ ; CHECK-NOT: ret
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
@@ -39,5 +61,4 @@ define void @dog() #0 {
; CHECK-NEXT: str w8, [sp], #16
; CHECK-NEXT: ret
-
attributes #0 = { noredzone nounwind ssp uwtable "no-frame-pointer-elim"="false" "target-cpu"="cyclone" }
OpenPOWER on IntegriCloud