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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
| ; RUN: opt < %s -gvn -enable-pre -S | FileCheck %s
declare void @may_exit() nounwind
declare void @may_exit_1(i32) nounwind
define i32 @main(i32 %p, i32 %q) {
; CHECK-LABEL: @main(
block1:
%cmp = icmp eq i32 %p, %q
br i1 %cmp, label %block2, label %block3
block2:
%a = add i32 %p, 1
br label %block4
block3:
br label %block4
; CHECK: %.pre = add i32 %p, 1
; CHECK-NEXT: br label %block4
block4:
%b = add i32 %p, 1
ret i32 %b
; CHECK: %b.pre-phi = phi i32 [ %.pre, %block3 ], [ %a, %block2 ]
; CHECK-NEXT: ret i32 %b.pre-phi
}
; Don't PRE across implicit control flow.
define i32 @test2(i32 %p, i32 %q) {
; CHECK-LABEL: @test2
; CHECK: block1:
block1:
%cmp = icmp eq i32 %p, %q
br i1 %cmp, label %block2, label %block3
block2:
%a = sdiv i32 %p, %q
br label %block4
block3:
br label %block4
; CHECK: block4:
; CHECK-NEXT: call void @may_exit(
; CHECK-NEXT: %b = sdiv
; CHECK-NEXT: ret i32 %b
block4:
call void @may_exit() nounwind
%b = sdiv i32 %p, %q
ret i32 %b
}
; Don't PRE across implicit control flow.
define i32 @test3(i32 %p, i32 %q, i1 %r) {
; CHECK-LABEL: @test3
; CHECK: block1:
block1:
br i1 %r, label %block2, label %block3
block2:
%a = sdiv i32 %p, %q
br label %block4
block3:
br label %block4
block4:
; CHECK: block4:
; CHECK-NEXT: phi i32
; CHECK-NEXT: call void @may_exit_1(
; CHECK-NEXT: %b = sdiv
; CHECK-NEXT: ret i32 %b
%phi = phi i32 [ 0, %block3 ], [ %a, %block2 ]
call void @may_exit_1(i32 %phi) nounwind
%b = sdiv i32 %p, %q
ret i32 %b
}
; It's OK to PRE an instruction that is guaranteed to be safe to execute
; speculatively.
; TODO: Does it make any sense in this case?
define i32 @test4(i32 %p, i32 %q) {
; CHECK-LABEL: @test4
; CHECK: block1:
block1:
%cmp = icmp eq i32 %p, %q
br i1 %cmp, label %block2, label %block3
block2:
%a = sdiv i32 %p, 6
br label %block4
block3:
br label %block4
; CHECK: block4:
; CHECK-NEXT: %b.pre-phi = phi i32
; CHECK-NEXT: call void @may_exit(
; CHECK-NEXT: ret i32 %b
block4:
call void @may_exit() nounwind
%b = sdiv i32 %p, 6
ret i32 %b
}
; It is OK to PRE across implicit control flow if we don't insert new
; instructions.
define i32 @test5(i1 %cond, i32 %p, i32 %q) {
; CHECK-LABEL: @test5
; CHECK: block1:
block1:
br i1 %cond, label %block2, label %block3
block2:
%a = sdiv i32 %p, %q
br label %block4
block3:
%b = sdiv i32 %p, %q
br label %block4
; CHECK: block4:
; CHECK-NEXT: %c.pre-phi = phi i32 [ %b, %block3 ], [ %a, %block2 ]
; CHECK-NEXT: call void @may_exit()
; CHECK-NEXT: ret i32 %c.pre-phi
block4:
call void @may_exit() nounwind
%c = sdiv i32 %p, %q
ret i32 %c
}
|