mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-14 15:39:00 +00:00
Implement bottom-up fast-isel. This has the advantage of not requiring
a separate DCE pass over MachineInstrs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@107804 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f423a69839
commit
4df83ed159
@ -19,6 +19,7 @@
|
|||||||
#include "llvm/ADT/SmallSet.h"
|
#include "llvm/ADT/SmallSet.h"
|
||||||
#endif
|
#endif
|
||||||
#include "llvm/CodeGen/ValueTypes.h"
|
#include "llvm/CodeGen/ValueTypes.h"
|
||||||
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
@ -55,15 +56,17 @@ protected:
|
|||||||
const TargetInstrInfo &TII;
|
const TargetInstrInfo &TII;
|
||||||
const TargetLowering &TLI;
|
const TargetLowering &TLI;
|
||||||
const TargetRegisterInfo &TRI;
|
const TargetRegisterInfo &TRI;
|
||||||
bool IsBottomUp;
|
MachineBasicBlock::iterator LastLocalValue;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/// getLastLocalValue - Return the position of the last instruction
|
||||||
|
/// emitted for materializing constants for use in the current block.
|
||||||
|
MachineBasicBlock::iterator getLastLocalValue() { return LastLocalValue; }
|
||||||
|
|
||||||
/// startNewBlock - Set the current block to which generated machine
|
/// startNewBlock - Set the current block to which generated machine
|
||||||
/// instructions will be appended, and clear the local CSE map.
|
/// instructions will be appended, and clear the local CSE map.
|
||||||
///
|
///
|
||||||
void startNewBlock() {
|
void startNewBlock();
|
||||||
LocalValueMap.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// getCurDebugLoc() - Return current debug location information.
|
/// getCurDebugLoc() - Return current debug location information.
|
||||||
DebugLoc getCurDebugLoc() const { return DL; }
|
DebugLoc getCurDebugLoc() const { return DL; }
|
||||||
|
@ -329,19 +329,15 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM,
|
|||||||
if (OptLevel != CodeGenOpt::None)
|
if (OptLevel != CodeGenOpt::None)
|
||||||
PM.add(createOptimizePHIsPass());
|
PM.add(createOptimizePHIsPass());
|
||||||
|
|
||||||
// Delete dead machine instructions regardless of optimization level.
|
|
||||||
//
|
|
||||||
// At -O0, fast-isel frequently creates dead instructions.
|
|
||||||
//
|
|
||||||
// With optimization, dead code should already be eliminated. However
|
|
||||||
// there is one known exception: lowered code for arguments that are only
|
|
||||||
// used by tail calls, where the tail calls reuse the incoming stack
|
|
||||||
// arguments directly (see t11 in test/CodeGen/X86/sibcall.ll).
|
|
||||||
PM.add(createDeadMachineInstructionElimPass());
|
|
||||||
printAndVerify(PM, "After codegen DCE pass",
|
|
||||||
/* allowDoubleDefs= */ true);
|
|
||||||
|
|
||||||
if (OptLevel != CodeGenOpt::None) {
|
if (OptLevel != CodeGenOpt::None) {
|
||||||
|
// With optimization, dead code should already be eliminated. However
|
||||||
|
// there is one known exception: lowered code for arguments that are only
|
||||||
|
// used by tail calls, where the tail calls reuse the incoming stack
|
||||||
|
// arguments directly (see t11 in test/CodeGen/X86/sibcall.ll).
|
||||||
|
PM.add(createDeadMachineInstructionElimPass());
|
||||||
|
printAndVerify(PM, "After codegen DCE pass",
|
||||||
|
/* allowDoubleDefs= */ true);
|
||||||
|
|
||||||
PM.add(createOptimizeExtsPass());
|
PM.add(createOptimizeExtsPass());
|
||||||
if (!DisableMachineLICM)
|
if (!DisableMachineLICM)
|
||||||
PM.add(createMachineLICMPass());
|
PM.add(createMachineLICMPass());
|
||||||
|
@ -57,6 +57,17 @@
|
|||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
/// startNewBlock - Set the current block to which generated machine
|
||||||
|
/// instructions will be appended, and clear the local CSE map.
|
||||||
|
///
|
||||||
|
void FastISel::startNewBlock() {
|
||||||
|
LocalValueMap.clear();
|
||||||
|
|
||||||
|
// Start out as end(), meaining no local-value instructions have
|
||||||
|
// been emitted.
|
||||||
|
LastLocalValue = FuncInfo.MBB->end();
|
||||||
|
}
|
||||||
|
|
||||||
bool FastISel::hasTrivialKill(const Value *V) const {
|
bool FastISel::hasTrivialKill(const Value *V) const {
|
||||||
// Don't consider constants or arguments to have trivial kills.
|
// Don't consider constants or arguments to have trivial kills.
|
||||||
const Instruction *I = dyn_cast<Instruction>(V);
|
const Instruction *I = dyn_cast<Instruction>(V);
|
||||||
@ -109,12 +120,9 @@ unsigned FastISel::getRegForValue(const Value *V) {
|
|||||||
|
|
||||||
// In bottom-up mode, just create the virtual register which will be used
|
// In bottom-up mode, just create the virtual register which will be used
|
||||||
// to hold the value. It will be materialized later.
|
// to hold the value. It will be materialized later.
|
||||||
if (IsBottomUp) {
|
if (isa<Instruction>(V)) {
|
||||||
Reg = createResultReg(TLI.getRegClassFor(VT));
|
Reg = createResultReg(TLI.getRegClassFor(VT));
|
||||||
if (isa<Instruction>(V))
|
FuncInfo.ValueMap[V] = Reg;
|
||||||
FuncInfo.ValueMap[V] = Reg;
|
|
||||||
else
|
|
||||||
LocalValueMap[V] = Reg;
|
|
||||||
return Reg;
|
return Reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,8 +188,10 @@ unsigned FastISel::materializeRegForValue(const Value *V, MVT VT) {
|
|||||||
|
|
||||||
// Don't cache constant materializations in the general ValueMap.
|
// Don't cache constant materializations in the general ValueMap.
|
||||||
// To do so would require tracking what uses they dominate.
|
// To do so would require tracking what uses they dominate.
|
||||||
if (Reg != 0)
|
if (Reg != 0) {
|
||||||
LocalValueMap[V] = Reg;
|
LocalValueMap[V] = Reg;
|
||||||
|
LastLocalValue = MRI.getVRegDef(Reg);
|
||||||
|
}
|
||||||
return Reg;
|
return Reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,12 +220,20 @@ unsigned FastISel::UpdateValueMap(const Value *I, unsigned Reg) {
|
|||||||
|
|
||||||
unsigned &AssignedReg = FuncInfo.ValueMap[I];
|
unsigned &AssignedReg = FuncInfo.ValueMap[I];
|
||||||
if (AssignedReg == 0)
|
if (AssignedReg == 0)
|
||||||
|
// Use the new register.
|
||||||
AssignedReg = Reg;
|
AssignedReg = Reg;
|
||||||
else if (Reg != AssignedReg) {
|
else if (Reg != AssignedReg) {
|
||||||
const TargetRegisterClass *RegClass = MRI.getRegClass(Reg);
|
// We already have a register for this value. Replace uses of
|
||||||
TII.copyRegToReg(*FuncInfo.MBB, FuncInfo.InsertPt, AssignedReg,
|
// the existing register with uses of the new one.
|
||||||
Reg, RegClass, RegClass, DL);
|
MRI.replaceRegWith(AssignedReg, Reg);
|
||||||
|
// Replace uses of the existing register in PHINodesToUpdate too.
|
||||||
|
for (unsigned i = 0, e = FuncInfo.PHINodesToUpdate.size(); i != e; ++i)
|
||||||
|
if (FuncInfo.PHINodesToUpdate[i].second == AssignedReg)
|
||||||
|
FuncInfo.PHINodesToUpdate[i].second = Reg;
|
||||||
|
// And update the ValueMap.
|
||||||
|
AssignedReg = Reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
return AssignedReg;
|
return AssignedReg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -736,11 +754,15 @@ FastISel::SelectLoad(const User *I) {
|
|||||||
BasicBlock::iterator ScanFrom = LI;
|
BasicBlock::iterator ScanFrom = LI;
|
||||||
if (const Value *V = FindAvailableLoadedValue(LI->getPointerOperand(),
|
if (const Value *V = FindAvailableLoadedValue(LI->getPointerOperand(),
|
||||||
LI->getParent(), ScanFrom)) {
|
LI->getParent(), ScanFrom)) {
|
||||||
|
if (!isa<Instruction>(V) ||
|
||||||
|
cast<Instruction>(V)->getParent() == LI->getParent() ||
|
||||||
|
(isa<AllocaInst>(V) && FuncInfo.StaticAllocaMap.count(cast<AllocaInst>(V)))) {
|
||||||
unsigned ResultReg = getRegForValue(V);
|
unsigned ResultReg = getRegForValue(V);
|
||||||
if (ResultReg != 0) {
|
if (ResultReg != 0) {
|
||||||
UpdateValueMap(I, ResultReg);
|
UpdateValueMap(I, ResultReg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -871,8 +893,7 @@ FastISel::FastISel(FunctionLoweringInfo &funcInfo)
|
|||||||
TD(*TM.getTargetData()),
|
TD(*TM.getTargetData()),
|
||||||
TII(*TM.getInstrInfo()),
|
TII(*TM.getInstrInfo()),
|
||||||
TLI(*TM.getTargetLowering()),
|
TLI(*TM.getTargetLowering()),
|
||||||
TRI(*TM.getRegisterInfo()),
|
TRI(*TM.getRegisterInfo()) {
|
||||||
IsBottomUp(false) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FastISel::~FastISel() {}
|
FastISel::~FastISel() {}
|
||||||
|
@ -78,6 +78,13 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf) {
|
|||||||
MF = &mf;
|
MF = &mf;
|
||||||
RegInfo = &MF->getRegInfo();
|
RegInfo = &MF->getRegInfo();
|
||||||
|
|
||||||
|
// Check whether the function can return without sret-demotion.
|
||||||
|
SmallVector<ISD::OutputArg, 4> Outs;
|
||||||
|
GetReturnInfo(Fn->getReturnType(),
|
||||||
|
Fn->getAttributes().getRetAttributes(), Outs, TLI);
|
||||||
|
CanLowerReturn = TLI.CanLowerReturn(Fn->getCallingConv(), Fn->isVarArg(),
|
||||||
|
Outs, Fn->getContext());
|
||||||
|
|
||||||
// Create a vreg for each argument register that is not dead and is used
|
// Create a vreg for each argument register that is not dead and is used
|
||||||
// outside of the entry block for the function.
|
// outside of the entry block for the function.
|
||||||
for (Function::const_arg_iterator AI = Fn->arg_begin(), E = Fn->arg_end();
|
for (Function::const_arg_iterator AI = Fn->arg_begin(), E = Fn->arg_end();
|
||||||
|
@ -951,12 +951,10 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) {
|
|||||||
|
|
||||||
// If this is an instruction which fast-isel has deferred, select it now.
|
// If this is an instruction which fast-isel has deferred, select it now.
|
||||||
if (const Instruction *Inst = dyn_cast<Instruction>(V)) {
|
if (const Instruction *Inst = dyn_cast<Instruction>(V)) {
|
||||||
assert(Inst->isSafeToSpeculativelyExecute() &&
|
unsigned InReg = FuncInfo.InitializeRegForValue(Inst);
|
||||||
"Instruction with side effects deferred!");
|
RegsForValue RFV(*DAG.getContext(), TLI, InReg, Inst->getType());
|
||||||
visit(*Inst);
|
SDValue Chain = DAG.getEntryNode();
|
||||||
DenseMap<const Value *, SDValue>::iterator NIt = NodeMap.find(Inst);
|
return RFV.getCopyFromRegs(DAG, FuncInfo, getCurDebugLoc(), Chain, NULL);
|
||||||
if (NIt != NodeMap.end() && NIt->second.getNode())
|
|
||||||
return NIt->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm_unreachable("Can't get register for value!");
|
llvm_unreachable("Can't get register for value!");
|
||||||
@ -1259,7 +1257,7 @@ SelectionDAGBuilder::ShouldEmitAsBranches(const std::vector<CaseBlock> &Cases){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SelectionDAGBuilder::visitBr(const BranchInst &I) {
|
void SelectionDAGBuilder::visitBr(const BranchInst &I) {
|
||||||
MachineBasicBlock *BrMBB = FuncInfo.MBBMap[I.getParent()];
|
MachineBasicBlock *BrMBB = FuncInfo.MBB;
|
||||||
|
|
||||||
// Update machine-CFG edges.
|
// Update machine-CFG edges.
|
||||||
MachineBasicBlock *Succ0MBB = FuncInfo.MBBMap[I.getSuccessor(0)];
|
MachineBasicBlock *Succ0MBB = FuncInfo.MBBMap[I.getSuccessor(0)];
|
||||||
@ -1585,7 +1583,7 @@ void SelectionDAGBuilder::visitBitTestCase(MachineBasicBlock* NextMBB,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) {
|
void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) {
|
||||||
MachineBasicBlock *InvokeMBB = FuncInfo.MBBMap[I.getParent()];
|
MachineBasicBlock *InvokeMBB = FuncInfo.MBB;
|
||||||
|
|
||||||
// Retrieve successors.
|
// Retrieve successors.
|
||||||
MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)];
|
MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)];
|
||||||
@ -2113,7 +2111,7 @@ size_t SelectionDAGBuilder::Clusterify(CaseVector& Cases,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SelectionDAGBuilder::visitSwitch(const SwitchInst &SI) {
|
void SelectionDAGBuilder::visitSwitch(const SwitchInst &SI) {
|
||||||
MachineBasicBlock *SwitchMBB = FuncInfo.MBBMap[SI.getParent()];
|
MachineBasicBlock *SwitchMBB = FuncInfo.MBB;
|
||||||
|
|
||||||
// Figure out which block is immediately after the current one.
|
// Figure out which block is immediately after the current one.
|
||||||
MachineBasicBlock *NextBlock = 0;
|
MachineBasicBlock *NextBlock = 0;
|
||||||
@ -2179,7 +2177,7 @@ void SelectionDAGBuilder::visitSwitch(const SwitchInst &SI) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SelectionDAGBuilder::visitIndirectBr(const IndirectBrInst &I) {
|
void SelectionDAGBuilder::visitIndirectBr(const IndirectBrInst &I) {
|
||||||
MachineBasicBlock *IndirectBrMBB = FuncInfo.MBBMap[I.getParent()];
|
MachineBasicBlock *IndirectBrMBB = FuncInfo.MBB;
|
||||||
|
|
||||||
// Update machine-CFG edges with unique successors.
|
// Update machine-CFG edges with unique successors.
|
||||||
SmallVector<BasicBlock*, 32> succs;
|
SmallVector<BasicBlock*, 32> succs;
|
||||||
@ -3839,7 +3837,7 @@ SelectionDAGBuilder::EmitFuncArgumentDbgValue(const DbgValueInst &DI,
|
|||||||
if (DV.isInlinedFnArgument(MF.getFunction()))
|
if (DV.isInlinedFnArgument(MF.getFunction()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MachineBasicBlock *MBB = FuncInfo.MBBMap[DI.getParent()];
|
MachineBasicBlock *MBB = FuncInfo.MBB;
|
||||||
if (MBB != &MF.front())
|
if (MBB != &MF.front())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -4102,7 +4100,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
|||||||
}
|
}
|
||||||
case Intrinsic::eh_exception: {
|
case Intrinsic::eh_exception: {
|
||||||
// Insert the EXCEPTIONADDR instruction.
|
// Insert the EXCEPTIONADDR instruction.
|
||||||
assert(FuncInfo.MBBMap[I.getParent()]->isLandingPad() &&
|
assert(FuncInfo.MBB->isLandingPad() &&
|
||||||
"Call to eh.exception not in landing pad!");
|
"Call to eh.exception not in landing pad!");
|
||||||
SDVTList VTs = DAG.getVTList(TLI.getPointerTy(), MVT::Other);
|
SDVTList VTs = DAG.getVTList(TLI.getPointerTy(), MVT::Other);
|
||||||
SDValue Ops[1];
|
SDValue Ops[1];
|
||||||
@ -4114,7 +4112,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case Intrinsic::eh_selector: {
|
case Intrinsic::eh_selector: {
|
||||||
MachineBasicBlock *CallMBB = FuncInfo.MBBMap[I.getParent()];
|
MachineBasicBlock *CallMBB = FuncInfo.MBB;
|
||||||
MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI();
|
MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI();
|
||||||
if (CallMBB->isLandingPad())
|
if (CallMBB->isLandingPad())
|
||||||
AddCatchInfo(I, &MMI, CallMBB);
|
AddCatchInfo(I, &MMI, CallMBB);
|
||||||
@ -4124,7 +4122,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
|||||||
#endif
|
#endif
|
||||||
// FIXME: Mark exception selector register as live in. Hack for PR1508.
|
// FIXME: Mark exception selector register as live in. Hack for PR1508.
|
||||||
unsigned Reg = TLI.getExceptionSelectorRegister();
|
unsigned Reg = TLI.getExceptionSelectorRegister();
|
||||||
if (Reg) FuncInfo.MBBMap[I.getParent()]->addLiveIn(Reg);
|
if (Reg) FuncInfo.MBB->addLiveIn(Reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert the EHSELECTION instruction.
|
// Insert the EHSELECTION instruction.
|
||||||
@ -5901,9 +5899,6 @@ void SelectionDAGISel::LowerArguments(const BasicBlock *LLVMBB) {
|
|||||||
GetReturnInfo(F.getReturnType(), F.getAttributes().getRetAttributes(),
|
GetReturnInfo(F.getReturnType(), F.getAttributes().getRetAttributes(),
|
||||||
Outs, TLI);
|
Outs, TLI);
|
||||||
|
|
||||||
FuncInfo->CanLowerReturn = TLI.CanLowerReturn(F.getCallingConv(),
|
|
||||||
F.isVarArg(),
|
|
||||||
Outs, F.getContext());
|
|
||||||
if (!FuncInfo->CanLowerReturn) {
|
if (!FuncInfo->CanLowerReturn) {
|
||||||
// Put in an sret pointer parameter before all the other parameters.
|
// Put in an sret pointer parameter before all the other parameters.
|
||||||
SmallVector<EVT, 1> ValueVTs;
|
SmallVector<EVT, 1> ValueVTs;
|
||||||
|
@ -680,60 +680,55 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
|||||||
|
|
||||||
BasicBlock::const_iterator const Begin = LLVMBB->getFirstNonPHI();
|
BasicBlock::const_iterator const Begin = LLVMBB->getFirstNonPHI();
|
||||||
BasicBlock::const_iterator const End = LLVMBB->end();
|
BasicBlock::const_iterator const End = LLVMBB->end();
|
||||||
BasicBlock::const_iterator BI = Begin;
|
BasicBlock::const_iterator BI = End;
|
||||||
|
|
||||||
// Lower any arguments needed in this block if this is the entry block.
|
|
||||||
if (LLVMBB == &Fn.getEntryBlock())
|
|
||||||
LowerArguments(LLVMBB);
|
|
||||||
|
|
||||||
// Setup an EH landing-pad block.
|
|
||||||
if (FuncInfo->MBB->isLandingPad())
|
|
||||||
PrepareEHLandingPad();
|
|
||||||
|
|
||||||
// Before doing SelectionDAG ISel, see if FastISel has been requested.
|
// Before doing SelectionDAG ISel, see if FastISel has been requested.
|
||||||
if (FastIS) {
|
if (FastIS) {
|
||||||
// Emit code for any incoming arguments. This must happen before
|
|
||||||
// beginning FastISel on the entry block.
|
|
||||||
if (LLVMBB == &Fn.getEntryBlock()) {
|
|
||||||
CurDAG->setRoot(SDB->getControlRoot());
|
|
||||||
SDB->clear();
|
|
||||||
CodeGenAndEmitDAG();
|
|
||||||
}
|
|
||||||
FastIS->startNewBlock();
|
FastIS->startNewBlock();
|
||||||
|
|
||||||
// Do FastISel on as many instructions as possible.
|
// Do FastISel on as many instructions as possible.
|
||||||
for (; BI != End; ++BI) {
|
for (; BI != Begin; --BI) {
|
||||||
#if 0
|
const Instruction *Inst = llvm::prior(BI);
|
||||||
// Defer instructions with no side effects; they'll be emitted
|
|
||||||
// on-demand later.
|
// If we no longer require this instruction, skip it.
|
||||||
if (BI->isSafeToSpeculativelyExecute() &&
|
if (!Inst->mayWriteToMemory() &&
|
||||||
!FuncInfo->isExportedInst(BI))
|
!isa<TerminatorInst>(Inst) &&
|
||||||
|
!isa<DbgInfoIntrinsic>(Inst) &&
|
||||||
|
!FuncInfo->isExportedInst(Inst))
|
||||||
continue;
|
continue;
|
||||||
#endif
|
|
||||||
|
// Bottom-up: reset the insert pos at the top, after any local-value
|
||||||
|
// instructions.
|
||||||
|
MachineBasicBlock::iterator LVIP = FastIS->getLastLocalValue();
|
||||||
|
if (LVIP != FuncInfo->MBB->end())
|
||||||
|
FuncInfo->InsertPt = next(LVIP);
|
||||||
|
else
|
||||||
|
FuncInfo->InsertPt = FuncInfo->MBB->getFirstNonPHI();
|
||||||
|
|
||||||
// Try to select the instruction with FastISel.
|
// Try to select the instruction with FastISel.
|
||||||
if (FastIS->SelectInstruction(BI))
|
if (FastIS->SelectInstruction(Inst))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Then handle certain instructions as single-LLVM-Instruction blocks.
|
// Then handle certain instructions as single-LLVM-Instruction blocks.
|
||||||
if (isa<CallInst>(BI)) {
|
if (isa<CallInst>(Inst)) {
|
||||||
++NumFastIselFailures;
|
++NumFastIselFailures;
|
||||||
if (EnableFastISelVerbose || EnableFastISelAbort) {
|
if (EnableFastISelVerbose || EnableFastISelAbort) {
|
||||||
dbgs() << "FastISel missed call: ";
|
dbgs() << "FastISel missed call: ";
|
||||||
BI->dump();
|
Inst->dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!BI->getType()->isVoidTy() && !BI->use_empty()) {
|
if (!Inst->getType()->isVoidTy() && !Inst->use_empty()) {
|
||||||
unsigned &R = FuncInfo->ValueMap[BI];
|
unsigned &R = FuncInfo->ValueMap[Inst];
|
||||||
if (!R)
|
if (!R)
|
||||||
R = FuncInfo->CreateRegs(BI->getType());
|
R = FuncInfo->CreateRegs(Inst->getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HadTailCall = false;
|
bool HadTailCall = false;
|
||||||
SelectBasicBlock(BI, llvm::next(BI), HadTailCall);
|
SelectBasicBlock(Inst, BI, HadTailCall);
|
||||||
|
|
||||||
// If the call was emitted as a tail call, we're done with the block.
|
// If the call was emitted as a tail call, we're done with the block.
|
||||||
if (HadTailCall) {
|
if (HadTailCall) {
|
||||||
BI = End;
|
--BI;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -746,7 +741,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
|||||||
++NumFastIselFailures;
|
++NumFastIselFailures;
|
||||||
if (EnableFastISelVerbose || EnableFastISelAbort) {
|
if (EnableFastISelVerbose || EnableFastISelAbort) {
|
||||||
dbgs() << "FastISel miss: ";
|
dbgs() << "FastISel miss: ";
|
||||||
BI->dump();
|
Inst->dump();
|
||||||
}
|
}
|
||||||
if (EnableFastISelAbort)
|
if (EnableFastISelAbort)
|
||||||
// The "fast" selector couldn't handle something and bailed.
|
// The "fast" selector couldn't handle something and bailed.
|
||||||
@ -757,13 +752,21 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FuncInfo->InsertPt = FuncInfo->MBB->getFirstNonPHI();
|
||||||
|
|
||||||
|
// Setup an EH landing-pad block.
|
||||||
|
if (FuncInfo->MBB->isLandingPad())
|
||||||
|
PrepareEHLandingPad();
|
||||||
|
|
||||||
|
// Lower any arguments needed in this block if this is the entry block.
|
||||||
|
if (LLVMBB == &Fn.getEntryBlock())
|
||||||
|
LowerArguments(LLVMBB);
|
||||||
|
|
||||||
// Run SelectionDAG instruction selection on the remainder of the block
|
// Run SelectionDAG instruction selection on the remainder of the block
|
||||||
// not handled by FastISel. If FastISel is not run, this is the entire
|
// not handled by FastISel. If FastISel is not run, this is the entire
|
||||||
// block.
|
// block.
|
||||||
if (BI != End) {
|
bool HadTailCall;
|
||||||
bool HadTailCall;
|
SelectBasicBlock(Begin, BI, HadTailCall);
|
||||||
SelectBasicBlock(BI, End, HadTailCall);
|
|
||||||
}
|
|
||||||
|
|
||||||
FinishBasicBlock();
|
FinishBasicBlock();
|
||||||
FuncInfo->PHINodesToUpdate.clear();
|
FuncInfo->PHINodesToUpdate.clear();
|
||||||
@ -963,7 +966,8 @@ SelectionDAGISel::FinishBasicBlock() {
|
|||||||
for (unsigned i = 0, e = Succs.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Succs.size(); i != e; ++i) {
|
||||||
FuncInfo->MBB = Succs[i];
|
FuncInfo->MBB = Succs[i];
|
||||||
FuncInfo->InsertPt = FuncInfo->MBB->end();
|
FuncInfo->InsertPt = FuncInfo->MBB->end();
|
||||||
// BB may have been removed from the CFG if a branch was constant folded.
|
// FuncInfo->MBB may have been removed from the CFG if a branch was
|
||||||
|
// constant folded.
|
||||||
if (ThisBB->isSuccessor(FuncInfo->MBB)) {
|
if (ThisBB->isSuccessor(FuncInfo->MBB)) {
|
||||||
for (MachineBasicBlock::iterator Phi = FuncInfo->MBB->begin();
|
for (MachineBasicBlock::iterator Phi = FuncInfo->MBB->begin();
|
||||||
Phi != FuncInfo->MBB->end() && Phi->isPHI();
|
Phi != FuncInfo->MBB->end() && Phi->isPHI();
|
||||||
|
@ -108,6 +108,7 @@ private:
|
|||||||
bool X86SelectCall(const Instruction *I);
|
bool X86SelectCall(const Instruction *I);
|
||||||
|
|
||||||
CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool isTailCall = false);
|
CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool isTailCall = false);
|
||||||
|
CCAssignFn *CCAssignFnForRet(CallingConv::ID CC, bool isTailCall = false);
|
||||||
|
|
||||||
const X86InstrInfo *getInstrInfo() const {
|
const X86InstrInfo *getInstrInfo() const {
|
||||||
return getTargetMachine()->getInstrInfo();
|
return getTargetMachine()->getInstrInfo();
|
||||||
@ -181,6 +182,20 @@ CCAssignFn *X86FastISel::CCAssignFnForCall(CallingConv::ID CC,
|
|||||||
return CC_X86_32_C;
|
return CC_X86_32_C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// CCAssignFnForRet - Selects the correct CCAssignFn for a given calling
|
||||||
|
/// convention.
|
||||||
|
CCAssignFn *X86FastISel::CCAssignFnForRet(CallingConv::ID CC,
|
||||||
|
bool isTaillCall) {
|
||||||
|
if (Subtarget->is64Bit()) {
|
||||||
|
if (Subtarget->isTargetWin64())
|
||||||
|
return RetCC_X86_Win64_C;
|
||||||
|
else
|
||||||
|
return RetCC_X86_64_C;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RetCC_X86_32_C;
|
||||||
|
}
|
||||||
|
|
||||||
/// X86FastEmitLoad - Emit a machine instruction to load a value of type VT.
|
/// X86FastEmitLoad - Emit a machine instruction to load a value of type VT.
|
||||||
/// The address is either pre-computed, i.e. Ptr, or a GlobalAddress, i.e. GV.
|
/// The address is either pre-computed, i.e. Ptr, or a GlobalAddress, i.e. GV.
|
||||||
/// Return true and the result register by reference if it is possible.
|
/// Return true and the result register by reference if it is possible.
|
||||||
@ -689,34 +704,39 @@ bool X86FastISel::X86SelectRet(const Instruction *I) {
|
|||||||
if (F.isVarArg())
|
if (F.isVarArg())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SmallVector<ISD::OutputArg, 4> Outs;
|
if (Ret->getNumOperands() > 0) {
|
||||||
GetReturnInfo(F.getReturnType(), F.getAttributes().getRetAttributes(),
|
SmallVector<ISD::OutputArg, 4> Outs;
|
||||||
Outs, TLI);
|
GetReturnInfo(F.getReturnType(), F.getAttributes().getRetAttributes(),
|
||||||
|
Outs, TLI);
|
||||||
|
|
||||||
// Analyze operands of the call, assigning locations to each operand.
|
// Analyze operands of the call, assigning locations to each operand.
|
||||||
SmallVector<CCValAssign, 16> ValLocs;
|
SmallVector<CCValAssign, 16> ValLocs;
|
||||||
CCState CCInfo(CC, F.isVarArg(), TM, ValLocs, I->getContext());
|
CCState CCInfo(CC, F.isVarArg(), TM, ValLocs, I->getContext());
|
||||||
CCInfo.AnalyzeReturn(Outs, CCAssignFnForCall(CC));
|
CCInfo.AnalyzeReturn(Outs, CCAssignFnForRet(CC));
|
||||||
|
|
||||||
// Copy the return value into registers.
|
const Value *RV = Ret->getOperand(0);
|
||||||
for (unsigned i = 0, e = ValLocs.size(); i != e; ++i) {
|
|
||||||
CCValAssign &VA = ValLocs[i];
|
|
||||||
|
|
||||||
// Don't bother handling odd stuff for now.
|
|
||||||
if (VA.getLocInfo() != CCValAssign::Full)
|
|
||||||
return false;
|
|
||||||
if (!VA.isRegLoc())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const Value *RV = Ret->getOperand(VA.getValNo());
|
|
||||||
unsigned Reg = getRegForValue(RV);
|
unsigned Reg = getRegForValue(RV);
|
||||||
|
if (Reg == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
TargetRegisterClass* RC = TLI.getRegClassFor(VA.getValVT());
|
// Copy the return value into registers.
|
||||||
bool Emitted = TII.copyRegToReg(*FuncInfo.MBB, FuncInfo.InsertPt,
|
for (unsigned i = 0, e = ValLocs.size(); i != e; ++i) {
|
||||||
VA.getLocReg(), Reg, RC, RC, DL);
|
CCValAssign &VA = ValLocs[i];
|
||||||
assert(Emitted && "Failed to emit a copy instruction!"); Emitted=Emitted;
|
|
||||||
|
// Don't bother handling odd stuff for now.
|
||||||
|
if (VA.getLocInfo() != CCValAssign::Full)
|
||||||
|
return false;
|
||||||
|
if (!VA.isRegLoc())
|
||||||
|
return false;
|
||||||
|
|
||||||
MRI.addLiveOut(X86::XMM0);
|
TargetRegisterClass* RC = TLI.getRegClassFor(VA.getValVT());
|
||||||
|
bool Emitted = TII.copyRegToReg(*FuncInfo.MBB, FuncInfo.InsertPt,
|
||||||
|
VA.getLocReg(), Reg + VA.getValNo(),
|
||||||
|
RC, RC, DL);
|
||||||
|
assert(Emitted && "Failed to emit a copy instruction!"); Emitted=Emitted;
|
||||||
|
|
||||||
|
MRI.addLiveOut(VA.getLocReg());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now emit the RET.
|
// Now emit the RET.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
; CHECK: foo:
|
; CHECK: foo:
|
||||||
; CHECK-NEXT: movq %rdi, -8(%rsp)
|
; CHECK-NEXT: movq %rdi, -8(%rsp)
|
||||||
; CHECK-NEXT: movq %rsi, -16(%rsp)
|
; CHECK-NEXT: movq %rsi, -16(%rsp)
|
||||||
; CHECK: movsd 128(%rsi,%rdi,8), %xmm0
|
; CHECK-NEXT: movsd 128(%rsi,%rdi,8), %xmm0
|
||||||
; CHECK-NEXT: ret
|
; CHECK-NEXT: ret
|
||||||
|
|
||||||
define double @foo(i64 %x, double* %p) nounwind {
|
define double @foo(i64 %x, double* %p) nounwind {
|
||||||
|
@ -49,9 +49,10 @@ entry:
|
|||||||
ret i32 %tmp2
|
ret i32 %tmp2
|
||||||
}
|
}
|
||||||
|
|
||||||
define i1 @ptrtoint_i1(i8* %p) nounwind {
|
define void @ptrtoint_i1(i8* %p, i1* %q) nounwind {
|
||||||
%t = ptrtoint i8* %p to i1
|
%t = ptrtoint i8* %p to i1
|
||||||
ret i1 %t
|
store i1 %t, i1* %q
|
||||||
|
ret void
|
||||||
}
|
}
|
||||||
define i8* @inttoptr_i1(i1 %p) nounwind {
|
define i8* @inttoptr_i1(i1 %p) nounwind {
|
||||||
%t = inttoptr i1 %p to i8*
|
%t = inttoptr i1 %p to i8*
|
||||||
@ -86,11 +87,8 @@ define i8 @mul_i8(i8 %a) nounwind {
|
|||||||
ret i8 %tmp
|
ret i8 %tmp
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @store_i1(i1* %p, i1 %t) nounwind {
|
define void @load_store_i1(i1* %p, i1* %q) nounwind {
|
||||||
store i1 %t, i1* %p
|
%t = load i1* %p
|
||||||
|
store i1 %t, i1* %q
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
define i1 @load_i1(i1* %p) nounwind {
|
|
||||||
%t = load i1* %p
|
|
||||||
ret i1 %t
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user