aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms
diff options
context:
space:
mode:
authorDale Johannesen <dalej@apple.com>2009-06-17 20:48:23 +0000
committerDale Johannesen <dalej@apple.com>2009-06-17 20:48:23 +0000
commita19b67fbac4046bd9e57119dcb39d6c6a6897cb8 (patch)
treeb1be492f650e7abae0d9d3f388a7a2f7e20068b5 /lib/Transforms
parenta1a8c7150585718e1e248f1058c9ce850763abf1 (diff)
downloadexternal_llvm-a19b67fbac4046bd9e57119dcb39d6c6a6897cb8.zip
external_llvm-a19b67fbac4046bd9e57119dcb39d6c6a6897cb8.tar.gz
external_llvm-a19b67fbac4046bd9e57119dcb39d6c6a6897cb8.tar.bz2
This fixes a bug introduced in 72661, which can
move loads back past a check that the load address is valid, see new testcase. The test that went in with 72661 has exactly this case, except that the conditional it's moving past is checking something else; I've settled for changing that test to reference a global, not a pointer. It may be possible to scan all the tests you pass and make sure none of them are checking any component of the address, but it's not trivial and I'm not trying to do that here. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73632 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/Scalar/GVN.cpp19
1 files changed, 18 insertions, 1 deletions
diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp
index 1e89ef7..f4a9898 100644
--- a/lib/Transforms/Scalar/GVN.cpp
+++ b/lib/Transforms/Scalar/GVN.cpp
@@ -37,6 +37,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/Local.h"
#include <cstdio>
using namespace llvm;
@@ -1075,6 +1076,7 @@ bool GVN::processNonLocalLoad(LoadInst *LI,
BasicBlock *TmpBB = LoadBB;
bool isSinglePred = false;
+ bool allSingleSucc = true;
while (TmpBB->getSinglePredecessor()) {
isSinglePred = true;
TmpBB = TmpBB->getSinglePredecessor();
@@ -1084,6 +1086,8 @@ bool GVN::processNonLocalLoad(LoadInst *LI,
return false;
if (Blockers.count(TmpBB))
return false;
+ if (TmpBB->getTerminator()->getNumSuccessors() != 1)
+ allSingleSucc = false;
}
assert(TmpBB);
@@ -1160,7 +1164,20 @@ bool GVN::processNonLocalLoad(LoadInst *LI,
<< UnavailablePred->getName() << "': " << *LI);
return false;
}
-
+
+ // Make sure it is valid to move this load here. We have to watch out for:
+ // @1 = getelementptr (i8* p, ...
+ // test p and branch if == 0
+ // load @1
+ // It is valid to have the getelementptr before the test, even if p can be 0,
+ // as getelementptr only does address arithmetic.
+ // If we are not pushing the value through any multiple-successor blocks
+ // we do not have this case. Otherwise, check that the load is safe to
+ // put anywhere; this can be improved, but should be conservatively safe.
+ if (!allSingleSucc &&
+ !isSafeToLoadUnconditionally(LoadPtr, UnavailablePred->getTerminator()))
+ return false;
+
// Okay, we can eliminate this load by inserting a reload in the predecessor
// and using PHI construction to get the value in the other predecessors, do
// it.