Sink dag combine's post index load / store code that swap base ptr and index into the target hook. Only the target knows whether the swap is safe. In Thumb2 mode, the offset must be an immediate. rdar://7998649

llvm-svn: 104060
This commit is contained in:
Evan Cheng 2010-05-18 21:31:17 +00:00
parent feedc90c57
commit f19384d54a
3 changed files with 40 additions and 5 deletions

View File

@ -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<ConstantSDNode>(Offset) &&
cast<ConstantSDNode>(Offset)->isNullValue())

View File

@ -4407,9 +4407,11 @@ bool ARMTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
bool isSEXTLoad = false;
if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
VT = LD->getMemoryVT();
Ptr = LD->getBasePtr();
isSEXTLoad = LD->getExtensionType() == ISD::SEXTLOAD;
} else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
VT = ST->getMemoryVT();
Ptr = ST->getBasePtr();
} else
return false;
@ -4424,6 +4426,18 @@ bool ARMTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
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;
}

View File

@ -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 ; <i64*> [#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 ; <i64> [#uses=0]
unreachable
bb.nph96: ; preds = %entry
unreachable
}