aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2009-10-29 17:47:20 +0000
committerDan Gohman <gohman@apple.com>2009-10-29 17:47:20 +0000
commit5c95230f25a51835375ebaae77b841c6d2c57889 (patch)
treef9185adc7e9d51ac20b58b63c597af9dfef59ade
parenta33ac6a4c18b51888bc8fd8c36b7d5cbe561161f (diff)
downloadexternal_llvm-5c95230f25a51835375ebaae77b841c6d2c57889.zip
external_llvm-5c95230f25a51835375ebaae77b841c6d2c57889.tar.gz
external_llvm-5c95230f25a51835375ebaae77b841c6d2c57889.tar.bz2
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
-rw-r--r--lib/CodeGen/MachineLICM.cpp112
1 files changed, 62 insertions, 50 deletions
diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp
index cf958f5..5ab0ff7 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<PseudoSourceValue>(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<MachineInstr *, 2> 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<PseudoSourceValue>(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<MachineInstr *, 2> 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