summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM/ARMISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/ARM/ARMISelLowering.cpp')
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.cpp40
1 files changed, 36 insertions, 4 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 12ed20c2ea4..1d07e773f9d 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -715,6 +715,10 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
setIndexedStoreAction(im, MVT::i16, Legal);
setIndexedStoreAction(im, MVT::i32, Legal);
}
+ } else {
+ // Thumb-1 has limited post-inc load/store support - LDM r0!, {r1}.
+ setIndexedLoadAction(ISD::POST_INC, MVT::i32, Legal);
+ setIndexedStoreAction(ISD::POST_INC, MVT::i32, Legal);
}
setOperationAction(ISD::SADDO, MVT::i32, Custom);
@@ -8247,6 +8251,19 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
MI.dump();
llvm_unreachable("Unexpected instr type to insert");
}
+
+ // Thumb1 post-indexed loads are really just single-register LDMs.
+ case ARM::tLDR_postidx: {
+ BuildMI(*BB, MI, dl, TII->get(ARM::tLDMIA_UPD))
+ .addOperand(MI->getOperand(1)) // Rn_wb
+ .addOperand(MI->getOperand(2)) // Rn
+ .addOperand(MI->getOperand(3)) // PredImm
+ .addOperand(MI->getOperand(4)) // PredReg
+ .addOperand(MI->getOperand(0)); // Rt
+ MI->eraseFromParent();
+ return BB;
+ }
+
// The Thumb2 pre-indexed stores have the same MI operands, they just
// define them differently in the .td files from the isel patterns, so
// they need pseudos.
@@ -11596,22 +11613,37 @@ bool ARMTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
SDValue &Offset,
ISD::MemIndexedMode &AM,
SelectionDAG &DAG) const {
- if (Subtarget->isThumb1Only())
- return false;
-
EVT VT;
SDValue Ptr;
- bool isSEXTLoad = false;
+ bool isSEXTLoad = false, isNonExt;
if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
VT = LD->getMemoryVT();
Ptr = LD->getBasePtr();
isSEXTLoad = LD->getExtensionType() == ISD::SEXTLOAD;
+ isNonExt = LD->getExtensionType() == ISD::NON_EXTLOAD;
} else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
VT = ST->getMemoryVT();
Ptr = ST->getBasePtr();
+ isNonExt = !ST->isTruncatingStore();
} else
return false;
+ if (Subtarget->isThumb1Only()) {
+ // Thumb-1 can do a limited post-inc load or store as an updating LDM. It
+ // must be non-extending/truncating, i32, with an offset of 4.
+ assert(Op->getValueType(0) == MVT::i32 && "Non-i32 post-inc op?!");
+ if (Op->getOpcode() != ISD::ADD || !isNonExt)
+ return false;
+ auto *RHS = dyn_cast<ConstantSDNode>(Op->getOperand(1));
+ if (!RHS || RHS->getZExtValue() != 4)
+ return false;
+
+ Offset = Op->getOperand(1);
+ Base = Op->getOperand(0);
+ AM = ISD::POST_INC;
+ return true;
+ }
+
bool isInc;
bool isLegal = false;
if (Subtarget->isThumb2())
OpenPOWER on IntegriCloud