|
2 | 2 | ; RUN: opt < %s -S -passes=instcombine | FileCheck %s
|
3 | 3 |
|
4 | 4 | declare i32 @llvm.cttz.i32(i32, i1)
|
| 5 | +declare i32 @llvm.ctlz.i32(i32, i1) |
5 | 6 | declare <2 x i64> @llvm.cttz.v2i64(<2 x i64>, i1)
|
6 | 7 | declare void @use(i32)
|
7 | 8 |
|
@@ -118,3 +119,109 @@ define <2 x i64> @cttz_sext_zero_def_vec(<2 x i32> %x) {
|
118 | 119 | %tz = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %s, i1 false)
|
119 | 120 | ret <2 x i64> %tz
|
120 | 121 | }
|
| 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