mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-04-17 15:10:07 +00:00
Move TryToFoldFastISelLoad to FastISel, where it belongs. In general, I'm
trying to move as much FastISel logic as possible out of the main path in SelectionDAGISel - intermixing them just adds confusion. llvm-svn: 179902
This commit is contained in:
parent
3b258b6b24
commit
09f182f14c
@ -123,11 +123,27 @@ public:
|
|||||||
/// index value.
|
/// index value.
|
||||||
std::pair<unsigned, bool> getRegForGEPIndex(const Value *V);
|
std::pair<unsigned, bool> getRegForGEPIndex(const Value *V);
|
||||||
|
|
||||||
/// TryToFoldLoad - The specified machine instr operand is a vreg, and that
|
/// \brief We're checking to see if we can fold \p LI the \p FoldInst.
|
||||||
|
/// Note that we could have a sequence where multiple LLVM IR instructions
|
||||||
|
/// are folded into the same machineinstr. For example we could have:
|
||||||
|
/// A: x = load i32 *P
|
||||||
|
/// B: y = icmp A, 42
|
||||||
|
/// C: br y, ...
|
||||||
|
///
|
||||||
|
/// In this scenario, \p LI is "A", and \p FoldInst is "C". We know
|
||||||
|
/// about "B" (and any other folded instructions) because it is between
|
||||||
|
/// A and C.
|
||||||
|
///
|
||||||
|
/// If we succeed folding, return true.
|
||||||
|
///
|
||||||
|
bool tryToFoldLoad(const LoadInst *LI, const Instruction *FoldInst);
|
||||||
|
|
||||||
|
/// \brief The specified machine instr operand is a vreg, and that
|
||||||
/// vreg is being provided by the specified load instruction. If possible,
|
/// vreg is being provided by the specified load instruction. If possible,
|
||||||
/// try to fold the load as an operand to the instruction, returning true if
|
/// try to fold the load as an operand to the instruction, returning true if
|
||||||
/// possible.
|
/// possible.
|
||||||
virtual bool TryToFoldLoad(MachineInstr * /*MI*/, unsigned /*OpNo*/,
|
/// This method should be implemented by targets.
|
||||||
|
virtual bool tryToFoldLoadIntoMI(MachineInstr * /*MI*/, unsigned /*OpNo*/,
|
||||||
const LoadInst * /*LI*/) {
|
const LoadInst * /*LI*/) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -259,9 +259,6 @@ private:
|
|||||||
void SelectBasicBlock(BasicBlock::const_iterator Begin,
|
void SelectBasicBlock(BasicBlock::const_iterator Begin,
|
||||||
BasicBlock::const_iterator End,
|
BasicBlock::const_iterator End,
|
||||||
bool &HadTailCall);
|
bool &HadTailCall);
|
||||||
|
|
||||||
bool TryToFoldFastISelLoad(const LoadInst *LI, const Instruction *FoldInst,
|
|
||||||
FastISel *FastIS);
|
|
||||||
void FinishBasicBlock();
|
void FinishBasicBlock();
|
||||||
|
|
||||||
void CodeGenAndEmitDAG();
|
void CodeGenAndEmitDAG();
|
||||||
|
@ -1505,3 +1505,68 @@ bool FastISel::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FastISel::tryToFoldLoad(const LoadInst *LI, const Instruction *FoldInst) {
|
||||||
|
// We know that the load has a single use, but don't know what it is. If it
|
||||||
|
// isn't one of the folded instructions, then we can't succeed here. Handle
|
||||||
|
// this by scanning the single-use users of the load until we get to FoldInst.
|
||||||
|
unsigned MaxUsers = 6; // Don't scan down huge single-use chains of instrs.
|
||||||
|
|
||||||
|
const Instruction *TheUser = LI->use_back();
|
||||||
|
while (TheUser != FoldInst && // Scan up until we find FoldInst.
|
||||||
|
// Stay in the right block.
|
||||||
|
TheUser->getParent() == FoldInst->getParent() &&
|
||||||
|
--MaxUsers) { // Don't scan too far.
|
||||||
|
// If there are multiple or no uses of this instruction, then bail out.
|
||||||
|
if (!TheUser->hasOneUse())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
TheUser = TheUser->use_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we didn't find the fold instruction, then we failed to collapse the
|
||||||
|
// sequence.
|
||||||
|
if (TheUser != FoldInst)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Don't try to fold volatile loads. Target has to deal with alignment
|
||||||
|
// constraints.
|
||||||
|
if (LI->isVolatile()) return false;
|
||||||
|
|
||||||
|
// Figure out which vreg this is going into. If there is no assigned vreg yet
|
||||||
|
// then there actually was no reference to it. Perhaps the load is referenced
|
||||||
|
// by a dead instruction.
|
||||||
|
unsigned LoadReg = getRegForValue(LI);
|
||||||
|
if (LoadReg == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check to see what the uses of this vreg are. If it has no uses, or more
|
||||||
|
// than one use (at the machine instr level) then we can't fold it.
|
||||||
|
MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(LoadReg);
|
||||||
|
if (RI == MRI.reg_end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// See if there is exactly one use of the vreg. If there are multiple uses,
|
||||||
|
// then the instruction got lowered to multiple machine instructions or the
|
||||||
|
// use of the loaded value ended up being multiple operands of the result, in
|
||||||
|
// either case, we can't fold this.
|
||||||
|
MachineRegisterInfo::reg_iterator PostRI = RI; ++PostRI;
|
||||||
|
if (PostRI != MRI.reg_end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
assert(RI.getOperand().isUse() &&
|
||||||
|
"The only use of the vreg must be a use, we haven't emitted the def!");
|
||||||
|
|
||||||
|
MachineInstr *User = &*RI;
|
||||||
|
|
||||||
|
// Set the insertion point properly. Folding the load can cause generation of
|
||||||
|
// other random instructions (like sign extends) for addressing modes, make
|
||||||
|
// sure they get inserted in a logical place before the new instruction.
|
||||||
|
FuncInfo.InsertPt = User;
|
||||||
|
FuncInfo.MBB = User->getParent();
|
||||||
|
|
||||||
|
// Ask the target to try folding the load.
|
||||||
|
return tryToFoldLoadIntoMI(User, RI.getOperandNo(), LI);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -835,84 +835,6 @@ void SelectionDAGISel::PrepareEHLandingPad() {
|
|||||||
if (Reg) MBB->addLiveIn(Reg);
|
if (Reg) MBB->addLiveIn(Reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TryToFoldFastISelLoad - We're checking to see if we can fold the specified
|
|
||||||
/// load into the specified FoldInst. Note that we could have a sequence where
|
|
||||||
/// multiple LLVM IR instructions are folded into the same machineinstr. For
|
|
||||||
/// example we could have:
|
|
||||||
/// A: x = load i32 *P
|
|
||||||
/// B: y = icmp A, 42
|
|
||||||
/// C: br y, ...
|
|
||||||
///
|
|
||||||
/// In this scenario, LI is "A", and FoldInst is "C". We know about "B" (and
|
|
||||||
/// any other folded instructions) because it is between A and C.
|
|
||||||
///
|
|
||||||
/// If we succeed in folding the load into the operation, return true.
|
|
||||||
///
|
|
||||||
bool SelectionDAGISel::TryToFoldFastISelLoad(const LoadInst *LI,
|
|
||||||
const Instruction *FoldInst,
|
|
||||||
FastISel *FastIS) {
|
|
||||||
// We know that the load has a single use, but don't know what it is. If it
|
|
||||||
// isn't one of the folded instructions, then we can't succeed here. Handle
|
|
||||||
// this by scanning the single-use users of the load until we get to FoldInst.
|
|
||||||
unsigned MaxUsers = 6; // Don't scan down huge single-use chains of instrs.
|
|
||||||
|
|
||||||
const Instruction *TheUser = LI->use_back();
|
|
||||||
while (TheUser != FoldInst && // Scan up until we find FoldInst.
|
|
||||||
// Stay in the right block.
|
|
||||||
TheUser->getParent() == FoldInst->getParent() &&
|
|
||||||
--MaxUsers) { // Don't scan too far.
|
|
||||||
// If there are multiple or no uses of this instruction, then bail out.
|
|
||||||
if (!TheUser->hasOneUse())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
TheUser = TheUser->use_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we didn't find the fold instruction, then we failed to collapse the
|
|
||||||
// sequence.
|
|
||||||
if (TheUser != FoldInst)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Don't try to fold volatile loads. Target has to deal with alignment
|
|
||||||
// constraints.
|
|
||||||
if (LI->isVolatile()) return false;
|
|
||||||
|
|
||||||
// Figure out which vreg this is going into. If there is no assigned vreg yet
|
|
||||||
// then there actually was no reference to it. Perhaps the load is referenced
|
|
||||||
// by a dead instruction.
|
|
||||||
unsigned LoadReg = FastIS->getRegForValue(LI);
|
|
||||||
if (LoadReg == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check to see what the uses of this vreg are. If it has no uses, or more
|
|
||||||
// than one use (at the machine instr level) then we can't fold it.
|
|
||||||
MachineRegisterInfo::reg_iterator RI = RegInfo->reg_begin(LoadReg);
|
|
||||||
if (RI == RegInfo->reg_end())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// See if there is exactly one use of the vreg. If there are multiple uses,
|
|
||||||
// then the instruction got lowered to multiple machine instructions or the
|
|
||||||
// use of the loaded value ended up being multiple operands of the result, in
|
|
||||||
// either case, we can't fold this.
|
|
||||||
MachineRegisterInfo::reg_iterator PostRI = RI; ++PostRI;
|
|
||||||
if (PostRI != RegInfo->reg_end())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
assert(RI.getOperand().isUse() &&
|
|
||||||
"The only use of the vreg must be a use, we haven't emitted the def!");
|
|
||||||
|
|
||||||
MachineInstr *User = &*RI;
|
|
||||||
|
|
||||||
// Set the insertion point properly. Folding the load can cause generation of
|
|
||||||
// other random instructions (like sign extends) for addressing modes, make
|
|
||||||
// sure they get inserted in a logical place before the new instruction.
|
|
||||||
FuncInfo->InsertPt = User;
|
|
||||||
FuncInfo->MBB = User->getParent();
|
|
||||||
|
|
||||||
// Ask the target to try folding the load.
|
|
||||||
return FastIS->TryToFoldLoad(User, RI.getOperandNo(), LI);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// isFoldedOrDeadInstruction - Return true if the specified instruction is
|
/// isFoldedOrDeadInstruction - Return true if the specified instruction is
|
||||||
/// side-effect free and is either dead or folded into a generated instruction.
|
/// side-effect free and is either dead or folded into a generated instruction.
|
||||||
/// Return false if it needs to be emitted.
|
/// Return false if it needs to be emitted.
|
||||||
@ -1113,7 +1035,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
|||||||
}
|
}
|
||||||
if (BeforeInst != Inst && isa<LoadInst>(BeforeInst) &&
|
if (BeforeInst != Inst && isa<LoadInst>(BeforeInst) &&
|
||||||
BeforeInst->hasOneUse() &&
|
BeforeInst->hasOneUse() &&
|
||||||
TryToFoldFastISelLoad(cast<LoadInst>(BeforeInst), Inst, FastIS)) {
|
FastIS->tryToFoldLoad(cast<LoadInst>(BeforeInst), Inst)) {
|
||||||
// If we succeeded, don't re-select the load.
|
// If we succeeded, don't re-select the load.
|
||||||
BI = llvm::next(BasicBlock::const_iterator(BeforeInst));
|
BI = llvm::next(BasicBlock::const_iterator(BeforeInst));
|
||||||
--NumFastIselRemaining;
|
--NumFastIselRemaining;
|
||||||
|
@ -144,7 +144,7 @@ class ARMFastISel : public FastISel {
|
|||||||
virtual bool TargetSelectInstruction(const Instruction *I);
|
virtual bool TargetSelectInstruction(const Instruction *I);
|
||||||
virtual unsigned TargetMaterializeConstant(const Constant *C);
|
virtual unsigned TargetMaterializeConstant(const Constant *C);
|
||||||
virtual unsigned TargetMaterializeAlloca(const AllocaInst *AI);
|
virtual unsigned TargetMaterializeAlloca(const AllocaInst *AI);
|
||||||
virtual bool TryToFoldLoad(MachineInstr *MI, unsigned OpNo,
|
virtual bool tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
|
||||||
const LoadInst *LI);
|
const LoadInst *LI);
|
||||||
virtual bool FastLowerArguments();
|
virtual bool FastLowerArguments();
|
||||||
private:
|
private:
|
||||||
@ -2797,11 +2797,11 @@ bool ARMFastISel::TargetSelectInstruction(const Instruction *I) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TryToFoldLoad - The specified machine instr operand is a vreg, and that
|
/// \brief The specified machine instr operand is a vreg, and that
|
||||||
/// vreg is being provided by the specified load instruction. If possible,
|
/// vreg is being provided by the specified load instruction. If possible,
|
||||||
/// try to fold the load as an operand to the instruction, returning true if
|
/// try to fold the load as an operand to the instruction, returning true if
|
||||||
/// successful.
|
/// successful.
|
||||||
bool ARMFastISel::TryToFoldLoad(MachineInstr *MI, unsigned OpNo,
|
bool ARMFastISel::tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
|
||||||
const LoadInst *LI) {
|
const LoadInst *LI) {
|
||||||
// Verify we have a legal type before going any further.
|
// Verify we have a legal type before going any further.
|
||||||
MVT VT;
|
MVT VT;
|
||||||
|
@ -68,11 +68,11 @@ public:
|
|||||||
|
|
||||||
virtual bool TargetSelectInstruction(const Instruction *I);
|
virtual bool TargetSelectInstruction(const Instruction *I);
|
||||||
|
|
||||||
/// TryToFoldLoad - The specified machine instr operand is a vreg, and that
|
/// \brief The specified machine instr operand is a vreg, and that
|
||||||
/// vreg is being provided by the specified load instruction. If possible,
|
/// vreg is being provided by the specified load instruction. If possible,
|
||||||
/// try to fold the load as an operand to the instruction, returning true if
|
/// try to fold the load as an operand to the instruction, returning true if
|
||||||
/// possible.
|
/// possible.
|
||||||
virtual bool TryToFoldLoad(MachineInstr *MI, unsigned OpNo,
|
virtual bool tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
|
||||||
const LoadInst *LI);
|
const LoadInst *LI);
|
||||||
|
|
||||||
virtual bool FastLowerArguments();
|
virtual bool FastLowerArguments();
|
||||||
@ -2395,11 +2395,7 @@ unsigned X86FastISel::TargetMaterializeFloatZero(const ConstantFP *CF) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// TryToFoldLoad - The specified machine instr operand is a vreg, and that
|
bool X86FastISel::tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
|
||||||
/// vreg is being provided by the specified load instruction. If possible,
|
|
||||||
/// try to fold the load as an operand to the instruction, returning true if
|
|
||||||
/// possible.
|
|
||||||
bool X86FastISel::TryToFoldLoad(MachineInstr *MI, unsigned OpNo,
|
|
||||||
const LoadInst *LI) {
|
const LoadInst *LI) {
|
||||||
X86AddressMode AM;
|
X86AddressMode AM;
|
||||||
if (!X86SelectAddress(LI->getOperand(0), AM))
|
if (!X86SelectAddress(LI->getOperand(0), AM))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user