aboutsummaryrefslogtreecommitdiff
path: root/test/Transforms/SimplifyCFG/2008-05-16-PHIBlockMerge.ll
blob: 59e886b2ddbe546c222e256c3b5cfd4d638f6f87 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
; RUN: opt < %s -simplifycfg -S > %t
; RUN: not grep {^BB.tomerge} %t
; RUN  grep {^BB.nomerge} %t | count 2

; ModuleID = '<stdin>' 
declare i1 @foo()

declare i1 @bar(i32)

; This function can't be merged
define void @a() {
entry:
	br label %BB.nomerge

BB.nomerge:		; preds = %Common, %entry
        ; This phi has a conflicting value (0) with below phi (2), so blocks
        ; can't be merged.
	%a = phi i32 [ 1, %entry ], [ 0, %Common ]		; <i32> [#uses=1]
	br label %Succ

Succ:		; preds = %Common, %BB.nomerge
	%b = phi i32 [ %a, %BB.nomerge ], [ 2, %Common ]		; <i32> [#uses=0]
	%conde = call i1 @foo( )		; <i1> [#uses=1]
	br i1 %conde, label %Common, label %Exit

Common:		; preds = %Succ
	%cond = call i1 @foo( )		; <i1> [#uses=1]
	br i1 %cond, label %BB.nomerge, label %Succ

Exit:		; preds = %Succ
	ret void
}

; This function can't be merged
define void @b() {
entry:
	br label %BB.nomerge

BB.nomerge:		; preds = %Common, %entry
	br label %Succ

Succ:		; preds = %Common, %BB.nomerge
        ; This phi has confliction values for Common and (through BB) Common,
        ; blocks can't be merged
	%b = phi i32 [ 1, %BB.nomerge ], [ 2, %Common ]		; <i32> [#uses=0]
	%conde = call i1 @foo( )		; <i1> [#uses=1]
	br i1 %conde, label %Common, label %Exit

Common:		; preds = %Succ
	%cond = call i1 @foo( )		; <i1> [#uses=1]
	br i1 %cond, label %BB.nomerge, label %Succ

Exit:		; preds = %Succ
	ret void
}

; This function can be merged
define void @c() {
entry:
	br label %BB.tomerge

BB.tomerge:		; preds = %Common, %entry
	br label %Succ

Succ:		; preds = %Common, %BB.tomerge, %Pre-Exit
        ; This phi has identical values for Common and (through BB) Common,
        ; blocks can't be merged
	%b = phi i32 [ 1, %BB.tomerge ], [ 1, %Common ], [ 2, %Pre-Exit ]
	%conde = call i1 @foo( )		; <i1> [#uses=1]
	br i1 %conde, label %Common, label %Pre-Exit

Common:		; preds = %Succ
	%cond = call i1 @foo( )		; <i1> [#uses=1]
	br i1 %cond, label %BB.tomerge, label %Succ

Pre-Exit:       ; preds = %Succ
        ; This adds a backedge, so the %b phi node gets a third branch and is
        ; not completely trivial
	%cond2 = call i1 @foo( )		; <i1> [#uses=1]
	br i1 %cond2, label %Succ, label %Exit
        
Exit:		; preds = %Pre-Exit
	ret void
}

; This function can be merged
define void @d() {
entry:
	br label %BB.tomerge

BB.tomerge:		; preds = %Common, %entry
        ; This phi has a matching value (0) with below phi (0), so blocks
        ; can be merged.
	%a = phi i32 [ 1, %entry ], [ 0, %Common ]		; <i32> [#uses=1]
	br label %Succ

Succ:		; preds = %Common, %BB.tomerge
	%b = phi i32 [ %a, %BB.tomerge ], [ 0, %Common ]		; <i32> [#uses=0]
	%conde = call i1 @foo( )		; <i1> [#uses=1]
	br i1 %conde, label %Common, label %Exit

Common:		; preds = %Succ
	%cond = call i1 @foo( )		; <i1> [#uses=1]
	br i1 %cond, label %BB.tomerge, label %Succ

Exit:		; preds = %Succ
	ret void
}

; This function can be merged
define void @e() {
entry:
	br label %BB.tomerge

BB.tomerge:		; preds = %Use, %entry
        ; This phi is used somewhere else than Succ, but this should not prevent
        ; merging this block
	%a = phi i32 [ 1, %entry ], [ 0, %Use ]		; <i32> [#uses=1]
	br label %Succ

Succ:		; preds = %BB.tomerge
	%conde = call i1 @foo( )		; <i1> [#uses=1]
	br i1 %conde, label %Use, label %Exit

Use:		; preds = %Succ
	%cond = call i1 @bar( i32 %a )		; <i1> [#uses=1]
	br i1 %cond, label %BB.tomerge, label %Exit

Exit:		; preds = %Use, %Succ
	ret void
}