diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 7b5fbf97d3a..33f595541c6 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -20,10 +20,12 @@ namespace llvm { +class AllocaInst; class ConstantFP; class MachineBasicBlock; class MachineConstantPool; class MachineFunction; +class MachineFrameInfo; class MachineRegisterInfo; class TargetData; class TargetInstrInfo; @@ -40,8 +42,11 @@ protected: DenseMap LocalValueMap; DenseMap &ValueMap; DenseMap &MBBMap; + DenseMap &StaticAllocaMap; MachineFunction &MF; MachineRegisterInfo &MRI; + MachineFrameInfo &MFI; + MachineConstantPool &MCP; const TargetMachine &TM; const TargetData &TD; const TargetInstrInfo &TII; @@ -90,7 +95,8 @@ public: protected: FastISel(MachineFunction &mf, DenseMap &vm, - DenseMap &bm); + DenseMap &bm, + DenseMap &am); /// FastEmit_r - This method is called by target-independent code /// to request that an instruction with the given type and opcode @@ -234,8 +240,13 @@ protected: /// TargetMaterializeConstant - Emit a constant in a register using /// target-specific logic, such as constant pool loads. - virtual unsigned TargetMaterializeConstant(Constant* C, - MachineConstantPool* MCP) { + virtual unsigned TargetMaterializeConstant(Constant* C) { + return 0; + } + + /// TargetMaterializeAlloca - Emit an alloca address in a register using + /// target-specific logic. + virtual unsigned TargetMaterializeAlloca(AllocaInst* C) { return 0; } diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 598a46bf01a..85279bb5817 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -33,6 +33,7 @@ #include namespace llvm { + class AllocaInst; class Function; class FastISel; class MachineBasicBlock; @@ -1120,7 +1121,8 @@ public: virtual FastISel * createFastISel(MachineFunction &, DenseMap &, - DenseMap &) { + DenseMap &, + DenseMap &) { return 0; } diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index 912dc322ff2..8a70b061873 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -37,14 +37,14 @@ unsigned FastISel::getRegForValue(Value *V) { return 0; if (ConstantInt *CI = dyn_cast(V)) { if (CI->getValue().getActiveBits() > 64) - return TargetMaterializeConstant(CI, - MBB->getParent()->getConstantPool()); + return TargetMaterializeConstant(CI); // Don't cache constant materializations. To do so would require // tracking what uses they dominate. Reg = FastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue()); } else if (isa(V)) { - return TargetMaterializeConstant(dyn_cast(V), - MBB->getParent()->getConstantPool()); + return TargetMaterializeConstant(cast(V)); + } else if (isa(V)) { + return TargetMaterializeAlloca(cast(V)); } else if (isa(V)) { Reg = FastEmit_i(VT, VT, ISD::Constant, 0); } else if (ConstantFP *CF = dyn_cast(V)) { @@ -58,19 +58,16 @@ unsigned FastISel::getRegForValue(Value *V) { uint32_t IntBitWidth = IntVT.getSizeInBits(); if (Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true, APFloat::rmTowardZero) != APFloat::opOK) - return TargetMaterializeConstant(CF, - MBB->getParent()->getConstantPool()); + return TargetMaterializeConstant(CF); APInt IntVal(IntBitWidth, 2, x); unsigned IntegerReg = FastEmit_i(IntVT.getSimpleVT(), IntVT.getSimpleVT(), ISD::Constant, IntVal.getZExtValue()); if (IntegerReg == 0) - return TargetMaterializeConstant(CF, - MBB->getParent()->getConstantPool()); + return TargetMaterializeConstant(CF); Reg = FastEmit_r(IntVT.getSimpleVT(), VT, ISD::SINT_TO_FP, IntegerReg); if (Reg == 0) - return TargetMaterializeConstant(CF, - MBB->getParent()->getConstantPool());; + return TargetMaterializeConstant(CF); } } else if (ConstantExpr *CE = dyn_cast(V)) { if (!SelectOperator(CE, CE->getOpcode())) return 0; @@ -83,8 +80,7 @@ unsigned FastISel::getRegForValue(Value *V) { } if (!Reg && isa(V)) - return TargetMaterializeConstant(cast(V), - MBB->getParent()->getConstantPool()); + return TargetMaterializeConstant(cast(V)); LocalValueMap[V] = Reg; return Reg; @@ -416,6 +412,14 @@ FastISel::SelectOperator(User *I, unsigned Opcode) { case Instruction::PHI: // PHI nodes are already emitted. return true; + + case Instruction::Alloca: + // FunctionLowering has the static-sized case covered. + if (StaticAllocaMap.count(cast(I))) + return true; + + // Dynamic-sized alloca is not handled yet. + return false; case Instruction::BitCast: return SelectBitCast(I); @@ -453,12 +457,16 @@ FastISel::SelectOperator(User *I, unsigned Opcode) { FastISel::FastISel(MachineFunction &mf, DenseMap &vm, - DenseMap &bm) + DenseMap &bm, + DenseMap &am) : MBB(0), ValueMap(vm), MBBMap(bm), + StaticAllocaMap(am), MF(mf), MRI(MF.getRegInfo()), + MFI(*MF.getFrameInfo()), + MCP(*MF.getConstantPool()), TM(MF.getTarget()), TD(*TM.getTargetData()), TII(*TM.getInstrInfo()), diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index f47abb3c30d..c9376a1a535 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -737,7 +737,8 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF) { // FastISel doesn't support EH landing pads, which require special handling. if (EnableFastISel && !BB->isLandingPad()) { if (FastISel *F = TLI.createFastISel(*FuncInfo->MF, FuncInfo->ValueMap, - FuncInfo->MBBMap)) { + FuncInfo->MBBMap, + FuncInfo->StaticAllocaMap)) { // Emit code for any incoming arguments. This must happen before // beginning FastISel on the entry block. if (LLVMBB == &Fn.getEntryBlock()) { diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index 3f5d6f99f61..343732e6801 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -31,10 +31,6 @@ using namespace llvm; class X86FastISel : public FastISel { - /// MFI - Keep track of objects allocated on the stack. - /// - MachineFrameInfo *MFI; - /// Subtarget - Keep a pointer to the X86Subtarget around so that we can /// make the right decision when generating code for different targets. const X86Subtarget *Subtarget; @@ -53,8 +49,9 @@ class X86FastISel : public FastISel { public: explicit X86FastISel(MachineFunction &mf, DenseMap &vm, - DenseMap &bm) - : FastISel(mf, vm, bm), MFI(MF.getFrameInfo()) { + DenseMap &bm, + DenseMap &am) + : FastISel(mf, vm, bm, am) { Subtarget = &TM.getSubtarget(); StackPtr = Subtarget->is64Bit() ? X86::RSP : X86::ESP; X86ScalarSSEf64 = Subtarget->hasSSE2(); @@ -66,10 +63,10 @@ public: #include "X86GenFastISel.inc" private: - bool X86FastEmitLoad(MVT VT, unsigned Op0, Value *V, unsigned &RR); + bool X86FastEmitLoad(MVT VT, const X86AddressMode &AM, unsigned &RR); bool X86FastEmitStore(MVT VT, unsigned Val, - unsigned Ptr, unsigned Offset, Value *V); + const X86AddressMode &AM); bool X86FastEmitExtend(ISD::NodeType Opc, MVT DstVT, unsigned Src, MVT SrcVT, unsigned &ResultReg); @@ -77,6 +74,8 @@ private: bool X86SelectConstAddr(Value *V, unsigned &Op0, bool isCall = false, bool inReg = false); + bool X86SelectAddress(Value *V, X86AddressMode &AM); + bool X86SelectLoad(Instruction *I); bool X86SelectStore(Instruction *I); @@ -97,7 +96,9 @@ private: CCAssignFn *CCAssignFnForCall(unsigned CC, bool isTailCall = false); - unsigned TargetMaterializeConstant(Constant *C, MachineConstantPool* MCP); + unsigned TargetMaterializeConstant(Constant *C); + + unsigned TargetMaterializeAlloca(AllocaInst *C); /// isScalarFPTypeInSSEReg - Return true if the specified scalar FP type is /// computed in an SSE register, not on the X87 floating point stack. @@ -151,7 +152,7 @@ CCAssignFn *X86FastISel::CCAssignFnForCall(unsigned CC, bool isTaillCall) { /// 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. /// Return true and the result register by reference if it is possible. -bool X86FastISel::X86FastEmitLoad(MVT VT, unsigned Ptr, Value *GV, +bool X86FastISel::X86FastEmitLoad(MVT VT, const X86AddressMode &AM, unsigned &ResultReg) { // Get opcode and regclass of the output for the given load instruction. unsigned Opc = 0; @@ -200,12 +201,6 @@ bool X86FastISel::X86FastEmitLoad(MVT VT, unsigned Ptr, Value *GV, } ResultReg = createResultReg(RC); - X86AddressMode AM; - if (Ptr) - // Address is in register. - AM.Base.Reg = Ptr; - else - AM.GV = cast(GV); addFullAddress(BuildMI(MBB, TII.get(Opc), ResultReg), AM); return true; } @@ -216,7 +211,7 @@ bool X86FastISel::X86FastEmitLoad(MVT VT, unsigned Ptr, Value *GV, /// i.e. V. Return true if it is possible. bool X86FastISel::X86FastEmitStore(MVT VT, unsigned Val, - unsigned Ptr, unsigned Offset, Value *V) { + const X86AddressMode &AM) { // Get opcode and regclass of the output for the given store instruction. unsigned Opc = 0; const TargetRegisterClass *RC = NULL; @@ -263,13 +258,6 @@ X86FastISel::X86FastEmitStore(MVT VT, unsigned Val, break; } - X86AddressMode AM; - if (Ptr) { - // Address is in register. - AM.Base.Reg = Ptr; - AM.Disp = Offset; - } else - AM.GV = cast(V); addFullAddress(BuildMI(MBB, TII.get(Opc)), AM).addReg(Val); return true; } @@ -331,6 +319,39 @@ bool X86FastISel::X86SelectConstAddr(Value *V, unsigned &Op0, return true; } +/// X86SelectAddress - Attempt to fill in an address from the given value. +/// +bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM) { + // Look past bitcasts. + if (const BitCastInst *BC = dyn_cast(V)) + return X86SelectAddress(BC->getOperand(0), AM); + + if (const AllocaInst *A = dyn_cast(V)) { + DenseMap::iterator SI = StaticAllocaMap.find(A); + if (SI == StaticAllocaMap.end()) + return false; + AM.BaseType = X86AddressMode::FrameIndexBase; + AM.Base.FrameIndex = SI->second; + } else if (unsigned Ptr = lookUpRegForValue(V)) { + AM.Base.Reg = Ptr; + } else { + // Handle constant address. + // FIXME: If load type is something we can't handle, this can result in + // a dead stub load instruction. + if (isa(V) && X86SelectConstAddr(V, AM.Base.Reg)) { + if (AM.Base.Reg == 0) + AM.GV = cast(V); + } else { + AM.Base.Reg = getRegForValue(V); + if (AM.Base.Reg == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + } + } + + return true; +} + /// X86SelectStore - Select and emit code to implement store instructions. bool X86FastISel::X86SelectStore(Instruction* I) { MVT VT; @@ -341,21 +362,11 @@ bool X86FastISel::X86SelectStore(Instruction* I) { // Unhandled operand. Halt "fast" selection and bail. return false; - Value *V = I->getOperand(1); - unsigned Ptr = lookUpRegForValue(V); - if (!Ptr) { - // Handle constant load address. - // FIXME: If load type is something we can't handle, this can result in - // a dead stub load instruction. - if (!isa(V) || !X86SelectConstAddr(V, Ptr)) { - Ptr = getRegForValue(V); - if (Ptr == 0) - // Unhandled operand. Halt "fast" selection and bail. - return false; - } - } + X86AddressMode AM; + if (!X86SelectAddress(I->getOperand(1), AM)) + return false; - return X86FastEmitStore(VT, Val, Ptr, 0, V); + return X86FastEmitStore(VT, Val, AM); } /// X86SelectLoad - Select and emit code to implement load instructions. @@ -365,22 +376,12 @@ bool X86FastISel::X86SelectLoad(Instruction *I) { if (!isTypeLegal(I->getType(), TLI, VT)) return false; - Value *V = I->getOperand(0); - unsigned Ptr = lookUpRegForValue(V); - if (!Ptr) { - // Handle constant load address. - // FIXME: If load type is something we can't handle, this can result in - // a dead stub load instruction. - if (!isa(V) || !X86SelectConstAddr(V, Ptr)) { - Ptr = getRegForValue(V); - if (Ptr == 0) - // Unhandled operand. Halt "fast" selection and bail. - return false; - } - } + X86AddressMode AM; + if (!X86SelectAddress(I->getOperand(0), AM)) + return false; unsigned ResultReg = 0; - if (X86FastEmitLoad(VT, Ptr, V, ResultReg)) { + if (X86FastEmitLoad(VT, AM, ResultReg)) { UpdateValueMap(I, ResultReg); return true; } @@ -831,7 +832,10 @@ bool X86FastISel::X86SelectCall(Instruction *I) { RegArgs.push_back(VA.getLocReg()); } else { unsigned LocMemOffset = VA.getLocMemOffset(); - X86FastEmitStore(ArgVT, Arg, StackPtr, LocMemOffset, NULL); + X86AddressMode AM; + AM.Base.Reg = StackPtr; + AM.Disp = LocMemOffset; + X86FastEmitStore(ArgVT, Arg, AM); } } @@ -885,7 +889,7 @@ bool X86FastISel::X86SelectCall(Instruction *I) { MVT ResVT = RVLocs[0].getValVT(); unsigned Opc = ResVT == MVT::f32 ? X86::ST_Fp80m32 : X86::ST_Fp80m64; unsigned MemSize = ResVT.getSizeInBits()/8; - int FI = MFI->CreateStackObject(MemSize, MemSize); + int FI = MFI.CreateStackObject(MemSize, MemSize); addFrameReference(BuildMI(MBB, TII.get(Opc)), FI).addReg(ResultReg); DstRC = ResVT == MVT::f32 ? X86::FR32RegisterClass : X86::FR64RegisterClass; @@ -938,8 +942,7 @@ X86FastISel::TargetSelectInstruction(Instruction *I) { return false; } -unsigned X86FastISel::TargetMaterializeConstant(Constant *C, - MachineConstantPool* MCP) { +unsigned X86FastISel::TargetMaterializeConstant(Constant *C) { // Can't handle PIC-mode yet. if (TM.getRelocationModel() == Reloc::PIC_) return 0; @@ -1010,15 +1013,27 @@ unsigned X86FastISel::TargetMaterializeConstant(Constant *C, Align = Log2_64(Align); } - unsigned MCPOffset = MCP->getConstantPoolIndex(C, Align); + unsigned MCPOffset = MCP.getConstantPoolIndex(C, Align); addConstantPoolReference(BuildMI(MBB, TII.get(Opc), ResultReg), MCPOffset); return ResultReg; } +unsigned X86FastISel::TargetMaterializeAlloca(AllocaInst *C) { + X86AddressMode AM; + if (!X86SelectAddress(C, AM)) + return 0; + unsigned Opc = Subtarget->is64Bit() ? X86::LEA64r : X86::LEA32r; + TargetRegisterClass* RC = TLI.getRegClassFor(TLI.getPointerTy()); + unsigned ResultReg = createResultReg(RC); + addFullAddress(BuildMI(MBB, TII.get(Opc), ResultReg), AM); + return ResultReg; +} + namespace llvm { llvm::FastISel *X86::createFastISel(MachineFunction &mf, DenseMap &vm, - DenseMap &bm) { - return new X86FastISel(mf, vm, bm); + DenseMap &bm, + DenseMap &am) { + return new X86FastISel(mf, vm, bm, am); } } diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 2ddddf6fb15..ab4510a8720 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -1886,8 +1886,10 @@ FastISel * X86TargetLowering::createFastISel(MachineFunction &mf, DenseMap &vm, DenseMap &bm) { - return X86::createFastISel(mf, vm, bm); + MachineBasicBlock *> &bm, + DenseMap &am) { + + return X86::createFastISel(mf, vm, bm, am); } diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 6ff053f6fec..e5fc8ed4b71 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -473,7 +473,8 @@ namespace llvm { virtual FastISel * createFastISel(MachineFunction &mf, DenseMap &, - DenseMap &); + DenseMap &, + DenseMap &); private: /// Subtarget - Keep a pointer to the X86Subtarget around so that we can @@ -604,7 +605,8 @@ namespace llvm { namespace X86 { FastISel *createFastISel(MachineFunction &mf, DenseMap &, - DenseMap &); + DenseMap &, + DenseMap &); } }