1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
3
4define i1 @bitcast_and_cmp(i32* readonly %src, i32* readnone %min, i32* readnone %max) {
5; CHECK-LABEL: @bitcast_and_cmp(
6; CHECK-NEXT:  check.0.min:
7; CHECK-NEXT:    [[SRC_C:%.*]] = bitcast i32* [[SRC:%.*]] to i8*
8; CHECK-NEXT:    [[MIN_C:%.*]] = bitcast i32* [[MIN:%.*]] to i8*
9; CHECK-NEXT:    [[MAX_C:%.*]] = bitcast i32* [[MAX:%.*]] to i16*
10; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 3
11; CHECK-NEXT:    [[GEP_3_C:%.*]] = bitcast i32* [[GEP_3]] to i16*
12; CHECK-NEXT:    [[C_MIN_0:%.*]] = icmp ult i8* [[SRC_C]], [[MIN_C]]
13; CHECK-NEXT:    [[C_MAX_3:%.*]] = icmp ugt i16* [[GEP_3_C]], [[MAX_C]]
14; CHECK-NEXT:    [[OR:%.*]] = or i1 [[C_MIN_0]], [[C_MAX_3]]
15; CHECK-NEXT:    br i1 [[OR]], label [[TRAP:%.*]], label [[CHECKS:%.*]]
16; CHECK:       trap:
17; CHECK-NEXT:    ret i1 false
18; CHECK:       checks:
19; CHECK-NEXT:    [[C_3_MIN:%.*]] = icmp ult i32* [[GEP_3]], [[MIN]]
20; CHECK-NEXT:    [[C_3_MAX:%.*]] = icmp ult i32* [[GEP_3]], [[MAX]]
21; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 false, [[C_3_MAX]]
22; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 1
23; CHECK-NEXT:    [[C_1_MIN:%.*]] = icmp ult i32* [[GEP_1]], [[MIN]]
24; CHECK-NEXT:    [[C_1_MAX:%.*]] = icmp ult i32* [[GEP_1]], [[MAX]]
25; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 false, true
26; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 2
27; CHECK-NEXT:    [[C_2_MIN:%.*]] = icmp ult i32* [[GEP_2]], [[MIN]]
28; CHECK-NEXT:    [[C_2_MAX:%.*]] = icmp ult i32* [[GEP_2]], [[MAX]]
29; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 false, true
30; CHECK-NEXT:    [[GEP_4:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 4
31; CHECK-NEXT:    [[C_4_MIN:%.*]] = icmp ult i32* [[GEP_4]], [[MIN]]
32; CHECK-NEXT:    [[C_4_MAX:%.*]] = icmp ult i32* [[GEP_4]], [[MAX]]
33; CHECK-NEXT:    [[RES_4:%.*]] = xor i1 false, [[C_4_MAX]]
34; CHECK-NEXT:    [[RES_5:%.*]] = xor i1 [[RES_1]], [[RES_2]]
35; CHECK-NEXT:    [[RES_6:%.*]] = xor i1 [[RES_5]], [[RES_3]]
36; CHECK-NEXT:    [[RES_7:%.*]] = xor i1 [[RES_6]], [[RES_4]]
37; CHECK-NEXT:    ret i1 [[RES_7]]
38;
39check.0.min:
40  %src.c = bitcast i32* %src to i8*
41  %min.c = bitcast i32* %min to i8*
42  %max.c = bitcast i32* %max to i16*
43
44  %gep.3 = getelementptr inbounds i32, i32* %src, i64 3
45  %gep.3.c = bitcast i32* %gep.3 to i16*
46  %c.min.0 = icmp ult i8* %src.c, %min.c
47  %c.max.3 = icmp ugt i16* %gep.3.c, %max.c
48
49  %or = or i1 %c.min.0, %c.max.3
50  br i1 %or, label %trap, label %checks
51
52trap:
53  ret i1 0
54
55checks:
56  %c.3.min = icmp ult i32* %gep.3, %min
57  %c.3.max = icmp ult i32* %gep.3, %max
58  %res.1 = xor i1 %c.3.min, %c.3.max
59
60  %gep.1 = getelementptr inbounds i32, i32* %src, i64 1
61  %c.1.min = icmp ult i32* %gep.1, %min
62  %c.1.max = icmp ult i32* %gep.1, %max
63  %res.2 = xor i1 %c.1.min, %c.1.max
64
65  %gep.2 = getelementptr inbounds i32, i32* %src, i64 2
66  %c.2.min = icmp ult i32* %gep.2, %min
67  %c.2.max = icmp ult i32* %gep.2, %max
68  %res.3 = xor i1 %c.2.min, %c.2.max
69
70  %gep.4 = getelementptr inbounds i32, i32* %src, i64 4
71  %c.4.min = icmp ult i32* %gep.4, %min
72  %c.4.max = icmp ult i32* %gep.4, %max
73  %res.4 = xor i1 %c.4.min, %c.4.max
74
75  %res.5 = xor i1 %res.1, %res.2
76  %res.6 = xor i1 %res.5, %res.3
77  %res.7 = xor i1 %res.6, %res.4
78
79  ret i1 %res.7
80}
81
82define i1 @gep0_and_cmp(i32* readonly %src, i32* readnone %min, i32* readnone %max) {
83; CHECK-LABEL: @gep0_and_cmp(
84; CHECK-NEXT:  check.0.min:
85; CHECK-NEXT:    [[SRC_C:%.*]] = getelementptr i32, i32* [[SRC:%.*]], i64 0
86; CHECK-NEXT:    [[MIN_C:%.*]] = getelementptr i32, i32* [[MIN:%.*]], i64 0
87; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 3
88; CHECK-NEXT:    [[GEP_3_C:%.*]] = getelementptr i32, i32* [[GEP_3]], i32 0
89; CHECK-NEXT:    [[C_MIN_0:%.*]] = icmp ult i32* [[SRC_C]], [[MIN_C]]
90; CHECK-NEXT:    [[C_MAX_3:%.*]] = icmp ugt i32* [[GEP_3_C]], [[MAX:%.*]]
91; CHECK-NEXT:    [[OR:%.*]] = or i1 [[C_MIN_0]], [[C_MAX_3]]
92; CHECK-NEXT:    br i1 [[OR]], label [[TRAP:%.*]], label [[CHECKS:%.*]]
93; CHECK:       trap:
94; CHECK-NEXT:    ret i1 false
95; CHECK:       checks:
96; CHECK-NEXT:    [[C_3_MIN:%.*]] = icmp ult i32* [[GEP_3]], [[MIN]]
97; CHECK-NEXT:    [[C_3_MAX:%.*]] = icmp ult i32* [[GEP_3]], [[MAX]]
98; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 false, [[C_3_MAX]]
99; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 1
100; CHECK-NEXT:    [[C_1_MIN:%.*]] = icmp ult i32* [[GEP_1]], [[MIN]]
101; CHECK-NEXT:    [[C_1_MAX:%.*]] = icmp ult i32* [[GEP_1]], [[MAX]]
102; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 false, true
103; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 2
104; CHECK-NEXT:    [[C_2_MIN:%.*]] = icmp ult i32* [[GEP_2]], [[MIN]]
105; CHECK-NEXT:    [[C_2_MAX:%.*]] = icmp ult i32* [[GEP_2]], [[MAX]]
106; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 false, true
107; CHECK-NEXT:    [[GEP_4:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 4
108; CHECK-NEXT:    [[C_4_MIN:%.*]] = icmp ult i32* [[GEP_4]], [[MIN]]
109; CHECK-NEXT:    [[C_4_MAX:%.*]] = icmp ult i32* [[GEP_4]], [[MAX]]
110; CHECK-NEXT:    [[RES_4:%.*]] = xor i1 false, [[C_4_MAX]]
111; CHECK-NEXT:    [[RES_5:%.*]] = xor i1 [[RES_1]], [[RES_2]]
112; CHECK-NEXT:    [[RES_6:%.*]] = xor i1 [[RES_5]], [[RES_3]]
113; CHECK-NEXT:    [[RES_7:%.*]] = xor i1 [[RES_6]], [[RES_4]]
114; CHECK-NEXT:    ret i1 [[RES_7]]
115;
116check.0.min:
117  %src.c = getelementptr i32, i32* %src, i64 0
118  %min.c = getelementptr i32, i32* %min, i64 0
119
120  %gep.3 = getelementptr inbounds i32, i32* %src, i64 3
121  %gep.3.c = getelementptr i32, i32* %gep.3, i32 0
122  %c.min.0 = icmp ult i32* %src.c, %min.c
123  %c.max.3 = icmp ugt i32* %gep.3.c, %max
124
125  %or = or i1 %c.min.0, %c.max.3
126  br i1 %or, label %trap, label %checks
127
128trap:
129  ret i1 0
130
131checks:
132  %c.3.min = icmp ult i32* %gep.3, %min
133  %c.3.max = icmp ult i32* %gep.3, %max
134  %res.1 = xor i1 %c.3.min, %c.3.max
135
136  %gep.1 = getelementptr inbounds i32, i32* %src, i64 1
137  %c.1.min = icmp ult i32* %gep.1, %min
138  %c.1.max = icmp ult i32* %gep.1, %max
139  %res.2 = xor i1 %c.1.min, %c.1.max
140
141  %gep.2 = getelementptr inbounds i32, i32* %src, i64 2
142  %c.2.min = icmp ult i32* %gep.2, %min
143  %c.2.max = icmp ult i32* %gep.2, %max
144  %res.3 = xor i1 %c.2.min, %c.2.max
145
146  %gep.4 = getelementptr inbounds i32, i32* %src, i64 4
147  %c.4.min = icmp ult i32* %gep.4, %min
148  %c.4.max = icmp ult i32* %gep.4, %max
149  %res.4 = xor i1 %c.4.min, %c.4.max
150
151  %res.5 = xor i1 %res.1, %res.2
152  %res.6 = xor i1 %res.5, %res.3
153  %res.7 = xor i1 %res.6, %res.4
154
155  ret i1 %res.7
156}
157
158; Should not look through addresspacecast, because it may change the pointer
159; value.
160define i1 @addrspacecast_and_cmp(i32* readonly %src, i32* readnone %min, i32* readnone %max) {
161; CHECK-LABEL: @addrspacecast_and_cmp(
162; CHECK-NEXT:  check.0.min:
163; CHECK-NEXT:    [[SRC_C:%.*]] = addrspacecast i32* [[SRC:%.*]] to i8 addrspace(1)*
164; CHECK-NEXT:    [[MIN_C:%.*]] = addrspacecast i32* [[MIN:%.*]] to i8 addrspace(1)*
165; CHECK-NEXT:    [[MAX_C:%.*]] = addrspacecast i32* [[MAX:%.*]] to i16 addrspace(1)*
166; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 3
167; CHECK-NEXT:    [[GEP_3_C:%.*]] = addrspacecast i32* [[GEP_3]] to i16 addrspace(1)*
168; CHECK-NEXT:    [[C_MIN_0:%.*]] = icmp ult i8 addrspace(1)* [[SRC_C]], [[MIN_C]]
169; CHECK-NEXT:    [[C_MAX_3:%.*]] = icmp ugt i16 addrspace(1)* [[GEP_3_C]], [[MAX_C]]
170; CHECK-NEXT:    [[OR:%.*]] = or i1 [[C_MIN_0]], [[C_MAX_3]]
171; CHECK-NEXT:    br i1 [[OR]], label [[TRAP:%.*]], label [[CHECKS:%.*]]
172; CHECK:       trap:
173; CHECK-NEXT:    ret i1 false
174; CHECK:       checks:
175; CHECK-NEXT:    [[C_3_MIN:%.*]] = icmp ult i32* [[GEP_3]], [[MIN]]
176; CHECK-NEXT:    [[C_3_MAX:%.*]] = icmp ult i32* [[GEP_3]], [[MAX]]
177; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_3_MIN]], [[C_3_MAX]]
178; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 1
179; CHECK-NEXT:    [[C_1_MIN:%.*]] = icmp ult i32* [[GEP_1]], [[MIN]]
180; CHECK-NEXT:    [[C_1_MAX:%.*]] = icmp ult i32* [[GEP_1]], [[MAX]]
181; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[C_1_MIN]], [[C_1_MAX]]
182; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 2
183; CHECK-NEXT:    [[C_2_MIN:%.*]] = icmp ult i32* [[GEP_2]], [[MIN]]
184; CHECK-NEXT:    [[C_2_MAX:%.*]] = icmp ult i32* [[GEP_2]], [[MAX]]
185; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[C_2_MIN]], [[C_2_MAX]]
186; CHECK-NEXT:    [[GEP_4:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 4
187; CHECK-NEXT:    [[C_4_MIN:%.*]] = icmp ult i32* [[GEP_4]], [[MIN]]
188; CHECK-NEXT:    [[C_4_MAX:%.*]] = icmp ult i32* [[GEP_4]], [[MAX]]
189; CHECK-NEXT:    [[RES_4:%.*]] = xor i1 [[C_4_MIN]], [[C_4_MAX]]
190; CHECK-NEXT:    [[RES_5:%.*]] = xor i1 [[RES_1]], [[RES_2]]
191; CHECK-NEXT:    [[RES_6:%.*]] = xor i1 [[RES_5]], [[RES_3]]
192; CHECK-NEXT:    [[RES_7:%.*]] = xor i1 [[RES_6]], [[RES_4]]
193; CHECK-NEXT:    ret i1 [[RES_7]]
194;
195check.0.min:
196  %src.c = addrspacecast i32* %src to i8 addrspace(1)*
197  %min.c = addrspacecast i32* %min to i8 addrspace(1)*
198  %max.c = addrspacecast i32* %max to i16 addrspace(1)*
199
200  %gep.3 = getelementptr inbounds i32, i32* %src, i64 3
201  %gep.3.c = addrspacecast i32* %gep.3 to i16 addrspace(1) *
202  %c.min.0 = icmp ult i8 addrspace(1)* %src.c, %min.c
203  %c.max.3 = icmp ugt i16 addrspace(1)* %gep.3.c, %max.c
204
205  %or = or i1 %c.min.0, %c.max.3
206  br i1 %or, label %trap, label %checks
207
208trap:
209  ret i1 0
210
211checks:
212  %c.3.min = icmp ult i32* %gep.3, %min
213  %c.3.max = icmp ult i32* %gep.3, %max
214  %res.1 = xor i1 %c.3.min, %c.3.max
215
216  %gep.1 = getelementptr inbounds i32, i32* %src, i64 1
217  %c.1.min = icmp ult i32* %gep.1, %min
218  %c.1.max = icmp ult i32* %gep.1, %max
219  %res.2 = xor i1 %c.1.min, %c.1.max
220
221  %gep.2 = getelementptr inbounds i32, i32* %src, i64 2
222  %c.2.min = icmp ult i32* %gep.2, %min
223  %c.2.max = icmp ult i32* %gep.2, %max
224  %res.3 = xor i1 %c.2.min, %c.2.max
225
226  %gep.4 = getelementptr inbounds i32, i32* %src, i64 4
227  %c.4.min = icmp ult i32* %gep.4, %min
228  %c.4.max = icmp ult i32* %gep.4, %max
229  %res.4 = xor i1 %c.4.min, %c.4.max
230
231  %res.5 = xor i1 %res.1, %res.2
232  %res.6 = xor i1 %res.5, %res.3
233  %res.7 = xor i1 %res.6, %res.4
234
235  ret i1 %res.7
236}
237