mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
Create HandlePHINodesInSuccessorBlocksFast, a version of
HandlePHINodesInSuccessorBlocks that works FastISel-style. This allows PHI nodes to be updated correctly while using FastISel. This also involves some code reorganization; ValueMap and MBBMap are now members of the FastISel class, so they needn't be passed around explicitly anymore. Also, SelectInstructions is changed to SelectInstruction, and only does one instruction at a time. llvm-svn: 55746
This commit is contained in:
parent
49483d797e
commit
18cc2a26df
@ -36,6 +36,8 @@ class TargetRegisterClass;
|
||||
class FastISel {
|
||||
protected:
|
||||
MachineBasicBlock *MBB;
|
||||
DenseMap<const Value *, unsigned> &ValueMap;
|
||||
DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap;
|
||||
MachineFunction &MF;
|
||||
MachineRegisterInfo &MRI;
|
||||
const TargetMachine &TM;
|
||||
@ -44,17 +46,18 @@ protected:
|
||||
const TargetLowering &TLI;
|
||||
|
||||
public:
|
||||
/// SelectInstructions - Do "fast" instruction selection over the
|
||||
/// LLVM IR instructions in the range [Begin, N) where N is either
|
||||
/// End or the first unsupported instruction. Return N.
|
||||
/// ValueMap is filled in with a mapping of LLVM IR Values to
|
||||
/// virtual register numbers. MBB is a block to which to append
|
||||
/// the generated MachineInstrs.
|
||||
BasicBlock::iterator
|
||||
SelectInstructions(BasicBlock::iterator Begin, BasicBlock::iterator End,
|
||||
DenseMap<const Value *, unsigned> &ValueMap,
|
||||
DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap,
|
||||
MachineBasicBlock *MBB);
|
||||
/// setCurrentBlock - Set the current block, to which generated
|
||||
/// machine instructions will be appended.
|
||||
///
|
||||
void setCurrentBlock(MachineBasicBlock *mbb) {
|
||||
MBB = mbb;
|
||||
}
|
||||
|
||||
/// SelectInstruction - Do "fast" instruction selection for the given
|
||||
/// LLVM IR instruction, and append generated machine instructions to
|
||||
/// the current block. Return true if selection was successful.
|
||||
///
|
||||
bool SelectInstruction(Instruction *I);
|
||||
|
||||
/// TargetSelectInstruction - This method is called by target-independent
|
||||
/// code when the normal FastISel process fails to select an instruction.
|
||||
@ -62,15 +65,18 @@ public:
|
||||
/// fit into FastISel's framework. It returns true if it was successful.
|
||||
///
|
||||
virtual bool
|
||||
TargetSelectInstruction(Instruction *I,
|
||||
DenseMap<const Value *, unsigned> &ValueMap,
|
||||
DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap,
|
||||
MachineBasicBlock *MBB) = 0;
|
||||
TargetSelectInstruction(Instruction *I) = 0;
|
||||
|
||||
/// getRegForValue - Create a virtual register and arrange for it to
|
||||
/// be assigned the value for the given LLVM value.
|
||||
unsigned getRegForValue(Value *V);
|
||||
|
||||
virtual ~FastISel();
|
||||
|
||||
protected:
|
||||
explicit FastISel(MachineFunction &mf);
|
||||
FastISel(MachineFunction &mf,
|
||||
DenseMap<const Value *, unsigned> &vm,
|
||||
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm);
|
||||
|
||||
/// FastEmit_r - This method is called by target-independent code
|
||||
/// to request that an instruction with the given type and opcode
|
||||
@ -208,26 +214,18 @@ protected:
|
||||
/// from a specified index of a superregister.
|
||||
unsigned FastEmitInst_extractsubreg(unsigned Op0, uint32_t Idx);
|
||||
|
||||
unsigned getRegForValue(Value *V,
|
||||
DenseMap<const Value*, unsigned> &ValueMap);
|
||||
|
||||
void UpdateValueMap(Instruction* I, unsigned Reg,
|
||||
DenseMap<const Value*, unsigned> &ValueMap);
|
||||
void UpdateValueMap(Instruction* I, unsigned Reg);
|
||||
|
||||
unsigned createResultReg(const TargetRegisterClass *RC);
|
||||
|
||||
private:
|
||||
bool SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
|
||||
DenseMap<const Value*, unsigned> &ValueMap);
|
||||
bool SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode);
|
||||
|
||||
bool SelectGetElementPtr(Instruction *I,
|
||||
DenseMap<const Value*, unsigned> &ValueMap);
|
||||
bool SelectGetElementPtr(Instruction *I);
|
||||
|
||||
bool SelectBitCast(Instruction *I,
|
||||
DenseMap<const Value*, unsigned> &ValueMap);
|
||||
bool SelectBitCast(Instruction *I);
|
||||
|
||||
bool SelectCast(Instruction *I, ISD::NodeType Opcode,
|
||||
DenseMap<const Value*, unsigned> &ValueMap);
|
||||
bool SelectCast(Instruction *I, ISD::NodeType Opcode);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "llvm/CodeGen/SelectionDAG.h"
|
||||
|
||||
namespace llvm {
|
||||
class FastISel;
|
||||
class SelectionDAGLowering;
|
||||
class SDValue;
|
||||
class MachineRegisterInfo;
|
||||
@ -118,6 +119,8 @@ private:
|
||||
|
||||
void HandlePHINodesInSuccessorBlocks(BasicBlock *LLVMBB);
|
||||
|
||||
bool HandlePHINodesInSuccessorBlocksFast(BasicBlock *LLVMBB, FastISel *F);
|
||||
|
||||
/// Pick a safe ordering for instructions for each target node in the
|
||||
/// graph.
|
||||
ScheduleDAG *Schedule();
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "llvm/CodeGen/SelectionDAGNodes.h"
|
||||
#include "llvm/CodeGen/RuntimeLibcalls.h"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
@ -1116,7 +1117,12 @@ public:
|
||||
|
||||
/// createFastISel - This method returns a target specific FastISel object,
|
||||
/// or null if the target does not support "fast" ISel.
|
||||
virtual FastISel *createFastISel(MachineFunction &) { return 0; }
|
||||
virtual FastISel *
|
||||
createFastISel(MachineFunction &,
|
||||
DenseMap<const Value *, unsigned> &,
|
||||
DenseMap<const BasicBlock *, MachineBasicBlock *> &) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Inline Asm Support hooks
|
||||
|
@ -25,8 +25,7 @@ using namespace llvm;
|
||||
// tracking what uses they dominate. Non-constants, however, already
|
||||
// have the SSA def-doms-use requirement enforced, so we can cache their
|
||||
// computations.
|
||||
unsigned FastISel::getRegForValue(Value *V,
|
||||
DenseMap<const Value*, unsigned> &ValueMap) {
|
||||
unsigned FastISel::getRegForValue(Value *V) {
|
||||
if (ValueMap.count(V))
|
||||
return ValueMap[V];
|
||||
|
||||
@ -78,8 +77,7 @@ unsigned FastISel::getRegForValue(Value *V,
|
||||
/// NOTE: This is only necessary because we might select a block that uses
|
||||
/// a value before we select the block that defines the value. It might be
|
||||
/// possible to fix this by selecting blocks in reverse postorder.
|
||||
void FastISel::UpdateValueMap(Instruction* I, unsigned Reg,
|
||||
DenseMap<const Value*, unsigned> &ValueMap) {
|
||||
void FastISel::UpdateValueMap(Instruction* I, unsigned Reg) {
|
||||
if (!ValueMap.count(I))
|
||||
ValueMap[I] = Reg;
|
||||
else
|
||||
@ -90,8 +88,7 @@ void FastISel::UpdateValueMap(Instruction* I, unsigned Reg,
|
||||
/// SelectBinaryOp - Select and emit code for a binary operator instruction,
|
||||
/// which has an opcode which directly corresponds to the given ISD opcode.
|
||||
///
|
||||
bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
|
||||
DenseMap<const Value*, unsigned> &ValueMap) {
|
||||
bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode) {
|
||||
MVT VT = MVT::getMVT(I->getType(), /*HandleUnknown=*/true);
|
||||
if (VT == MVT::Other || !VT.isSimple())
|
||||
// Unhandled type. Halt "fast" selection and bail.
|
||||
@ -103,7 +100,7 @@ bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
|
||||
if (!TLI.isTypeLegal(VT))
|
||||
return false;
|
||||
|
||||
unsigned Op0 = getRegForValue(I->getOperand(0), ValueMap);
|
||||
unsigned Op0 = getRegForValue(I->getOperand(0));
|
||||
if (Op0 == 0)
|
||||
// Unhandled operand. Halt "fast" selection and bail.
|
||||
return false;
|
||||
@ -114,7 +111,7 @@ bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
|
||||
ISDOpcode, Op0, CI->getZExtValue());
|
||||
if (ResultReg != 0) {
|
||||
// We successfully emitted code for the given LLVM Instruction.
|
||||
UpdateValueMap(I, ResultReg, ValueMap);
|
||||
UpdateValueMap(I, ResultReg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -125,12 +122,12 @@ bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
|
||||
ISDOpcode, Op0, CF);
|
||||
if (ResultReg != 0) {
|
||||
// We successfully emitted code for the given LLVM Instruction.
|
||||
UpdateValueMap(I, ResultReg, ValueMap);
|
||||
UpdateValueMap(I, ResultReg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Op1 = getRegForValue(I->getOperand(1), ValueMap);
|
||||
unsigned Op1 = getRegForValue(I->getOperand(1));
|
||||
if (Op1 == 0)
|
||||
// Unhandled operand. Halt "fast" selection and bail.
|
||||
return false;
|
||||
@ -144,13 +141,12 @@ bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
|
||||
return false;
|
||||
|
||||
// We successfully emitted code for the given LLVM Instruction.
|
||||
UpdateValueMap(I, ResultReg, ValueMap);
|
||||
UpdateValueMap(I, ResultReg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FastISel::SelectGetElementPtr(Instruction *I,
|
||||
DenseMap<const Value*, unsigned> &ValueMap) {
|
||||
unsigned N = getRegForValue(I->getOperand(0), ValueMap);
|
||||
bool FastISel::SelectGetElementPtr(Instruction *I) {
|
||||
unsigned N = getRegForValue(I->getOperand(0));
|
||||
if (N == 0)
|
||||
// Unhandled operand. Halt "fast" selection and bail.
|
||||
return false;
|
||||
@ -190,7 +186,7 @@ bool FastISel::SelectGetElementPtr(Instruction *I,
|
||||
|
||||
// N = N + Idx * ElementSize;
|
||||
uint64_t ElementSize = TD.getABITypeSize(Ty);
|
||||
unsigned IdxN = getRegForValue(Idx, ValueMap);
|
||||
unsigned IdxN = getRegForValue(Idx);
|
||||
if (IdxN == 0)
|
||||
// Unhandled operand. Halt "fast" selection and bail.
|
||||
return false;
|
||||
@ -220,12 +216,11 @@ bool FastISel::SelectGetElementPtr(Instruction *I,
|
||||
}
|
||||
|
||||
// We successfully emitted code for the given LLVM Instruction.
|
||||
UpdateValueMap(I, N, ValueMap);
|
||||
UpdateValueMap(I, N);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FastISel::SelectCast(Instruction *I, ISD::NodeType Opcode,
|
||||
DenseMap<const Value*, unsigned> &ValueMap) {
|
||||
bool FastISel::SelectCast(Instruction *I, ISD::NodeType Opcode) {
|
||||
MVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
|
||||
MVT DstVT = TLI.getValueType(I->getType());
|
||||
|
||||
@ -235,7 +230,7 @@ bool FastISel::SelectCast(Instruction *I, ISD::NodeType Opcode,
|
||||
// Unhandled type. Halt "fast" selection and bail.
|
||||
return false;
|
||||
|
||||
unsigned InputReg = getRegForValue(I->getOperand(0), ValueMap);
|
||||
unsigned InputReg = getRegForValue(I->getOperand(0));
|
||||
if (!InputReg)
|
||||
// Unhandled operand. Halt "fast" selection and bail.
|
||||
return false;
|
||||
@ -247,18 +242,17 @@ bool FastISel::SelectCast(Instruction *I, ISD::NodeType Opcode,
|
||||
if (!ResultReg)
|
||||
return false;
|
||||
|
||||
UpdateValueMap(I, ResultReg, ValueMap);
|
||||
UpdateValueMap(I, ResultReg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FastISel::SelectBitCast(Instruction *I,
|
||||
DenseMap<const Value*, unsigned> &ValueMap) {
|
||||
bool FastISel::SelectBitCast(Instruction *I) {
|
||||
// If the bitcast doesn't change the type, just use the operand value.
|
||||
if (I->getType() == I->getOperand(0)->getType()) {
|
||||
unsigned Reg = getRegForValue(I->getOperand(0), ValueMap);
|
||||
unsigned Reg = getRegForValue(I->getOperand(0));
|
||||
if (Reg == 0)
|
||||
return false;
|
||||
UpdateValueMap(I, Reg, ValueMap);
|
||||
UpdateValueMap(I, Reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -272,7 +266,7 @@ bool FastISel::SelectBitCast(Instruction *I,
|
||||
// Unhandled type. Halt "fast" selection and bail.
|
||||
return false;
|
||||
|
||||
unsigned Op0 = getRegForValue(I->getOperand(0), ValueMap);
|
||||
unsigned Op0 = getRegForValue(I->getOperand(0));
|
||||
if (Op0 == 0)
|
||||
// Unhandled operand. Halt "fast" selection and bail.
|
||||
return false;
|
||||
@ -298,143 +292,124 @@ bool FastISel::SelectBitCast(Instruction *I,
|
||||
if (!ResultReg)
|
||||
return false;
|
||||
|
||||
UpdateValueMap(I, ResultReg, ValueMap);
|
||||
UpdateValueMap(I, ResultReg);
|
||||
return true;
|
||||
}
|
||||
|
||||
BasicBlock::iterator
|
||||
FastISel::SelectInstructions(BasicBlock::iterator Begin,
|
||||
BasicBlock::iterator End,
|
||||
DenseMap<const Value*, unsigned> &ValueMap,
|
||||
DenseMap<const BasicBlock*,
|
||||
MachineBasicBlock *> &MBBMap,
|
||||
MachineBasicBlock *mbb) {
|
||||
MBB = mbb;
|
||||
BasicBlock::iterator I = Begin;
|
||||
bool
|
||||
FastISel::SelectInstruction(Instruction *I) {
|
||||
switch (I->getOpcode()) {
|
||||
case Instruction::Add: {
|
||||
ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FADD : ISD::ADD;
|
||||
return SelectBinaryOp(I, Opc);
|
||||
}
|
||||
case Instruction::Sub: {
|
||||
ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FSUB : ISD::SUB;
|
||||
return SelectBinaryOp(I, Opc);
|
||||
}
|
||||
case Instruction::Mul: {
|
||||
ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FMUL : ISD::MUL;
|
||||
return SelectBinaryOp(I, Opc);
|
||||
}
|
||||
case Instruction::SDiv:
|
||||
return SelectBinaryOp(I, ISD::SDIV);
|
||||
case Instruction::UDiv:
|
||||
return SelectBinaryOp(I, ISD::UDIV);
|
||||
case Instruction::FDiv:
|
||||
return SelectBinaryOp(I, ISD::FDIV);
|
||||
case Instruction::SRem:
|
||||
return SelectBinaryOp(I, ISD::SREM);
|
||||
case Instruction::URem:
|
||||
return SelectBinaryOp(I, ISD::UREM);
|
||||
case Instruction::FRem:
|
||||
return SelectBinaryOp(I, ISD::FREM);
|
||||
case Instruction::Shl:
|
||||
return SelectBinaryOp(I, ISD::SHL);
|
||||
case Instruction::LShr:
|
||||
return SelectBinaryOp(I, ISD::SRL);
|
||||
case Instruction::AShr:
|
||||
return SelectBinaryOp(I, ISD::SRA);
|
||||
case Instruction::And:
|
||||
return SelectBinaryOp(I, ISD::AND);
|
||||
case Instruction::Or:
|
||||
return SelectBinaryOp(I, ISD::OR);
|
||||
case Instruction::Xor:
|
||||
return SelectBinaryOp(I, ISD::XOR);
|
||||
|
||||
for (; I != End; ++I) {
|
||||
switch (I->getOpcode()) {
|
||||
case Instruction::Add: {
|
||||
ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FADD : ISD::ADD;
|
||||
if (!SelectBinaryOp(I, Opc, ValueMap)) return I; break;
|
||||
}
|
||||
case Instruction::Sub: {
|
||||
ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FSUB : ISD::SUB;
|
||||
if (!SelectBinaryOp(I, Opc, ValueMap)) return I; break;
|
||||
}
|
||||
case Instruction::Mul: {
|
||||
ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FMUL : ISD::MUL;
|
||||
if (!SelectBinaryOp(I, Opc, ValueMap)) return I; break;
|
||||
}
|
||||
case Instruction::SDiv:
|
||||
if (!SelectBinaryOp(I, ISD::SDIV, ValueMap)) return I; break;
|
||||
case Instruction::UDiv:
|
||||
if (!SelectBinaryOp(I, ISD::UDIV, ValueMap)) return I; break;
|
||||
case Instruction::FDiv:
|
||||
if (!SelectBinaryOp(I, ISD::FDIV, ValueMap)) return I; break;
|
||||
case Instruction::SRem:
|
||||
if (!SelectBinaryOp(I, ISD::SREM, ValueMap)) return I; break;
|
||||
case Instruction::URem:
|
||||
if (!SelectBinaryOp(I, ISD::UREM, ValueMap)) return I; break;
|
||||
case Instruction::FRem:
|
||||
if (!SelectBinaryOp(I, ISD::FREM, ValueMap)) return I; break;
|
||||
case Instruction::Shl:
|
||||
if (!SelectBinaryOp(I, ISD::SHL, ValueMap)) return I; break;
|
||||
case Instruction::LShr:
|
||||
if (!SelectBinaryOp(I, ISD::SRL, ValueMap)) return I; break;
|
||||
case Instruction::AShr:
|
||||
if (!SelectBinaryOp(I, ISD::SRA, ValueMap)) return I; break;
|
||||
case Instruction::And:
|
||||
if (!SelectBinaryOp(I, ISD::AND, ValueMap)) return I; break;
|
||||
case Instruction::Or:
|
||||
if (!SelectBinaryOp(I, ISD::OR, ValueMap)) return I; break;
|
||||
case Instruction::Xor:
|
||||
if (!SelectBinaryOp(I, ISD::XOR, ValueMap)) return I; break;
|
||||
case Instruction::GetElementPtr:
|
||||
return SelectGetElementPtr(I);
|
||||
|
||||
case Instruction::GetElementPtr:
|
||||
if (!SelectGetElementPtr(I, ValueMap)) return I;
|
||||
break;
|
||||
case Instruction::Br: {
|
||||
BranchInst *BI = cast<BranchInst>(I);
|
||||
|
||||
case Instruction::Br: {
|
||||
BranchInst *BI = cast<BranchInst>(I);
|
||||
if (BI->isUnconditional()) {
|
||||
MachineFunction::iterator NextMBB =
|
||||
next(MachineFunction::iterator(MBB));
|
||||
BasicBlock *LLVMSucc = BI->getSuccessor(0);
|
||||
MachineBasicBlock *MSucc = MBBMap[LLVMSucc];
|
||||
|
||||
if (BI->isUnconditional()) {
|
||||
MachineFunction::iterator NextMBB =
|
||||
next(MachineFunction::iterator(MBB));
|
||||
BasicBlock *LLVMSucc = BI->getSuccessor(0);
|
||||
MachineBasicBlock *MSucc = MBBMap[LLVMSucc];
|
||||
|
||||
if (NextMBB != MF.end() && MSucc == NextMBB) {
|
||||
// The unconditional fall-through case, which needs no instructions.
|
||||
} else {
|
||||
// The unconditional branch case.
|
||||
TII.InsertBranch(*MBB, MSucc, NULL, SmallVector<MachineOperand, 0>());
|
||||
}
|
||||
MBB->addSuccessor(MSucc);
|
||||
break;
|
||||
}
|
||||
|
||||
// Conditional branches are not handed yet.
|
||||
// Halt "fast" selection and bail.
|
||||
return I;
|
||||
}
|
||||
|
||||
case Instruction::PHI:
|
||||
// PHI nodes are already emitted.
|
||||
break;
|
||||
|
||||
case Instruction::BitCast:
|
||||
if (!SelectBitCast(I, ValueMap)) return I; break;
|
||||
|
||||
case Instruction::FPToSI:
|
||||
if (!SelectCast(I, ISD::FP_TO_SINT, ValueMap)) return I;
|
||||
break;
|
||||
case Instruction::ZExt:
|
||||
if (!SelectCast(I, ISD::ZERO_EXTEND, ValueMap)) return I;
|
||||
break;
|
||||
case Instruction::SExt:
|
||||
if (!SelectCast(I, ISD::SIGN_EXTEND, ValueMap)) return I;
|
||||
break;
|
||||
case Instruction::Trunc:
|
||||
if (!SelectCast(I, ISD::TRUNCATE, ValueMap)) return I;
|
||||
break;
|
||||
case Instruction::SIToFP:
|
||||
if (!SelectCast(I, ISD::SINT_TO_FP, ValueMap)) return I;
|
||||
break;
|
||||
|
||||
case Instruction::IntToPtr: // Deliberate fall-through.
|
||||
case Instruction::PtrToInt: {
|
||||
MVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
|
||||
MVT DstVT = TLI.getValueType(I->getType());
|
||||
if (SrcVT.getSimpleVT() == DstVT.getSimpleVT()) {
|
||||
if (ValueMap[I->getOperand(0)]) {
|
||||
UpdateValueMap(I, ValueMap[I->getOperand(0)], ValueMap);
|
||||
break;
|
||||
} else
|
||||
// Unhandled operand
|
||||
return I;
|
||||
} else if (DstVT.bitsGT(SrcVT)) {
|
||||
if (!SelectCast(I, ISD::ZERO_EXTEND, ValueMap)) return I;
|
||||
break;
|
||||
if (NextMBB != MF.end() && MSucc == NextMBB) {
|
||||
// The unconditional fall-through case, which needs no instructions.
|
||||
} else {
|
||||
// TODO: Handle SrcVT > DstVT, where truncation is needed.
|
||||
return I;
|
||||
// The unconditional branch case.
|
||||
TII.InsertBranch(*MBB, MSucc, NULL, SmallVector<MachineOperand, 0>());
|
||||
}
|
||||
MBB->addSuccessor(MSucc);
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
// Unhandled instruction. Halt "fast" selection and bail.
|
||||
return I;
|
||||
}
|
||||
|
||||
// Conditional branches are not handed yet.
|
||||
// Halt "fast" selection and bail.
|
||||
return false;
|
||||
}
|
||||
|
||||
return I;
|
||||
case Instruction::PHI:
|
||||
// PHI nodes are already emitted.
|
||||
return true;
|
||||
|
||||
case Instruction::BitCast:
|
||||
return SelectBitCast(I);
|
||||
|
||||
case Instruction::FPToSI:
|
||||
return SelectCast(I, ISD::FP_TO_SINT);
|
||||
case Instruction::ZExt:
|
||||
return SelectCast(I, ISD::ZERO_EXTEND);
|
||||
case Instruction::SExt:
|
||||
return SelectCast(I, ISD::SIGN_EXTEND);
|
||||
case Instruction::Trunc:
|
||||
return SelectCast(I, ISD::TRUNCATE);
|
||||
case Instruction::SIToFP:
|
||||
return SelectCast(I, ISD::SINT_TO_FP);
|
||||
|
||||
case Instruction::IntToPtr: // Deliberate fall-through.
|
||||
case Instruction::PtrToInt: {
|
||||
MVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
|
||||
MVT DstVT = TLI.getValueType(I->getType());
|
||||
if (DstVT.bitsGT(SrcVT))
|
||||
return SelectCast(I, ISD::ZERO_EXTEND);
|
||||
if (DstVT.bitsLT(SrcVT))
|
||||
return SelectCast(I, ISD::TRUNCATE);
|
||||
unsigned Reg = getRegForValue(I->getOperand(0));
|
||||
if (Reg == 0) return false;
|
||||
UpdateValueMap(I, Reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
// Unhandled instruction. Halt "fast" selection and bail.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
FastISel::FastISel(MachineFunction &mf)
|
||||
: MF(mf),
|
||||
MRI(mf.getRegInfo()),
|
||||
TM(mf.getTarget()),
|
||||
FastISel::FastISel(MachineFunction &mf,
|
||||
DenseMap<const Value *, unsigned> &vm,
|
||||
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm)
|
||||
: MBB(0),
|
||||
ValueMap(vm),
|
||||
MBBMap(bm),
|
||||
MF(mf),
|
||||
MRI(MF.getRegInfo()),
|
||||
TM(MF.getTarget()),
|
||||
TD(*TM.getTargetData()),
|
||||
TII(*TM.getInstrInfo()),
|
||||
TLI(*TM.getTargetLowering()) {
|
||||
|
@ -4757,9 +4757,64 @@ SelectionDAGISel::HandlePHINodesInSuccessorBlocks(BasicBlock *LLVMBB) {
|
||||
}
|
||||
}
|
||||
SDL->ConstantsOut.clear();
|
||||
|
||||
// Lower the terminator after the copies are emitted.
|
||||
SDL->visit(*LLVMBB->getTerminator());
|
||||
}
|
||||
|
||||
/// This is the Fast-ISel version of HandlePHINodesInSuccessorBlocks. It only
|
||||
/// supports legal types, and it emits MachineInstrs directly instead of
|
||||
/// creating SelectionDAG nodes.
|
||||
///
|
||||
bool
|
||||
SelectionDAGISel::HandlePHINodesInSuccessorBlocksFast(BasicBlock *LLVMBB,
|
||||
FastISel *F) {
|
||||
TerminatorInst *TI = LLVMBB->getTerminator();
|
||||
|
||||
SmallPtrSet<MachineBasicBlock *, 4> SuccsHandled;
|
||||
unsigned OrigNumPHINodesToUpdate = SDL->PHINodesToUpdate.size();
|
||||
|
||||
// Check successor nodes' PHI nodes that expect a constant to be available
|
||||
// from this block.
|
||||
for (unsigned succ = 0, e = TI->getNumSuccessors(); succ != e; ++succ) {
|
||||
BasicBlock *SuccBB = TI->getSuccessor(succ);
|
||||
if (!isa<PHINode>(SuccBB->begin())) continue;
|
||||
MachineBasicBlock *SuccMBB = FuncInfo->MBBMap[SuccBB];
|
||||
|
||||
// If this terminator has multiple identical successors (common for
|
||||
// switches), only handle each succ once.
|
||||
if (!SuccsHandled.insert(SuccMBB)) continue;
|
||||
|
||||
MachineBasicBlock::iterator MBBI = SuccMBB->begin();
|
||||
PHINode *PN;
|
||||
|
||||
// At this point we know that there is a 1-1 correspondence between LLVM PHI
|
||||
// nodes and Machine PHI nodes, but the incoming operands have not been
|
||||
// emitted yet.
|
||||
for (BasicBlock::iterator I = SuccBB->begin();
|
||||
(PN = dyn_cast<PHINode>(I)); ++I) {
|
||||
// Ignore dead phi's.
|
||||
if (PN->use_empty()) continue;
|
||||
|
||||
// Only handle legal types. Two interesting things to note here. First,
|
||||
// by bailing out early, we may leave behind some dead instructions,
|
||||
// since SelectionDAG's HandlePHINodesInSuccessorBlocks will insert its
|
||||
// own moves. Second, this check is necessary becuase FastISel doesn't
|
||||
// use CreateRegForValue to create registers, so it always creates
|
||||
// exactly one register for each non-void instruction.
|
||||
MVT VT = TLI.getValueType(PN->getType(), /*AllowUnknown=*/true);
|
||||
if (VT == MVT::Other || !TLI.isTypeLegal(VT)) {
|
||||
SDL->PHINodesToUpdate.resize(OrigNumPHINodesToUpdate);
|
||||
return false;
|
||||
}
|
||||
|
||||
Value *PHIOp = PN->getIncomingValueForBlock(LLVMBB);
|
||||
|
||||
unsigned Reg = F->getRegForValue(PHIOp);
|
||||
if (Reg == 0) {
|
||||
SDL->PHINodesToUpdate.resize(OrigNumPHINodesToUpdate);
|
||||
return false;
|
||||
}
|
||||
SDL->PHINodesToUpdate.push_back(std::make_pair(MBBI++, Reg));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -408,8 +408,12 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB,
|
||||
}
|
||||
|
||||
// Handle PHI nodes in successor blocks.
|
||||
if (End == LLVMBB->end())
|
||||
if (End == LLVMBB->end()) {
|
||||
HandlePHINodesInSuccessorBlocks(LLVMBB);
|
||||
|
||||
// Lower the terminator after the copies are emitted.
|
||||
SDL->visit(*LLVMBB->getTerminator());
|
||||
}
|
||||
|
||||
// Make sure the root of the DAG is up-to-date.
|
||||
CurDAG->setRoot(SDL->getControlRoot());
|
||||
@ -606,8 +610,9 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF) {
|
||||
BasicBlock *LLVMBB = &*I;
|
||||
BB = FuncInfo->MBBMap[LLVMBB];
|
||||
|
||||
BasicBlock::iterator Begin = LLVMBB->begin();
|
||||
BasicBlock::iterator End = LLVMBB->end();
|
||||
BasicBlock::iterator const Begin = LLVMBB->begin();
|
||||
BasicBlock::iterator const End = LLVMBB->end();
|
||||
BasicBlock::iterator I = Begin;
|
||||
|
||||
// Lower any arguments needed in this block if this is the entry block.
|
||||
if (LLVMBB == &Fn.getEntryBlock())
|
||||
@ -616,7 +621,8 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF) {
|
||||
// Before doing SelectionDAG ISel, see if FastISel has been requested.
|
||||
// FastISel doesn't support EH landing pads, which require special handling.
|
||||
if (EnableFastISel && !BB->isLandingPad()) {
|
||||
if (FastISel *F = TLI.createFastISel(*FuncInfo->MF)) {
|
||||
if (FastISel *F = TLI.createFastISel(*FuncInfo->MF, FuncInfo->ValueMap,
|
||||
FuncInfo->MBBMap)) {
|
||||
// Emit code for any incoming arguments. This must happen before
|
||||
// beginning FastISel on the entry block.
|
||||
if (LLVMBB == &Fn.getEntryBlock()) {
|
||||
@ -624,45 +630,51 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF) {
|
||||
CodeGenAndEmitDAG();
|
||||
SDL->clear();
|
||||
}
|
||||
F->setCurrentBlock(BB);
|
||||
// Do FastISel on as many instructions as possible.
|
||||
while (Begin != End) {
|
||||
Begin = F->SelectInstructions(Begin, End, FuncInfo->ValueMap,
|
||||
FuncInfo->MBBMap, BB);
|
||||
|
||||
// If the "fast" selector selected the entire block, we're done.
|
||||
if (Begin == End)
|
||||
break;
|
||||
|
||||
// Next, try calling the target to attempt to handle the instruction.
|
||||
if (F->TargetSelectInstruction(Begin, FuncInfo->ValueMap,
|
||||
FuncInfo->MBBMap, BB)) {
|
||||
++Begin;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle certain instructions as single-LLVM-Instruction blocks.
|
||||
if (isa<CallInst>(Begin) || isa<LoadInst>(Begin) ||
|
||||
isa<StoreInst>(Begin)) {
|
||||
if (Begin->getType() != Type::VoidTy) {
|
||||
unsigned &R = FuncInfo->ValueMap[Begin];
|
||||
if (!R)
|
||||
R = FuncInfo->CreateRegForValue(Begin);
|
||||
for (; I != End; ++I) {
|
||||
// Just before the terminator instruction, insert instructions to
|
||||
// feed PHI nodes in successor blocks.
|
||||
if (isa<TerminatorInst>(I))
|
||||
if (!HandlePHINodesInSuccessorBlocksFast(LLVMBB, F)) {
|
||||
if (DisableFastISelAbort)
|
||||
break;
|
||||
#ifndef NDEBUG
|
||||
I->dump();
|
||||
#endif
|
||||
assert(0 && "FastISel didn't handle a PHI in a successor");
|
||||
}
|
||||
|
||||
SelectBasicBlock(LLVMBB, Begin, next(Begin));
|
||||
++Begin;
|
||||
// First try normal tablegen-generated "fast" selection.
|
||||
if (F->SelectInstruction(I))
|
||||
continue;
|
||||
|
||||
// Next, try calling the target to attempt to handle the instruction.
|
||||
if (F->TargetSelectInstruction(I))
|
||||
continue;
|
||||
|
||||
// Then handle certain instructions as single-LLVM-Instruction blocks.
|
||||
if (isa<CallInst>(I) || isa<LoadInst>(I) ||
|
||||
isa<StoreInst>(I)) {
|
||||
if (I->getType() != Type::VoidTy) {
|
||||
unsigned &R = FuncInfo->ValueMap[I];
|
||||
if (!R)
|
||||
R = FuncInfo->CreateRegForValue(I);
|
||||
}
|
||||
|
||||
SelectBasicBlock(LLVMBB, I, next(I));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!DisableFastISelAbort &&
|
||||
// For now, don't abort on non-conditional-branch terminators.
|
||||
(!isa<TerminatorInst>(Begin) ||
|
||||
(isa<BranchInst>(Begin) &&
|
||||
cast<BranchInst>(Begin)->isUnconditional()))) {
|
||||
(!isa<TerminatorInst>(I) ||
|
||||
(isa<BranchInst>(I) &&
|
||||
cast<BranchInst>(I)->isUnconditional()))) {
|
||||
// The "fast" selector couldn't handle something and bailed.
|
||||
// For the purpose of debugging, just abort.
|
||||
#ifndef NDEBUG
|
||||
Begin->dump();
|
||||
I->dump();
|
||||
#endif
|
||||
assert(0 && "FastISel didn't select the entire block");
|
||||
}
|
||||
@ -674,12 +686,9 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF) {
|
||||
|
||||
// Run SelectionDAG instruction selection on the remainder of the block
|
||||
// not handled by FastISel. If FastISel is not run, this is the entire
|
||||
// block. If FastISel is run and happens to handle all of the
|
||||
// LLVM Instructions in the block, [Begin,End) will be an empty range,
|
||||
// but we still need to run this so that
|
||||
// HandlePHINodesInSuccessorBlocks is called and any resulting code
|
||||
// is emitted.
|
||||
SelectBasicBlock(LLVMBB, Begin, End);
|
||||
// block.
|
||||
if (I != End)
|
||||
SelectBasicBlock(LLVMBB, I, End);
|
||||
|
||||
FinishBasicBlock();
|
||||
}
|
||||
|
@ -30,34 +30,27 @@ class X86FastISel : public FastISel {
|
||||
const X86Subtarget *Subtarget;
|
||||
|
||||
public:
|
||||
explicit X86FastISel(MachineFunction &mf) : FastISel(mf) {
|
||||
explicit X86FastISel(MachineFunction &mf,
|
||||
DenseMap<const Value *, unsigned> &vm,
|
||||
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm)
|
||||
: FastISel(mf, vm, bm) {
|
||||
Subtarget = &TM.getSubtarget<X86Subtarget>();
|
||||
}
|
||||
|
||||
virtual bool
|
||||
TargetSelectInstruction(Instruction *I,
|
||||
DenseMap<const Value *, unsigned> &ValueMap,
|
||||
DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap,
|
||||
MachineBasicBlock *MBB);
|
||||
virtual bool TargetSelectInstruction(Instruction *I);
|
||||
|
||||
#include "X86GenFastISel.inc"
|
||||
|
||||
private:
|
||||
bool X86SelectConstAddr(Value *V,
|
||||
DenseMap<const Value *, unsigned> &ValueMap,
|
||||
MachineBasicBlock *MBB, unsigned &Op0);
|
||||
bool X86SelectConstAddr(Value *V, unsigned &Op0);
|
||||
|
||||
bool X86SelectLoad(Instruction *I,
|
||||
DenseMap<const Value *, unsigned> &ValueMap,
|
||||
MachineBasicBlock *MBB);
|
||||
bool X86SelectLoad(Instruction *I);
|
||||
};
|
||||
|
||||
/// X86SelectConstAddr - Select and emit code to materialize constant address.
|
||||
///
|
||||
bool X86FastISel::X86SelectConstAddr(Value *V,
|
||||
DenseMap<const Value *, unsigned> &ValueMap,
|
||||
MachineBasicBlock *MBB,
|
||||
unsigned &Op0) {
|
||||
unsigned &Op0) {
|
||||
// FIXME: Only GlobalAddress for now.
|
||||
GlobalValue *GV = dyn_cast<GlobalValue>(V);
|
||||
if (!GV)
|
||||
@ -84,9 +77,7 @@ bool X86FastISel::X86SelectConstAddr(Value *V,
|
||||
|
||||
/// X86SelectLoad - Select and emit code to implement load instructions.
|
||||
///
|
||||
bool X86FastISel::X86SelectLoad(Instruction *I,
|
||||
DenseMap<const Value *, unsigned> &ValueMap,
|
||||
MachineBasicBlock *MBB) {
|
||||
bool X86FastISel::X86SelectLoad(Instruction *I) {
|
||||
MVT VT = MVT::getMVT(I->getType(), /*HandleUnknown=*/true);
|
||||
if (VT == MVT::Other || !VT.isSimple())
|
||||
// Unhandled type. Halt "fast" selection and bail.
|
||||
@ -102,10 +93,10 @@ bool X86FastISel::X86SelectLoad(Instruction *I,
|
||||
return false;
|
||||
|
||||
Value *V = I->getOperand(0);
|
||||
unsigned Op0 = getRegForValue(V, ValueMap);
|
||||
unsigned Op0 = getRegForValue(V);
|
||||
if (Op0 == 0) {
|
||||
// Handle constant load address.
|
||||
if (!isa<Constant>(V) || !X86SelectConstAddr(V, ValueMap, MBB, Op0))
|
||||
if (!isa<Constant>(V) || !X86SelectConstAddr(V, Op0))
|
||||
// Unhandled operand. Halt "fast" selection and bail.
|
||||
return false;
|
||||
}
|
||||
@ -164,27 +155,26 @@ bool X86FastISel::X86SelectLoad(Instruction *I,
|
||||
else
|
||||
AM.GV = cast<GlobalValue>(V);
|
||||
addFullAddress(BuildMI(MBB, TII.get(Opc), ResultReg), AM);
|
||||
UpdateValueMap(I, ResultReg, ValueMap);
|
||||
UpdateValueMap(I, ResultReg);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
X86FastISel::TargetSelectInstruction(Instruction *I,
|
||||
DenseMap<const Value *, unsigned> &ValueMap,
|
||||
DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap,
|
||||
MachineBasicBlock *MBB) {
|
||||
X86FastISel::TargetSelectInstruction(Instruction *I) {
|
||||
switch (I->getOpcode()) {
|
||||
default: break;
|
||||
case Instruction::Load:
|
||||
return X86SelectLoad(I, ValueMap, MBB);
|
||||
return X86SelectLoad(I);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
llvm::FastISel *X86::createFastISel(MachineFunction &mf) {
|
||||
return new X86FastISel(mf);
|
||||
llvm::FastISel *X86::createFastISel(MachineFunction &mf,
|
||||
DenseMap<const Value *, unsigned> &vm,
|
||||
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm) {
|
||||
return new X86FastISel(mf, vm, bm);
|
||||
}
|
||||
}
|
||||
|
@ -1879,8 +1879,12 @@ bool X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Call,
|
||||
return false;
|
||||
}
|
||||
|
||||
FastISel *X86TargetLowering::createFastISel(MachineFunction &mf) {
|
||||
return X86::createFastISel(mf);
|
||||
FastISel *
|
||||
X86TargetLowering::createFastISel(MachineFunction &mf,
|
||||
DenseMap<const Value *, unsigned> &vm,
|
||||
DenseMap<const BasicBlock *,
|
||||
MachineBasicBlock *> &bm) {
|
||||
return X86::createFastISel(mf, vm, bm);
|
||||
}
|
||||
|
||||
|
||||
|
@ -470,7 +470,10 @@ namespace llvm {
|
||||
|
||||
/// createFastISel - This method returns a target specific FastISel object,
|
||||
/// or null if the target does not support "fast" ISel.
|
||||
virtual FastISel *createFastISel(MachineFunction &mf);
|
||||
virtual FastISel *
|
||||
createFastISel(MachineFunction &mf,
|
||||
DenseMap<const Value *, unsigned> &,
|
||||
DenseMap<const BasicBlock *, MachineBasicBlock *> &);
|
||||
|
||||
private:
|
||||
/// Subtarget - Keep a pointer to the X86Subtarget around so that we can
|
||||
@ -598,7 +601,9 @@ namespace llvm {
|
||||
};
|
||||
|
||||
namespace X86 {
|
||||
FastISel *createFastISel(MachineFunction &mf);
|
||||
FastISel *createFastISel(MachineFunction &mf,
|
||||
DenseMap<const Value *, unsigned> &,
|
||||
DenseMap<const BasicBlock *, MachineBasicBlock *> &);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user