X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FARMISelLowering.cpp;h=40ede7409aca8e2b396db11eb19362a2f9e3064c;hb=277074721680253b151efd49d0263a07fafbec3d;hp=60348c1a5b53b3e3a70f9e0098ec8a2bf278cd32;hpb=9a2ef9509e76869c3d658fb3e321d9b9e9d479d9;p=oota-llvm.git diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 60348c1a5b5..40ede7409ac 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -22,6 +22,7 @@ #include "ARMTargetMachine.h" #include "llvm/CallingConv.h" #include "llvm/Constants.h" +#include "llvm/Instruction.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -30,6 +31,7 @@ #include "llvm/CodeGen/SSARegMap.h" #include "llvm/Target/TargetOptions.h" #include "llvm/ADT/VectorExtras.h" +#include "llvm/Support/MathExtras.h" using namespace llvm; ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) @@ -167,7 +169,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setOperationAction(ISD::LOCATION, MVT::Other, Expand); setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); // FIXME - use subtarget debug flags - if (Subtarget->isTargetDarwin()) + if (!Subtarget->isTargetDarwin()) setOperationAction(ISD::LABEL, MVT::Other, Expand); setOperationAction(ISD::RET, MVT::Other, Custom); @@ -338,35 +340,42 @@ static bool FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, } static void -HowToPassArgument(MVT::ValueType ObjectVT, - unsigned NumGPRs, unsigned &ObjSize, unsigned &ObjGPRs) { - ObjSize = 0; - ObjGPRs = 0; - +HowToPassArgument(MVT::ValueType ObjectVT, unsigned NumGPRs, + unsigned StackOffset, unsigned &NeededGPRs, + unsigned &NeededStackSize, unsigned &GPRPad, + unsigned &StackPad, unsigned Flags) { + NeededStackSize = 0; + NeededGPRs = 0; + StackPad = 0; + GPRPad = 0; + unsigned align = (Flags >> ISD::ParamFlags::OrigAlignmentOffs); + GPRPad = NumGPRs % ((align + 3)/4); + StackPad = StackOffset % align; + unsigned firstGPR = NumGPRs + GPRPad; switch (ObjectVT) { default: assert(0 && "Unhandled argument type!"); case MVT::i32: case MVT::f32: - if (NumGPRs < 4) - ObjGPRs = 1; + if (firstGPR < 4) + NeededGPRs = 1; else - ObjSize = 4; + NeededStackSize = 4; break; case MVT::i64: case MVT::f64: - if (NumGPRs < 3) - ObjGPRs = 2; - else if (NumGPRs == 3) { - ObjGPRs = 1; - ObjSize = 4; + if (firstGPR < 3) + NeededGPRs = 2; + else if (firstGPR == 3) { + NeededGPRs = 1; + NeededStackSize = 4; } else - ObjSize = 8; + NeededStackSize = 8; } } -// This transforms a ISD::CALL node into a -// callseq_star <- ARMISD:CALL <- callseq_end -// chain +/// LowerCALL - Lowering a ISD::CALL node into a callseq_start <- +/// ARMISD:CALL <- callseq_end chain. Also add input and output parameter +/// nodes. SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) { MVT::ValueType RetVT= Op.Val->getValueType(0); SDOperand Chain = Op.getOperand(0); @@ -383,12 +392,16 @@ SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) { // Add up all the space actually used. for (unsigned i = 0; i < NumOps; ++i) { - unsigned ObjSize = 0; - unsigned ObjGPRs = 0; + unsigned ObjSize; + unsigned ObjGPRs; + unsigned StackPad; + unsigned GPRPad; MVT::ValueType ObjectVT = Op.getOperand(5+2*i).getValueType(); - HowToPassArgument(ObjectVT, NumGPRs, ObjSize, ObjGPRs); - NumBytes += ObjSize; - NumGPRs += ObjGPRs; + unsigned Flags = Op.getConstantOperandVal(5+2*i+1); + HowToPassArgument(ObjectVT, NumGPRs, NumBytes, ObjGPRs, ObjSize, + GPRPad, StackPad, Flags); + NumBytes += ObjSize + StackPad; + NumGPRs += ObjGPRs + GPRPad; } // Adjust the stack pointer for the new arguments... @@ -407,18 +420,24 @@ SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) { std::vector MemOpChains; for (unsigned i = 0; i != NumOps; ++i) { SDOperand Arg = Op.getOperand(5+2*i); + unsigned Flags = Op.getConstantOperandVal(5+2*i+1); MVT::ValueType ArgVT = Arg.getValueType(); - unsigned ObjSize = 0; - unsigned ObjGPRs = 0; - HowToPassArgument(ArgVT, NumGPRs, ObjSize, ObjGPRs); + unsigned ObjSize; + unsigned ObjGPRs; + unsigned GPRPad; + unsigned StackPad; + HowToPassArgument(ArgVT, NumGPRs, ArgOffset, ObjGPRs, + ObjSize, GPRPad, StackPad, Flags); + NumGPRs += GPRPad; + ArgOffset += StackPad; if (ObjGPRs > 0) { switch (ArgVT) { default: assert(0 && "Unexpected ValueType for argument!"); case MVT::i32: RegsToPass.push_back(std::make_pair(GPRArgRegs[NumGPRs], Arg)); break; - case MVT::f32: + case MVT::f32: RegsToPass.push_back(std::make_pair(GPRArgRegs[NumGPRs], DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Arg))); break; @@ -436,7 +455,7 @@ SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) { MemOpChains.push_back(DAG.getStore(Chain, Hi, PtrOff, NULL, 0)); } break; - } + } case MVT::f64: { SDOperand Cvt = DAG.getNode(ARMISD::FMRRD, DAG.getVTList(MVT::i32, MVT::i32), @@ -715,7 +734,7 @@ static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG, } static SDOperand LowerFORMAL_ARGUMENT(SDOperand Op, SelectionDAG &DAG, - unsigned *vRegs, unsigned ArgNo, + unsigned *vRegs, unsigned ArgNo, unsigned &NumGPRs, unsigned &ArgOffset) { MachineFunction &MF = DAG.getMachineFunction(); MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType(); @@ -727,9 +746,15 @@ static SDOperand LowerFORMAL_ARGUMENT(SDOperand Op, SelectionDAG &DAG, ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; - unsigned ObjSize = 0; - unsigned ObjGPRs = 0; - HowToPassArgument(ObjectVT, NumGPRs, ObjSize, ObjGPRs); + unsigned ObjSize; + unsigned ObjGPRs; + unsigned GPRPad; + unsigned StackPad; + unsigned Flags = Op.getConstantOperandVal(ArgNo + 3); + HowToPassArgument(ObjectVT, NumGPRs, ArgOffset, ObjGPRs, + ObjSize, GPRPad, StackPad, Flags); + NumGPRs += GPRPad; + ArgOffset += StackPad; SDOperand ArgValue; if (ObjGPRs == 1) { @@ -808,13 +833,16 @@ ARMTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) { SSARegMap *RegMap = MF.getSSARegMap(); MachineFrameInfo *MFI = MF.getFrameInfo(); ARMFunctionInfo *AFI = MF.getInfo(); - unsigned VARegSaveSize = (4 - NumGPRs) * 4; + unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); + unsigned VARegSize = (4 - NumGPRs) * 4; + unsigned VARegSaveSize = (VARegSize + Align - 1) & ~(Align - 1); if (VARegSaveSize) { // If this function is vararg, store any remaining integer argument regs // to their spots on the stack so that they may be loaded by deferencing // the result of va_next. AFI->setVarArgsRegSaveSize(VARegSaveSize); - VarArgsFrameIndex = MFI->CreateFixedObject(VARegSaveSize, ArgOffset); + VarArgsFrameIndex = MFI->CreateFixedObject(VARegSaveSize, ArgOffset + + VARegSaveSize - VARegSize); SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, getPointerTy()); SmallVector MemOps; @@ -1242,17 +1270,104 @@ ARMTargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI, // ARM Optimization Hooks //===----------------------------------------------------------------------===// -/// isLegalAddressImmediate - Return true if the integer value or -/// GlobalValue can be used as the offset of the target addressing mode. -bool ARMTargetLowering::isLegalAddressImmediate(int64_t V) const { - // ARM allows a 12-bit immediate field. - return V == V & ((1LL << 12) - 1); +/// isLegalAddressExpression - Return true if the binary expression made up of +/// specified opcode, operands, and type can be folded into target addressing +/// mode for load / store of the given type. +bool ARMTargetLowering::isLegalAddressExpression(unsigned Opc, Value *Op0, + Value *Op1, const Type *Ty) const { + if (ConstantInt *Op1C = dyn_cast(Op1)) { + if (Opc == Instruction::Add) + return isLegalAddressImmediate(Op1C->getSExtValue(), Ty); + if (Opc == Instruction::Sub) + return isLegalAddressImmediate(-Op1C->getSExtValue(), Ty); + } + return false; +} + +/// isLegalAddressImmediate - Return true if the integer value can be used +/// as the offset of the target addressing mode for load / store of the +/// given type. +bool ARMTargetLowering::isLegalAddressImmediate(int64_t V,const Type *Ty) const{ + if (V == 0) + return true; + + MVT::ValueType VT = getValueType(Ty); + if (Subtarget->isThumb()) { + if (V < 0) + return false; + + unsigned Scale = 1; + switch (VT) { + default: return false; + case MVT::i1: + case MVT::i8: + // Scale == 1; + break; + case MVT::i16: + // Scale == 2; + Scale = 2; + break; + case MVT::i32: + // Scale == 4; + Scale = 4; + break; + } + + if ((V & (Scale - 1)) != 0) + return false; + V /= Scale; + return V == V & ((1LL << 5) - 1); + } + + if (V < 0) + V = - V; + switch (VT) { + default: return false; + case MVT::i1: + case MVT::i8: + case MVT::i32: + // +- imm12 + return V == V & ((1LL << 12) - 1); + case MVT::i16: + // +- imm8 + return V == V & ((1LL << 8) - 1); + case MVT::f32: + case MVT::f64: + if (!Subtarget->hasVFP2()) + return false; + if ((V % 3) != 0) + return false; + V >>= 2; + return V == V & ((1LL << 8) - 1); + } } bool ARMTargetLowering::isLegalAddressImmediate(GlobalValue *GV) const { return false; } +/// isLegalAddressScale - Return true if the integer value can be used as +/// the scale of the target addressing mode for load / store of the given +/// type. +bool ARMTargetLowering::isLegalAddressScale(int64_t S, const Type *Ty) const { + if (Subtarget->isThumb()) + return false; + + MVT::ValueType VT = getValueType(Ty); + switch (VT) { + default: return false; + case MVT::i1: + case MVT::i8: + case MVT::i32: + // r + r + if (S == 2) + return true; + // r + r << imm + S &= ~1; + return isPowerOf2_32(S); + } +} + static bool getIndexedAddressParts(SDNode *Ptr, MVT::ValueType VT, bool isSEXTLoad, SDOperand &Base, SDOperand &Offset, bool &isInc,