diff options
| -rw-r--r-- | llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp | 11 | ||||
| -rw-r--r-- | llvm/test/Transforms/MemCpyOpt/process_store.ll | 39 |
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 +} |

