diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index d6e761f2bc3d..bfa302cf0954 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -5284,10 +5284,6 @@ bool DAGCombiner::CombineToPostIndexedLoadStore(SDNode *N) { SDValue Offset; ISD::MemIndexedMode AM = ISD::UNINDEXED; if (TLI.getPostIndexedAddressParts(N, Op, BasePtr, Offset, AM, DAG)) { - if (Ptr == Offset && Op->getOpcode() == ISD::ADD) - std::swap(BasePtr, Offset); - if (Ptr != BasePtr) - continue; // Don't create a indexed load / store with zero offset. if (isa(Offset) && cast(Offset)->isNullValue()) diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index c284a7e04396..f5373cb0e7f3 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -4407,9 +4407,11 @@ bool ARMTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op, bool isSEXTLoad = false; if (LoadSDNode *LD = dyn_cast(N)) { VT = LD->getMemoryVT(); + Ptr = LD->getBasePtr(); isSEXTLoad = LD->getExtensionType() == ISD::SEXTLOAD; } else if (StoreSDNode *ST = dyn_cast(N)) { VT = ST->getMemoryVT(); + Ptr = ST->getBasePtr(); } else return false; @@ -4417,13 +4419,25 @@ bool ARMTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op, bool isLegal = false; if (Subtarget->isThumb2()) isLegal = getT2IndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset, - isInc, DAG); + isInc, DAG); else isLegal = getARMIndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset, isInc, DAG); if (!isLegal) return false; + if (Ptr != Base) { + // Swap base ptr and offset to catch more post-index load / store when + // it's legal. In Thumb2 mode, offset must be an immediate. + if (Ptr == Offset && Op->getOpcode() == ISD::ADD && + !Subtarget->isThumb2()) + std::swap(Base, Offset); + + // Post-indexed load / store update the base pointer. + if (Ptr != Base) + return false; + } + AM = isInc ? ISD::POST_INC : ISD::POST_DEC; return true; } diff --git a/llvm/test/CodeGen/ARM/2010-05-18-PostIndexBug.ll b/llvm/test/CodeGen/ARM/2010-05-18-PostIndexBug.ll new file mode 100644 index 000000000000..99072283c296 --- /dev/null +++ b/llvm/test/CodeGen/ARM/2010-05-18-PostIndexBug.ll @@ -0,0 +1,25 @@ +; RUN: llc < %s -mtriple=armv7-apple-darwin | FileCheck %s -check-prefix=ARM +; RUN: llc < %s -mtriple=thumbv7-apple-darwin | FileCheck %s -check-prefix=THUMB +; rdar://7998649 + +%struct.foo = type { i64, i64 } + +define arm_apcscc zeroext i8 @t(%struct.foo* %this) noreturn optsize { +entry: +; ARM: t: +; ARM: str r0, [r1], r0 + +; THUMB: t: +; THUMB-NOT: str r0, [r1], r0 +; THUMB: str r0, [r1] + %0 = getelementptr inbounds %struct.foo* %this, i32 0, i32 1 ; [#uses=1] + store i32 undef, i32* inttoptr (i32 8 to i32*), align 8 + br i1 undef, label %bb.nph96, label %bb3 + +bb3: ; preds = %entry + %1 = load i64* %0, align 4 ; [#uses=0] + unreachable + +bb.nph96: ; preds = %entry + unreachable +}