From a70dca156fa76d452f54829b5c5f962ddfd94ef2 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 9 Oct 2009 23:27:56 +0000 Subject: [PATCH] Factor out LiveIntervalAnalysis' code to determine whether an instruction is trivially rematerializable and integrate it into TargetInstrInfo::isTriviallyReMaterializable. This way, all places that need to know whether an instruction is rematerializable will get the same answer. This enables the useful parts of the aggressive-remat option by default -- using AliasAnalysis to determine whether a memory location is invariant, and removes the questionable parts -- rematting operations with virtual register inputs that may not be live everywhere. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@83687 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/MachineInstr.h | 8 +- include/llvm/Target/TargetInstrInfo.h | 32 ++++--- lib/CodeGen/DeadMachineInstructionElim.cpp | 2 +- lib/CodeGen/LiveIntervalAnalysis.cpp | 99 ++-------------------- lib/CodeGen/MachineInstr.cpp | 12 +-- lib/CodeGen/MachineLICM.cpp | 4 +- lib/CodeGen/MachineSink.cpp | 6 +- lib/CodeGen/PostRASchedulerList.cpp | 18 ++-- lib/CodeGen/ScheduleDAGInstrs.cpp | 4 +- lib/CodeGen/ScheduleDAGInstrs.h | 2 +- lib/CodeGen/SimpleRegisterCoalescing.cpp | 7 +- lib/CodeGen/SimpleRegisterCoalescing.h | 1 + lib/CodeGen/TargetInstrInfoImpl.cpp | 88 +++++++++++++++++++ lib/CodeGen/TwoAddressInstructionPass.cpp | 8 +- 14 files changed, 161 insertions(+), 130 deletions(-) diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 27265da772f..de22710fe6e 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -275,11 +275,13 @@ public: /// isSafeToMove - Return true if it is safe to move this instruction. If /// SawStore is set to true, it means that there is a store (or call) between /// the instruction's location and its intended destination. - bool isSafeToMove(const TargetInstrInfo *TII, bool &SawStore) const; + bool isSafeToMove(const TargetInstrInfo *TII, bool &SawStore, + AliasAnalysis *AA) const; /// isSafeToReMat - Return true if it's safe to rematerialize the specified /// instruction which defined the specified register instead of copying it. - bool isSafeToReMat(const TargetInstrInfo *TII, unsigned DstReg) const; + bool isSafeToReMat(const TargetInstrInfo *TII, unsigned DstReg, + AliasAnalysis *AA) const; /// hasVolatileMemoryRef - Return true if this instruction may have a /// volatile memory reference, or if the information describing the @@ -292,7 +294,7 @@ public: /// loading a value from the constant pool or from from the argument area of /// a function if it does not change. This should only return true of *all* /// loads the instruction does are invariant (if it does multiple loads). - bool isInvariantLoad(AliasAnalysis *AA = 0) const; + bool isInvariantLoad(AliasAnalysis *AA) const; // // Debugging support diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 74a47c2bc23..8070c7d08e7 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -103,24 +103,34 @@ public: /// isTriviallyReMaterializable - Return true if the instruction is trivially /// rematerializable, meaning it has no side effects and requires no operands /// that aren't always available. - bool isTriviallyReMaterializable(const MachineInstr *MI) const { - return MI->getDesc().isRematerializable() && - isReallyTriviallyReMaterializable(MI); + bool isTriviallyReMaterializable(const MachineInstr *MI, + AliasAnalysis *AA = 0) const { + return MI->getOpcode() == IMPLICIT_DEF || + (MI->getDesc().isRematerializable() && + (isReallyTriviallyReMaterializable(MI) || + isReallyTriviallyReMaterializableGeneric(MI, AA))); } protected: /// isReallyTriviallyReMaterializable - For instructions with opcodes for - /// which the M_REMATERIALIZABLE flag is set, this function tests whether the - /// instruction itself is actually trivially rematerializable, considering - /// its operands. This is used for targets that have instructions that are - /// only trivially rematerializable for specific uses. This predicate must - /// return false if the instruction has any side effects other than - /// producing a value, or if it requres any address registers that are not - /// always available. + /// which the M_REMATERIALIZABLE flag is set, this hook lets the target + /// specify whether the instruction is actually trivially rematerializable, + /// taking into consideration its operands. This predicate must return false + /// if the instruction has any side effects other than producing a value, or + /// if it requres any address registers that are not always available. virtual bool isReallyTriviallyReMaterializable(const MachineInstr *MI) const { - return true; + return false; } +private: + /// isReallyTriviallyReMaterializableGeneric - For instructions with opcodes + /// for which the M_REMATERIALIZABLE flag is set and the target hook + /// isReallyTriviallyReMaterializable returns false, this function does + /// target-independent tests to determine if the instruction is really + /// trivially rematerializable. + bool isReallyTriviallyReMaterializableGeneric(const MachineInstr *MI, + AliasAnalysis *AA) const; + public: /// Return true if the instruction is a register to register move and return /// the source and dest operands and their sub-register indices by reference. diff --git a/lib/CodeGen/DeadMachineInstructionElim.cpp b/lib/CodeGen/DeadMachineInstructionElim.cpp index e104d8cec0e..078ed3d31b1 100644 --- a/lib/CodeGen/DeadMachineInstructionElim.cpp +++ b/lib/CodeGen/DeadMachineInstructionElim.cpp @@ -53,7 +53,7 @@ FunctionPass *llvm::createDeadMachineInstructionElimPass() { bool DeadMachineInstructionElim::isDead(const MachineInstr *MI) const { // Don't delete instructions with side effects. bool SawStore = false; - if (!MI->isSafeToMove(TII, SawStore)) + if (!MI->isSafeToMove(TII, SawStore, 0)) return false; // Examine each operand. diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index 135cc1719f7..93d3d4c8389 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -50,8 +50,6 @@ using namespace llvm; static cl::opt DisableReMat("disable-rematerialization", cl::init(false), cl::Hidden); -static cl::opt EnableAggressiveRemat("aggressive-remat", cl::Hidden); - static cl::opt EnableFastSpilling("fast-spill", cl::init(false), cl::Hidden); @@ -1408,99 +1406,12 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li, if (DisableReMat) return false; - if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) - return true; - - int FrameIdx = 0; - if (tii_->isLoadFromStackSlot(MI, FrameIdx) && - mf_->getFrameInfo()->isImmutableObjectIndex(FrameIdx)) - // FIXME: Let target specific isReallyTriviallyReMaterializable determines - // this but remember this is not safe to fold into a two-address - // instruction. - // This is a load from fixed stack slot. It can be rematerialized. - return true; - - // If the target-specific rules don't identify an instruction as - // being trivially rematerializable, use some target-independent - // rules. - if (!tii_->isTriviallyReMaterializable(MI)) { - if (!EnableAggressiveRemat) - return false; - - const TargetInstrDesc &TID = MI->getDesc(); - - // Avoid instructions obviously unsafe for remat. - if (TID.hasUnmodeledSideEffects() || TID.isNotDuplicable() || - TID.mayStore()) - return false; - - // Avoid instructions which load from potentially varying memory. - if (TID.mayLoad() && !MI->isInvariantLoad(aa_)) - return false; - - // If any of the registers accessed are non-constant, conservatively assume - // the instruction is not rematerializable. - unsigned ImpUse = 0; - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - if (MO.isReg()) { - unsigned Reg = MO.getReg(); - if (Reg == 0) - continue; - if (TargetRegisterInfo::isPhysicalRegister(Reg)) { - if (MO.isUse()) { - // If the physreg has no defs anywhere, it's just an ambient register - // and we can freely move its uses. Alternatively, if it's allocatable, - // it could get allocated to something with a def during allocation. - if (!mri_->def_empty(Reg)) - return false; - if (allocatableRegs_.test(Reg)) - return false; - // Check for a def among the register's aliases too. - for (const unsigned *Alias = tri_->getAliasSet(Reg); *Alias; ++Alias) { - unsigned AliasReg = *Alias; - if (!mri_->def_empty(AliasReg)) - return false; - if (allocatableRegs_.test(AliasReg)) - return false; - } - } else { - // A physreg def. We can't remat it. - return false; - } - continue; - } - - // Only allow one def, and that in the first operand. - if (MO.isDef() != (i == 0)) - return false; - - // Only allow constant-valued registers. - bool IsLiveIn = mri_->isLiveIn(Reg); - MachineRegisterInfo::def_iterator I = mri_->def_begin(Reg), - E = mri_->def_end(); - - // For the def, it should be the only def of that register. - if (MO.isDef() && (next(I) != E || IsLiveIn)) - return false; - - if (MO.isUse()) { - // Only allow one use other register use, as that's all the - // remat mechanisms support currently. - if (Reg != li.reg) { - if (ImpUse == 0) - ImpUse = Reg; - else if (Reg != ImpUse) - return false; - } - // For the use, there should be only one associated def. - if (I != E && (next(I) != E || IsLiveIn)) - return false; - } - } - } - } + if (!tii_->isTriviallyReMaterializable(MI, aa_)) + return false; + // Target-specific code can mark an instruction as being rematerializable + // if it has one virtual reg use, though it had better be something like + // a PIC base register which is likely to be live everywhere. unsigned ImpUse = getReMatImplicitUse(li, MI); if (ImpUse) { const LiveInterval &ImpLi = getInterval(ImpUse); diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index c4a99715e25..becdef3f660 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -933,7 +933,8 @@ void MachineInstr::copyPredicates(const MachineInstr *MI) { /// SawStore is set to true, it means that there is a store (or call) between /// the instruction's location and its intended destination. bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, - bool &SawStore) const { + bool &SawStore, + AliasAnalysis *AA) const { // Ignore stuff that we obviously can't move. if (TID->mayStore() || TID->isCall()) { SawStore = true; @@ -947,7 +948,7 @@ bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, // destination. The check for isInvariantLoad gives the targe the chance to // classify the load as always returning a constant, e.g. a constant pool // load. - if (TID->mayLoad() && !isInvariantLoad()) + if (TID->mayLoad() && !isInvariantLoad(AA)) // Otherwise, this is a real load. If there is a store between the load and // end of block, or if the load is volatile, we can't move it. return !SawStore && !hasVolatileMemoryRef(); @@ -958,10 +959,11 @@ bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, /// isSafeToReMat - Return true if it's safe to rematerialize the specified /// instruction which defined the specified register instead of copying it. bool MachineInstr::isSafeToReMat(const TargetInstrInfo *TII, - unsigned DstReg) const { + unsigned DstReg, + AliasAnalysis *AA) const { bool SawStore = false; - if (!TII->isTriviallyReMaterializable(this) || - !isSafeToMove(TII, SawStore)) + if (!TII->isTriviallyReMaterializable(this, AA) || + !isSafeToMove(TII, SawStore, AA)) return false; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { const MachineOperand &MO = getOperand(i); diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp index 5612899875b..f92ddb2b908 100644 --- a/lib/CodeGen/MachineLICM.cpp +++ b/lib/CodeGen/MachineLICM.cpp @@ -317,12 +317,10 @@ bool MachineLICM::IsProfitableToHoist(MachineInstr &MI) { if (MI.getOpcode() == TargetInstrInfo::IMPLICIT_DEF) return false; - const TargetInstrDesc &TID = MI.getDesc(); - // FIXME: For now, only hoist re-materilizable instructions. LICM will // increase register pressure. We want to make sure it doesn't increase // spilling. - if (!TII->isTriviallyReMaterializable(&MI)) + if (!TII->isTriviallyReMaterializable(&MI, AA)) return false; // If result(s) of this instruction is used by PHIs, then don't hoist it. diff --git a/lib/CodeGen/MachineSink.cpp b/lib/CodeGen/MachineSink.cpp index e5c34201ef9..0f3b33f54d4 100644 --- a/lib/CodeGen/MachineSink.cpp +++ b/lib/CodeGen/MachineSink.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineDominators.h" +#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" @@ -39,6 +40,7 @@ namespace { MachineFunction *CurMF; // Current MachineFunction MachineRegisterInfo *RegInfo; // Machine register information MachineDominatorTree *DT; // Machine dominator tree + AliasAnalysis *AA; BitVector AllocatableSet; // Which physregs are allocatable? public: @@ -50,6 +52,7 @@ namespace { virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); MachineFunctionPass::getAnalysisUsage(AU); + AU.addRequired(); AU.addRequired(); AU.addPreserved(); } @@ -100,6 +103,7 @@ bool MachineSinking::runOnMachineFunction(MachineFunction &MF) { TRI = TM->getRegisterInfo(); RegInfo = &CurMF->getRegInfo(); DT = &getAnalysis(); + AA = &getAnalysis(); AllocatableSet = TRI->getAllocatableSet(*CurMF); bool EverMadeChange = false; @@ -151,7 +155,7 @@ bool MachineSinking::ProcessBlock(MachineBasicBlock &MBB) { /// instruction out of its current block into a successor. bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) { // Check if it's safe to move the instruction. - if (!MI->isSafeToMove(TII, SawStore)) + if (!MI->isSafeToMove(TII, SawStore, AA)) return false; // FIXME: This should include support for sinking instructions within the diff --git a/lib/CodeGen/PostRASchedulerList.cpp b/lib/CodeGen/PostRASchedulerList.cpp index 662ab01a37c..ad8ba6c0137 100644 --- a/lib/CodeGen/PostRASchedulerList.cpp +++ b/lib/CodeGen/PostRASchedulerList.cpp @@ -31,6 +31,7 @@ #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetInstrInfo.h" @@ -76,12 +77,15 @@ DebugMod("postra-sched-debugmod", namespace { class VISIBILITY_HIDDEN PostRAScheduler : public MachineFunctionPass { + AliasAnalysis *AA; + public: static char ID; PostRAScheduler() : MachineFunctionPass(&ID) {} void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); + AU.addRequired(); AU.addRequired(); AU.addPreserved(); AU.addRequired(); @@ -119,6 +123,9 @@ namespace { /// HazardRec - The hazard recognizer to use. ScheduleHazardRecognizer *HazardRec; + /// AA - AliasAnalysis for making memory reference queries. + AliasAnalysis *AA; + /// Classes - For live regs that are only used in one register class in a /// live range, the register class. If the register is not live, the /// corresponding value is null. If the register is live but used in @@ -146,10 +153,11 @@ namespace { SchedulePostRATDList(MachineFunction &MF, const MachineLoopInfo &MLI, const MachineDominatorTree &MDT, - ScheduleHazardRecognizer *HR) + ScheduleHazardRecognizer *HR, + AliasAnalysis *aa) : ScheduleDAGInstrs(MF, MLI, MDT), Topo(SUnits), AllocatableSet(TRI->getAllocatableSet(MF)), - HazardRec(HR) {} + HazardRec(HR), AA(aa) {} ~SchedulePostRATDList() { delete HazardRec; @@ -241,7 +249,7 @@ bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) { (ScheduleHazardRecognizer *)new ExactHazardRecognizer(InstrItins) : (ScheduleHazardRecognizer *)new SimpleHazardRecognizer(); - SchedulePostRATDList Scheduler(Fn, MLI, MDT, HR); + SchedulePostRATDList Scheduler(Fn, MLI, MDT, HR, AA); // Loop over all of the basic blocks for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); @@ -379,7 +387,7 @@ void SchedulePostRATDList::Schedule() { DEBUG(errs() << "********** List Scheduling **********\n"); // Build the scheduling graph. - BuildSchedGraph(); + BuildSchedGraph(AA); if (EnableAntiDepBreaking) { if (BreakAntiDependencies()) { @@ -392,7 +400,7 @@ void SchedulePostRATDList::Schedule() { SUnits.clear(); EntrySU = SUnit(); ExitSU = SUnit(); - BuildSchedGraph(); + BuildSchedGraph(AA); } } diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp b/lib/CodeGen/ScheduleDAGInstrs.cpp index f50844f44a7..44e9296661a 100644 --- a/lib/CodeGen/ScheduleDAGInstrs.cpp +++ b/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -123,7 +123,7 @@ void ScheduleDAGInstrs::StartBlock(MachineBasicBlock *BB) { } } -void ScheduleDAGInstrs::BuildSchedGraph() { +void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) { // We'll be allocating one SUnit for each instruction, plus one for // the region exit node. SUnits.reserve(BB->size()); @@ -375,7 +375,7 @@ void ScheduleDAGInstrs::BuildSchedGraph() { // Treat all other stores conservatively. goto new_chain; } else if (TID.mayLoad()) { - if (MI->isInvariantLoad()) { + if (MI->isInvariantLoad(AA)) { // Invariant load, no chain dependencies needed! } else if (const Value *V = getUnderlyingObjectForInstr(MI)) { // A load from a specific PseudoSourceValue. Add precise dependencies. diff --git a/lib/CodeGen/ScheduleDAGInstrs.h b/lib/CodeGen/ScheduleDAGInstrs.h index e928ca12026..f079bd597db 100644 --- a/lib/CodeGen/ScheduleDAGInstrs.h +++ b/lib/CodeGen/ScheduleDAGInstrs.h @@ -155,7 +155,7 @@ namespace llvm { /// BuildSchedGraph - Build SUnits from the MachineBasicBlock that we are /// input. - virtual void BuildSchedGraph(); + virtual void BuildSchedGraph(AliasAnalysis *AA); /// ComputeLatency - Compute node latency. /// diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index 21bf5ea8d08..9c283b0f023 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -17,6 +17,7 @@ #include "VirtRegMap.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/Value.h" +#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineLoopInfo.h" @@ -72,6 +73,7 @@ const PassInfo *const llvm::SimpleRegisterCoalescingID = &X; void SimpleRegisterCoalescing::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); + AU.addRequired(); AU.addRequired(); AU.addPreserved(); AU.addRequired(); @@ -646,10 +648,10 @@ bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt, const TargetInstrDesc &TID = DefMI->getDesc(); if (!TID.isAsCheapAsAMove()) return false; - if (!tii_->isTriviallyReMaterializable(DefMI)) + if (!tii_->isTriviallyReMaterializable(DefMI, AA)) return false; bool SawStore = false; - if (!DefMI->isSafeToMove(tii_, SawStore)) + if (!DefMI->isSafeToMove(tii_, SawStore, AA)) return false; if (TID.getNumDefs() != 1) return false; @@ -2655,6 +2657,7 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { tri_ = tm_->getRegisterInfo(); tii_ = tm_->getInstrInfo(); li_ = &getAnalysis(); + AA = &getAnalysis(); loopInfo = &getAnalysis(); DEBUG(errs() << "********** SIMPLE REGISTER COALESCING **********\n" diff --git a/lib/CodeGen/SimpleRegisterCoalescing.h b/lib/CodeGen/SimpleRegisterCoalescing.h index 1d59a234616..3ebe3a1f7de 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.h +++ b/lib/CodeGen/SimpleRegisterCoalescing.h @@ -45,6 +45,7 @@ namespace llvm { const TargetInstrInfo* tii_; LiveIntervals *li_; const MachineLoopInfo* loopInfo; + AliasAnalysis *AA; BitVector allocatableRegs_; DenseMap allocatableRCRegs_; diff --git a/lib/CodeGen/TargetInstrInfoImpl.cpp b/lib/CodeGen/TargetInstrInfoImpl.cpp index ab67cd2a08d..2211308856c 100644 --- a/lib/CodeGen/TargetInstrInfoImpl.cpp +++ b/lib/CodeGen/TargetInstrInfoImpl.cpp @@ -13,11 +13,14 @@ //===----------------------------------------------------------------------===// #include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -238,3 +241,88 @@ TargetInstrInfo::foldMemoryOperand(MachineFunction &MF, return NewMI; } + +bool +TargetInstrInfo::isReallyTriviallyReMaterializableGeneric(const MachineInstr * + MI, + AliasAnalysis * + AA) const { + const MachineFunction &MF = *MI->getParent()->getParent(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + const TargetMachine &TM = MF.getTarget(); + const TargetInstrInfo &TII = *TM.getInstrInfo(); + const TargetRegisterInfo &TRI = *TM.getRegisterInfo(); + + // A load from a fixed stack slot can be rematerialized. This may be + // redundant with subsequent checks, but it's target-independent, + // simple, and a common case. + int FrameIdx = 0; + if (TII.isLoadFromStackSlot(MI, FrameIdx) && + MF.getFrameInfo()->isImmutableObjectIndex(FrameIdx)) + return true; + + const TargetInstrDesc &TID = MI->getDesc(); + + // Avoid instructions obviously unsafe for remat. + if (TID.hasUnmodeledSideEffects() || TID.isNotDuplicable() || + TID.mayStore()) + return false; + + // Avoid instructions which load from potentially varying memory. + if (TID.mayLoad() && !MI->isInvariantLoad(AA)) + return false; + + // If any of the registers accessed are non-constant, conservatively assume + // the instruction is not rematerializable. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) + continue; + + // Check for a well-behaved physical register. + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + if (MO.isUse()) { + // If the physreg has no defs anywhere, it's just an ambient register + // and we can freely move its uses. Alternatively, if it's allocatable, + // it could get allocated to something with a def during allocation. + if (!MRI.def_empty(Reg)) + return false; + BitVector AllocatableRegs = TRI.getAllocatableSet(MF, 0); + if (AllocatableRegs.test(Reg)) + return false; + // Check for a def among the register's aliases too. + for (const unsigned *Alias = TRI.getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + if (!MRI.def_empty(AliasReg)) + return false; + if (AllocatableRegs.test(AliasReg)) + return false; + } + } else { + // A physreg def. We can't remat it. + return false; + } + continue; + } + + // Only allow one virtual-register def, and that in the first operand. + if (MO.isDef() != (i == 0)) + return false; + + // For the def, it should be the only def of that register. + if (MO.isDef() && (next(MRI.def_begin(Reg)) != MRI.def_end() || + MRI.isLiveIn(Reg))) + return false; + + // Don't allow any virtual-register uses. Rematting an instruction with + // virtual register uses would length the live ranges of the uses, which + // is not necessarily a good idea, certainly not "trivial". + if (MO.isUse()) + return false; + } + + // Everything checked out. + return true; +} diff --git a/lib/CodeGen/TwoAddressInstructionPass.cpp b/lib/CodeGen/TwoAddressInstructionPass.cpp index a343fa4fc20..a5a0f5bdcc2 100644 --- a/lib/CodeGen/TwoAddressInstructionPass.cpp +++ b/lib/CodeGen/TwoAddressInstructionPass.cpp @@ -34,6 +34,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" @@ -62,6 +63,7 @@ namespace { const TargetRegisterInfo *TRI; MachineRegisterInfo *MRI; LiveVariables *LV; + AliasAnalysis *AA; // DistanceMap - Keep track the distance of a MI from the start of the // current basic block. @@ -130,6 +132,7 @@ namespace { virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); + AU.addRequired(); AU.addPreserved(); AU.addPreservedID(MachineLoopInfoID); AU.addPreservedID(MachineDominatorsID); @@ -160,7 +163,7 @@ bool TwoAddressInstructionPass::Sink3AddrInstruction(MachineBasicBlock *MBB, MachineBasicBlock::iterator OldPos) { // Check if it's safe to move this instruction. bool SeenStore = true; // Be conservative. - if (!MI->isSafeToMove(TII, SeenStore)) + if (!MI->isSafeToMove(TII, SeenStore, AA)) return false; unsigned DefReg = 0; @@ -903,6 +906,7 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) { TII = TM.getInstrInfo(); TRI = TM.getRegisterInfo(); LV = getAnalysisIfAvailable(); + AA = &getAnalysis(); bool MadeChange = false; @@ -1027,7 +1031,7 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) { // copying it. if (DefMI && DefMI->getDesc().isAsCheapAsAMove() && - DefMI->isSafeToReMat(TII, regB) && + DefMI->isSafeToReMat(TII, regB, AA) && isProfitableToReMat(regB, rc, mi, DefMI, mbbi, Dist)){ DEBUG(errs() << "2addr: REMATTING : " << *DefMI << "\n"); unsigned regASubIdx = mi->getOperand(DstIdx).getSubReg();