diff options
author | Chris Lattner <sabre@nondot.org> | 2008-01-08 23:08:06 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-01-08 23:08:06 +0000 |
commit | 07649d9265c9a378fe753f80601ae5f4de3312dc (patch) | |
tree | 2eabcc37ee50dfa67da49656a189f8e3b9214e07 | |
parent | 0c5714bb9944ed085fb5854ac4c6abf941c532ed (diff) |
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
-rw-r--r-- | lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 36 | ||||
-rw-r--r-- | test/CodeGen/X86/longlong-deadload.ll | 11 |
2 files changed, 44 insertions, 3 deletions
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index e581ed3d94..0bb11fa330 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -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; } diff --git a/test/CodeGen/X86/longlong-deadload.ll b/test/CodeGen/X86/longlong-deadload.ll new file mode 100644 index 0000000000..a8e2c31d94 --- /dev/null +++ b/test/CodeGen/X86/longlong-deadload.ll @@ -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 +} + |