[Thumb-1] Select post-increment load and store where possible
Thumb-1 doesn't have post-inc or pre-inc load or store instructions. However the LDM/STM instructions with writeback can function as post-inc load/store:
ldm r0!, {r1} @ load from r0 into r1 and increment r0 by 4
Obviously, this only works if the post increment is 4.
llvm-svn: 275540
diff --git a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
index 1b1b775..c5e1d97 100644
--- a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -195,6 +195,7 @@
private:
/// Indexed (pre/post inc/dec) load matching code for ARM.
bool tryARMIndexedLoad(SDNode *N);
+ bool tryT1IndexedLoad(SDNode *N);
bool tryT2IndexedLoad(SDNode *N);
/// SelectVLD - Select NEON load intrinsics. NumVecs should be
@@ -1543,6 +1544,31 @@
return false;
}
+bool ARMDAGToDAGISel::tryT1IndexedLoad(SDNode *N) {
+ LoadSDNode *LD = cast<LoadSDNode>(N);
+ EVT LoadedVT = LD->getMemoryVT();
+ ISD::MemIndexedMode AM = LD->getAddressingMode();
+ if (AM == ISD::UNINDEXED || LD->getExtensionType() != ISD::NON_EXTLOAD ||
+ AM != ISD::POST_INC || LoadedVT.getSimpleVT().SimpleTy != MVT::i32)
+ return false;
+
+ auto *COffs = dyn_cast<ConstantSDNode>(LD->getOffset());
+ if (!COffs || COffs->getZExtValue() != 4)
+ return false;
+
+ // A T1 post-indexed load is just a single register LDM: LDM r0!, {r1}.
+ // The encoding of LDM is not how the rest of ISel expects a post-inc load to
+ // look however, so we use a pseudo here and switch it for a tLDMIA_UPD after
+ // ISel.
+ SDValue Chain = LD->getChain();
+ SDValue Base = LD->getBasePtr();
+ SDValue Ops[]= { Base, getAL(CurDAG, SDLoc(N)),
+ CurDAG->getRegister(0, MVT::i32), Chain };
+ ReplaceNode(N, CurDAG->getMachineNode(ARM::tLDR_postidx, SDLoc(N), MVT::i32, MVT::i32,
+ MVT::Other, Ops));
+ return true;
+}
+
bool ARMDAGToDAGISel::tryT2IndexedLoad(SDNode *N) {
LoadSDNode *LD = cast<LoadSDNode>(N);
ISD::MemIndexedMode AM = LD->getAddressingMode();
@@ -3015,6 +3041,9 @@
if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
if (tryT2IndexedLoad(N))
return;
+ } else if (Subtarget->isThumb()) {
+ if (tryT1IndexedLoad(N))
+ return;
} else if (tryARMIndexedLoad(N))
return;
// Other cases are autogenerated.