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
| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -correlated-propagation -S < %s | FileCheck %s
declare void @use()
; test requires a mix of context sensative refinement, and analysis
; of the originating IR pattern. Neither part is enough in isolation.
define void @test1(i1 %c, i1 %c2) {
; CHECK-LABEL: @test1(
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i64 -1, i64 1
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[C2:%.*]], i64 [[SEL]], i64 0
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[SEL2]], 0
; CHECK-NEXT: br i1 [[CMP]], label [[TAKEN:%.*]], label [[UNTAKEN:%.*]]
; CHECK: taken:
; CHECK-NEXT: call void @use() [ "deopt"(i64 1) ]
; CHECK-NEXT: ret void
; CHECK: untaken:
; CHECK-NEXT: ret void
;
%sel = select i1 %c, i64 -1, i64 1
%sel2 = select i1 %c2, i64 %sel, i64 0
%cmp = icmp sgt i64 %sel2, 0
br i1 %cmp, label %taken, label %untaken
taken:
call void @use() ["deopt" (i64 %sel2)]
ret void
untaken:
ret void
}
declare void @llvm.assume(i1)
declare void @llvm.experimental.guard(i1,...)
; Same as test1, but with assume not branch
define void @test1_assume(i1 %c, i1 %c2) {
; CHECK-LABEL: @test1_assume(
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i64 -1, i64 1
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[C2:%.*]], i64 [[SEL]], i64 0
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[SEL2]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: call void @use() [ "deopt"(i64 1) ]
; CHECK-NEXT: ret void
;
%sel = select i1 %c, i64 -1, i64 1
%sel2 = select i1 %c2, i64 %sel, i64 0
%cmp = icmp sgt i64 %sel2, 0
call void @llvm.assume(i1 %cmp)
call void @use() ["deopt" (i64 %sel2)]
ret void
}
; Same as test1, but with guard not branch
define void @test1_guard(i1 %c, i1 %c2) {
; CHECK-LABEL: @test1_guard(
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i64 -1, i64 1
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[C2:%.*]], i64 [[SEL]], i64 0
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[SEL2]], 0
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[CMP]]) [ "deopt"(i64 [[SEL2]]) ]
; CHECK-NEXT: call void @use() [ "deopt"(i64 1) ]
; CHECK-NEXT: ret void
;
%sel = select i1 %c, i64 -1, i64 1
%sel2 = select i1 %c2, i64 %sel, i64 0
%cmp = icmp sgt i64 %sel2, 0
call void (i1, ...) @llvm.experimental.guard(i1 %cmp) ["deopt" (i64 %sel2)]
call void @use() ["deopt" (i64 %sel2)]
ret void
}
;; The rest of these are slight variations on the patterns
;; producing 1 of several adjacent constants to test generality
define void @test2(i1 %c, i1 %c2) {
; CHECK-LABEL: @test2(
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i64 0, i64 1
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[C2:%.*]], i64 [[SEL]], i64 -1
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[SEL2]], 0
; CHECK-NEXT: br i1 [[CMP]], label [[TAKEN:%.*]], label [[UNTAKEN:%.*]]
; CHECK: taken:
; CHECK-NEXT: call void @use() [ "deopt"(i64 1) ]
; CHECK-NEXT: ret void
; CHECK: untaken:
; CHECK-NEXT: ret void
;
%sel = select i1 %c, i64 0, i64 1
%sel2 = select i1 %c2, i64 %sel, i64 -1
%cmp = icmp sgt i64 %sel2, 0
br i1 %cmp, label %taken, label %untaken
taken:
call void @use() ["deopt" (i64 %sel2)]
ret void
untaken:
ret void
}
define void @test3(i1 %c, i1 %c2) {
; CHECK-LABEL: @test3(
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i64 0, i64 1
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[C2:%.*]], i64 [[SEL]], i64 2
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[SEL2]], 1
; CHECK-NEXT: br i1 [[CMP]], label [[TAKEN:%.*]], label [[UNTAKEN:%.*]]
; CHECK: taken:
; CHECK-NEXT: call void @use() [ "deopt"(i64 2) ]
; CHECK-NEXT: ret void
; CHECK: untaken:
; CHECK-NEXT: ret void
;
%sel = select i1 %c, i64 0, i64 1
%sel2 = select i1 %c2, i64 %sel, i64 2
%cmp = icmp sgt i64 %sel2, 1
br i1 %cmp, label %taken, label %untaken
taken:
call void @use() ["deopt" (i64 %sel2)]
ret void
untaken:
ret void
}
define void @test4(i1 %c, i1 %c2) {
; CHECK-LABEL: @test4(
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i64 0, i64 1
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[C2:%.*]], i64 0, i64 1
; CHECK-NEXT: [[ADD1:%.*]] = add nuw nsw i64 0, [[SEL]]
; CHECK-NEXT: [[ADD2:%.*]] = add nuw nsw i64 [[ADD1]], [[SEL2]]
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[ADD2]], 1
; CHECK-NEXT: br i1 [[CMP]], label [[TAKEN:%.*]], label [[UNTAKEN:%.*]]
; CHECK: taken:
; CHECK-NEXT: call void @use() [ "deopt"(i64 2) ]
; CHECK-NEXT: ret void
; CHECK: untaken:
; CHECK-NEXT: ret void
;
%sel = select i1 %c, i64 0, i64 1
%sel2 = select i1 %c2, i64 0, i64 1
%add1 = add i64 0, %sel
%add2 = add i64 %add1, %sel2
%cmp = icmp sgt i64 %add2, 1
br i1 %cmp, label %taken, label %untaken
taken:
call void @use() ["deopt" (i64 %add2)]
ret void
untaken:
ret void
}
|