From 5c95230f25a51835375ebaae77b841c6d2c57889 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 29 Oct 2009 17:47:20 +0000 Subject: [PATCH] Refactor the code for unfolding a load into a separate function. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85515 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineLICM.cpp | 112 ++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 50 deletions(-) diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp index cf958f5a86c..5ab0ff745d1 100644 --- a/lib/CodeGen/MachineLICM.cpp +++ b/lib/CodeGen/MachineLICM.cpp @@ -105,6 +105,12 @@ namespace { /// void HoistRegion(MachineDomTreeNode *N); + /// ExtractHoistableLoad - Unfold a load from the given machineinstr if + /// the load itself could be hoisted. Return the unfolded and hoistable + /// load, or null if the load couldn't be unfolded or if it wouldn't + /// be hoistable. + MachineInstr *ExtractHoistableLoad(MachineInstr *MI); + /// Hoist - When an instruction is found to only use loop invariant operands /// that is safe to hoist, this instruction is called to do the dirty work. /// @@ -369,62 +375,68 @@ static const MachineInstr *LookForDuplicate(const MachineInstr *MI, return 0; } +MachineInstr *MachineLICM::ExtractHoistableLoad(MachineInstr *MI) { + // If not, we may be able to unfold a load and hoist that. + // First test whether the instruction is loading from an amenable + // memory location. + if (!MI->getDesc().mayLoad()) return 0; + if (!MI->hasOneMemOperand()) return 0; + MachineMemOperand *MMO = *MI->memoperands_begin(); + if (MMO->isVolatile()) return 0; + MachineFunction &MF = *MI->getParent()->getParent(); + if (!MMO->getValue()) return 0; + if (const PseudoSourceValue *PSV = + dyn_cast(MMO->getValue())) { + if (!PSV->isConstant(MF.getFrameInfo())) return 0; + } else { + if (!AA->pointsToConstantMemory(MMO->getValue())) return 0; + } + // Next determine the register class for a temporary register. + unsigned NewOpc = + TII->getOpcodeAfterMemoryUnfold(MI->getOpcode(), + /*UnfoldLoad=*/true, + /*UnfoldStore=*/false); + if (NewOpc == 0) return 0; + const TargetInstrDesc &TID = TII->get(NewOpc); + if (TID.getNumDefs() != 1) return 0; + const TargetRegisterClass *RC = TID.OpInfo[0].getRegClass(TRI); + // Ok, we're unfolding. Create a temporary register and do the unfold. + unsigned Reg = RegInfo->createVirtualRegister(RC); + SmallVector NewMIs; + bool Success = + TII->unfoldMemoryOperand(MF, MI, Reg, + /*UnfoldLoad=*/true, /*UnfoldStore=*/false, + NewMIs); + (void)Success; + assert(Success && + "unfoldMemoryOperand failed when getOpcodeAfterMemoryUnfold " + "succeeded!"); + assert(NewMIs.size() == 2 && + "Unfolded a load into multiple instructions!"); + MachineBasicBlock *MBB = MI->getParent(); + MBB->insert(MI, NewMIs[0]); + MBB->insert(MI, NewMIs[1]); + // If unfolding produced a load that wasn't loop-invariant or profitable to + // hoist, discard the new instructions and bail. + if (!IsLoopInvariantInst(*NewMIs[0]) || !IsProfitableToHoist(*NewMIs[0])) { + NewMIs[0]->eraseFromParent(); + NewMIs[1]->eraseFromParent(); + return 0; + } + // Otherwise we successfully unfolded a load that we can hoist. + MI->eraseFromParent(); + return NewMIs[0]; +} + /// Hoist - When an instruction is found to use only loop invariant operands /// that are safe to hoist, this instruction is called to do the dirty work. /// void MachineLICM::Hoist(MachineInstr *MI) { // First check whether we should hoist this instruction. if (!IsLoopInvariantInst(*MI) || !IsProfitableToHoist(*MI)) { - // If not, we may be able to unfold a load and hoist that. - // First test whether the instruction is loading from an amenable - // memory location. - if (!MI->getDesc().mayLoad()) return; - if (!MI->hasOneMemOperand()) return; - MachineMemOperand *MMO = *MI->memoperands_begin(); - if (MMO->isVolatile()) return; - MachineFunction &MF = *MI->getParent()->getParent(); - if (!MMO->getValue()) return; - if (const PseudoSourceValue *PSV = - dyn_cast(MMO->getValue())) { - if (!PSV->isConstant(MF.getFrameInfo())) return; - } else { - if (!AA->pointsToConstantMemory(MMO->getValue())) return; - } - // Next determine the register class for a temporary register. - unsigned NewOpc = - TII->getOpcodeAfterMemoryUnfold(MI->getOpcode(), - /*UnfoldLoad=*/true, - /*UnfoldStore=*/false); - if (NewOpc == 0) return; - const TargetInstrDesc &TID = TII->get(NewOpc); - if (TID.getNumDefs() != 1) return; - const TargetRegisterClass *RC = TID.OpInfo[0].getRegClass(TRI); - // Ok, we're unfolding. Create a temporary register and do the unfold. - unsigned Reg = RegInfo->createVirtualRegister(RC); - SmallVector NewMIs; - bool Success = - TII->unfoldMemoryOperand(MF, MI, Reg, - /*UnfoldLoad=*/true, /*UnfoldStore=*/false, - NewMIs); - (void)Success; - assert(Success && - "unfoldMemoryOperand failed when getOpcodeAfterMemoryUnfold " - "succeeded!"); - assert(NewMIs.size() == 2 && - "Unfolded a load into multiple instructions!"); - MachineBasicBlock *MBB = MI->getParent(); - MBB->insert(MI, NewMIs[0]); - MBB->insert(MI, NewMIs[1]); - // If unfolding produced a load that wasn't loop-invariant or profitable to - // hoist, discard the new instructions and bail. - if (!IsLoopInvariantInst(*NewMIs[0]) || !IsProfitableToHoist(*NewMIs[0])) { - NewMIs[0]->eraseFromParent(); - NewMIs[1]->eraseFromParent(); - return; - } - // Otherwise we successfully unfolded a load that we can hoist. - MI->eraseFromParent(); - MI = NewMIs[0]; + // If not, try unfolding a hoistable load. + MI = ExtractHoistableLoad(MI); + if (!MI) return; } // Now move the instructions to the predecessor, inserting it before any