#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"
#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)
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);
}
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);
// 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...
std::vector<SDOperand> 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;
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),
}
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();
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) {
SSARegMap *RegMap = MF.getSSARegMap();
MachineFrameInfo *MFI = MF.getFrameInfo();
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- 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<SDOperand, 4> MemOps;
// 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<ConstantInt>(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,