diff options
author | Daniel Berlin <dberlin@dberlin.org> | 2017-02-28 22:57:50 +0000 |
---|---|---|
committer | Daniel Berlin <dberlin@dberlin.org> | 2017-02-28 22:57:50 +0000 |
commit | 03f6938edcafa11817bcf4cdd526ce94c9f3e5e5 (patch) | |
tree | 6468454ec7635fa8a64d20f38f6ab4970b4c5283 /llvm/test | |
parent | 13ed0b691e554595afd1e8b130709e292c4599e3 (diff) | |
download | bcm5719-llvm-03f6938edcafa11817bcf4cdd526ce94c9f3e5e5.tar.gz bcm5719-llvm-03f6938edcafa11817bcf4cdd526ce94c9f3e5e5.zip |
Fix PR 24415 (at least), by making our post-dominator tree behavior sane.
Summary:
Currently, our post-dom tree tries to ignore and remove the effects of
infinite loops. It fails miserably at this, because it tries to do it
ahead of time, and thus can only detect self-loops, and any other type
of infinite loop, it pretends doesn't exist at all.
This can, in a bunch of cases, lead to wrong answers and a completely
empty post-dom tree.
Wrong answer:
```
declare void foo()
define internal void @f() {
entry:
br i1 undef, label %bb35, label %bb3.i
bb3.i:
call void @foo()
br label %bb3.i
bb35.loopexit3:
br label %bb35
bb35:
ret void
}
```
We get:
```
Inorder PostDominator Tree:
[1] <<exit node>> {0,7}
[2] %bb35 {1,6}
[3] %bb35.loopexit3 {2,3}
[3] %entry {4,5}
```
This is a trivial modification of the testcase for PR 6047
Note that we pretend bb3.i doesn't exist.
We also pretend that bb35 post-dominates entry.
While it's true that it does not exit in a theoretical sense, it's not
really helpful to try to ignore the effect and pretend that bb35
post-dominates entry. Worse, we pretend the infinite loop does
nothing (it's usually considered a side-effect), and doesn't even
exist, even when it calls a function. Sadly, this makes it impossible
to use when you are trying to move code safely. All compilers also
create virtual or real single exit nodes (including us), and connect
infinite loops there (which this patch does). In fact, others have
worked around our behavior here, to the point of building their own
post-dom trees:
https://zneak.github.io/fcd/2016/02/17/structuring.html and pointing
out the region infrastructure is near-useless for them with postdom in
this state :(
Completely empty post-dom tree:
```
define void @spam() #0 {
bb:
br label %bb1
bb1: ; preds = %bb1, %bb
br label %bb1
bb2: ; No predecessors!
ret void
}
```
Printing analysis 'Post-Dominator Tree Construction' for function 'foo':
=============================--------------------------------
Inorder PostDominator Tree:
[1] <<exit node>> {0,1}
:(
(note that even if you ignore the effects of infinite loops, bb2
should be present as an exit node that post-dominates nothing).
This patch changes post-dom to properly handle infinite loops and does
root finding during calculation to prevent empty tress in such cases.
We match gcc's (and the canonical theoretical) behavior for infinite
loops (find the backedge, connect it to the exit block).
Testcases coming as soon as i finish running this on a ton of random graphs :)
Reviewers: chandlerc, davide
Subscribers: bryant, llvm-commits
Differential Revision: https://reviews.llvm.org/D29705
llvm-svn: 296535
Diffstat (limited to 'llvm/test')
-rw-r--r-- | llvm/test/Analysis/PostDominators/pr24415.ll | 18 | ||||
-rw-r--r-- | llvm/test/Analysis/PostDominators/pr6047_a.ll | 7 | ||||
-rw-r--r-- | llvm/test/Analysis/PostDominators/pr6047_b.ll | 8 | ||||
-rw-r--r-- | llvm/test/Analysis/PostDominators/pr6047_c.ll | 51 | ||||
-rw-r--r-- | llvm/test/Analysis/PostDominators/pr6047_d.ll | 10 | ||||
-rw-r--r-- | llvm/test/Analysis/RegionInfo/infinite_loop.ll | 4 | ||||
-rw-r--r-- | llvm/test/Analysis/RegionInfo/infinite_loop_2.ll | 11 | ||||
-rw-r--r-- | llvm/test/Analysis/RegionInfo/infinite_loop_3.ll | 19 | ||||
-rw-r--r-- | llvm/test/Analysis/RegionInfo/infinite_loop_4.ll | 14 | ||||
-rw-r--r-- | llvm/test/Analysis/RegionInfo/infinite_loop_5_a.ll | 1 | ||||
-rw-r--r-- | llvm/test/Analysis/RegionInfo/infinite_loop_5_b.ll | 1 | ||||
-rw-r--r-- | llvm/test/Transforms/StructurizeCFG/branch-on-argument.ll | 9 | ||||
-rw-r--r-- | llvm/test/Transforms/StructurizeCFG/no-branch-to-entry.ll | 1 |
13 files changed, 120 insertions, 34 deletions
diff --git a/llvm/test/Analysis/PostDominators/pr24415.ll b/llvm/test/Analysis/PostDominators/pr24415.ll new file mode 100644 index 00000000000..e71c33bacf6 --- /dev/null +++ b/llvm/test/Analysis/PostDominators/pr24415.ll @@ -0,0 +1,18 @@ +; RUN: opt < %s -postdomtree -analyze | FileCheck %s +; RUN: opt < %s -passes='print<postdomtree>' 2>&1 | FileCheck %s + +; Function Attrs: nounwind ssp uwtable +define void @foo() { + br label %1 + +; <label>:1 ; preds = %0, %1 + br label %1 + ; No predecessors! + ret void +} + +; CHECK: Inorder PostDominator Tree: +; CHECK-NEXT: [1] <<exit node>> {0,7} +; CHECK-NEXT: [2] %2 {1,2} +; CHECK-NEXT: [2] %1 {3,6} +; CHECK-NEXT: [3] %0 {4,5} diff --git a/llvm/test/Analysis/PostDominators/pr6047_a.ll b/llvm/test/Analysis/PostDominators/pr6047_a.ll index ec1455b46fe..05f87125025 100644 --- a/llvm/test/Analysis/PostDominators/pr6047_a.ll +++ b/llvm/test/Analysis/PostDominators/pr6047_a.ll @@ -12,4 +12,9 @@ bb35.loopexit3: bb35: ret void } -; CHECK: [3] %entry +;CHECK:Inorder PostDominator Tree: +;CHECK-NEXT: [1] <<exit node>> {0,9} +;CHECK-NEXT: [2] %bb35 {1,4} +;CHECK-NEXT: [3] %bb35.loopexit3 {2,3} +;CHECK-NEXT: [2] %entry {5,6} +;CHECK-NEXT: [2] %bb3.i {7,8} diff --git a/llvm/test/Analysis/PostDominators/pr6047_b.ll b/llvm/test/Analysis/PostDominators/pr6047_b.ll index 7bd2c86b737..f5ff754fa65 100644 --- a/llvm/test/Analysis/PostDominators/pr6047_b.ll +++ b/llvm/test/Analysis/PostDominators/pr6047_b.ll @@ -16,4 +16,10 @@ bb35.loopexit3: bb35: ret void } -; CHECK: [4] %entry +; CHECK: Inorder PostDominator Tree: +; CHECK-NEXT: [1] <<exit node>> {0,11} +; CHECK-NEXT: [2] %bb35 {1,4} +; CHECK-NEXT: [3] %bb35.loopexit3 {2,3} +; CHECK-NEXT: [2] %a {5,6} +; CHECK-NEXT: [2] %entry {7,8} +; CHECK-NEXT: [2] %bb3.i {9,10} diff --git a/llvm/test/Analysis/PostDominators/pr6047_c.ll b/llvm/test/Analysis/PostDominators/pr6047_c.ll index 08c9551f156..24a7f1ae562 100644 --- a/llvm/test/Analysis/PostDominators/pr6047_c.ll +++ b/llvm/test/Analysis/PostDominators/pr6047_c.ll @@ -144,4 +144,53 @@ bb35.loopexit3: bb35: ret void } -; CHECK: [3] %entry +; CHECK: Inorder PostDominator Tree: +; CHECK-NEXT: [1] <<exit node>> {0,97} +; CHECK-NEXT: [2] %bb35 {1,92} +; CHECK-NEXT: [3] %bb35.loopexit3 {2,3} +; CHECK-NEXT: [3] %bb35.loopexit {4,5} +; CHECK-NEXT: [3] %bb31 {6,7} +; CHECK-NEXT: [3] %bb30 {8,9} +; CHECK-NEXT: [3] %bb30.loopexit1 {10,11} +; CHECK-NEXT: [3] %bb30.loopexit {12,13} +; CHECK-NEXT: [3] %bb23 {14,15} +; CHECK-NEXT: [3] %bb23.us {16,17} +; CHECK-NEXT: [3] %bb23.preheader {18,19} +; CHECK-NEXT: [3] %bb23.us.preheader {20,21} +; CHECK-NEXT: [3] %bb.nph {22,23} +; CHECK-NEXT: [3] %bb29.preheader {24,25} +; CHECK-NEXT: [3] %bb20 {26,27} +; CHECK-NEXT: [3] %bb19 {28,29} +; CHECK-NEXT: [3] %bb.nph14 {30,31} +; CHECK-NEXT: [3] %bb17.loopexit.split {32,33} +; CHECK-NEXT: [3] %bb16 {34,35} +; CHECK-NEXT: [3] %bb15 {36,37} +; CHECK-NEXT: [3] %bb15.loopexit2 {38,39} +; CHECK-NEXT: [3] %bb15.loopexit {40,41} +; CHECK-NEXT: [3] %bb8 {42,43} +; CHECK-NEXT: [3] %bb8.us {44,45} +; CHECK-NEXT: [3] %bb8.preheader {46,47} +; CHECK-NEXT: [3] %bb8.us.preheader {48,49} +; CHECK-NEXT: [3] %bb.nph18 {50,51} +; CHECK-NEXT: [3] %bb14.preheader {52,53} +; CHECK-NEXT: [3] %bb5 {54,55} +; CHECK-NEXT: [3] %bb4 {56,57} +; CHECK-NEXT: [3] %bb.nph21 {58,59} +; CHECK-NEXT: [3] %bb3.i.loopexit.us {60,61} +; CHECK-NEXT: [3] %bb8.i.us {62,63} +; CHECK-NEXT: [3] %bb4.i.us {64,65} +; CHECK-NEXT: [3] %bb6.i.us {66,67} +; CHECK-NEXT: [3] %bb1.i.us {68,69} +; CHECK-NEXT: [3] %bb.i4.us.backedge {70,71} +; CHECK-NEXT: [3] %bb7.i.us {72,73} +; CHECK-NEXT: [3] %bb.i4.us {74,75} +; CHECK-NEXT: [3] %bb3.split.us {76,77} +; CHECK-NEXT: [3] %bb3 {78,79} +; CHECK-NEXT: [3] %bb32.preheader {80,81} +; CHECK-NEXT: [3] %_float32_unpack.exit8 {82,83} +; CHECK-NEXT: [3] %bb.i5 {84,85} +; CHECK-NEXT: [3] %_float32_unpack.exit {86,87} +; CHECK-NEXT: [3] %bb.i {88,89} +; CHECK-NEXT: [3] %bb {90,91} +; CHECK-NEXT: [2] %entry {93,94} +; CHECK-NEXT: [2] %bb3.i {95,96} diff --git a/llvm/test/Analysis/PostDominators/pr6047_d.ll b/llvm/test/Analysis/PostDominators/pr6047_d.ll index 4cfa88029ae..a3e9f16903c 100644 --- a/llvm/test/Analysis/PostDominators/pr6047_d.ll +++ b/llvm/test/Analysis/PostDominators/pr6047_d.ll @@ -21,4 +21,12 @@ bb35.loopexit3: bb35: ret void } -; CHECK: [4] %entry +; CHECK: Inorder PostDominator Tree: +; CHECK-NEXT: [1] <<exit node>> {0,15} +; CHECK-NEXT: [2] %bb35 {1,4} +; CHECK-NEXT: [3] %bb35.loopexit3 {2,3} +; CHECK-NEXT: [2] %c {5,12} +; CHECK-NEXT: [3] %b {6,7} +; CHECK-NEXT: [3] %entry {8,9} +; CHECK-NEXT: [3] %a {10,11} +; CHECK-NEXT: [2] %bb3.i {13,14} diff --git a/llvm/test/Analysis/RegionInfo/infinite_loop.ll b/llvm/test/Analysis/RegionInfo/infinite_loop.ll index 61abef8ff7a..06ab6cc7481 100644 --- a/llvm/test/Analysis/RegionInfo/infinite_loop.ll +++ b/llvm/test/Analysis/RegionInfo/infinite_loop.ll @@ -16,6 +16,4 @@ define void @normal_condition() nounwind { } ; CHECK-NOT: => ; CHECK: [0] 0 => <Function Return> -; CHECK: [1] 1 => 4 -; STAT: 2 region - The # of regions -; STAT: 1 region - The # of simple regions +; STAT: 1 region - The # of regions diff --git a/llvm/test/Analysis/RegionInfo/infinite_loop_2.ll b/llvm/test/Analysis/RegionInfo/infinite_loop_2.ll index 56e83cfdebb..6df5a9fe563 100644 --- a/llvm/test/Analysis/RegionInfo/infinite_loop_2.ll +++ b/llvm/test/Analysis/RegionInfo/infinite_loop_2.ll @@ -26,12 +26,11 @@ define void @normal_condition() nounwind { } ; CHECK-NOT: => ; CHECK: [0] 0 => <Function Return> -; CHECK: [1] 1 => 3 +; CHECK: [1] 5 => 6 ; STAT: 2 region - The # of regions -; STAT: 1 region - The # of simple regions -; BBIT: 0, 1, 2, 5, 11, 6, 12, 3, 4, -; BBIT: 1, 2, 5, 11, 6, 12, +; BBIT: 0, 1, 2, 5, 11, 6, 12, 3, 4, +; BBIT: 5, 11, 12, -; RNIT: 0, 1 => 3, 3, 4, -; RNIT: 1, 2, 5, 11, 6, 12, +; RNIT: 0, 1, 2, 5 => 6, 6, 3, 4, +; RNIT: 5, 11, 12, diff --git a/llvm/test/Analysis/RegionInfo/infinite_loop_3.ll b/llvm/test/Analysis/RegionInfo/infinite_loop_3.ll index 4538f0f7858..c1eda620c28 100644 --- a/llvm/test/Analysis/RegionInfo/infinite_loop_3.ll +++ b/llvm/test/Analysis/RegionInfo/infinite_loop_3.ll @@ -38,16 +38,15 @@ define void @normal_condition() nounwind { ret void } ; CHECK-NOT: => -; CHECK: [0] 0 => <Function Return> -; CHECK-NEXT: [1] 1 => 3 -; CHECK-NEXT: [1] 7 => 1 +; CHECK:[0] 0 => <Function Return> +; CHECK-NEXT: [1] 5 => 6 +; CHECK-NEXT: [1] 9 => 10 ; STAT: 3 region - The # of regions -; STAT: 2 region - The # of simple regions -; BBIT: 0, 7, 1, 2, 5, 11, 6, 12, 3, 4, 8, 9, 13, 10, 14, -; BBIT: 7, 8, 9, 13, 10, 14, -; BBIT: 1, 2, 5, 11, 6, 12, +; BBIT: 0, 7, 1, 2, 5, 11, 6, 12, 3, 4, 8, 9, 13, 10, 14, +; BBIT: 5, 11, 12, +; BBIT: 9, 13, 14, -; RNIT: 0, 7 => 1, 1 => 3, 3, 4, -; RNIT: 7, 8, 9, 13, 10, 14, -; RNIT: 1, 2, 5, 11, 6, 12, +; RNIT: 0, 7, 1, 2, 5 => 6, 6, 3, 4, 8, 9 => 10, 10, +; RNIT: 5, 11, 12, +; RNIT: 9, 13, 14, diff --git a/llvm/test/Analysis/RegionInfo/infinite_loop_4.ll b/llvm/test/Analysis/RegionInfo/infinite_loop_4.ll index 4ac9068f0dd..7aca6d79da3 100644 --- a/llvm/test/Analysis/RegionInfo/infinite_loop_4.ll +++ b/llvm/test/Analysis/RegionInfo/infinite_loop_4.ll @@ -38,12 +38,14 @@ define void @normal_condition() nounwind { } ; CHECK-NOT: => ; CHECK: [0] 0 => <Function Return> -; CHECK-NEXT: [1] 7 => 3 -; STAT: 2 region - The # of regions +; CHECK-NEXT: [1] 2 => 10 +; CHECK_NEXT: [2] 5 => 6 +; STAT: 3 region - The # of regions ; STAT: 1 region - The # of simple regions ; BBIT: 0, 7, 1, 2, 5, 11, 6, 10, 8, 9, 13, 14, 12, 3, 4, -; BBIT: 7, 1, 2, 5, 11, 6, 10, 8, 9, 13, 14, 12, - -; RNIT: 0, 7 => 3, 3, 4, -; RNIT: 7, 1, 2, 5, 11, 6, 10, 8, 9, 13, 14, 12, +; BBIT: 2, 5, 11, 6, 12, +; BBIT: 5, 11, 12, +; RNIT: 0, 7, 1, 2 => 10, 10, 8, 9, 13, 14, 3, 4, +; RNIT: 2, 5 => 6, 6, +; RNIT: 5, 11, 12, diff --git a/llvm/test/Analysis/RegionInfo/infinite_loop_5_a.ll b/llvm/test/Analysis/RegionInfo/infinite_loop_5_a.ll index b0e52861b7c..b0ffb9b8008 100644 --- a/llvm/test/Analysis/RegionInfo/infinite_loop_5_a.ll +++ b/llvm/test/Analysis/RegionInfo/infinite_loop_5_a.ll @@ -19,6 +19,5 @@ define void @normal_condition() nounwind { ; CHECK: Region tree: ; CHECK-NEXT: [0] 0 => <Function Return> -; CHECK-NEXT: [1] 7 => 3 ; CHECK-NEXT: End region tree diff --git a/llvm/test/Analysis/RegionInfo/infinite_loop_5_b.ll b/llvm/test/Analysis/RegionInfo/infinite_loop_5_b.ll index 49580c9de3d..9759ea873c5 100644 --- a/llvm/test/Analysis/RegionInfo/infinite_loop_5_b.ll +++ b/llvm/test/Analysis/RegionInfo/infinite_loop_5_b.ll @@ -21,5 +21,4 @@ define void @normal_condition() nounwind { ; CHECK: Region tree: ; CHECK-NEXT: [0] 0 => <Function Return> -; CHECK-NEXT: [1] 7 => 3 ; CHECK-NEXT: End region tree diff --git a/llvm/test/Transforms/StructurizeCFG/branch-on-argument.ll b/llvm/test/Transforms/StructurizeCFG/branch-on-argument.ll index 386994f1fd9..cdd4b70592b 100644 --- a/llvm/test/Transforms/StructurizeCFG/branch-on-argument.ll +++ b/llvm/test/Transforms/StructurizeCFG/branch-on-argument.ll @@ -3,14 +3,17 @@ ; CHECK-LABEL: @invert_branch_on_arg_inf_loop( ; CHECK: entry: ; CHECK: %arg.inv = xor i1 %arg, true -; CHECK: phi i1 [ false, %Flow1 ], [ %arg.inv, %entry ] define void @invert_branch_on_arg_inf_loop(i32 addrspace(1)* %out, i1 %arg) { entry: - br i1 %arg, label %for.end, label %for.body + br i1 %arg, label %for.end, label %sesestart +sesestart: + br label %for.body for.body: ; preds = %entry, %for.body store i32 999, i32 addrspace(1)* %out, align 4 - br label %for.body + br i1 %arg, label %for.body, label %seseend +seseend: + ret void for.end: ; preds = %Flow ret void diff --git a/llvm/test/Transforms/StructurizeCFG/no-branch-to-entry.ll b/llvm/test/Transforms/StructurizeCFG/no-branch-to-entry.ll index 1db1060ca82..cda890faa35 100644 --- a/llvm/test/Transforms/StructurizeCFG/no-branch-to-entry.ll +++ b/llvm/test/Transforms/StructurizeCFG/no-branch-to-entry.ll @@ -1,3 +1,4 @@ +; XFAIL: * ; RUN: opt -S -o - -structurizecfg -verify-dom-info < %s | FileCheck %s ; CHECK-LABEL: @no_branch_to_entry_undef( |