Skip to content

Commit c8bc1ab

Browse files
committed
[InstCombine] Add tests for cttz of lowest set bit (NFC)
1 parent 95075d3 commit c8bc1ab

File tree

1 file changed

+107
-0
lines changed
  • llvm/test/Transforms/InstCombine

1 file changed

+107
-0
lines changed

llvm/test/Transforms/InstCombine/cttz.ll

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
; RUN: opt < %s -S -passes=instcombine | FileCheck %s
33

44
declare i32 @llvm.cttz.i32(i32, i1)
5+
declare i32 @llvm.ctlz.i32(i32, i1)
56
declare <2 x i64> @llvm.cttz.v2i64(<2 x i64>, i1)
67
declare void @use(i32)
78

@@ -118,3 +119,109 @@ define <2 x i64> @cttz_sext_zero_def_vec(<2 x i32> %x) {
118119
%tz = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %s, i1 false)
119120
ret <2 x i64> %tz
120121
}
122+
123+
define i32 @cttz_of_lowest_set_bit(i32 %x) {
124+
; CHECK-LABEL: @cttz_of_lowest_set_bit(
125+
; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[X:%.*]]
126+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[X]]
127+
; CHECK-NEXT: [[TZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[AND]], i1 false), !range [[RNG1]]
128+
; CHECK-NEXT: ret i32 [[TZ]]
129+
;
130+
%sub = sub i32 0, %x
131+
%and = and i32 %sub, %x
132+
%tz = call i32 @llvm.cttz.i32(i32 %and, i1 false)
133+
ret i32 %tz
134+
}
135+
136+
define i32 @cttz_of_lowest_set_bit_commuted(i32 %xx) {
137+
; CHECK-LABEL: @cttz_of_lowest_set_bit_commuted(
138+
; CHECK-NEXT: [[X:%.*]] = udiv i32 42, [[XX:%.*]]
139+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X]]
140+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[SUB]]
141+
; CHECK-NEXT: [[TZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[AND]], i1 false), !range [[RNG1]]
142+
; CHECK-NEXT: ret i32 [[TZ]]
143+
;
144+
%x = udiv i32 42, %xx ; thwart complexity-based canonicalization
145+
%sub = sub i32 0, %x
146+
%and = and i32 %x, %sub
147+
%tz = call i32 @llvm.cttz.i32(i32 %and, i1 false)
148+
ret i32 %tz
149+
}
150+
151+
define i32 @cttz_of_lowest_set_bit_poison_flag(i32 %x) {
152+
; CHECK-LABEL: @cttz_of_lowest_set_bit_poison_flag(
153+
; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[X:%.*]]
154+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[X]]
155+
; CHECK-NEXT: [[TZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[AND]], i1 true), !range [[RNG1]]
156+
; CHECK-NEXT: ret i32 [[TZ]]
157+
;
158+
%sub = sub i32 0, %x
159+
%and = and i32 %sub, %x
160+
%tz = call i32 @llvm.cttz.i32(i32 %and, i1 true)
161+
ret i32 %tz
162+
}
163+
164+
define <2 x i64> @cttz_of_lowest_set_bit_vec(<2 x i64> %x) {
165+
; CHECK-LABEL: @cttz_of_lowest_set_bit_vec(
166+
; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i64> zeroinitializer, [[X:%.*]]
167+
; CHECK-NEXT: [[AND:%.*]] = and <2 x i64> [[SUB]], [[X]]
168+
; CHECK-NEXT: [[TZ:%.*]] = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[AND]], i1 false), !range [[RNG2]]
169+
; CHECK-NEXT: ret <2 x i64> [[TZ]]
170+
;
171+
%sub = sub <2 x i64> zeroinitializer, %x
172+
%and = and <2 x i64> %sub, %x
173+
%tz = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %and, i1 false)
174+
ret <2 x i64> %tz
175+
}
176+
177+
define <2 x i64> @cttz_of_lowest_set_bit_vec_undef(<2 x i64> %x) {
178+
; CHECK-LABEL: @cttz_of_lowest_set_bit_vec_undef(
179+
; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i64> zeroinitializer, [[X:%.*]]
180+
; CHECK-NEXT: [[AND:%.*]] = and <2 x i64> [[SUB]], [[X]]
181+
; CHECK-NEXT: [[TZ:%.*]] = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[AND]], i1 false), !range [[RNG2]]
182+
; CHECK-NEXT: ret <2 x i64> [[TZ]]
183+
;
184+
%sub = sub <2 x i64> zeroinitializer, %x
185+
%and = and <2 x i64> %sub, %x
186+
%tz = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %and, i1 false)
187+
ret <2 x i64> %tz
188+
}
189+
190+
define i32 @cttz_of_lowest_set_bit_wrong_const(i32 %x) {
191+
; CHECK-LABEL: @cttz_of_lowest_set_bit_wrong_const(
192+
; CHECK-NEXT: [[SUB:%.*]] = sub i32 1, [[X:%.*]]
193+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[X]]
194+
; CHECK-NEXT: [[TZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[AND]], i1 false), !range [[RNG3:![0-9]+]]
195+
; CHECK-NEXT: ret i32 [[TZ]]
196+
;
197+
%sub = sub i32 1, %x
198+
%and = and i32 %sub, %x
199+
%tz = call i32 @llvm.cttz.i32(i32 %and, i1 false)
200+
ret i32 %tz
201+
}
202+
203+
define i32 @cttz_of_lowest_set_bit_wrong_operand(i32 %x, i32 %y) {
204+
; CHECK-LABEL: @cttz_of_lowest_set_bit_wrong_operand(
205+
; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[Y:%.*]]
206+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[X:%.*]]
207+
; CHECK-NEXT: [[TZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[AND]], i1 false), !range [[RNG1]]
208+
; CHECK-NEXT: ret i32 [[TZ]]
209+
;
210+
%sub = sub i32 0, %y
211+
%and = and i32 %sub, %x
212+
%tz = call i32 @llvm.cttz.i32(i32 %and, i1 false)
213+
ret i32 %tz
214+
}
215+
216+
define i32 @cttz_of_lowest_set_bit_wrong_intrinsic(i32 %x) {
217+
; CHECK-LABEL: @cttz_of_lowest_set_bit_wrong_intrinsic(
218+
; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[X:%.*]]
219+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[X]]
220+
; CHECK-NEXT: [[TZ:%.*]] = call i32 @llvm.ctlz.i32(i32 [[AND]], i1 false), !range [[RNG1]]
221+
; CHECK-NEXT: ret i32 [[TZ]]
222+
;
223+
%sub = sub i32 0, %x
224+
%and = and i32 %sub, %x
225+
%tz = call i32 @llvm.ctlz.i32(i32 %and, i1 false)
226+
ret i32 %tz
227+
}

0 commit comments

Comments
 (0)