summaryrefslogtreecommitdiff
path: root/lib/Target/ARM
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/ARM')
-rw-r--r--lib/Target/ARM/ARMAsmPrinter.cpp2
-rw-r--r--lib/Target/ARM/ARMCallLowering.cpp4
-rw-r--r--lib/Target/ARM/ARMExpandPseudoInsts.cpp5
-rw-r--r--lib/Target/ARM/ARMFastISel.cpp5
-rw-r--r--lib/Target/ARM/ARMFrameLowering.cpp7
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td8
-rw-r--r--lib/Target/ARM/ARMLoadStoreOptimizer.cpp1
-rw-r--r--lib/Target/ARM/ARMSubtarget.h11
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp4
9 files changed, 36 insertions, 11 deletions
diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp
index 582153daebde9..b24d3420d1d96 100644
--- a/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/lib/Target/ARM/ARMAsmPrinter.cpp
@@ -1276,6 +1276,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
// Add 's' bit operand (always reg0 for this)
.addReg(0));
+ assert(Subtarget->hasV4TOps());
EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::BX)
.addReg(MI->getOperand(0).getReg()));
return;
@@ -1896,6 +1897,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
.addImm(ARMCC::AL)
.addReg(0));
+ assert(Subtarget->hasV4TOps());
EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::BX)
.addReg(ScratchReg)
// Predicate.
diff --git a/lib/Target/ARM/ARMCallLowering.cpp b/lib/Target/ARM/ARMCallLowering.cpp
index 051827a6a6a2f..a1a31e1e7fae2 100644
--- a/lib/Target/ARM/ARMCallLowering.cpp
+++ b/lib/Target/ARM/ARMCallLowering.cpp
@@ -251,7 +251,9 @@ bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
const Value *Val, unsigned VReg) const {
assert(!Val == !VReg && "Return value without a vreg");
- auto Ret = MIRBuilder.buildInstrNoInsert(ARM::BX_RET).add(predOps(ARMCC::AL));
+ auto const &ST = MIRBuilder.getMF().getSubtarget<ARMSubtarget>();
+ unsigned Opcode = ST.getReturnOpcode();
+ auto Ret = MIRBuilder.buildInstrNoInsert(Opcode).add(predOps(ARMCC::AL));
if (!lowerReturnVal(MIRBuilder, Val, VReg, Ret))
return false;
diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp
index 46d8f0dba6914..376727729d893 100644
--- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp
+++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp
@@ -1030,8 +1030,11 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
if (STI->isThumb())
MIB.add(predOps(ARMCC::AL));
} else if (RetOpcode == ARM::TCRETURNri) {
+ unsigned Opcode =
+ STI->isThumb() ? ARM::tTAILJMPr
+ : (STI->hasV4TOps() ? ARM::TAILJMPr : ARM::TAILJMPr4);
BuildMI(MBB, MBBI, dl,
- TII.get(STI->isThumb() ? ARM::tTAILJMPr : ARM::TAILJMPr))
+ TII.get(Opcode))
.addReg(JumpTarget.getReg(), RegState::Kill);
}
diff --git a/lib/Target/ARM/ARMFastISel.cpp b/lib/Target/ARM/ARMFastISel.cpp
index bf00ef61c2d1b..5dc93734ab593 100644
--- a/lib/Target/ARM/ARMFastISel.cpp
+++ b/lib/Target/ARM/ARMFastISel.cpp
@@ -1332,6 +1332,8 @@ bool ARMFastISel::SelectIndirectBr(const Instruction *I) {
if (AddrReg == 0) return false;
unsigned Opc = isThumb2 ? ARM::tBRIND : ARM::BX;
+ assert(isThumb2 || Subtarget->hasV4TOps());
+
AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc)).addReg(AddrReg));
@@ -2168,9 +2170,8 @@ bool ARMFastISel::SelectRet(const Instruction *I) {
RetRegs.push_back(VA.getLocReg());
}
- unsigned RetOpc = isThumb2 ? ARM::tBX_RET : ARM::BX_RET;
MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(RetOpc));
+ TII.get(Subtarget->getReturnOpcode()));
AddOptionalDefs(MIB);
for (unsigned R : RetRegs)
MIB.addReg(R, RegState::Implicit);
diff --git a/lib/Target/ARM/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp
index 16b54e8848c23..00b788a1b530b 100644
--- a/lib/Target/ARM/ARMFrameLowering.cpp
+++ b/lib/Target/ARM/ARMFrameLowering.cpp
@@ -479,7 +479,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
if (DPRCSSize > 0) {
// Since vpush register list cannot have gaps, there may be multiple vpush
// instructions in the prologue.
- while (MBBI->getOpcode() == ARM::VSTMDDB_UPD) {
+ while (MBBI != MBB.end() && MBBI->getOpcode() == ARM::VSTMDDB_UPD) {
DefCFAOffsetCandidates.addInst(MBBI, sizeOfSPAdjustment(*MBBI));
LastPush = MBBI++;
}
@@ -2397,9 +2397,8 @@ void ARMFrameLowering::adjustForSegmentedStacks(
BuildMI(AllocMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex);
- // bx lr - Return from this function.
- Opcode = Thumb ? ARM::tBX_RET : ARM::BX_RET;
- BuildMI(AllocMBB, DL, TII.get(Opcode)).add(predOps(ARMCC::AL));
+ // Return from this function.
+ BuildMI(AllocMBB, DL, TII.get(ST->getReturnOpcode())).add(predOps(ARMCC::AL));
// Restore SR0 and SR1 in case of __morestack() was not called.
// pop {SR0, SR1}
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index 7206083a70791..c488cd347fe1e 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -2425,7 +2425,7 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [SP] in {
def TAILJMPr : ARMPseudoExpand<(outs), (ins tcGPR:$dst),
4, IIC_Br, [],
(BX GPR:$dst)>, Sched<[WriteBr]>,
- Requires<[IsARM]>;
+ Requires<[IsARM, HasV4T]>;
}
// Secure Monitor Call is a system instruction.
@@ -5589,6 +5589,12 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in
(MOVr PC, GPR:$dst, (ops 14, zero_reg), zero_reg)>,
Requires<[IsARM, NoV4T]>, Sched<[WriteBr]>;
+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [SP] in
+ def TAILJMPr4 : ARMPseudoExpand<(outs), (ins GPR:$dst),
+ 4, IIC_Br, [],
+ (MOVr PC, GPR:$dst, (ops 14, zero_reg), zero_reg)>,
+ Requires<[IsARM, NoV4T]>, Sched<[WriteBr]>;
+
// Large immediate handling.
// 32-bit immediate using two piece mod_imms or movw + movt.
diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
index 7a452d4a20952..5d57b6803c08a 100644
--- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
+++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
@@ -1909,6 +1909,7 @@ bool ARMLoadStoreOpt::CombineMovBx(MachineBasicBlock &MBB) {
for (auto Use : Prev->uses())
if (Use.isKill()) {
+ assert(STI->hasV4TOps());
BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(ARM::tBX))
.addReg(Use.getReg(), RegState::Kill)
.add(predOps(ARMCC::AL))
diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h
index e15b17512c964..9d749537dc3b8 100644
--- a/lib/Target/ARM/ARMSubtarget.h
+++ b/lib/Target/ARM/ARMSubtarget.h
@@ -729,6 +729,17 @@ public:
/// True if fast-isel is used.
bool useFastISel() const;
+
+ /// Returns the correct return opcode for the current feature set.
+ /// Use BX if available to allow mixing thumb/arm code, but fall back
+ /// to plain mov pc,lr on ARMv4.
+ unsigned getReturnOpcode() const {
+ if (isThumb())
+ return ARM::tBX_RET;
+ if (hasV4TOps())
+ return ARM::BX_RET;
+ return ARM::MOVPCLR;
+ }
};
} // end namespace llvm
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
index b8a8b1f7619a0..2ab7bfe4410bd 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
@@ -142,9 +142,9 @@ std::string ARM_MC::ParseARMTriple(const Triple &TT, StringRef CPU) {
if (isThumb) {
if (ARMArchFeature.empty())
- ARMArchFeature = "+thumb-mode";
+ ARMArchFeature = "+thumb-mode,+v4t";
else
- ARMArchFeature += ",+thumb-mode";
+ ARMArchFeature += ",+thumb-mode,+v4t";
}
if (TT.isOSNaCl()) {