1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 2; RUN: opt -S -passes=instcombine < %s | FileCheck %s 3 4; https://llvm.org/bugs/show_bug.cgi?id=25900 5; An arithmetic shift right of a power of two is not a power 6; of two if the original value is the sign bit. Therefore, 7; we can't transform the sdiv into a udiv. 8 9declare i16 @llvm.bitreverse.i16(i16) 10declare i16 @llvm.bswap.i16(i16) 11declare i16 @llvm.ctpop.i16(i16) 12declare i16 @llvm.fshl.i16(i16, i16, i16) 13declare i16 @llvm.fshr.i16(i16, i16, i16) 14declare i16 @llvm.umax.i16(i16, i16) 15 16define i32 @pr25900(i32 %d) { 17; CHECK-LABEL: define i32 @pr25900 18; CHECK-SAME: (i32 [[D:%.*]]) { 19; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[D]], 31 20; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 4, [[ASHR]] 21; CHECK-NEXT: ret i32 [[DIV]] 22; 23 %and = and i32 %d, -2147483648 24; The next 3 lines prevent another fold from masking the bug. 25 %ext = zext i32 %and to i64 26 %or = or i64 %ext, 4294967296 27 %trunc = trunc i64 %or to i32 28 %ashr = ashr exact i32 %trunc, 31 29 %div = sdiv i32 4, %ashr 30 ret i32 %div 31 32} 33 34define i8 @trunc_is_pow2_or_zero(i16 %x, i8 %y) { 35; CHECK-LABEL: define i8 @trunc_is_pow2_or_zero 36; CHECK-SAME: (i16 [[X:%.*]], i8 [[Y:%.*]]) { 37; CHECK-NEXT: [[XP2:%.*]] = shl i16 4, [[X]] 38; CHECK-NEXT: [[XX:%.*]] = trunc i16 [[XP2]] to i8 39; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[XX]], -1 40; CHECK-NEXT: [[R:%.*]] = and i8 [[Y]], [[TMP1]] 41; CHECK-NEXT: ret i8 [[R]] 42; 43 %xp2 = shl i16 4, %x 44 %xx = trunc i16 %xp2 to i8 45 46 %r = urem i8 %y, %xx 47 ret i8 %r 48} 49 50define i8 @trunc_is_pow2_or_zero_fail(i16 %x, i8 %y) { 51; CHECK-LABEL: define i8 @trunc_is_pow2_or_zero_fail 52; CHECK-SAME: (i16 [[X:%.*]], i8 [[Y:%.*]]) { 53; CHECK-NEXT: [[XP2:%.*]] = shl i16 5, [[X]] 54; CHECK-NEXT: [[XX:%.*]] = trunc i16 [[XP2]] to i8 55; CHECK-NEXT: [[R:%.*]] = urem i8 [[Y]], [[XX]] 56; CHECK-NEXT: ret i8 [[R]] 57; 58 %xp2 = shl i16 5, %x 59 %xx = trunc i16 %xp2 to i8 60 61 %r = urem i8 %y, %xx 62 ret i8 %r 63} 64 65define i1 @trunc_is_pow2_fail(i16 %x, i8 %y) { 66; CHECK-LABEL: define i1 @trunc_is_pow2_fail 67; CHECK-SAME: (i16 [[X:%.*]], i8 [[Y:%.*]]) { 68; CHECK-NEXT: [[XP2:%.*]] = shl i16 4, [[X]] 69; CHECK-NEXT: [[XX:%.*]] = trunc i16 [[XP2]] to i8 70; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y]], [[XX]] 71; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[XX]] 72; CHECK-NEXT: ret i1 [[R]] 73; 74 %xp2 = shl i16 4, %x 75 %xx = trunc i16 %xp2 to i8 76 77 %and = and i8 %y, %xx 78 %r = icmp eq i8 %and, %xx 79 ret i1 %r 80} 81 82define i16 @bswap_is_pow2_or_zero(i16 %x, i16 %y) { 83; CHECK-LABEL: define i16 @bswap_is_pow2_or_zero 84; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 85; CHECK-NEXT: [[XP2:%.*]] = shl i16 4, [[X]] 86; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.bswap.i16(i16 [[XP2]]) 87; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[XX]], -1 88; CHECK-NEXT: [[R:%.*]] = and i16 [[Y]], [[TMP1]] 89; CHECK-NEXT: ret i16 [[R]] 90; 91 %xp2 = shl i16 4, %x 92 %xx = call i16 @llvm.bswap.i16(i16 %xp2) 93 94 %r = urem i16 %y, %xx 95 ret i16 %r 96} 97 98define i16 @bswap_is_pow2_or_zero_fail(i16 %x, i16 %y) { 99; CHECK-LABEL: define i16 @bswap_is_pow2_or_zero_fail 100; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 101; CHECK-NEXT: [[XP2:%.*]] = shl i16 5, [[X]] 102; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.bswap.i16(i16 [[XP2]]) 103; CHECK-NEXT: [[R:%.*]] = urem i16 [[Y]], [[XX]] 104; CHECK-NEXT: ret i16 [[R]] 105; 106 %xp2 = shl i16 5, %x 107 %xx = call i16 @llvm.bswap.i16(i16 %xp2) 108 109 %r = urem i16 %y, %xx 110 ret i16 %r 111} 112 113define i1 @bswap_is_pow2(i16 %x, i16 %y) { 114; CHECK-LABEL: define i1 @bswap_is_pow2 115; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 116; CHECK-NEXT: [[XP2:%.*]] = shl nuw i16 1, [[X]] 117; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.bswap.i16(i16 [[XP2]]) 118; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 119; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0 120; CHECK-NEXT: ret i1 [[R]] 121; 122 %xp2 = shl i16 1, %x 123 %xx = call i16 @llvm.bswap.i16(i16 %xp2) 124 125 %and = and i16 %y, %xx 126 %r = icmp eq i16 %and, %xx 127 ret i1 %r 128} 129 130define i1 @bswap_is_pow2_fail(i16 %x, i16 %y) { 131; CHECK-LABEL: define i1 @bswap_is_pow2_fail 132; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 133; CHECK-NEXT: [[XP2:%.*]] = shl i16 2, [[X]] 134; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.bswap.i16(i16 [[XP2]]) 135; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 136; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]] 137; CHECK-NEXT: ret i1 [[R]] 138; 139 %xp2 = shl i16 2, %x 140 %xx = call i16 @llvm.bswap.i16(i16 %xp2) 141 142 %and = and i16 %y, %xx 143 %r = icmp eq i16 %and, %xx 144 ret i1 %r 145} 146 147define i16 @bitreverse_is_pow2_or_zero(i16 %x, i16 %y) { 148; CHECK-LABEL: define i16 @bitreverse_is_pow2_or_zero 149; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 150; CHECK-NEXT: [[XP2:%.*]] = shl i16 4, [[X]] 151; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.bitreverse.i16(i16 [[XP2]]) 152; CHECK-NEXT: [[TMP1:%.*]] = add nsw i16 [[XX]], -1 153; CHECK-NEXT: [[R:%.*]] = and i16 [[Y]], [[TMP1]] 154; CHECK-NEXT: ret i16 [[R]] 155; 156 %xp2 = shl i16 4, %x 157 %xx = call i16 @llvm.bitreverse.i16(i16 %xp2) 158 159 %r = urem i16 %y, %xx 160 ret i16 %r 161} 162 163define i16 @bitreverse_is_pow2_or_zero_fail(i16 %x, i16 %y) { 164; CHECK-LABEL: define i16 @bitreverse_is_pow2_or_zero_fail 165; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 166; CHECK-NEXT: [[XP2:%.*]] = shl i16 5, [[X]] 167; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.bitreverse.i16(i16 [[XP2]]) 168; CHECK-NEXT: [[R:%.*]] = urem i16 [[Y]], [[XX]] 169; CHECK-NEXT: ret i16 [[R]] 170; 171 %xp2 = shl i16 5, %x 172 %xx = call i16 @llvm.bitreverse.i16(i16 %xp2) 173 174 %r = urem i16 %y, %xx 175 ret i16 %r 176} 177 178define i1 @bitreverse_is_pow2(i16 %x, i16 %y) { 179; CHECK-LABEL: define i1 @bitreverse_is_pow2 180; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 181; CHECK-NEXT: [[XP2:%.*]] = shl nuw i16 1, [[X]] 182; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.bitreverse.i16(i16 [[XP2]]) 183; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 184; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0 185; CHECK-NEXT: ret i1 [[R]] 186; 187 %xp2 = shl i16 1, %x 188 %xx = call i16 @llvm.bitreverse.i16(i16 %xp2) 189 190 %and = and i16 %y, %xx 191 %r = icmp eq i16 %and, %xx 192 ret i1 %r 193} 194 195define i1 @bitreverse_is_pow2_fail(i16 %x, i16 %y) { 196; CHECK-LABEL: define i1 @bitreverse_is_pow2_fail 197; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 198; CHECK-NEXT: [[XP2:%.*]] = shl i16 2, [[X]] 199; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.bitreverse.i16(i16 [[XP2]]) 200; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 201; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]] 202; CHECK-NEXT: ret i1 [[R]] 203; 204 %xp2 = shl i16 2, %x 205 %xx = call i16 @llvm.bitreverse.i16(i16 %xp2) 206 207 %and = and i16 %y, %xx 208 %r = icmp eq i16 %and, %xx 209 ret i1 %r 210} 211 212define i16 @fshl_is_pow2_or_zero(i16 %x, i16 %y, i16 %z) { 213; CHECK-LABEL: define i16 @fshl_is_pow2_or_zero 214; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) { 215; CHECK-NEXT: [[XP2:%.*]] = shl i16 4, [[X]] 216; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.fshl.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]]) 217; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[XX]], -1 218; CHECK-NEXT: [[R:%.*]] = and i16 [[Y]], [[TMP1]] 219; CHECK-NEXT: ret i16 [[R]] 220; 221 %xp2 = shl i16 4, %x 222 %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %xp2, i16 %z) 223 224 %r = urem i16 %y, %xx 225 ret i16 %r 226} 227 228define i16 @fshl_is_pow2_or_zero_fail_not_rotate(i16 %w, i16 %x, i16 %y, i16 %z) { 229; CHECK-LABEL: define i16 @fshl_is_pow2_or_zero_fail_not_rotate 230; CHECK-SAME: (i16 [[W:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) { 231; CHECK-NEXT: [[XP2:%.*]] = shl i16 4, [[X]] 232; CHECK-NEXT: [[WP2:%.*]] = shl i16 2, [[W]] 233; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.fshl.i16(i16 [[XP2]], i16 [[WP2]], i16 [[Z]]) 234; CHECK-NEXT: [[R:%.*]] = urem i16 [[Y]], [[XX]] 235; CHECK-NEXT: ret i16 [[R]] 236; 237 %xp2 = shl i16 4, %x 238 %wp2 = shl i16 2, %w 239 %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %wp2, i16 %z) 240 241 %r = urem i16 %y, %xx 242 ret i16 %r 243} 244 245define i16 @fshl_is_pow2_or_zero_fail(i16 %x, i16 %y, i16 %z) { 246; CHECK-LABEL: define i16 @fshl_is_pow2_or_zero_fail 247; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) { 248; CHECK-NEXT: [[XP2:%.*]] = shl i16 5, [[X]] 249; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.fshl.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]]) 250; CHECK-NEXT: [[R:%.*]] = urem i16 [[Y]], [[XX]] 251; CHECK-NEXT: ret i16 [[R]] 252; 253 %xp2 = shl i16 5, %x 254 %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %xp2, i16 %z) 255 256 %r = urem i16 %y, %xx 257 ret i16 %r 258} 259 260define i1 @fshl_is_pow2(i16 %x, i16 %y, i16 %z) { 261; CHECK-LABEL: define i1 @fshl_is_pow2 262; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) { 263; CHECK-NEXT: [[XP2:%.*]] = shl nuw i16 1, [[X]] 264; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.fshl.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]]) 265; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 266; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0 267; CHECK-NEXT: ret i1 [[R]] 268; 269 %xp2 = shl i16 1, %x 270 %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %xp2, i16 %z) 271 272 %and = and i16 %y, %xx 273 %r = icmp eq i16 %and, %xx 274 ret i1 %r 275} 276 277define i1 @fshl_is_pow2_fail(i16 %x, i16 %y, i16 %z) { 278; CHECK-LABEL: define i1 @fshl_is_pow2_fail 279; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) { 280; CHECK-NEXT: [[XP2:%.*]] = shl i16 2, [[X]] 281; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.fshl.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]]) 282; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 283; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]] 284; CHECK-NEXT: ret i1 [[R]] 285; 286 %xp2 = shl i16 2, %x 287 %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %xp2, i16 %z) 288 289 %and = and i16 %y, %xx 290 %r = icmp eq i16 %and, %xx 291 ret i1 %r 292} 293 294define i16 @fshr_is_pow2_or_zero(i16 %x, i16 %y, i16 %z) { 295; CHECK-LABEL: define i16 @fshr_is_pow2_or_zero 296; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) { 297; CHECK-NEXT: [[XP2:%.*]] = shl i16 4, [[X]] 298; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.fshr.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]]) 299; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[XX]], -1 300; CHECK-NEXT: [[R:%.*]] = and i16 [[Y]], [[TMP1]] 301; CHECK-NEXT: ret i16 [[R]] 302; 303 %xp2 = shl i16 4, %x 304 %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %xp2, i16 %z) 305 306 %r = urem i16 %y, %xx 307 ret i16 %r 308} 309 310define i16 @fshr_is_pow2_or_zero_fail_not_rotate(i16 %w, i16 %x, i16 %y, i16 %z) { 311; CHECK-LABEL: define i16 @fshr_is_pow2_or_zero_fail_not_rotate 312; CHECK-SAME: (i16 [[W:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) { 313; CHECK-NEXT: [[XP2:%.*]] = shl i16 4, [[X]] 314; CHECK-NEXT: [[WP2:%.*]] = shl i16 2, [[W]] 315; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.fshr.i16(i16 [[XP2]], i16 [[WP2]], i16 [[Z]]) 316; CHECK-NEXT: [[R:%.*]] = urem i16 [[Y]], [[XX]] 317; CHECK-NEXT: ret i16 [[R]] 318; 319 %xp2 = shl i16 4, %x 320 %wp2 = shl i16 2, %w 321 %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %wp2, i16 %z) 322 323 %r = urem i16 %y, %xx 324 ret i16 %r 325} 326 327define i16 @fshr_is_pow2_or_zero_fail(i16 %x, i16 %y, i16 %z) { 328; CHECK-LABEL: define i16 @fshr_is_pow2_or_zero_fail 329; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) { 330; CHECK-NEXT: [[XP2:%.*]] = shl i16 5, [[X]] 331; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.fshr.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]]) 332; CHECK-NEXT: [[R:%.*]] = urem i16 [[Y]], [[XX]] 333; CHECK-NEXT: ret i16 [[R]] 334; 335 %xp2 = shl i16 5, %x 336 %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %xp2, i16 %z) 337 338 %r = urem i16 %y, %xx 339 ret i16 %r 340} 341 342define i1 @fshr_is_pow2(i16 %x, i16 %y, i16 %z) { 343; CHECK-LABEL: define i1 @fshr_is_pow2 344; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) { 345; CHECK-NEXT: [[XP2:%.*]] = shl nuw i16 1, [[X]] 346; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.fshr.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]]) 347; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 348; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0 349; CHECK-NEXT: ret i1 [[R]] 350; 351 %xp2 = shl i16 1, %x 352 %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %xp2, i16 %z) 353 354 %and = and i16 %y, %xx 355 %r = icmp eq i16 %and, %xx 356 ret i1 %r 357} 358 359define i1 @fshr_is_pow2_fail(i16 %x, i16 %y, i16 %z) { 360; CHECK-LABEL: define i1 @fshr_is_pow2_fail 361; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) { 362; CHECK-NEXT: [[XP2:%.*]] = shl i16 2, [[X]] 363; CHECK-NEXT: [[XX:%.*]] = call i16 @llvm.fshr.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]]) 364; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 365; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]] 366; CHECK-NEXT: ret i1 [[R]] 367; 368 %xp2 = shl i16 2, %x 369 %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %xp2, i16 %z) 370 371 %and = and i16 %y, %xx 372 %r = icmp eq i16 %and, %xx 373 ret i1 %r 374} 375 376define i16 @mul_is_pow2_or_zero(i16 %x, i16 %y, i16 %z) { 377; CHECK-LABEL: define i16 @mul_is_pow2_or_zero 378; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) { 379; CHECK-NEXT: [[XP2:%.*]] = shl i16 4, [[X]] 380; CHECK-NEXT: [[ZP2:%.*]] = shl i16 2, [[Z]] 381; CHECK-NEXT: [[XX:%.*]] = mul i16 [[XP2]], [[ZP2]] 382; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[XX]], -1 383; CHECK-NEXT: [[R:%.*]] = and i16 [[Y]], [[TMP1]] 384; CHECK-NEXT: ret i16 [[R]] 385; 386 %xp2 = shl i16 4, %x 387 %zp2 = shl i16 2, %z 388 %xx = mul i16 %xp2, %zp2 389 390 %r = urem i16 %y, %xx 391 ret i16 %r 392} 393 394define i16 @mul_is_pow2_or_zero_fail(i16 %x, i16 %y, i16 %z) { 395; CHECK-LABEL: define i16 @mul_is_pow2_or_zero_fail 396; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) { 397; CHECK-NEXT: [[XP2:%.*]] = shl i16 4, [[X]] 398; CHECK-NEXT: [[ZP2:%.*]] = shl i16 5, [[Z]] 399; CHECK-NEXT: [[XX:%.*]] = mul i16 [[XP2]], [[ZP2]] 400; CHECK-NEXT: [[R:%.*]] = urem i16 [[Y]], [[XX]] 401; CHECK-NEXT: ret i16 [[R]] 402; 403 %xp2 = shl i16 4, %x 404 %zp2 = shl i16 5, %z 405 %xx = mul i16 %xp2, %zp2 406 407 %r = urem i16 %y, %xx 408 ret i16 %r 409} 410 411define i1 @mul_is_pow2(i16 %x, i16 %y, i16 %z) { 412; CHECK-LABEL: define i1 @mul_is_pow2 413; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) { 414; CHECK-NEXT: [[XSMALL:%.*]] = and i16 [[X]], 3 415; CHECK-NEXT: [[ZSMALL:%.*]] = and i16 [[Z]], 3 416; CHECK-NEXT: [[ZP2:%.*]] = shl nuw nsw i16 2, [[ZSMALL]] 417; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i16 [[XSMALL]], 2 418; CHECK-NEXT: [[XX:%.*]] = shl nuw nsw i16 [[ZP2]], [[TMP1]] 419; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 420; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0 421; CHECK-NEXT: ret i1 [[R]] 422; 423 %xsmall = and i16 %x, 3 424 %zsmall = and i16 %z, 3 425 %xp2 = shl i16 4, %xsmall 426 %zp2 = shl i16 2, %zsmall 427 %xx = mul i16 %xp2, %zp2 428 429 %and = and i16 %y, %xx 430 %r = icmp eq i16 %and, %xx 431 ret i1 %r 432} 433 434define i1 @mul_is_pow2_fail(i16 %x, i16 %y, i16 %z) { 435; CHECK-LABEL: define i1 @mul_is_pow2_fail 436; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) { 437; CHECK-NEXT: [[XSMALL:%.*]] = and i16 [[X]], 7 438; CHECK-NEXT: [[ZSMALL:%.*]] = and i16 [[Z]], 7 439; CHECK-NEXT: [[ZP2:%.*]] = shl nuw nsw i16 2, [[ZSMALL]] 440; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i16 [[XSMALL]], 2 441; CHECK-NEXT: [[XX:%.*]] = shl i16 [[ZP2]], [[TMP1]] 442; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 443; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]] 444; CHECK-NEXT: ret i1 [[R]] 445; 446 %xsmall = and i16 %x, 7 447 %zsmall = and i16 %z, 7 448 %xp2 = shl i16 4, %xsmall 449 %zp2 = shl i16 2, %zsmall 450 %xx = mul i16 %xp2, %zp2 451 452 %and = and i16 %y, %xx 453 %r = icmp eq i16 %and, %xx 454 ret i1 %r 455} 456 457define i1 @mul_is_pow2_fail2(i16 %x, i16 %y, i16 %z) { 458; CHECK-LABEL: define i1 @mul_is_pow2_fail2 459; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) { 460; CHECK-NEXT: [[XSMALL:%.*]] = and i16 [[X]], 3 461; CHECK-NEXT: [[ZSMALL:%.*]] = and i16 [[Z]], 3 462; CHECK-NEXT: [[XP2:%.*]] = shl nuw nsw i16 3, [[XSMALL]] 463; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i16 [[ZSMALL]], 1 464; CHECK-NEXT: [[XX:%.*]] = shl nuw nsw i16 [[XP2]], [[TMP1]] 465; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 466; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]] 467; CHECK-NEXT: ret i1 [[R]] 468; 469 %xsmall = and i16 %x, 3 470 %zsmall = and i16 %z, 3 471 %xp2 = shl i16 3, %xsmall 472 %zp2 = shl i16 2, %zsmall 473 %xx = mul i16 %xp2, %zp2 474 475 %and = and i16 %y, %xx 476 %r = icmp eq i16 %and, %xx 477 ret i1 %r 478} 479 480define i1 @shl_is_pow2(i16 %x, i16 %y) { 481; CHECK-LABEL: define i1 @shl_is_pow2 482; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 483; CHECK-NEXT: [[XSMALL:%.*]] = and i16 [[X]], 7 484; CHECK-NEXT: [[XX:%.*]] = shl nuw nsw i16 4, [[XSMALL]] 485; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 486; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0 487; CHECK-NEXT: ret i1 [[R]] 488; 489 %xsmall = and i16 %x, 7 490 %xx = shl i16 4, %xsmall 491 492 %and = and i16 %y, %xx 493 %r = icmp eq i16 %and, %xx 494 ret i1 %r 495} 496 497define i1 @shl_is_pow2_fail(i16 %x, i16 %y) { 498; CHECK-LABEL: define i1 @shl_is_pow2_fail 499; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 500; CHECK-NEXT: [[XSMALL:%.*]] = and i16 [[X]], 7 501; CHECK-NEXT: [[XX:%.*]] = shl i16 512, [[XSMALL]] 502; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 503; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]] 504; CHECK-NEXT: ret i1 [[R]] 505; 506 %xsmall = and i16 %x, 7 507 %xx = shl i16 512, %xsmall 508 509 %and = and i16 %y, %xx 510 %r = icmp eq i16 %and, %xx 511 ret i1 %r 512} 513 514define i1 @shl_is_pow2_fail2(i16 %x, i16 %y) { 515; CHECK-LABEL: define i1 @shl_is_pow2_fail2 516; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 517; CHECK-NEXT: [[XSMALL:%.*]] = and i16 [[X]], 7 518; CHECK-NEXT: [[XX:%.*]] = shl nuw nsw i16 5, [[XSMALL]] 519; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 520; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]] 521; CHECK-NEXT: ret i1 [[R]] 522; 523 %xsmall = and i16 %x, 7 524 %xx = shl i16 5, %xsmall 525 526 %and = and i16 %y, %xx 527 %r = icmp eq i16 %and, %xx 528 ret i1 %r 529} 530 531define i1 @lshr_is_pow2(i16 %x, i16 %y) { 532; CHECK-LABEL: define i1 @lshr_is_pow2 533; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 534; CHECK-NEXT: [[XSMALL:%.*]] = and i16 [[X]], 7 535; CHECK-NEXT: [[XX:%.*]] = lshr exact i16 512, [[XSMALL]] 536; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 537; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0 538; CHECK-NEXT: ret i1 [[R]] 539; 540 %xsmall = and i16 %x, 7 541 %xx = lshr i16 512, %xsmall 542 543 %and = and i16 %y, %xx 544 %r = icmp eq i16 %and, %xx 545 ret i1 %r 546} 547 548define i1 @lshr_is_pow2_fail(i16 %x, i16 %y) { 549; CHECK-LABEL: define i1 @lshr_is_pow2_fail 550; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 551; CHECK-NEXT: [[XSMALL:%.*]] = and i16 [[X]], 7 552; CHECK-NEXT: [[XX:%.*]] = lshr i16 4, [[XSMALL]] 553; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 554; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]] 555; CHECK-NEXT: ret i1 [[R]] 556; 557 %xsmall = and i16 %x, 7 558 %xx = lshr i16 4, %xsmall 559 560 %and = and i16 %y, %xx 561 %r = icmp eq i16 %and, %xx 562 ret i1 %r 563} 564 565define i1 @lshr_is_pow2_fail2(i16 %x, i16 %y) { 566; CHECK-LABEL: define i1 @lshr_is_pow2_fail2 567; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 568; CHECK-NEXT: [[XSMALL:%.*]] = and i16 [[X]], 7 569; CHECK-NEXT: [[XX:%.*]] = lshr i16 513, [[XSMALL]] 570; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 571; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]] 572; CHECK-NEXT: ret i1 [[R]] 573; 574 %xsmall = and i16 %x, 7 575 %xx = lshr i16 513, %xsmall 576 577 %and = and i16 %y, %xx 578 %r = icmp eq i16 %and, %xx 579 ret i1 %r 580} 581 582define i1 @and_is_pow2(i16 %x, i16 %y) { 583; CHECK-LABEL: define i1 @and_is_pow2 584; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 585; CHECK-NEXT: [[XNZ:%.*]] = or i16 [[X]], 4 586; CHECK-NEXT: [[X_NEG:%.*]] = sub nsw i16 0, [[XNZ]] 587; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[Y]], [[X_NEG]] 588; CHECK-NEXT: [[AND:%.*]] = and i16 [[TMP1]], [[XNZ]] 589; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0 590; CHECK-NEXT: ret i1 [[R]] 591; 592 %xnz = or i16 %x, 4 593 %x_neg = sub i16 0, %xnz 594 %xx = and i16 %xnz, %x_neg 595 596 %and = and i16 %y, %xx 597 %r = icmp eq i16 %and, %xx 598 ret i1 %r 599} 600 601define i1 @and_is_pow2_fail(i16 %x, i16 %y) { 602; CHECK-LABEL: define i1 @and_is_pow2_fail 603; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { 604; CHECK-NEXT: [[X_NEG:%.*]] = sub i16 0, [[X]] 605; CHECK-NEXT: [[XX:%.*]] = and i16 [[X]], [[X_NEG]] 606; CHECK-NEXT: [[AND:%.*]] = and i16 [[Y]], [[XX]] 607; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]] 608; CHECK-NEXT: ret i1 [[R]] 609; 610 %x_neg = sub i16 0, %x 611 %xx = and i16 %x, %x_neg 612 613 %and = and i16 %y, %xx 614 %r = icmp eq i16 %and, %xx 615 ret i1 %r 616} 617 618define i16 @i1_is_pow2_or_zero(i1 %x, i16 %y) { 619; CHECK-LABEL: define i16 @i1_is_pow2_or_zero 620; CHECK-SAME: (i1 [[X:%.*]], i16 [[Y:%.*]]) { 621; CHECK-NEXT: [[XX:%.*]] = zext i1 [[X]] to i16 622; CHECK-NEXT: [[R:%.*]] = or i16 [[Y]], [[XX]] 623; CHECK-NEXT: ret i16 [[R]] 624; 625 %xx = zext i1 %x to i16 626 %yy = xor i16 %y, %xx 627 %r = call i16 @llvm.umax.i16(i16 %yy, i16 %y) 628 ret i16 %r 629} 630 631define i16 @i1_is_pow2_or_zero2(i1 %x, i16 %y0, i16 %z) { 632; CHECK-LABEL: define i16 @i1_is_pow2_or_zero2 633; CHECK-SAME: (i1 [[X:%.*]], i16 [[Y0:%.*]], i16 [[Z:%.*]]) { 634; CHECK-NEXT: [[XX:%.*]] = zext i1 [[X]] to i16 635; CHECK-NEXT: [[Y:%.*]] = or i16 [[Y0]], [[Z]] 636; CHECK-NEXT: [[R:%.*]] = or i16 [[Y]], [[XX]] 637; CHECK-NEXT: ret i16 [[R]] 638; 639 %xx = zext i1 %x to i16 640 %y = or i16 %y0, %z 641 %yy = xor i16 %y, %xx 642 %r = call i16 @llvm.umax.i16(i16 %yy, i16 %y) 643 ret i16 %r 644} 645