aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp13
-rw-r--r--lib/Target/ARM/ARMBaseRegisterInfo.cpp18
-rw-r--r--lib/Target/ARM/ARMConstantIslandPass.cpp2
-rw-r--r--lib/Target/ARM/ARMISelDAGToDAG.cpp15
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp94
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td20
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td4
-rw-r--r--lib/Target/ARM/ARMMachineFunctionInfo.h1
-rw-r--r--lib/Target/ARM/ARMTargetAsmInfo.cpp2
-rw-r--r--lib/Target/ARM/Thumb2InstrInfo.cpp284
-rw-r--r--lib/Target/ARM/Thumb2InstrInfo.h61
-rw-r--r--lib/Target/ARM/Thumb2RegisterInfo.cpp701
-rw-r--r--lib/Target/ARM/Thumb2RegisterInfo.h16
-rw-r--r--test/CodeGen/Thumb2/thumb2-mulhi.ll2
-rw-r--r--test/CodeGen/Thumb2/thumb2-select_xform.ll2
15 files changed, 107 insertions, 1128 deletions
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 9d72a128d1..485545c63a 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -215,8 +215,11 @@ static void EmitLiveInCopy(MachineBasicBlock *MBB,
--Pos;
}
- TII.copyRegToReg(*MBB, Pos, VirtReg, PhysReg, RC, RC);
- CopyRegMap.insert(std::make_pair(prior(Pos), VirtReg));
+ bool Emitted = TII.copyRegToReg(*MBB, Pos, VirtReg, PhysReg, RC, RC);
+ assert(Emitted && "Unable to issue a live-in copy instruction!\n");
+ (void) Emitted;
+
+CopyRegMap.insert(std::make_pair(prior(Pos), VirtReg));
if (Coalesced) {
if (&*InsertPos == UseMI) ++InsertPos;
MBB->erase(UseMI);
@@ -247,8 +250,10 @@ static void EmitLiveInCopies(MachineBasicBlock *EntryMBB,
E = MRI.livein_end(); LI != E; ++LI)
if (LI->second) {
const TargetRegisterClass *RC = MRI.getRegClass(LI->second);
- TII.copyRegToReg(*EntryMBB, EntryMBB->begin(),
- LI->second, LI->first, RC, RC);
+ bool Emitted = TII.copyRegToReg(*EntryMBB, EntryMBB->begin(),
+ LI->second, LI->first, RC, RC);
+ assert(Emitted && "Unable to issue a live-in copy instruction!\n");
+ (void) Emitted;
}
}
}
diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp
index 0c05904d61..4a77b638d8 100644
--- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp
+++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp
@@ -227,7 +227,7 @@ ARMBaseRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
0
};
- if (STI.isThumb()) {
+ if (STI.isThumb1Only()) {
return STI.isTargetDarwin()
? DarwinThumbCalleeSavedRegClasses : ThumbCalleeSavedRegClasses;
}
@@ -565,7 +565,7 @@ ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
}
bool ForceLRSpill = false;
- if (!LRSpilled && AFI->isThumbFunction()) {
+ if (!LRSpilled && AFI->isThumb1OnlyFunction()) {
unsigned FnSize = TII.GetFunctionSizeInBytes(MF);
// Force LR to be spilled if the Thumb function size is > 2048. This enables
// use of BL to implement far jump. If it turns out that it's not needed
@@ -607,8 +607,8 @@ ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
if (CS1Spilled && !UnspilledCS1GPRs.empty()) {
for (unsigned i = 0, e = UnspilledCS1GPRs.size(); i != e; ++i) {
unsigned Reg = UnspilledCS1GPRs[i];
- // Don't spiil high register if the function is thumb
- if (!AFI->isThumbFunction() ||
+ // Don't spill high register if the function is thumb1
+ if (!AFI->isThumb1OnlyFunction() ||
isARMLowRegister(Reg) || Reg == ARM::LR) {
MF.getRegInfo().setPhysRegUsed(Reg);
AFI->setCSRegisterIsSpilled(Reg);
@@ -618,7 +618,7 @@ ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
}
}
} else if (!UnspilledCS2GPRs.empty() &&
- !AFI->isThumbFunction()) {
+ !AFI->isThumb1OnlyFunction()) {
unsigned Reg = UnspilledCS2GPRs.front();
MF.getRegInfo().setPhysRegUsed(Reg);
AFI->setCSRegisterIsSpilled(Reg);
@@ -631,7 +631,7 @@ ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
// to materialize a stack offset. If so, either spill one additional
// callee-saved register or reserve a special spill slot to facilitate
// register scavenging.
- if (RS && !ExtraCSSpill && !AFI->isThumbFunction()) {
+ if (RS && !ExtraCSSpill && !AFI->isThumb1OnlyFunction()) {
MachineFrameInfo *MFI = MF.getFrameInfo();
unsigned Size = estimateStackSize(MF, MFI);
unsigned Limit = (1 << 12) - 1;
@@ -730,7 +730,7 @@ unsigned ARMBaseRegisterInfo::getRegisterPairEven(unsigned Reg,
return ARM::R0;
case ARM::R3:
// FIXME!
- return STI.isThumb() ? 0 : ARM::R2;
+ return STI.isThumb1Only() ? 0 : ARM::R2;
case ARM::R5:
return ARM::R4;
case ARM::R7:
@@ -804,7 +804,7 @@ unsigned ARMBaseRegisterInfo::getRegisterPairOdd(unsigned Reg,
return ARM::R1;
case ARM::R2:
// FIXME!
- return STI.isThumb() ? 0 : ARM::R3;
+ return STI.isThumb1Only() ? 0 : ARM::R3;
case ARM::R4:
return ARM::R5;
case ARM::R6:
@@ -1003,7 +1003,7 @@ static
unsigned findScratchRegister(RegScavenger *RS, const TargetRegisterClass *RC,
ARMFunctionInfo *AFI) {
unsigned Reg = RS ? RS->FindUnusedReg(RC, true) : (unsigned) ARM::R12;
- assert (!AFI->isThumbFunction());
+ assert (!AFI->isThumb1OnlyFunction());
if (Reg == 0)
// Try a already spilled CS register.
Reg = RS->FindUnusedReg(RC, AFI->getSpilledCSRegisters());
diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp
index 3898a0a922..34c9d70e69 100644
--- a/lib/Target/ARM/ARMConstantIslandPass.cpp
+++ b/lib/Target/ARM/ARMConstantIslandPass.cpp
@@ -124,6 +124,7 @@ namespace {
const TargetInstrInfo *TII;
ARMFunctionInfo *AFI;
bool isThumb;
+ bool isThumb1Only;
bool isThumb2;
public:
static char ID;
@@ -214,6 +215,7 @@ bool ARMConstantIslands::runOnMachineFunction(MachineFunction &Fn) {
TII = Fn.getTarget().getInstrInfo();
AFI = Fn.getInfo<ARMFunctionInfo>();
isThumb = AFI->isThumbFunction();
+ isThumb1Only = AFI->isThumb1OnlyFunction();
isThumb2 = AFI->isThumb2Function();
HasFarJump = false;
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp
index 50db5896dd..e012d31c82 100644
--- a/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -870,7 +870,7 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
TLI.getPointerTy());
SDNode *ResNode;
- if (Subtarget->isThumb())
+ if (Subtarget->isThumb1Only())
ResNode = CurDAG->getTargetNode(ARM::tLDRcp, dl, MVT::i32, MVT::Other,
CPIdx, CurDAG->getEntryNode());
else {
@@ -896,18 +896,19 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
// Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
int FI = cast<FrameIndexSDNode>(N)->getIndex();
SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
- if (Subtarget->isThumb()) {
+ if (Subtarget->isThumb1Only()) {
return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI,
CurDAG->getTargetConstant(0, MVT::i32));
} else {
SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
CurDAG->getRegister(0, MVT::i32) };
- return CurDAG->SelectNodeTo(N, ARM::ADDri, MVT::i32, Ops, 5);
+ return CurDAG->SelectNodeTo(N, (Subtarget->hasThumb2()) ? ARM::t2ADDri : ARM::ADDri,
+ MVT::i32, Ops, 5);
}
}
case ISD::ADD: {
- if (!Subtarget->isThumb())
+ if (!Subtarget->isThumb1Only())
break;
// Select add sp, c to tADDhirr.
SDValue N0 = Op.getOperand(0);
@@ -938,7 +939,8 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
CurDAG->getTargetConstant(ShImm, MVT::i32),
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
CurDAG->getRegister(0, MVT::i32) };
- return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7);
+ return CurDAG->SelectNodeTo(N, (Subtarget->hasThumb2()) ?
+ ARM::t2ADDrs : ARM::ADDrs, MVT::i32, Ops, 7);
}
if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
SDValue V = Op.getOperand(0);
@@ -947,7 +949,8 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
CurDAG->getTargetConstant(ShImm, MVT::i32),
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
CurDAG->getRegister(0, MVT::i32) };
- return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7);
+ return CurDAG->SelectNodeTo(N, (Subtarget->hasThumb2()) ?
+ ARM::t2RSBrs : ARM::RSBrs, MVT::i32, Ops, 7);
}
}
break;
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
index 2d29142e38..9ededa9d3a 100644
--- a/lib/Target/ARM/ARMISelLowering.cpp
+++ b/lib/Target/ARM/ARMISelLowering.cpp
@@ -189,11 +189,11 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
setLibcallName(RTLIB::SRL_I128, 0);
setLibcallName(RTLIB::SRA_I128, 0);
- if (Subtarget->isThumb())
+ if (Subtarget->isThumb1Only())
addRegisterClass(MVT::i32, ARM::tGPRRegisterClass);
else
addRegisterClass(MVT::i32, ARM::GPRRegisterClass);
- if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb()) {
+ if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb1Only()) {
addRegisterClass(MVT::f32, ARM::SPRRegisterClass);
addRegisterClass(MVT::f64, ARM::DPRRegisterClass);
@@ -256,7 +256,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
} else {
setOperationAction(ISD::MUL, MVT::i64, Expand);
setOperationAction(ISD::MULHU, MVT::i32, Expand);
- if (!Subtarget->isThumb() && !Subtarget->hasV6Ops())
+ if (!Subtarget->isThumb1Only() && !Subtarget->hasV6Ops())
setOperationAction(ISD::MULHS, MVT::i32, Expand);
}
setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
@@ -310,7 +310,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
}
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
- if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb())
+ if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb1Only())
// Turn f64->i64 into FMRRD, i64 -> f64 to FMDRR iff target supports vfp2.
setOperationAction(ISD::BIT_CONVERT, MVT::i64, Custom);
@@ -340,7 +340,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
setOperationAction(ISD::FCOS, MVT::f64, Expand);
setOperationAction(ISD::FREM, MVT::f64, Expand);
setOperationAction(ISD::FREM, MVT::f32, Expand);
- if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb()) {
+ if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb1Only()) {
setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom);
setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom);
}
@@ -348,7 +348,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
setOperationAction(ISD::FPOW, MVT::f32, Expand);
// int <-> fp are custom expanded into bit_convert + ARMISD ops.
- if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb()) {
+ if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb1Only()) {
setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom);
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
@@ -942,7 +942,7 @@ SDValue ARMTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
// ARM call to a local ARM function is predicable.
isLocalARMFunc = !Subtarget->isThumb() && !isExt;
// tBX takes a register source operand.
- if (isARMFunc && Subtarget->isThumb() && !Subtarget->hasV5TOps()) {
+ if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, ARMPCLabelIndex,
ARMCP::CPStub, 4);
SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4);
@@ -961,7 +961,7 @@ SDValue ARMTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
isARMFunc = !Subtarget->isThumb() || isStub;
// tBX takes a register source operand.
const char *Sym = S->getSymbol();
- if (isARMFunc && Subtarget->isThumb() && !Subtarget->hasV5TOps()) {
+ if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(Sym, ARMPCLabelIndex,
ARMCP::CPStub, 4);
SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4);
@@ -977,7 +977,7 @@ SDValue ARMTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
// FIXME: handle tail calls differently.
unsigned CallOpc;
- if (Subtarget->isThumb()) {
+ if (Subtarget->isThumb1Only()) {
if (!Subtarget->hasV5TOps() && (!isDirect || isARMFunc))
CallOpc = ARMISD::CALL_NOLINK;
else
@@ -987,7 +987,7 @@ SDValue ARMTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
? (isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL)
: ARMISD::CALL_NOLINK;
}
- if (CallOpc == ARMISD::CALL_NOLINK && !Subtarget->isThumb()) {
+ if (CallOpc == ARMISD::CALL_NOLINK && !Subtarget->isThumb1Only()) {
// implicit def LR - LR mustn't be allocated as GRP:$dst of CALL_NOLINK
Chain = DAG.getCopyToReg(Chain, dl, ARM::LR, DAG.getUNDEF(MVT::i32),InFlag);
InFlag = Chain.getValue(1);
@@ -1345,7 +1345,7 @@ ARMTargetLowering::GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA,
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
TargetRegisterClass *RC;
- if (AFI->isThumbFunction())
+ if (AFI->isThumb1OnlyFunction())
RC = ARM::tGPRRegisterClass;
else
RC = ARM::GPRRegisterClass;
@@ -1423,7 +1423,7 @@ ARMTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
RC = ARM::SPRRegisterClass;
else if (FloatABIType == FloatABI::Hard && RegVT == MVT::f64)
RC = ARM::DPRRegisterClass;
- else if (AFI->isThumbFunction())
+ else if (AFI->isThumb1OnlyFunction())
RC = ARM::tGPRRegisterClass;
else
RC = ARM::GPRRegisterClass;
@@ -1501,7 +1501,7 @@ ARMTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
SmallVector<SDValue, 4> MemOps;
for (; NumGPRs < 4; ++NumGPRs) {
TargetRegisterClass *RC;
- if (AFI->isThumbFunction())
+ if (AFI->isThumb1OnlyFunction())
RC = ARM::tGPRRegisterClass;
else
RC = ARM::GPRRegisterClass;
@@ -1544,46 +1544,46 @@ static bool isFloatingPointZero(SDValue Op) {
return false;
}
-static bool isLegalCmpImmediate(unsigned C, bool isThumb) {
- return ( isThumb && (C & ~255U) == 0) ||
- (!isThumb && ARM_AM::getSOImmVal(C) != -1);
+static bool isLegalCmpImmediate(unsigned C, bool isThumb1Only) {
+ return ( isThumb1Only && (C & ~255U) == 0) ||
+ (!isThumb1Only && ARM_AM::getSOImmVal(C) != -1);
}
/// Returns appropriate ARM CMP (cmp) and corresponding condition code for
/// the given operands.
static SDValue getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
- SDValue &ARMCC, SelectionDAG &DAG, bool isThumb,
+ SDValue &ARMCC, SelectionDAG &DAG, bool isThumb1Only,
DebugLoc dl) {
if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS.getNode())) {
unsigned C = RHSC->getZExtValue();
- if (!isLegalCmpImmediate(C, isThumb)) {
+ if (!isLegalCmpImmediate(C, isThumb1Only)) {
// Constant does not fit, try adjusting it by one?
switch (CC) {
default: break;
case ISD::SETLT:
case ISD::SETGE:
- if (isLegalCmpImmediate(C-1, isThumb)) {
+ if (isLegalCmpImmediate(C-1, isThumb1Only)) {
CC = (CC == ISD::SETLT) ? ISD::SETLE : ISD::SETGT;
RHS = DAG.getConstant(C-1, MVT::i32);
}
break;
case ISD::SETULT:
case ISD::SETUGE:
- if (C > 0 && isLegalCmpImmediate(C-1, isThumb)) {
+ if (C > 0 && isLegalCmpImmediate(C-1, isThumb1Only)) {
CC = (CC == ISD::SETULT) ? ISD::SETULE : ISD::SETUGT;
RHS = DAG.getConstant(C-1, MVT::i32);
}
break;
case ISD::SETLE:
case ISD::SETGT:
- if (isLegalCmpImmediate(C+1, isThumb)) {
+ if (isLegalCmpImmediate(C+1, isThumb1Only)) {
CC = (CC == ISD::SETLE) ? ISD::SETLT : ISD::SETGE;
RHS = DAG.getConstant(C+1, MVT::i32);
}
break;
case ISD::SETULE:
case ISD::SETUGT:
- if (C < 0xffffffff && isLegalCmpImmediate(C+1, isThumb)) {
+ if (C < 0xffffffff && isLegalCmpImmediate(C+1, isThumb1Only)) {
CC = (CC == ISD::SETULE) ? ISD::SETULT : ISD::SETUGE;
RHS = DAG.getConstant(C+1, MVT::i32);
}
@@ -1632,7 +1632,7 @@ static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG,
if (LHS.getValueType() == MVT::i32) {
SDValue ARMCC;
SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
- SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMCC, DAG, ST->isThumb(), dl);
+ SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMCC, DAG, ST->isThumb1Only(), dl);
return DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMCC, CCR,Cmp);
}
@@ -1667,7 +1667,7 @@ static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG,
if (LHS.getValueType() == MVT::i32) {
SDValue ARMCC;
SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
- SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMCC, DAG, ST->isThumb(), dl);
+ SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMCC, DAG, ST->isThumb1Only(), dl);
return DAG.getNode(ARMISD::BRCOND, dl, MVT::Other,
Chain, Dest, ARMCC, CCR,Cmp);
}
@@ -1970,7 +1970,7 @@ static SDValue LowerShift(SDNode *N, SelectionDAG &DAG,
return SDValue();
// If we are in thumb mode, we don't have RRX.
- if (ST->isThumb()) return SDValue();
+ if (ST->isThumb1Only()) return SDValue();
// Okay, we have a 64-bit SRA or SRL of 1. Lower this to an RRX expr.
SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(0),
@@ -2810,7 +2810,7 @@ static bool isLegalAddressImmediate(int64_t V, MVT VT,
if (!VT.isSimple())
return false;
- if (Subtarget->isThumb()) {
+ if (Subtarget->isThumb()) { // FIXME for thumb2
if (V < 0)
return false;
@@ -2876,7 +2876,7 @@ bool ARMTargetLowering::isLegalAddressingMode(const AddrMode &AM,
case 0: // no scale reg, must be "r+i" or "r", or "i".
break;
case 1:
- if (Subtarget->isThumb())
+ if (Subtarget->isThumb()) // FIXME for thumb2
return false;
// FALL THROUGH.
default:
@@ -3130,7 +3130,7 @@ ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
// GCC RS6000 Constraint Letters
switch (Constraint[0]) {
case 'l':
- if (Subtarget->isThumb())
+ if (Subtarget->isThumb1Only())
return std::make_pair(0U, ARM::tGPRRegisterClass);
else
return std::make_pair(0U, ARM::GPRRegisterClass);
@@ -3211,10 +3211,16 @@ void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
switch (Constraint) {
case 'I':
- if (Subtarget->isThumb()) {
- // This must be a constant between 0 and 255, for ADD immediates.
+ if (Subtarget->isThumb1Only()) {
+ // This must be a constant between 0 and 255, for ADD
+ // immediates.
if (CVal >= 0 && CVal <= 255)
break;
+ } else if (Subtarget->isThumb2()) {
+ // A constant that can be used as an immediate value in a
+ // data-processing instruction.
+ if (ARM_AM::getT2SOImmVal(CVal) != -1)
+ break;
} else {
// A constant that can be used as an immediate value in a
// data-processing instruction.
@@ -3224,7 +3230,7 @@ void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
return;
case 'J':
- if (Subtarget->isThumb()) {
+ if (Subtarget->isThumb()) { // FIXME thumb2
// This must be a constant between -255 and -1, for negated ADD
// immediates. This can be used in GCC with an "n" modifier that
// prints the negated value, for use with SUB instructions. It is
@@ -3241,13 +3247,21 @@ void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
return;
case 'K':
- if (Subtarget->isThumb()) {
+ if (Subtarget->isThumb1Only()) {
// A 32-bit value where only one byte has a nonzero value. Exclude
// zero to match GCC. This constraint is used by GCC internally for
// constants that can be loaded with a move/shift combination.
// It is not useful otherwise but is implemented for compatibility.
if (CVal != 0 && ARM_AM::isThumbImmShiftedVal(CVal))
break;
+ } else if (Subtarget->isThumb2()) {
+ // A constant whose bitwise inverse can be used as an immediate
+ // value in a data-processing instruction. This can be used in GCC
+ // with a "B" modifier that prints the inverted value, for use with
+ // BIC and MVN instructions. It is not useful otherwise but is
+ // implemented for compatibility.
+ if (ARM_AM::getT2SOImmVal(~CVal) != -1)
+ break;
} else {
// A constant whose bitwise inverse can be used as an immediate
// value in a data-processing instruction. This can be used in GCC
@@ -3260,11 +3274,19 @@ void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
return;
case 'L':
- if (Subtarget->isThumb()) {
+ if (Subtarget->isThumb1Only()) {
// This must be a constant between -7 and 7,
// for 3-operand ADD/SUB immediate instructions.
if (CVal >= -7 && CVal < 7)
break;
+ } else if (Subtarget->isThumb2()) {
+ // A constant whose negation can be used as an immediate value in a
+ // data-processing instruction. This can be used in GCC with an "n"
+ // modifier that prints the negated value, for use with SUB
+ // instructions. It is not useful otherwise but is implemented for
+ // compatibility.
+ if (ARM_AM::getT2SOImmVal(-CVal) != -1)
+ break;
} else {
// A constant whose negation can be used as an immediate value in a
// data-processing instruction. This can be used in GCC with an "n"
@@ -3277,7 +3299,7 @@ void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
return;
case 'M':
- if (Subtarget->isThumb()) {
+ if (Subtarget->isThumb()) { // FIXME thumb2
// This must be a multiple of 4 between 0 and 1020, for
// ADD sp + immediate.
if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
@@ -3292,7 +3314,7 @@ void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
return;
case 'N':
- if (Subtarget->isThumb()) {
+ if (Subtarget->isThumb()) { // FIXME thumb2
// This must be a constant between 0 and 31, for shift amounts.
if (CVal >= 0 && CVal <= 31)
break;
@@ -3300,7 +3322,7 @@ void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
return;
case 'O':
- if (Subtarget->isThumb()) {
+ if (Subtarget->isThumb()) { // FIXME thumb2
// This must be a multiple of 4 between -508 and 508, for
// ADD/SUB sp = sp + immediate.
if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index acf96a21ab..fb7453a912 100644
--- a/lib/Target/ARM/ARMInstrThumb.td
+++ b/lib/Target/ARM/ARMInstrThumb.td
@@ -119,12 +119,12 @@ let Defs = [SP], Uses = [SP] in {
def tADJCALLSTACKUP :
PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2),
"@ tADJCALLSTACKUP $amt1",
- [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, Requires<[IsThumb]>;
+ [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, Requires<[IsThumb1Only]>;
def tADJCALLSTACKDOWN :
PseudoInst<(outs), (ins i32imm:$amt),
"@ tADJCALLSTACKDOWN $amt",
- [(ARMcallseq_start imm:$amt)]>, Requires<[IsThumb]>;
+ [(ARMcallseq_start imm:$amt)]>, Requires<[IsThumb1Only]>;
}
let isNotDuplicable = 1 in
@@ -155,7 +155,7 @@ def tADDspi : T1It<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
//
let isReturn = 1, isTerminator = 1 in {
- def tBX_RET : TI<(outs), (ins), "bx lr", [(ARMretflag)]>;
+ def tBX_RET : T1I<(outs), (ins), "bx lr", [(ARMretflag)]>;
// Alternative return instruction used by vararg functions.
def tBX_RET_vararg : T1I<(outs), (ins tGPR:$target), "bx $target", []>;
}
@@ -471,7 +471,7 @@ def tORR : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
def tREV : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"rev $dst, $src",
[(set tGPR:$dst, (bswap tGPR:$src))]>,
- Requires<[IsThumb, HasV6]>;
+ Requires<[IsThumb1Only, HasV6]>;
def tREV16 : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"rev16 $dst, $src",
@@ -480,7 +480,7 @@ def tREV16 : T1I<(outs tGPR:$dst), (ins tGPR:$src),
(or (and (shl tGPR:$src, (i32 8)), 0xFF00),
(or (and (srl tGPR:$src, (i32 8)), 0xFF0000),
(and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>,
- Requires<[IsThumb, HasV6]>;
+ Requires<[IsThumb1Only, HasV6]>;
def tREVSH : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"revsh $dst, $src",
@@ -488,7 +488,7 @@ def tREVSH : T1I<(outs tGPR:$dst), (ins tGPR:$src),
(sext_inreg
(or (srl (and tGPR:$src, 0xFFFF), (i32 8)),
(shl tGPR:$src, (i32 8))), i16))]>,
- Requires<[IsThumb, HasV6]>;
+ Requires<[IsThumb1Only, HasV6]>;
// rotate right register
let Defs = [CPSR] in
@@ -540,13 +540,13 @@ def tSUBspi : T1It<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs),
def tSXTB : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"sxtb $dst, $src",
[(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>,
- Requires<[IsThumb, HasV6]>;
+ Requires<[IsThumb1Only, HasV6]>;
// sign-extend short
def tSXTH : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"sxth $dst, $src",
[(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>,
- Requires<[IsThumb, HasV6]>;
+ Requires<[IsThumb1Only, HasV6]>;
// test
let isCommutable = 1, Defs = [CPSR] in
@@ -558,13 +558,13 @@ def tTST : T1I<(outs), (ins tGPR:$lhs, tGPR:$rhs),
def tUXTB : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"uxtb $dst, $src",
[(set tGPR:$dst, (and tGPR:$src, 0xFF))]>,
- Requires<[IsThumb, HasV6]>;
+ Requires<[IsThumb1Only, HasV6]>;
// zero-extend short
def tUXTH : T1I<(outs tGPR:$dst), (ins tGPR:$src),
"uxth $dst, $src",
[(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>,
- Requires<[IsThumb, HasV6]>;
+ Requires<[IsThumb1Only, HasV6]>;
// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC DAG operation.
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index 22d670ba24..11ae0ee75d 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -432,9 +432,9 @@ multiclass T2I_bin_rrot<string opc, PatFrag opnode> {
//
let isNotDuplicable = 1 in
-def t2PICADD : T2XI<(outs tGPR:$dst), (ins tGPR:$lhs, pclabel:$cp),
+def t2PICADD : T2XI<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp),
"$cp:\n\tadd $dst, pc",
- [(set tGPR:$dst, (ARMpic_add tGPR:$lhs, imm:$cp))]>;
+ [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>;
// LEApcrel - Load a pc-relative address into a register without offending the
diff --git a/lib/Target/ARM/ARMMachineFunctionInfo.h b/lib/Target/ARM/ARMMachineFunctionInfo.h
index 66d3df60e0..1f8c58f01a 100644
--- a/lib/Target/ARM/ARMMachineFunctionInfo.h
+++ b/lib/Target/ARM/ARMMachineFunctionInfo.h
@@ -119,6 +119,7 @@ public:
JumpTableUId(0), ConstPoolEntryUId(0) {}
bool isThumbFunction() const { return isThumb; }
+ bool isThumb1OnlyFunction() const { return isThumb && !hasThumb2; }
bool isThumb2Function() const { return isThumb && hasThumb2; }
unsigned getAlign() const { return Align; }
diff --git a/lib/Target/ARM/ARMTargetAsmInfo.cpp b/lib/Target/ARM/ARMTargetAsmInfo.cpp
index bf2c14e859..34c187492f 100644
--- a/lib/Target/ARM/ARMTargetAsmInfo.cpp
+++ b/lib/Target/ARM/ARMTargetAsmInfo.cpp
@@ -224,7 +224,7 @@ unsigned ARMTargetAsmInfo<BaseTAI>::getInlineAsmLength(const char *s) const {
} else if (inTextSection) {
// An instruction
atInsnStart = false;
- if (Subtarget->isThumb()) {
+ if (Subtarget->isThumb()) { // FIXME thumb2
// BL and BLX <non-reg> are 4 bytes, all others 2.
if (strncmp(Str, "blx", strlen("blx"))==0) {
const char* p = Str+3;
diff --git a/lib/Target/ARM/Thumb2InstrInfo.cpp b/lib/Target/ARM/Thumb2InstrInfo.cpp
index 76fc4fb2ad..bd37ae6eda 100644
--- a/lib/Target/ARM/Thumb2InstrInfo.cpp
+++ b/lib/Target/ARM/Thumb2InstrInfo.cpp
@@ -71,7 +71,7 @@ Thumb2InstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
// FIXME
switch (MBB.back().getOpcode()) {
- //case ARM::t2BX_RET:
+ case ARM::t2BX_RET:
// case ARM::LDM_RET:
case ARM::t2B: // Uncond branch.
case ARM::t2BR_JTr: // Jumptable branch.
@@ -90,285 +90,3 @@ Thumb2InstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
return false;
}
-
-
-bool Thumb2InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- unsigned DestReg, unsigned SrcReg,
- const TargetRegisterClass *DestRC,
- const TargetRegisterClass *SrcRC) const {
- DebugLoc DL = DebugLoc::getUnknownLoc();
- if (I != MBB.end()) DL = I->getDebugLoc();
-
- if (DestRC == ARM::GPRRegisterClass) {
- if (SrcRC == ARM::GPRRegisterClass) {
- return ARMBaseInstrInfo::copyRegToReg(MBB, I, DestReg, SrcReg, DestRC, SrcRC);
- } else if (SrcRC == ARM::tGPRRegisterClass) {
- BuildMI(MBB, I, DL, get(ARM::tMOVlor2hir), DestReg).addReg(SrcReg);
- return true;
- }
- } else if (DestRC == ARM::tGPRRegisterClass) {
- if (SrcRC == ARM::GPRRegisterClass) {
- BuildMI(MBB, I, DL, get(ARM::tMOVhir2lor), DestReg).addReg(SrcReg);
- return true;
- } else if (SrcRC == ARM::tGPRRegisterClass) {
- BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg).addReg(SrcReg);
- return true;
- }
- }
-
- return false;
-}
-
-
-
-
-
-
-bool Thumb2InstrInfo::isMoveInstr(const MachineInstr &MI,
- unsigned &SrcReg, unsigned &DstReg,
- unsigned& SrcSubIdx, unsigned& DstSubIdx) const {
- SrcSubIdx = DstSubIdx = 0; // No sub-registers.
-
- unsigned oc = MI.getOpcode();
- switch (oc) {
- default:
- return false;
- case ARM::tMOVr:
- case ARM::tMOVhir2lor:
- case ARM::tMOVlor2hir:
- case ARM::tMOVhir2hir:
- assert(MI.getDesc().getNumOperands() >= 2 &&
- MI.getOperand(0).isReg() &&
- MI.getOperand(1).isReg() &&
- "Invalid Thumb MOV instruction");
- SrcReg = MI.getOperand(1).getReg();
- DstReg = MI.getOperand(0).getReg();
- return true;
- }
-}
-
-unsigned Thumb2InstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
- int &FrameIndex) const {
- switch (MI->getOpcode()) {
- default: break;
- case ARM::tRestore:
- if (MI->getOperand(1).isFI() &&
- MI->getOperand(2).isImm() &&
- MI->getOperand(2).getImm() == 0) {
- FrameIndex = MI->getOperand(1).getIndex();
- return MI->getOperand(0).getReg();
- }
- break;
- }
- return 0;
-}
-
-unsigned Thumb2InstrInfo::isStoreToStackSlot(const MachineInstr *MI,
- int &FrameIndex) const {
- switch (MI->getOpcode()) {
- default: break;
- case ARM::tSpill:
- if (MI->getOperand(1).isFI() &&
- MI->getOperand(2).isImm() &&
- MI->getOperand(2).getImm() == 0) {
- FrameIndex = MI->getOperand(1).getIndex();
- return MI->getOperand(0).getReg();
- }
- break;
- }
- return 0;
-}
-
-bool Thumb2InstrInfo::
-canFoldMemoryOperand(const MachineInstr *MI,
- const SmallVectorImpl<unsigned> &Ops) const {
- if (Ops.size() != 1) return false;
-
- unsigned OpNum = Ops[0];
- unsigned Opc = MI->getOpcode();
- switch (Opc) {