llvm.org GIT mirror llvm / 4bc2f18
Fix a crash when the default of a switch is removed This patch fixes a problem that occurs in LowerSwitch when a switch statement has a PHI node as its condition, and the PHI node only has two incoming blocks, and one of those incoming blocks is through an unreachable default in the switch statement. When this condition occurs, LowerSwitch holds a pointer to the condition value, but removes the switch block as a predecessor of the PHI block, causing the PHI node to be replaced. LowerSwitch then tries to use its stale pointer to the original condition value, causing a crash. Differential Revision: https://reviews.llvm.org/D62560 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@362427 91177308-0d34-0410-b5e6-96231b3b80d8 Andrew Kaylor 3 months ago
2 changed file(s) with 41 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
583583 PopSucc->removePredecessor(OrigBlock);
584584 return;
585585 }
586
587 // If the condition was a PHI node with the switch block as a predecessor
588 // removing predecessors may have caused the condition to be erased.
589 // Getting the condition value again here protects against that.
590 Val = SI->getCondition();
586591 }
587592
588593 // Create a new, empty default block so that the new hierarchy of
0 ; RUN: opt < %s -lowerswitch -S | FileCheck %s
1
2 ; This test verifies -lowerswitch does not crash when an removing an
3 ; unreachable default branch causes a PHI node used as the switch
4 ; condition to be erased.
5
6 define void @f() local_unnamed_addr {
7 entry:
8 br label %sw.epilog
9
10 sw.epilog: ; preds = %sw.epilog.outer, %for.body
11 %i = phi i32 [ undef, %for.body ], [ 0, %entry ]
12 br i1 undef, label %for.body, label %for.end
13
14 for.body: ; preds = %sw.epilog
15 switch i32 %i, label %sw.epilog [
16 i32 0, label %sw.epilog.outer.backedge.loopexit
17 i32 1, label %sw.epilog.outer.backedge
18 ]
19
20 sw.epilog.outer.backedge.loopexit: ; preds = %for.body
21 br label %for.end
22
23 sw.epilog.outer.backedge: ; preds = %for.body
24 unreachable
25
26 for.end: ; preds = %sw.epilog
27 ret void
28 }
29
30 ; The phi and the switch should both be eliminated.
31 ; CHECK: @f()
32 ; CHECK: sw.epilog:
33 ; CHECK-NOT: phi
34 ; CHECK: for.body:
35 ; CHECK-NOT: switch