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
148
149
150
151
152
153
| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -disable-output -print-mustexecute %s 2>&1 | FileCheck %s
define i1 @header_with_icf(i32* noalias %p, i32 %high) {
; CHECK-LABEL: @header_with_icf(
; CHECK-LABEL: loop:
; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] ; (mustexec in: loop)
; CHECK: %v = load i32, i32* %p ; (mustexec in: loop)
; CHECK: call void @maythrow_and_use(i32 %v) ; (mustexec in: loop)
; CHECK-NOT: mustexec
entry:
br label %loop
loop:
%iv = phi i32 [0, %entry], [%iv.next, %loop]
%v = load i32, i32* %p
call void @maythrow_and_use(i32 %v)
%iv.next = add nsw nuw i32 %iv, 1
%exit.test = icmp slt i32 %iv, %high
br i1 %exit.test, label %exit, label %loop
exit:
ret i1 false
}
define i1 @split_header(i32* noalias %p, i32 %high) {
; CHECK-LABEL: @split_header(
; CHECK-LABEL: loop:
; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %next ] ; (mustexec in: loop)
; CHECK: %v = load i32, i32* %p ; (mustexec in: loop)
; CHECK: br label %next ; (mustexec in: loop)
; CHECK-NOT: mustexec
entry:
br label %loop
loop:
%iv = phi i32 [0, %entry], [%iv.next, %next]
%v = load i32, i32* %p
br label %next
next:
call void @maythrow_and_use(i32 %v)
%iv.next = add nsw nuw i32 %iv, 1
%exit.test = icmp slt i32 %iv, %high
br i1 %exit.test, label %exit, label %loop
exit:
ret i1 false
}
; FIXME: everything in inner loop header should be must execute
; for outer as well
define i1 @nested(i32* noalias %p, i32 %high) {
; CHECK-LABEL: @nested
; CHECK-LABEL: loop: ; preds = %next
; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %next ] ; (mustexec in: loop)
; CHECK: br label %inner_loop ; (mustexec in: loop)
; CHECK-LABEL: inner_loop:
; CHECK: %v = load i32, i32* %p ; (mustexec in: inner_loop)
; CHECK: %inner.test = icmp eq i32 %v, 0 ; (mustexec in: inner_loop)
; CHECK: br i1 %inner.test, label %inner_loop, label %next ; (mustexec in: inner_loop)
; CHECK-NOT: mustexec
entry:
br label %loop
loop:
%iv = phi i32 [0, %entry], [%iv.next, %next]
br label %inner_loop
inner_loop:
%v = load i32, i32* %p
%inner.test = icmp eq i32 %v, 0
br i1 %inner.test, label %inner_loop, label %next
next:
call void @maythrow_and_use(i32 %v)
%iv.next = add nsw nuw i32 %iv, 1
%exit.test = icmp slt i32 %iv, %high
br i1 %exit.test, label %exit, label %loop
exit:
ret i1 false
}
define i1 @nested_no_throw(i32* noalias %p, i32 %high) {
; CHECK-LABEL: @nested_no_throw
; CHECK-LABEL: loop: ; preds = %next
; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %next ] ; (mustexec in: loop)
; CHECK: br label %inner_loop ; (mustexec in: loop)
; CHECK-LABEL: inner_loop:
; CHECK: %v = load i32, i32* %p ; (mustexec in 2 loops: inner_loop, loop)
; CHECK: %inner.test = icmp eq i32 %v, 0 ; (mustexec in 2 loops: inner_loop, loop)
; CHECK: br i1 %inner.test, label %inner_loop, label %next ; (mustexec in 2 loops: inner_loop, loop)
; CHECK-LABEL: next:
; CHECK: %iv.next = add nuw nsw i32 %iv, 1 ; (mustexec in: loop)
; CHECK: %exit.test = icmp slt i32 %iv, %high ; (mustexec in: loop)
; CHECK: br i1 %exit.test, label %exit, label %loop ; (mustexec in: loop)
entry:
br label %loop
loop:
%iv = phi i32 [0, %entry], [%iv.next, %next]
br label %inner_loop
inner_loop:
%v = load i32, i32* %p
%inner.test = icmp eq i32 %v, 0
br i1 %inner.test, label %inner_loop, label %next
next:
%iv.next = add nsw nuw i32 %iv, 1
%exit.test = icmp slt i32 %iv, %high
br i1 %exit.test, label %exit, label %loop
exit:
ret i1 false
}
; Since all the instructions in the loop dominate the only exit
; and there's no implicit control flow in the loop, all must execute
; FIXME: handled by loop safety info, test it
define i1 @nothrow_loop(i32* noalias %p, i32 %high) {
; CHECK-LABEL: @nothrow_loop(
; CHECK-LABEL: loop:
; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %next ] ; (mustexec in: loop)
; CHECK: br label %next ; (mustexec in: loop)
; CHECK-LABEL: next:
; CHECK: %v = load i32, i32* %p ; (mustexec in: loop)
; CHECK: %iv.next = add nuw nsw i32 %iv, 1 ; (mustexec in: loop)
; CHECK: %exit.test = icmp slt i32 %iv, %high ; (mustexec in: loop)
; CHECK: br i1 %exit.test, label %exit, label %loop ; (mustexec in: loop)
; CHECK-NOT: mustexec
entry:
br label %loop
loop:
%iv = phi i32 [0, %entry], [%iv.next, %next]
br label %next
next:
%v = load i32, i32* %p
%iv.next = add nsw nuw i32 %iv, 1
%exit.test = icmp slt i32 %iv, %high
br i1 %exit.test, label %exit, label %loop
exit:
ret i1 false
}
declare void @maythrow_and_use(i32)
|