diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 8d6efb127c4..15cbe65aeb5 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -36,6 +36,8 @@ class TargetRegisterClass; class FastISel { protected: MachineBasicBlock *MBB; + DenseMap &ValueMap; + DenseMap &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 &ValueMap, - DenseMap &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 &ValueMap, - DenseMap &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 &vm, + DenseMap &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 &ValueMap); - - void UpdateValueMap(Instruction* I, unsigned Reg, - DenseMap &ValueMap); + void UpdateValueMap(Instruction* I, unsigned Reg); unsigned createResultReg(const TargetRegisterClass *RC); private: - bool SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode, - DenseMap &ValueMap); + bool SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode); - bool SelectGetElementPtr(Instruction *I, - DenseMap &ValueMap); + bool SelectGetElementPtr(Instruction *I); - bool SelectBitCast(Instruction *I, - DenseMap &ValueMap); + bool SelectBitCast(Instruction *I); - bool SelectCast(Instruction *I, ISD::NodeType Opcode, - DenseMap &ValueMap); + bool SelectCast(Instruction *I, ISD::NodeType Opcode); }; } diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 2f85e50a717..86274ae1877 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -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(); diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index e12cedc76df..598a46bf01a 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -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 #include @@ -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 &, + DenseMap &) { + return 0; + } //===--------------------------------------------------------------------===// // Inline Asm Support hooks diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index 12f12bd22c5..c057be5f769 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -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 &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 &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 &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 &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 &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 &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 &ValueMap, - DenseMap &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(I); - case Instruction::Br: { - BranchInst *BI = cast(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()); - } - 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()); } + 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 &vm, + DenseMap &bm) + : MBB(0), + ValueMap(vm), + MBBMap(bm), + MF(mf), + MRI(MF.getRegInfo()), + TM(MF.getTarget()), TD(*TM.getTargetData()), TII(*TM.getInstrInfo()), TLI(*TM.getTargetLowering()) { diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index 9df4bbaf732..3bbcdc99b55 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -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 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(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(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; +} diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index a2cf6a1b568..2b9ba38f20c 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -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(Begin) || isa(Begin) || - isa(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(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(I) || isa(I) || + isa(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(Begin) || - (isa(Begin) && - cast(Begin)->isUnconditional()))) { + (!isa(I) || + (isa(I) && + cast(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(); } diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index 658b65dba73..9b784b44497 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -30,34 +30,27 @@ class X86FastISel : public FastISel { const X86Subtarget *Subtarget; public: - explicit X86FastISel(MachineFunction &mf) : FastISel(mf) { + explicit X86FastISel(MachineFunction &mf, + DenseMap &vm, + DenseMap &bm) + : FastISel(mf, vm, bm) { Subtarget = &TM.getSubtarget(); } - virtual bool - TargetSelectInstruction(Instruction *I, - DenseMap &ValueMap, - DenseMap &MBBMap, - MachineBasicBlock *MBB); + virtual bool TargetSelectInstruction(Instruction *I); #include "X86GenFastISel.inc" private: - bool X86SelectConstAddr(Value *V, - DenseMap &ValueMap, - MachineBasicBlock *MBB, unsigned &Op0); + bool X86SelectConstAddr(Value *V, unsigned &Op0); - bool X86SelectLoad(Instruction *I, - DenseMap &ValueMap, - MachineBasicBlock *MBB); + bool X86SelectLoad(Instruction *I); }; /// X86SelectConstAddr - Select and emit code to materialize constant address. /// bool X86FastISel::X86SelectConstAddr(Value *V, - DenseMap &ValueMap, - MachineBasicBlock *MBB, - unsigned &Op0) { + unsigned &Op0) { // FIXME: Only GlobalAddress for now. GlobalValue *GV = dyn_cast(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 &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(V) || !X86SelectConstAddr(V, ValueMap, MBB, Op0)) + if (!isa(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(V); addFullAddress(BuildMI(MBB, TII.get(Opc), ResultReg), AM); - UpdateValueMap(I, ResultReg, ValueMap); + UpdateValueMap(I, ResultReg); return true; } bool -X86FastISel::TargetSelectInstruction(Instruction *I, - DenseMap &ValueMap, - DenseMap &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 &vm, + DenseMap &bm) { + return new X86FastISel(mf, vm, bm); } } diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index dceed6fa239..2cdd93c66b5 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -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 &vm, + DenseMap &bm) { + return X86::createFastISel(mf, vm, bm); } diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index c50769c6853..e83132d0071 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -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 &, + DenseMap &); 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 &, + DenseMap &); } }