llvm.org GIT mirror llvm / dee6650
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@330635 91177308-0d34-0410-b5e6-96231b3b80d8 Bjorn Pettersson 1 year, 6 months ago
2 changed file(s) with 49 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
13901390 bool MemCpyOptPass::iterateOnFunction(Function &F) {
13911391 bool MadeChange = false;
13921392
1393 DominatorTree &DT = LookupDomTree();
1394
13931395 // Walk all instruction in the function.
13941396 for (BasicBlock &BB : F) {
1397 // Skip unreachable blocks. For example processStore assumes that an
1398 // instruction in a BB can't be dominated by a later instruction in the
1399 // same BB (which is a scenario that can happen for an unreachable BB that
1400 // has itself as a predecessor).
1401 if (!DT.isReachableFromEntry(&BB))
1402 continue;
1403
13951404 for (BasicBlock::iterator BI = BB.begin(), BE = BB.end(); BI != BE;) {
1396 // Avoid invalidating the iterator.
1405 // Avoid invalidating the iterator.
13971406 Instruction *I = &*BI++;
13981407
13991408 bool RepeatInstruction = false;
0 ; RUN: opt < %s -memcpyopt -disable-output
1
2 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
3 target triple = "x86_64-unknown-linux-gnu"
4
5 @b = common dso_local local_unnamed_addr global i32 0, align 4
6 @a = common dso_local local_unnamed_addr global i32 0, align 4
7
8 declare dso_local i32 @f1()
9
10 ; Do not crash due to store first in BB.
11 define dso_local void @f2() {
12 for.end:
13 %0 = load i32, i32* @b, align 4
14 ret void
15
16 for.body:
17 store i32 %1, i32* @a, align 4
18 %call = call i32 @f1()
19 %cmp = icmp sge i32 %call, 0
20 %1 = load i32, i32* @b, align 4
21 br label %for.body
22 }
23
24 ; Do not crash due to call not before store in BB.
25 define dso_local void @f3() {
26 for.end:
27 %0 = load i32, i32* @b, align 4
28 ret void
29
30 for.body:
31 %t = add i32 %t2, 1
32 store i32 %1, i32* @a, align 4
33 %call = call i32 @f1()
34 %cmp = icmp sge i32 %call, 0
35 %1 = load i32, i32* @b, align 4
36 %t2 = xor i32 %t, 5
37 br label %for.body
38 }