@@ -51,3 +51,207 @@ define i1 @test(i32 %tmp1030) {
51
51
ret i1 %tmp1042
52
52
}
53
53
54
+ ; Last three instructions (ignoring ret) are equivalent of %val2 < %val1.
55
+ define i1 @test2 (i32 %a , i32 %b ) {
56
+ ; CHECK-LABEL: @test2(
57
+ ; CHECK-NEXT: [[VAL1:%.*]] = and i32 %a, 8
58
+ ; CHECK-NEXT: [[VAL2:%.*]] = and i32 %b, 8
59
+ ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[VAL2]], [[VAL1]]
60
+ ; CHECK-NEXT: ret i1 [[TMP1]]
61
+ ;
62
+ %val1 = and i32 %a , 8
63
+ %val2 = and i32 %b , 8
64
+ %cmp.a = icmp ne i32 %val1 , 0
65
+ %cmp.b = icmp eq i32 %val2 , 0
66
+ %and = and i1 %cmp.b , %cmp.a
67
+ ret i1 %and
68
+ }
69
+
70
+ ; Last three instructions (ignoring ret) are equivalent of %val2 < %val1.
71
+ define i1 @test3 (i32 %a , i32 %b ) {
72
+ ; CHECK-LABEL: @test3(
73
+ ; CHECK-NEXT: [[VAL1:%.*]] = and i32 %a, 8
74
+ ; CHECK-NEXT: [[VAL2:%.*]] = and i32 %b, 8
75
+ ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[VAL2]], [[VAL1]]
76
+ ; CHECK-NEXT: ret i1 [[TMP1]]
77
+ ;
78
+ %val1 = and i32 %a , 8
79
+ %val2 = and i32 %b , 8
80
+ %cmp.a = icmp ne i32 %val1 , 0
81
+ %cmp.b = icmp eq i32 %val2 , 0
82
+ %and = and i1 %cmp.a , %cmp.b
83
+ ret i1 %and
84
+ }
85
+
86
+ ; Last three instructions (ignoring ret) are equivalent of %val2 < %val1.
87
+ define i1 @test4 (i32 %a , i32 %b ) {
88
+ ; CHECK-LABEL: @test4(
89
+ ; CHECK-NEXT: [[VAL1:%.*]] = and i32 %a, 15
90
+ ; CHECK-NEXT: [[VAL2:%.*]] = and i32 %b, 24
91
+ ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[VAL2]], [[VAL1]]
92
+ ; CHECK-NEXT: ret i1 [[TMP1]]
93
+ ;
94
+ %val1 = and i32 %a , 15
95
+ %val2 = and i32 %b , 24
96
+ %cmp.a = icmp ne i32 %val1 , 0
97
+ %cmp.b = icmp eq i32 %val2 , 0
98
+ %and = and i1 %cmp.a , %cmp.b
99
+ ret i1 %and
100
+ }
101
+
102
+ ; Last three instructions (ignoring ret) are equivalent of %val2 < %val1.
103
+ define i1 @test5 (i32 %a , i32 %b ) {
104
+ ; CHECK-LABEL: @test5(
105
+ ; CHECK-NEXT: [[VAL1:%.*]] = and i32 %a, 15
106
+ ; CHECK-NEXT: [[VAL2:%.*]] = and i32 %b, 24
107
+ ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[VAL2]], [[VAL1]]
108
+ ; CHECK-NEXT: ret i1 [[TMP1]]
109
+ ;
110
+ %val1 = and i32 %a , 15
111
+ %val2 = and i32 %b , 24
112
+ %cmp.a = icmp ne i32 %val1 , 0
113
+ %cmp.b = icmp eq i32 %val2 , 0
114
+ %and = and i1 %cmp.b , %cmp.a
115
+ ret i1 %and
116
+ }
117
+
118
+ ; An optimization like those of previous tests is not possible
119
+ ; for example if %b = 8 and %a = 16, we have %val2 = 8 and
120
+ ; % %val1 = 16 so %val2 < %val1 but %and == 0.
121
+ define i1 @test6 (i32 %a , i32 %b ) {
122
+ ; CHECK-LABEL: @test6(
123
+ ; CHECK-NEXT: [[VAL1:%.*]] = and i32 %a, 16
124
+ ; CHECK-NEXT: [[VAL2:%.*]] = and i32 %b, 24
125
+ ; CHECK-NEXT: [[CMP_A:%.*]] = icmp ne i32 [[VAL1]], 0
126
+ ; CHECK-NEXT: [[CMP_B:%.*]] = icmp eq i32 [[VAL2]], 0
127
+ ; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP_B]], [[CMP_A]]
128
+ ; CHECK-NEXT: ret i1 [[AND]]
129
+ ;
130
+ %val1 = and i32 %a , 16
131
+ %val2 = and i32 %b , 24
132
+ %cmp.a = icmp ne i32 %val1 , 0
133
+ %cmp.b = icmp eq i32 %val2 , 0
134
+ %and = and i1 %cmp.b , %cmp.a
135
+ ret i1 %and
136
+ }
137
+
138
+ ; %a and %b have different widths. So optimization is not possible.
139
+ define i1 @test7 (i16 %a , i32 %b ) {
140
+ ; CHECK-LABEL: @test7(
141
+ ; CHECK-NEXT: [[VAL1:%.*]] = and i16 %a, 15
142
+ ; CHECK-NEXT: [[VAL2:%.*]] = and i32 %b, 24
143
+ ; CHECK-NEXT: [[CMP_A:%.*]] = icmp ne i16 [[VAL1]], 0
144
+ ; CHECK-NEXT: [[CMP_B:%.*]] = icmp eq i32 [[VAL2]], 0
145
+ ; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP_B]], [[CMP_A]]
146
+ ; CHECK-NEXT: ret i1 [[AND]]
147
+ ;
148
+ %val1 = and i16 %a , 15
149
+ %val2 = and i32 %b , 24
150
+ %cmp.a = icmp ne i16 %val1 , 0
151
+ %cmp.b = icmp eq i32 %val2 , 0
152
+ %and = and i1 %cmp.b , %cmp.a
153
+ ret i1 %and
154
+ }
155
+
156
+ ; The last three instructions can be simplified to checking %val1 != %val2.
157
+ ; After that other transformations change the code further.
158
+ define i1 @test8 (i32 %a , i32 %b ) {
159
+ ; CHECK-LABEL: @test8(
160
+ ; CHECK-NEXT: [[TMP1:%.*]] = xor i32 %a, %b
161
+ ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 8
162
+ ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
163
+ ; CHECK-NEXT: ret i1 [[TMP3]]
164
+ ;
165
+ %val1 = and i32 %a , 8
166
+ %val2 = and i32 %b , 8
167
+ %cmp.a = icmp ne i32 %val1 , 0
168
+ %cmp.b = icmp ne i32 %val2 , 0
169
+ %and = xor i1 %cmp.b , %cmp.a
170
+ ret i1 %and
171
+ }
172
+
173
+ ; Operands of and instructions, must be identical powers of 2 otherwise
174
+ ; a simplification, like that of previous testcase is not possible.
175
+ define i1 @test9 (i32 %a , i32 %b ) {
176
+ ; CHECK-LABEL: @test9(
177
+ ; CHECK-NEXT: [[VAL1:%.*]] = and i32 %a, 24
178
+ ; CHECK-NEXT: [[VAL2:%.*]] = and i32 %b, 24
179
+ ; CHECK-NEXT: [[CMP_A:%.*]] = icmp ne i32 [[VAL1]], 0
180
+ ; CHECK-NEXT: [[CMP_B:%.*]] = icmp ne i32 [[VAL2]], 0
181
+ ; CHECK-NEXT: [[AND:%.*]] = xor i1 [[CMP_B]], [[CMP_A]]
182
+ ; CHECK-NEXT: ret i1 [[AND]]
183
+ ;
184
+ %val1 = and i32 %a , 24
185
+ %val2 = and i32 %b , 24
186
+ %cmp.a = icmp ne i32 %val1 , 0
187
+ %cmp.b = icmp ne i32 %val2 , 0
188
+ %and = xor i1 %cmp.b , %cmp.a
189
+ ret i1 %and
190
+ }
191
+
192
+ ; The last three instructions are equivalent of checking %val1 != %val2.
193
+ ; After making this change, other transformation further change the code.
194
+ define i1 @test10 (i32 %a , i32 %b ) {
195
+ ; CHECK-LABEL: @test10(
196
+ ; CHECK-NEXT: [[TMP1:%.*]] = xor i32 %a, %b
197
+ ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 8
198
+ ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
199
+ ; CHECK-NEXT: ret i1 [[TMP3]]
200
+ ;
201
+ %val1 = and i32 %a , 8
202
+ %val2 = and i32 %b , 8
203
+ %cmp.a = icmp eq i32 %val1 , 0
204
+ %cmp.b = icmp eq i32 %val2 , 0
205
+ %and = xor i1 %cmp.b , %cmp.a
206
+ ret i1 %and
207
+ }
208
+
209
+ ; Cannot be simplified because of different width of %a and %b
210
+ define i1 @test11 (i16 %a , i32 %b ) {
211
+ ; CHECK-LABEL: @test11(
212
+ ; CHECK-NEXT: [[VAL1:%.*]] = and i16 %a, 8
213
+ ; CHECK-NEXT: [[VAL2:%.*]] = and i32 %b, 8
214
+ ; CHECK-NEXT: [[CMP_A:%.*]] = icmp ne i16 [[VAL1]], 0
215
+ ; CHECK-NEXT: [[CMP_B:%.*]] = icmp ne i32 [[VAL2]], 0
216
+ ; CHECK-NEXT: [[AND:%.*]] = xor i1 [[CMP_B]], [[CMP_A]]
217
+ ; CHECK-NEXT: ret i1 [[AND]]
218
+ ;
219
+ %val1 = and i16 %a , 8
220
+ %val2 = and i32 %b , 8
221
+ %cmp.a = icmp ne i16 %val1 , 0
222
+ %cmp.b = icmp ne i32 %val2 , 0
223
+ %and = xor i1 %cmp.b , %cmp.a
224
+ ret i1 %and
225
+ }
226
+
227
+ ; Similar to @test8 except that icmp instns use ugt here instead of ne.
228
+ define i1 @test12 (i32 %a , i32 %b ) {
229
+ ; CHECK-LABEL: @test12(
230
+ ; CHECK-NEXT: [[TMP1:%.*]] = xor i32 %a, %b
231
+ ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 8
232
+ ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
233
+ ; CHECK-NEXT: ret i1 [[TMP3]]
234
+ ;
235
+ %val1 = and i32 %a , 8
236
+ %val2 = and i32 %b , 8
237
+ %cmp.a = icmp ugt i32 %val1 , 0
238
+ %cmp.b = icmp ugt i32 %val2 , 0
239
+ %and = xor i1 %cmp.b , %cmp.a
240
+ ret i1 %and
241
+ }
242
+
243
+ ; Similar to @test3 except that the first icmp uses ugt instead of ne.
244
+ define i1 @test13 (i32 %a , i32 %b ) {
245
+ ; CHECK-LABEL: @test13(
246
+ ; CHECK-NEXT: [[VAL1:%.*]] = and i32 %a, 8
247
+ ; CHECK-NEXT: [[VAL2:%.*]] = and i32 %b, 8
248
+ ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[VAL2]], [[VAL1]]
249
+ ; CHECK-NEXT: ret i1 [[TMP1]]
250
+ ;
251
+ %val1 = and i32 %a , 8
252
+ %val2 = and i32 %b , 8
253
+ %cmp.a = icmp ugt i32 %val1 , 0
254
+ %cmp.b = icmp eq i32 %val2 , 0
255
+ %and = and i1 %cmp.a , %cmp.b
256
+ ret i1 %and
257
+ }
0 commit comments