summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Pettersson <bjorn.a.pettersson@ericsson.com>2018-04-23 19:55:04 +0000
committerBjorn Pettersson <bjorn.a.pettersson@ericsson.com>2018-04-23 19:55:04 +0000
commit8e484dc531a37cccc805335c0ede696b2b26fa9f (patch)
tree235637fa45dd59a208309c9189eb675f7a02ecb4
parent61908f651ed21237599af6ccfb555da3bcff6dd1 (diff)
downloadbcm5719-llvm-8e484dc531a37cccc805335c0ede696b2b26fa9f.tar.gz
bcm5719-llvm-8e484dc531a37cccc805335c0ede696b2b26fa9f.zip
[MemCpyOpt] Skip optimizing basic blocks not reachable from entry
Summary: Skip basic blocks not reachable from the entry node in MemCpyOptPass::iterateOnFunction. Code that is unreachable may have properties that do not exist for reachable code (an instruction in a basic block can for example be dominated by a later instruction in the same basic block, for example if there is a single block loop). MemCpyOptPass::processStore is only safe to use for reachable basic blocks, since it may iterate past the basic block beginning when used for unreachable blocks. By simply skipping to optimize unreachable basic blocks we can avoid asserts such as "Assertion `!NodePtr->isKnownSentinel()' failed." in MemCpyOptPass::processStore. The problem was detected by fuzz tests. Reviewers: eli.friedman, dneilson, efriedma Reviewed By: efriedma Subscribers: efriedma, llvm-commits Differential Revision: https://reviews.llvm.org/D45889 llvm-svn: 330635
-rw-r--r--llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp11
-rw-r--r--llvm/test/Transforms/MemCpyOpt/process_store.ll39
2 files changed, 49 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 39a674946b5..e21d09e65a1 100644
--- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -1391,10 +1391,19 @@ bool MemCpyOptPass::processByValArgument(CallSite CS, unsigned ArgNo) {
bool MemCpyOptPass::iterateOnFunction(Function &F) {
bool MadeChange = false;
+ DominatorTree &DT = LookupDomTree();
+
// Walk all instruction in the function.
for (BasicBlock &BB : F) {
+ // Skip unreachable blocks. For example processStore assumes that an
+ // instruction in a BB can't be dominated by a later instruction in the
+ // same BB (which is a scenario that can happen for an unreachable BB that
+ // has itself as a predecessor).
+ if (!DT.isReachableFromEntry(&BB))
+ continue;
+
for (BasicBlock::iterator BI = BB.begin(), BE = BB.end(); BI != BE;) {
- // Avoid invalidating the iterator.
+ // Avoid invalidating the iterator.
Instruction *I = &*BI++;
bool RepeatInstruction = false;
diff --git a/llvm/test/Transforms/MemCpyOpt/process_store.ll b/llvm/test/Transforms/MemCpyOpt/process_store.ll
new file mode 100644
index 00000000000..e2edef0a94f
--- /dev/null
+++ b/llvm/test/Transforms/MemCpyOpt/process_store.ll
@@ -0,0 +1,39 @@
+; RUN: opt < %s -memcpyopt -disable-output
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@b = common dso_local local_unnamed_addr global i32 0, align 4
+@a = common dso_local local_unnamed_addr global i32 0, align 4
+
+declare dso_local i32 @f1()
+
+; Do not crash due to store first in BB.
+define dso_local void @f2() {
+for.end:
+ %0 = load i32, i32* @b, align 4
+ ret void
+
+for.body:
+ store i32 %1, i32* @a, align 4
+ %call = call i32 @f1()
+ %cmp = icmp sge i32 %call, 0
+ %1 = load i32, i32* @b, align 4
+ br label %for.body
+}
+
+; Do not crash due to call not before store in BB.
+define dso_local void @f3() {
+for.end:
+ %0 = load i32, i32* @b, align 4
+ ret void
+
+for.body:
+ %t = add i32 %t2, 1
+ store i32 %1, i32* @a, align 4
+ %call = call i32 @f1()
+ %cmp = icmp sge i32 %call, 0
+ %1 = load i32, i32* @b, align 4
+ %t2 = xor i32 %t, 5
+ br label %for.body
+}
OpenPOWER on IntegriCloud