Make load->store deletion a bit smarter. This allows us to compile this:

void test(long long *P) { *P ^= 1; }

into just:

_test:
	movl	4(%esp), %eax
	xorl	$1, (%eax)
	ret

instead of code like this:

_test:
	movl	4(%esp), %ecx
        xorl    $1, (%ecx)
	movl	4(%ecx), %edx
	movl	%edx, 4(%ecx)
	ret



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45762 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2008-01-08 23:08:06 +00:00
parent 0c5714bb99
commit 07649d9265
2 changed files with 44 additions and 3 deletions

View File

@ -4122,6 +4122,34 @@ SDOperand DAGCombiner::visitLOAD(SDNode *N) {
return SDOperand();
}
/// ReachesChainWithoutSideEffects - Do a little local search to see if Src can
/// reach Dest without any side effects like a store, or call. Non-volatile
/// loads are ok though.
static bool ReachesChainWithoutSideEffects(SDOperand Src, SDOperand Dest,
unsigned Depth = 0) {
if (Src == Dest) return true;
// Don't search too deeply, we just want to be able to see through
// TokenFactor's etc.
if (Depth == 2) return false;
// If this is a token factor, all inputs to the TF happen in parallel. If any
// of the operands of the TF reach dest, then we can do the xform.
if (Src.getOpcode() == ISD::TokenFactor) {
for (unsigned i = 0, e = Src.getNumOperands(); i != e; ++i)
if (ReachesChainWithoutSideEffects(Src.getOperand(i), Dest, Depth+1))
return true;
return false;
}
// Loads don't have side effects, look through them.
if (LoadSDNode *Ld = dyn_cast<LoadSDNode>(Src)) {
if (!Ld->isVolatile())
return ReachesChainWithoutSideEffects(Ld->getChain(), Dest, Depth+1);
}
return false;
}
SDOperand DAGCombiner::visitSTORE(SDNode *N) {
StoreSDNode *ST = cast<StoreSDNode>(N);
SDOperand Chain = ST->getChain();
@ -4250,10 +4278,12 @@ SDOperand DAGCombiner::visitSTORE(SDNode *N) {
// If this is a load followed by a store to the same location, then the store
// is dead/noop.
if (LoadSDNode *Ld = dyn_cast<LoadSDNode>(Value)) {
if (Chain.Val == Ld && Ld->getBasePtr() == Ptr &&
if (Ld->getBasePtr() == Ptr && ST->getStoredVT() == Ld->getLoadedVT() &&
ST->getAddressingMode() == ISD::UNINDEXED &&
ST->getStoredVT() == Ld->getLoadedVT() &&
!ST->isVolatile()) {
!ST->isVolatile() &&
// There can't be any side effects between the load and store, such as
// a call or store.
ReachesChainWithoutSideEffects(Chain, SDOperand(Ld, 1))) {
// The store is dead, remove it.
return Chain;
}

View File

@ -0,0 +1,11 @@
; RUN: llvm-as < %s | llc -march=x86 | not grep '4{(%...)}
; This should not load or store the top part of *P.
define void @test(i64* %P) nounwind {
entry:
%tmp1 = load i64* %P, align 8 ; <i64> [#uses=1]
%tmp2 = xor i64 %tmp1, 1 ; <i64> [#uses=1]
store i64 %tmp2, i64* %P, align 8
ret void
}