llvm.org GIT mirror llvm / 21c6a2a
Merging r328798: ------------------------------------------------------------------------ r328798 | haicheng | 2018-03-29 09:01:26 -0700 (Thu, 29 Mar 2018) | 37 lines [JumpThreading] Don't select an edge that we know we can't thread In r312664 (D36404), JumpThreading stopped threading edges into loop headers. Unfortunately, I observed a significant performance regression as a result of this change. Upon further investigation, the problematic pattern looked something like this (after many high level optimizations): while (true) { bool cond = ...; if (!cond) { <body> } if (cond) break; } Now, naturally we want jump threading to essentially eliminate the second if check and hook up the edges appropriately. However, the above mentioned change, prevented it from doing this because it would have to thread an edge into the loop header. Upon further investigation, what is happening is that since both branches are threadable, JumpThreading picks one of them at arbitrarily. In my case, because of the way that the IR ended up, it tended to pick the one to the loop header, bailing out immediately after. However, if it had picked the one to the exit block, everything would have worked out fine (because the only remaining branch would then be folded, not thraded which is acceptable). Thus, to fix this problem, we can simply eliminate loop headers from consideration as possible threading targets earlier, to make sure that if there are multiple eligible branches, we can still thread one of the ones that don't target a loop header. Patch by Keno Fischer! Differential Revision: https://reviews.llvm.org/D42260 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_60@333577 91177308-0d34-0410-b5e6-96231b3b80d8 Tom Stellard 1 year, 3 months ago
2 changed file(s) with 115 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
14531453 if (PredToDest.second)
14541454 DestPopularity[PredToDest.second]++;
14551455
1456 if (DestPopularity.empty())
1457 return nullptr;
1458
14561459 // Find the most popular dest.
14571460 DenseMap::iterator DPI = DestPopularity.begin();
14581461 BasicBlock *MostPopularDest = DPI->first;
16281631 // threadable destination (the common case) we can avoid this.
16291632 BasicBlock *MostPopularDest = OnlyDest;
16301633
1631 if (MostPopularDest == MultipleDestSentinel)
1634 if (MostPopularDest == MultipleDestSentinel) {
1635 // Remove any loop headers from the Dest list, ThreadEdge conservatively
1636 // won't process them, but we might have other destination that are eligible
1637 // and we still want to process.
1638 erase_if(PredToDestList,
1639 [&](const std::pair &PredToDest) {
1640 return LoopHeaders.count(PredToDest.second) != 0;
1641 });
1642
1643 if (PredToDestList.empty())
1644 return false;
1645
16321646 MostPopularDest = FindMostPopularDest(BB, PredToDestList);
1647 }
16331648
16341649 // Now that we know what the most popular destination is, factor all
16351650 // predecessors that will jump to it into a single predecessor.
0 ; RUN: opt -S -jump-threading < %s | FileCheck %s
1
2 ; Check that the heuristic for avoiding accidental introduction of irreducible
3 ; loops doesn't also prevent us from threading simple constructs where this
4 ; isn't a problem.
5
6 declare void @opaque_body()
7
8 define void @jump_threading_loopheader() {
9 ; CHECK-LABEL: @jump_threading_loopheader
10 top:
11 br label %entry
12
13 entry:
14 %ind = phi i32 [0, %top], [%nextind, %latch]
15 %nextind = add i32 %ind, 1
16 %cmp = icmp ule i32 %ind, 10
17 ; CHECK: br i1 %cmp, label %latch, label %exit
18 br i1 %cmp, label %body, label %latch
19
20 body:
21 call void @opaque_body()
22 ; CHECK: br label %entry
23 br label %latch
24
25 latch:
26 %cond = phi i2 [1, %entry], [2, %body]
27 switch i2 %cond, label %unreach [
28 i2 2, label %entry
29 i2 1, label %exit
30 ]
31
32 unreach:
33 unreachable
34
35 exit:
36 ret void
37 }
38
39 ; We also need to check the opposite order of the branches, in the switch
40 ; instruction because jump-threading relies on that to decide which edge to
41 ; try to thread first.
42 define void @jump_threading_loopheader2() {
43 ; CHECK-LABEL: @jump_threading_loopheader2
44 top:
45 br label %entry
46
47 entry:
48 %ind = phi i32 [0, %top], [%nextind, %latch]
49 %nextind = add i32 %ind, 1
50 %cmp = icmp ule i32 %ind, 10
51 ; CHECK: br i1 %cmp, label %exit, label %latch
52 br i1 %cmp, label %body, label %latch
53
54 body:
55 call void @opaque_body()
56 ; CHECK: br label %entry
57 br label %latch
58
59 latch:
60 %cond = phi i2 [1, %entry], [2, %body]
61 switch i2 %cond, label %unreach [
62 i2 1, label %entry
63 i2 2, label %exit
64 ]
65
66 unreach:
67 unreachable
68
69 exit:
70 ret void
71 }
72
73 ; Check if we can handle undef branch condition.
74 define void @jump_threading_loopheader3() {
75 ; CHECK-LABEL: @jump_threading_loopheader3
76 top:
77 br label %entry
78
79 entry:
80 %ind = phi i32 [0, %top], [%nextind, %latch]
81 %nextind = add i32 %ind, 1
82 %cmp = icmp ule i32 %ind, 10
83 ; CHECK: br i1 %cmp, label %latch, label %exit
84 br i1 %cmp, label %body, label %latch
85
86 body:
87 call void @opaque_body()
88 ; CHECK: br label %entry
89 br label %latch
90
91 latch:
92 %phi = phi i32 [undef, %entry], [0, %body]
93 %cmp1 = icmp eq i32 %phi, 0
94 br i1 %cmp1, label %entry, label %exit
95
96 exit:
97 ret void
98 }