aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-01-08 23:08:06 +0000
committerChris Lattner <sabre@nondot.org>2008-01-08 23:08:06 +0000
commit07649d9265c9a378fe753f80601ae5f4de3312dc (patch)
tree2eabcc37ee50dfa67da49656a189f8e3b9214e07
parent0c5714bb9944ed085fb5854ac4c6abf941c532ed (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.cpp36
-rw-r--r--test/CodeGen/X86/longlong-deadload.ll11
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
+}
+