diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/CodeGen/Passes.h | 2 | ||||
-rw-r--r-- | llvm/include/llvm/Target/TargetInstrInfo.h | 3 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MachineOutliner.cpp | 15 | ||||
-rw-r--r-- | llvm/lib/CodeGen/TargetPassConfig.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 25 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstrInfo.h | 3 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86InstrInfo.cpp | 18 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86InstrInfo.h | 3 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/machine-outliner.ll | 37 |
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" } |