1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=instcombine -S < %s | FileCheck %s 3 4target datalayout = "e-m:e-i64:64-n8:16:32:64" 5 6declare i32 @llvm.bswap.i32(i32) 7declare i128 @llvm.bswap.i128(i128) 8declare <2 x i64> @llvm.bswap.v2i64(<2 x i64>) 9declare i32 @llvm.cttz.i32(i32, i1) nounwind readnone 10declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone 11declare i32 @llvm.ctpop.i32(i32) nounwind readnone 12declare <2 x i8> @llvm.cttz.v2i8(<2 x i8>, i1) nounwind readnone 13declare <2 x i8> @llvm.ctlz.v2i8(<2 x i8>, i1) nounwind readnone 14declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) nounwind readnone 15 16declare void @use(i32) 17declare void @usevec(<3 x i14>) 18 19define i32 @lshr_ctlz_zero_is_not_undef(i32 %x) { 20; CHECK-LABEL: @lshr_ctlz_zero_is_not_undef( 21; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 0 22; CHECK-NEXT: [[SH:%.*]] = zext i1 [[TMP1]] to i32 23; CHECK-NEXT: ret i32 [[SH]] 24; 25 %ct = call i32 @llvm.ctlz.i32(i32 %x, i1 false) 26 %sh = lshr i32 %ct, 5 27 ret i32 %sh 28} 29 30define i32 @lshr_cttz_zero_is_not_undef(i32 %x) { 31; CHECK-LABEL: @lshr_cttz_zero_is_not_undef( 32; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 0 33; CHECK-NEXT: [[SH:%.*]] = zext i1 [[TMP1]] to i32 34; CHECK-NEXT: ret i32 [[SH]] 35; 36 %ct = call i32 @llvm.cttz.i32(i32 %x, i1 false) 37 %sh = lshr i32 %ct, 5 38 ret i32 %sh 39} 40 41define i32 @lshr_ctpop(i32 %x) { 42; CHECK-LABEL: @lshr_ctpop( 43; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], -1 44; CHECK-NEXT: [[SH:%.*]] = zext i1 [[TMP1]] to i32 45; CHECK-NEXT: ret i32 [[SH]] 46; 47 %ct = call i32 @llvm.ctpop.i32(i32 %x) 48 %sh = lshr i32 %ct, 5 49 ret i32 %sh 50} 51 52define <2 x i8> @lshr_ctlz_zero_is_not_undef_splat_vec(<2 x i8> %x) { 53; CHECK-LABEL: @lshr_ctlz_zero_is_not_undef_splat_vec( 54; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer 55; CHECK-NEXT: [[SH:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8> 56; CHECK-NEXT: ret <2 x i8> [[SH]] 57; 58 %ct = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %x, i1 false) 59 %sh = lshr <2 x i8> %ct, <i8 3, i8 3> 60 ret <2 x i8> %sh 61} 62 63define <2 x i8> @lshr_cttz_zero_is_not_undef_splat_vec(<2 x i8> %x) { 64; CHECK-LABEL: @lshr_cttz_zero_is_not_undef_splat_vec( 65; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer 66; CHECK-NEXT: [[SH:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8> 67; CHECK-NEXT: ret <2 x i8> [[SH]] 68; 69 %ct = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %x, i1 false) 70 %sh = lshr <2 x i8> %ct, <i8 3, i8 3> 71 ret <2 x i8> %sh 72} 73 74define <2 x i8> @lshr_ctpop_splat_vec(<2 x i8> %x) { 75; CHECK-LABEL: @lshr_ctpop_splat_vec( 76; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], splat (i8 -1) 77; CHECK-NEXT: [[SH:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8> 78; CHECK-NEXT: ret <2 x i8> [[SH]] 79; 80 %ct = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x) 81 %sh = lshr <2 x i8> %ct, <i8 3, i8 3> 82 ret <2 x i8> %sh 83} 84 85define i32 @lshr_ctlz_zero_is_undef(i32 %x) { 86; CHECK-LABEL: @lshr_ctlz_zero_is_undef( 87; CHECK-NEXT: ret i32 0 88; 89 %ct = call i32 @llvm.ctlz.i32(i32 %x, i1 true) 90 %sh = lshr i32 %ct, 5 91 ret i32 %sh 92} 93 94define i32 @lshr_cttz_zero_is_undef(i32 %x) { 95; CHECK-LABEL: @lshr_cttz_zero_is_undef( 96; CHECK-NEXT: ret i32 0 97; 98 %ct = call i32 @llvm.cttz.i32(i32 %x, i1 true) 99 %sh = lshr i32 %ct, 5 100 ret i32 %sh 101} 102 103define <2 x i8> @lshr_ctlz_zero_is_undef_splat_vec(<2 x i8> %x) { 104; CHECK-LABEL: @lshr_ctlz_zero_is_undef_splat_vec( 105; CHECK-NEXT: ret <2 x i8> zeroinitializer 106; 107 %ct = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %x, i1 true) 108 %sh = lshr <2 x i8> %ct, <i8 3, i8 3> 109 ret <2 x i8> %sh 110} 111 112define i8 @lshr_ctlz_zero_is_undef_vec(<2 x i8> %x) { 113; CHECK-LABEL: @lshr_ctlz_zero_is_undef_vec( 114; CHECK-NEXT: ret i8 0 115; 116 %ct = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %x, i1 true) 117 %sh = lshr <2 x i8> %ct, <i8 3, i8 0> 118 %ex = extractelement <2 x i8> %sh, i32 0 119 ret i8 %ex 120} 121 122define <2 x i8> @lshr_cttz_zero_is_undef_splat_vec(<2 x i8> %x) { 123; CHECK-LABEL: @lshr_cttz_zero_is_undef_splat_vec( 124; CHECK-NEXT: ret <2 x i8> zeroinitializer 125; 126 %ct = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %x, i1 true) 127 %sh = lshr <2 x i8> %ct, <i8 3, i8 3> 128 ret <2 x i8> %sh 129} 130 131define i8 @lshr_cttz_zero_is_undef_vec(<2 x i8> %x) { 132; CHECK-LABEL: @lshr_cttz_zero_is_undef_vec( 133; CHECK-NEXT: ret i8 0 134; 135 %ct = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %x, i1 true) 136 %sh = lshr <2 x i8> %ct, <i8 3, i8 0> 137 %ex = extractelement <2 x i8> %sh, i32 0 138 ret i8 %ex 139} 140 141 142define i8 @lshr_exact(i8 %x) { 143; CHECK-LABEL: @lshr_exact( 144; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X:%.*]], 1 145; CHECK-NEXT: [[LSHR:%.*]] = and i8 [[TMP1]], 63 146; CHECK-NEXT: ret i8 [[LSHR]] 147; 148 %shl = shl i8 %x, 2 149 %add = add i8 %shl, 4 150 %lshr = lshr i8 %add, 2 151 ret i8 %lshr 152} 153 154define <2 x i8> @lshr_exact_splat_vec(<2 x i8> %x) { 155; CHECK-LABEL: @lshr_exact_splat_vec( 156; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], splat (i8 1) 157; CHECK-NEXT: [[LSHR:%.*]] = and <2 x i8> [[TMP1]], splat (i8 63) 158; CHECK-NEXT: ret <2 x i8> [[LSHR]] 159; 160 %shl = shl <2 x i8> %x, <i8 2, i8 2> 161 %add = add <2 x i8> %shl, <i8 4, i8 4> 162 %lshr = lshr <2 x i8> %add, <i8 2, i8 2> 163 ret <2 x i8> %lshr 164} 165 166define <2 x i8> @lshr_exact_splat_vec_nuw(<2 x i8> %x) { 167; CHECK-LABEL: @lshr_exact_splat_vec_nuw( 168; CHECK-NEXT: [[LSHR:%.*]] = add nuw <2 x i8> [[X:%.*]], splat (i8 1) 169; CHECK-NEXT: ret <2 x i8> [[LSHR]] 170; 171 %shl = shl nuw <2 x i8> %x, <i8 2, i8 2> 172 %add = add nuw <2 x i8> %shl, <i8 4, i8 4> 173 %lshr = lshr <2 x i8> %add, <i8 2, i8 2> 174 ret <2 x i8> %lshr 175} 176 177define i8 @shl_add(i8 %x, i8 %y) { 178; CHECK-LABEL: @shl_add( 179; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 [[Y:%.*]], 2 180; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], [[X:%.*]] 181; CHECK-NEXT: [[R:%.*]] = and i8 [[TMP2]], 63 182; CHECK-NEXT: ret i8 [[R]] 183; 184 %l = shl i8 %x, 2 185 %a = add i8 %l, %y 186 %r = lshr i8 %a, 2 187 ret i8 %r 188} 189 190define <2 x i8> @shl_add_commute_vec(<2 x i8> %x, <2 x i8> %py) { 191; CHECK-LABEL: @shl_add_commute_vec( 192; CHECK-NEXT: [[Y:%.*]] = mul <2 x i8> [[PY:%.*]], [[PY]] 193; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i8> [[Y]], splat (i8 3) 194; CHECK-NEXT: [[TMP2:%.*]] = add <2 x i8> [[TMP1]], [[X:%.*]] 195; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[TMP2]], splat (i8 31) 196; CHECK-NEXT: ret <2 x i8> [[R]] 197; 198 %y = mul <2 x i8> %py, %py ; thwart complexity-based canonicalization 199 %l = shl <2 x i8> %x, <i8 3, i8 3> 200 %a = add <2 x i8> %y, %l 201 %r = lshr <2 x i8> %a, <i8 3, i8 3> 202 ret <2 x i8> %r 203} 204 205define i32 @shl_add_use1(i32 %x, i32 %y) { 206; CHECK-LABEL: @shl_add_use1( 207; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 2 208; CHECK-NEXT: call void @use(i32 [[L]]) 209; CHECK-NEXT: [[A:%.*]] = add i32 [[L]], [[Y:%.*]] 210; CHECK-NEXT: [[R:%.*]] = lshr i32 [[A]], 2 211; CHECK-NEXT: ret i32 [[R]] 212; 213 %l = shl i32 %x, 2 214 call void @use(i32 %l) 215 %a = add i32 %l, %y 216 %r = lshr i32 %a, 2 217 ret i32 %r 218} 219 220define i32 @shl_add_use2(i32 %x, i32 %y) { 221; CHECK-LABEL: @shl_add_use2( 222; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 2 223; CHECK-NEXT: [[A:%.*]] = add i32 [[L]], [[Y:%.*]] 224; CHECK-NEXT: call void @use(i32 [[A]]) 225; CHECK-NEXT: [[R:%.*]] = lshr i32 [[A]], 2 226; CHECK-NEXT: ret i32 [[R]] 227; 228 %l = shl i32 %x, 2 229 %a = add i32 %l, %y 230 call void @use(i32 %a) 231 %r = lshr i32 %a, 2 232 ret i32 %r 233} 234 235define i16 @bool_zext(i1 %x) { 236; CHECK-LABEL: @bool_zext( 237; CHECK-NEXT: [[HIBIT:%.*]] = zext i1 [[X:%.*]] to i16 238; CHECK-NEXT: ret i16 [[HIBIT]] 239; 240 %sext = sext i1 %x to i16 241 %hibit = lshr i16 %sext, 15 242 ret i16 %hibit 243} 244 245define i32 @bool_zext_use(i1 %x) { 246; CHECK-LABEL: @bool_zext_use( 247; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[X:%.*]] to i32 248; CHECK-NEXT: call void @use(i32 [[SEXT]]) 249; CHECK-NEXT: [[HIBIT:%.*]] = zext i1 [[X]] to i32 250; CHECK-NEXT: ret i32 [[HIBIT]] 251; 252 %sext = sext i1 %x to i32 253 call void @use(i32 %sext) 254 %hibit = lshr i32 %sext, 31 255 ret i32 %hibit 256} 257 258define <2 x i8> @bool_zext_splat(<2 x i1> %x) { 259; CHECK-LABEL: @bool_zext_splat( 260; CHECK-NEXT: [[HIBIT:%.*]] = zext <2 x i1> [[X:%.*]] to <2 x i8> 261; CHECK-NEXT: ret <2 x i8> [[HIBIT]] 262; 263 %sext = sext <2 x i1> %x to <2 x i8> 264 %hibit = lshr <2 x i8> %sext, <i8 7, i8 7> 265 ret <2 x i8> %hibit 266} 267 268define i32 @smear_sign_and_widen(i8 %x) { 269; CHECK-LABEL: @smear_sign_and_widen( 270; CHECK-NEXT: [[TMP1:%.*]] = ashr i8 [[X:%.*]], 7 271; CHECK-NEXT: [[HIBIT:%.*]] = zext i8 [[TMP1]] to i32 272; CHECK-NEXT: ret i32 [[HIBIT]] 273; 274 %sext = sext i8 %x to i32 275 %hibit = lshr i32 %sext, 24 276 ret i32 %hibit 277} 278 279define i16 @smear_sign_and_widen_should_not_change_type(i4 %x) { 280; CHECK-LABEL: @smear_sign_and_widen_should_not_change_type( 281; CHECK-NEXT: [[SEXT:%.*]] = sext i4 [[X:%.*]] to i16 282; CHECK-NEXT: [[HIBIT:%.*]] = lshr i16 [[SEXT]], 12 283; CHECK-NEXT: ret i16 [[HIBIT]] 284; 285 %sext = sext i4 %x to i16 286 %hibit = lshr i16 %sext, 12 287 ret i16 %hibit 288} 289 290define <2 x i8> @smear_sign_and_widen_splat(<2 x i6> %x) { 291; CHECK-LABEL: @smear_sign_and_widen_splat( 292; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i6> [[X:%.*]], splat (i6 2) 293; CHECK-NEXT: [[HIBIT:%.*]] = zext <2 x i6> [[TMP1]] to <2 x i8> 294; CHECK-NEXT: ret <2 x i8> [[HIBIT]] 295; 296 %sext = sext <2 x i6> %x to <2 x i8> 297 %hibit = lshr <2 x i8> %sext, <i8 2, i8 2> 298 ret <2 x i8> %hibit 299} 300 301define i18 @fake_sext(i3 %x) { 302; CHECK-LABEL: @fake_sext( 303; CHECK-NEXT: [[TMP1:%.*]] = lshr i3 [[X:%.*]], 2 304; CHECK-NEXT: [[SH:%.*]] = zext nneg i3 [[TMP1]] to i18 305; CHECK-NEXT: ret i18 [[SH]] 306; 307 %sext = sext i3 %x to i18 308 %sh = lshr i18 %sext, 17 309 ret i18 %sh 310} 311 312; Avoid the transform if it would change the shift from a legal to illegal type. 313 314define i32 @fake_sext_but_should_not_change_type(i3 %x) { 315; CHECK-LABEL: @fake_sext_but_should_not_change_type( 316; CHECK-NEXT: [[SEXT:%.*]] = sext i3 [[X:%.*]] to i32 317; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[SEXT]], 31 318; CHECK-NEXT: ret i32 [[SH]] 319; 320 %sext = sext i3 %x to i32 321 %sh = lshr i32 %sext, 31 322 ret i32 %sh 323} 324 325define <2 x i8> @fake_sext_splat(<2 x i3> %x) { 326; CHECK-LABEL: @fake_sext_splat( 327; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i3> [[X:%.*]], splat (i3 2) 328; CHECK-NEXT: [[SH:%.*]] = zext nneg <2 x i3> [[TMP1]] to <2 x i8> 329; CHECK-NEXT: ret <2 x i8> [[SH]] 330; 331 %sext = sext <2 x i3> %x to <2 x i8> 332 %sh = lshr <2 x i8> %sext, <i8 7, i8 7> 333 ret <2 x i8> %sh 334} 335 336; Use a narrow shift: lshr (zext iM X to iN), C --> zext (lshr X, C) to iN 337 338define <2 x i32> @narrow_lshr_constant(<2 x i8> %x, <2 x i8> %y) { 339; CHECK-LABEL: @narrow_lshr_constant( 340; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i8> [[X:%.*]], splat (i8 3) 341; CHECK-NEXT: [[SH:%.*]] = zext nneg <2 x i8> [[TMP1]] to <2 x i32> 342; CHECK-NEXT: ret <2 x i32> [[SH]] 343; 344 %zx = zext <2 x i8> %x to <2 x i32> 345 %sh = lshr <2 x i32> %zx, <i32 3, i32 3> 346 ret <2 x i32> %sh 347} 348 349define i32 @mul_splat_fold(i32 %x) { 350; CHECK-LABEL: @mul_splat_fold( 351; CHECK-NEXT: ret i32 [[X:%.*]] 352; 353 %m = mul nuw i32 %x, 65537 354 %t = lshr i32 %m, 16 355 ret i32 %t 356} 357 358; Vector type, extra use, weird types are all ok. 359 360define <3 x i14> @mul_splat_fold_vec(<3 x i14> %x) { 361; CHECK-LABEL: @mul_splat_fold_vec( 362; CHECK-NEXT: [[M:%.*]] = mul nuw <3 x i14> [[X:%.*]], splat (i14 129) 363; CHECK-NEXT: call void @usevec(<3 x i14> [[M]]) 364; CHECK-NEXT: ret <3 x i14> [[X]] 365; 366 %m = mul nuw <3 x i14> %x, <i14 129, i14 129, i14 129> 367 call void @usevec(<3 x i14> %m) 368 %t = lshr <3 x i14> %m, <i14 7, i14 7, i14 7> 369 ret <3 x i14> %t 370} 371 372define i32 @shl_add_lshr_flag_preservation(i32 %x, i32 %c, i32 %y) { 373; CHECK-LABEL: @shl_add_lshr_flag_preservation( 374; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]] 375; CHECK-NEXT: [[LSHR:%.*]] = add nuw nsw i32 [[TMP1]], [[X:%.*]] 376; CHECK-NEXT: ret i32 [[LSHR]] 377; 378 %shl = shl nuw i32 %x, %c 379 %add = add nuw nsw i32 %shl, %y 380 %lshr = lshr exact i32 %add, %c 381 ret i32 %lshr 382} 383 384define i32 @shl_add_lshr(i32 %x, i32 %c, i32 %y) { 385; CHECK-LABEL: @shl_add_lshr( 386; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]] 387; CHECK-NEXT: [[LSHR:%.*]] = add nuw i32 [[TMP1]], [[X:%.*]] 388; CHECK-NEXT: ret i32 [[LSHR]] 389; 390 %shl = shl nuw i32 %x, %c 391 %add = add nuw i32 %shl, %y 392 %lshr = lshr i32 %add, %c 393 ret i32 %lshr 394} 395 396define i32 @shl_add_lshr_comm(i32 %x, i32 %c, i32 %y) { 397; CHECK-LABEL: @shl_add_lshr_comm( 398; CHECK-NEXT: [[Y2:%.*]] = mul i32 [[Y:%.*]], [[Y]] 399; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y2]], [[C:%.*]] 400; CHECK-NEXT: [[LSHR:%.*]] = add nuw i32 [[TMP1]], [[X:%.*]] 401; CHECK-NEXT: ret i32 [[LSHR]] 402; 403 %shl = shl nuw i32 %x, %c 404 %y2 = mul i32 %y, %y ; thwart complexity-based canonicalization 405 %add = add nuw i32 %y2, %shl 406 %lshr = lshr i32 %add, %c 407 ret i32 %lshr 408} 409 410; Negative test 411 412define i32 @shl_add_lshr_no_nuw(i32 %x, i32 %c, i32 %y) { 413; CHECK-LABEL: @shl_add_lshr_no_nuw( 414; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]] 415; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SHL]], [[Y:%.*]] 416; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[ADD]], [[C]] 417; CHECK-NEXT: ret i32 [[LSHR]] 418; 419 %shl = shl nuw i32 %x, %c 420 %add = add i32 %shl, %y 421 %lshr = lshr i32 %add, %c 422 ret i32 %lshr 423} 424 425; Negative test 426 427define i32 @shl_sub_lshr_not_exact(i32 %x, i32 %c, i32 %y) { 428; CHECK-LABEL: @shl_sub_lshr_not_exact( 429; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]] 430; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[SHL]], [[Y:%.*]] 431; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[SUB]], [[C]] 432; CHECK-NEXT: ret i32 [[LSHR]] 433; 434 %shl = shl nuw i32 %x, %c 435 %sub = sub nuw i32 %shl, %y 436 %lshr = lshr i32 %sub, %c 437 ret i32 %lshr 438} 439 440; Negative test 441 442define i32 @shl_sub_lshr_no_nuw(i32 %x, i32 %c, i32 %y) { 443; CHECK-LABEL: @shl_sub_lshr_no_nuw( 444; CHECK-NEXT: [[SHL:%.*]] = shl nsw i32 [[X:%.*]], [[C:%.*]] 445; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[SHL]], [[Y:%.*]] 446; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]] 447; CHECK-NEXT: ret i32 [[LSHR]] 448; 449 %shl = shl nsw i32 %x, %c 450 %sub = sub nsw i32 %shl, %y 451 %lshr = lshr exact i32 %sub, %c 452 ret i32 %lshr 453} 454 455define i32 @shl_sub_lshr(i32 %x, i32 %c, i32 %y) { 456; CHECK-LABEL: @shl_sub_lshr( 457; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]] 458; CHECK-NEXT: [[LSHR:%.*]] = sub nuw nsw i32 [[X:%.*]], [[TMP1]] 459; CHECK-NEXT: ret i32 [[LSHR]] 460; 461 %shl = shl nuw i32 %x, %c 462 %sub = sub nuw nsw i32 %shl, %y 463 %lshr = lshr exact i32 %sub, %c 464 ret i32 %lshr 465} 466 467define i32 @shl_sub_lshr_reverse(i32 %x, i32 %c, i32 %y) { 468; CHECK-LABEL: @shl_sub_lshr_reverse( 469; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]] 470; CHECK-NEXT: [[LSHR:%.*]] = sub nuw nsw i32 [[TMP1]], [[X:%.*]] 471; CHECK-NEXT: ret i32 [[LSHR]] 472; 473 %shl = shl nuw i32 %x, %c 474 %sub = sub nuw nsw i32 %y, %shl 475 %lshr = lshr exact i32 %sub, %c 476 ret i32 %lshr 477} 478 479define i32 @shl_sub_lshr_reverse_no_nsw(i32 %x, i32 %c, i32 %y) { 480; CHECK-LABEL: @shl_sub_lshr_reverse_no_nsw( 481; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]] 482; CHECK-NEXT: [[LSHR:%.*]] = sub nuw i32 [[TMP1]], [[X:%.*]] 483; CHECK-NEXT: ret i32 [[LSHR]] 484; 485 %shl = shl nuw i32 %x, %c 486 %sub = sub nuw i32 %y, %shl 487 %lshr = lshr exact i32 %sub, %c 488 ret i32 %lshr 489} 490 491define i32 @shl_sub_lshr_reverse_nsw_on_op1(i32 %x, i32 %c, i32 %y) { 492; CHECK-LABEL: @shl_sub_lshr_reverse_nsw_on_op1( 493; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]] 494; CHECK-NEXT: [[LSHR:%.*]] = sub nuw i32 [[TMP1]], [[X:%.*]] 495; CHECK-NEXT: ret i32 [[LSHR]] 496; 497 %shl = shl nuw nsw i32 %x, %c 498 %sub = sub nuw i32 %y, %shl 499 %lshr = lshr exact i32 %sub, %c 500 ret i32 %lshr 501} 502 503; Negative test 504 505define i32 @shl_sub_lshr_reverse_no_exact(i32 %x, i32 %c, i32 %y) { 506; CHECK-LABEL: @shl_sub_lshr_reverse_no_exact( 507; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]] 508; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[Y:%.*]], [[SHL]] 509; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[SUB]], [[C]] 510; CHECK-NEXT: ret i32 [[LSHR]] 511; 512 %shl = shl nuw i32 %x, %c 513 %sub = sub nuw nsw i32 %y, %shl 514 %lshr = lshr i32 %sub, %c 515 ret i32 %lshr 516} 517 518; Negative test 519 520define i32 @shl_sub_lshr_reverse_multiuse(i32 %x, i32 %c, i32 %y) { 521; CHECK-LABEL: @shl_sub_lshr_reverse_multiuse( 522; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]] 523; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[Y:%.*]], [[SHL]] 524; CHECK-NEXT: call void @use(i32 [[SUB]]) 525; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]] 526; CHECK-NEXT: ret i32 [[LSHR]] 527; 528 %shl = shl nuw i32 %x, %c 529 %sub = sub nuw i32 %y, %shl 530 call void @use(i32 %sub) 531 %lshr = lshr exact i32 %sub, %c 532 ret i32 %lshr 533} 534 535define i32 @shl_sub_lshr_reverse_multiuse2(i32 %x, i32 %c, i32 %y) { 536; CHECK-LABEL: @shl_sub_lshr_reverse_multiuse2( 537; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]] 538; CHECK-NEXT: call void @use(i32 [[SHL]]) 539; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C]] 540; CHECK-NEXT: [[LSHR:%.*]] = sub nuw i32 [[TMP1]], [[X]] 541; CHECK-NEXT: ret i32 [[LSHR]] 542; 543 %shl = shl nuw i32 %x, %c 544 call void @use(i32 %shl) 545 %sub = sub nuw i32 %y, %shl 546 %lshr = lshr exact i32 %sub, %c 547 ret i32 %lshr 548} 549 550; Negative test 551 552define i32 @shl_sub_lshr_reverse_no_nuw(i32 %x, i32 %c, i32 %y) { 553; CHECK-LABEL: @shl_sub_lshr_reverse_no_nuw( 554; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], [[C:%.*]] 555; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[Y:%.*]], [[SHL]] 556; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]] 557; CHECK-NEXT: ret i32 [[LSHR]] 558; 559 %shl = shl i32 %x, %c 560 %sub = sub nuw i32 %y, %shl 561 %lshr = lshr exact i32 %sub, %c 562 ret i32 %lshr 563} 564 565; Negative test 566 567define i32 @shl_sub_lshr_reverse_no_nsw_2(i32 %x, i32 %c, i32 %y) { 568; CHECK-LABEL: @shl_sub_lshr_reverse_no_nsw_2( 569; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i32 [[X:%.*]], [[C:%.*]] 570; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[Y:%.*]], [[SHL]] 571; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]] 572; CHECK-NEXT: ret i32 [[LSHR]] 573; 574 %shl = shl nuw nsw i32 %x, %c 575 %sub = sub i32 %y, %shl 576 %lshr = lshr exact i32 %sub, %c 577 ret i32 %lshr 578} 579 580define i32 @shl_or_lshr(i32 %x, i32 %c, i32 %y) { 581; CHECK-LABEL: @shl_or_lshr( 582; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]] 583; CHECK-NEXT: [[LSHR:%.*]] = or i32 [[TMP1]], [[X:%.*]] 584; CHECK-NEXT: ret i32 [[LSHR]] 585; 586 %shl = shl nuw i32 %x, %c 587 %or = or i32 %shl, %y 588 %lshr = lshr i32 %or, %c 589 ret i32 %lshr 590} 591 592define i32 @shl_or_disjoint_lshr(i32 %x, i32 %c, i32 %y) { 593; CHECK-LABEL: @shl_or_disjoint_lshr( 594; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]] 595; CHECK-NEXT: [[LSHR:%.*]] = or disjoint i32 [[TMP1]], [[X:%.*]] 596; CHECK-NEXT: ret i32 [[LSHR]] 597; 598 %shl = shl nuw i32 %x, %c 599 %or = or disjoint i32 %shl, %y 600 %lshr = lshr i32 %or, %c 601 ret i32 %lshr 602} 603 604define i32 @shl_or_lshr_comm(i32 %x, i32 %c, i32 %y) { 605; CHECK-LABEL: @shl_or_lshr_comm( 606; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]] 607; CHECK-NEXT: [[LSHR:%.*]] = or i32 [[TMP1]], [[X:%.*]] 608; CHECK-NEXT: ret i32 [[LSHR]] 609; 610 %shl = shl nuw i32 %x, %c 611 %or = or i32 %y, %shl 612 %lshr = lshr i32 %or, %c 613 ret i32 %lshr 614} 615 616define i32 @shl_or_disjoint_lshr_comm(i32 %x, i32 %c, i32 %y) { 617; CHECK-LABEL: @shl_or_disjoint_lshr_comm( 618; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]] 619; CHECK-NEXT: [[LSHR:%.*]] = or disjoint i32 [[TMP1]], [[X:%.*]] 620; CHECK-NEXT: ret i32 [[LSHR]] 621; 622 %shl = shl nuw i32 %x, %c 623 %or = or disjoint i32 %y, %shl 624 %lshr = lshr i32 %or, %c 625 ret i32 %lshr 626} 627 628define i32 @shl_xor_lshr(i32 %x, i32 %c, i32 %y) { 629; CHECK-LABEL: @shl_xor_lshr( 630; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]] 631; CHECK-NEXT: [[LSHR:%.*]] = xor i32 [[TMP1]], [[X:%.*]] 632; CHECK-NEXT: ret i32 [[LSHR]] 633; 634 %shl = shl nuw i32 %x, %c 635 %xor = xor i32 %shl, %y 636 %lshr = lshr i32 %xor, %c 637 ret i32 %lshr 638} 639 640define i32 @shl_xor_lshr_comm(i32 %x, i32 %c, i32 %y) { 641; CHECK-LABEL: @shl_xor_lshr_comm( 642; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]] 643; CHECK-NEXT: [[LSHR:%.*]] = xor i32 [[TMP1]], [[X:%.*]] 644; CHECK-NEXT: ret i32 [[LSHR]] 645; 646 %shl = shl nuw i32 %x, %c 647 %xor = xor i32 %y, %shl 648 %lshr = lshr i32 %xor, %c 649 ret i32 %lshr 650} 651 652define i32 @shl_and_lshr(i32 %x, i32 %c, i32 %y) { 653; CHECK-LABEL: @shl_and_lshr( 654; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]] 655; CHECK-NEXT: [[LSHR:%.*]] = and i32 [[TMP1]], [[X:%.*]] 656; CHECK-NEXT: ret i32 [[LSHR]] 657; 658 %shl = shl nuw i32 %x, %c 659 %and = and i32 %shl, %y 660 %lshr = lshr i32 %and, %c 661 ret i32 %lshr 662} 663 664define i32 @shl_and_lshr_comm(i32 %x, i32 %c, i32 %y) { 665; CHECK-LABEL: @shl_and_lshr_comm( 666; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]] 667; CHECK-NEXT: [[LSHR:%.*]] = and i32 [[TMP1]], [[X:%.*]] 668; CHECK-NEXT: ret i32 [[LSHR]] 669; 670 %shl = shl nuw i32 %x, %c 671 %and = and i32 %y, %shl 672 %lshr = lshr i32 %and, %c 673 ret i32 %lshr 674} 675 676define i32 @shl_lshr_and_exact(i32 %x, i32 %c, i32 %y) { 677; CHECK-LABEL: @shl_lshr_and_exact( 678; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]] 679; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]] 680; CHECK-NEXT: ret i32 [[TMP2]] 681; 682 %2 = shl nuw i32 %x, %c 683 %3 = and i32 %2, %y 684 %4 = lshr exact i32 %3, %c 685 ret i32 %4 686} 687 688; Negative test 689 690define i32 @shl_add_lshr_neg(i32 %x, i32 %y, i32 %z) { 691; CHECK-LABEL: @shl_add_lshr_neg( 692; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[Y:%.*]] 693; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[SHL]], [[Z:%.*]] 694; CHECK-NEXT: [[RES:%.*]] = lshr exact i32 [[ADD]], [[Z]] 695; CHECK-NEXT: ret i32 [[RES]] 696; 697 %shl = shl nuw i32 %x, %y 698 %add = add nuw nsw i32 %shl, %z 699 %res = lshr exact i32 %add, %z 700 ret i32 %res 701} 702 703define i32 @mul_splat_fold_wrong_mul_const(i32 %x) { 704; CHECK-LABEL: @mul_splat_fold_wrong_mul_const( 705; CHECK-NEXT: [[M:%.*]] = mul nuw i32 [[X:%.*]], 65538 706; CHECK-NEXT: [[T:%.*]] = lshr i32 [[M]], 16 707; CHECK-NEXT: ret i32 [[T]] 708; 709 %m = mul nuw i32 %x, 65538 710 %t = lshr i32 %m, 16 711 ret i32 %t 712} 713 714; Negative test 715 716define i32 @shl_add_lshr_multiuse(i32 %x, i32 %y, i32 %z) { 717; CHECK-LABEL: @shl_add_lshr_multiuse( 718; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[Y:%.*]] 719; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[SHL]], [[Z:%.*]] 720; CHECK-NEXT: call void @use(i32 [[ADD]]) 721; CHECK-NEXT: [[RES:%.*]] = lshr exact i32 [[ADD]], [[Z]] 722; CHECK-NEXT: ret i32 [[RES]] 723; 724 %shl = shl nuw i32 %x, %y 725 %add = add nuw nsw i32 %shl, %z 726 call void @use (i32 %add) 727 %res = lshr exact i32 %add, %z 728 ret i32 %res 729} 730 731define i32 @mul_splat_fold_wrong_lshr_const(i32 %x) { 732; CHECK-LABEL: @mul_splat_fold_wrong_lshr_const( 733; CHECK-NEXT: [[M:%.*]] = mul nuw i32 [[X:%.*]], 65537 734; CHECK-NEXT: [[T:%.*]] = lshr i32 [[M]], 15 735; CHECK-NEXT: ret i32 [[T]] 736; 737 %m = mul nuw i32 %x, 65537 738 %t = lshr i32 %m, 15 739 ret i32 %t 740} 741 742define i32 @mul_splat_fold_no_nuw(i32 %x) { 743; CHECK-LABEL: @mul_splat_fold_no_nuw( 744; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 16 745; CHECK-NEXT: [[T:%.*]] = add nsw i32 [[X]], [[TMP1]] 746; CHECK-NEXT: ret i32 [[T]] 747; 748 %m = mul nsw i32 %x, 65537 749 %t = lshr i32 %m, 16 750 ret i32 %t 751} 752 753; Negative test 754 755define i32 @mul_splat_fold_no_flags(i32 %x) { 756; CHECK-LABEL: @mul_splat_fold_no_flags( 757; CHECK-NEXT: [[M:%.*]] = mul i32 [[X:%.*]], 65537 758; CHECK-NEXT: [[T:%.*]] = lshr i32 [[M]], 16 759; CHECK-NEXT: ret i32 [[T]] 760; 761 %m = mul i32 %x, 65537 762 %t = lshr i32 %m, 16 763 ret i32 %t 764} 765 766; Negative test (but simplifies before we reach the mul_splat transform)- need more than 2 bits 767 768define i2 @mul_splat_fold_too_narrow(i2 %x) { 769; CHECK-LABEL: @mul_splat_fold_too_narrow( 770; CHECK-NEXT: ret i2 [[X:%.*]] 771; 772 %m = mul nuw i2 %x, 2 773 %t = lshr i2 %m, 1 774 ret i2 %t 775} 776 777define i32 @negative_and_odd(i32 %x) { 778; CHECK-LABEL: @negative_and_odd( 779; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 31 780; CHECK-NEXT: [[R:%.*]] = and i32 [[TMP1]], [[X]] 781; CHECK-NEXT: ret i32 [[R]] 782; 783 %s = srem i32 %x, 2 784 %r = lshr i32 %s, 31 785 ret i32 %r 786} 787 788define <2 x i7> @negative_and_odd_vec(<2 x i7> %x) { 789; CHECK-LABEL: @negative_and_odd_vec( 790; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i7> [[X:%.*]], splat (i7 6) 791; CHECK-NEXT: [[R:%.*]] = and <2 x i7> [[TMP1]], [[X]] 792; CHECK-NEXT: ret <2 x i7> [[R]] 793; 794 %s = srem <2 x i7> %x, <i7 2, i7 2> 795 %r = lshr <2 x i7> %s, <i7 6, i7 6> 796 ret <2 x i7> %r 797} 798 799; Negative test - this is still worth trying to avoid srem? 800 801define i32 @negative_and_odd_uses(i32 %x, ptr %p) { 802; CHECK-LABEL: @negative_and_odd_uses( 803; CHECK-NEXT: [[S:%.*]] = srem i32 [[X:%.*]], 2 804; CHECK-NEXT: store i32 [[S]], ptr [[P:%.*]], align 4 805; CHECK-NEXT: [[R:%.*]] = lshr i32 [[S]], 31 806; CHECK-NEXT: ret i32 [[R]] 807; 808 %s = srem i32 %x, 2 809 store i32 %s, ptr %p 810 %r = lshr i32 %s, 31 811 ret i32 %r 812} 813 814; Negative test - wrong divisor 815 816define i32 @srem3(i32 %x) { 817; CHECK-LABEL: @srem3( 818; CHECK-NEXT: [[S:%.*]] = srem i32 [[X:%.*]], 3 819; CHECK-NEXT: [[R:%.*]] = lshr i32 [[S]], 31 820; CHECK-NEXT: ret i32 [[R]] 821; 822 %s = srem i32 %x, 3 823 %r = lshr i32 %s, 31 824 ret i32 %r 825} 826 827; Negative test - wrong shift amount 828 829define i32 @srem2_lshr30(i32 %x) { 830; CHECK-LABEL: @srem2_lshr30( 831; CHECK-NEXT: [[S:%.*]] = srem i32 [[X:%.*]], 2 832; CHECK-NEXT: [[R:%.*]] = lshr i32 [[S]], 30 833; CHECK-NEXT: ret i32 [[R]] 834; 835 %s = srem i32 %x, 2 836 %r = lshr i32 %s, 30 837 ret i32 %r 838} 839 840define i12 @trunc_sandwich(i32 %x) { 841; CHECK-LABEL: @trunc_sandwich( 842; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 30 843; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12 844; CHECK-NEXT: ret i12 [[R1]] 845; 846 %sh = lshr i32 %x, 28 847 %tr = trunc i32 %sh to i12 848 %r = lshr i12 %tr, 2 849 ret i12 %r 850} 851 852define <2 x i12> @trunc_sandwich_splat_vec(<2 x i32> %x) { 853; CHECK-LABEL: @trunc_sandwich_splat_vec( 854; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr <2 x i32> [[X:%.*]], splat (i32 30) 855; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw <2 x i32> [[SUM_SHIFT]] to <2 x i12> 856; CHECK-NEXT: ret <2 x i12> [[R1]] 857; 858 %sh = lshr <2 x i32> %x, <i32 22, i32 22> 859 %tr = trunc <2 x i32> %sh to <2 x i12> 860 %r = lshr <2 x i12> %tr, <i12 8, i12 8> 861 ret <2 x i12> %r 862} 863 864define i12 @trunc_sandwich_min_shift1(i32 %x) { 865; CHECK-LABEL: @trunc_sandwich_min_shift1( 866; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 21 867; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12 868; CHECK-NEXT: ret i12 [[R1]] 869; 870 %sh = lshr i32 %x, 20 871 %tr = trunc i32 %sh to i12 872 %r = lshr i12 %tr, 1 873 ret i12 %r 874} 875 876define i12 @trunc_sandwich_small_shift1(i32 %x) { 877; CHECK-LABEL: @trunc_sandwich_small_shift1( 878; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 20 879; CHECK-NEXT: [[R1:%.*]] = trunc nuw i32 [[SUM_SHIFT]] to i12 880; CHECK-NEXT: [[R:%.*]] = and i12 [[R1]], 2047 881; CHECK-NEXT: ret i12 [[R]] 882; 883 %sh = lshr i32 %x, 19 884 %tr = trunc i32 %sh to i12 885 %r = lshr i12 %tr, 1 886 ret i12 %r 887} 888 889define i12 @trunc_sandwich_max_sum_shift(i32 %x) { 890; CHECK-LABEL: @trunc_sandwich_max_sum_shift( 891; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 31 892; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12 893; CHECK-NEXT: ret i12 [[R1]] 894; 895 %sh = lshr i32 %x, 20 896 %tr = trunc i32 %sh to i12 897 %r = lshr i12 %tr, 11 898 ret i12 %r 899} 900 901define i12 @trunc_sandwich_max_sum_shift2(i32 %x) { 902; CHECK-LABEL: @trunc_sandwich_max_sum_shift2( 903; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 31 904; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12 905; CHECK-NEXT: ret i12 [[R1]] 906; 907 %sh = lshr i32 %x, 30 908 %tr = trunc i32 %sh to i12 909 %r = lshr i12 %tr, 1 910 ret i12 %r 911} 912 913define i12 @trunc_sandwich_big_sum_shift1(i32 %x) { 914; CHECK-LABEL: @trunc_sandwich_big_sum_shift1( 915; CHECK-NEXT: ret i12 0 916; 917 %sh = lshr i32 %x, 21 918 %tr = trunc i32 %sh to i12 919 %r = lshr i12 %tr, 11 920 ret i12 %r 921} 922 923define i12 @trunc_sandwich_big_sum_shift2(i32 %x) { 924; CHECK-LABEL: @trunc_sandwich_big_sum_shift2( 925; CHECK-NEXT: ret i12 0 926; 927 %sh = lshr i32 %x, 31 928 %tr = trunc i32 %sh to i12 929 %r = lshr i12 %tr, 1 930 ret i12 %r 931} 932 933define i12 @trunc_sandwich_use1(i32 %x) { 934; CHECK-LABEL: @trunc_sandwich_use1( 935; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 28 936; CHECK-NEXT: call void @use(i32 [[SH]]) 937; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 30 938; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12 939; CHECK-NEXT: ret i12 [[R1]] 940; 941 %sh = lshr i32 %x, 28 942 call void @use(i32 %sh) 943 %tr = trunc i32 %sh to i12 944 %r = lshr i12 %tr, 2 945 ret i12 %r 946} 947 948define <3 x i9> @trunc_sandwich_splat_vec_use1(<3 x i14> %x) { 949; CHECK-LABEL: @trunc_sandwich_splat_vec_use1( 950; CHECK-NEXT: [[SH:%.*]] = lshr <3 x i14> [[X:%.*]], splat (i14 6) 951; CHECK-NEXT: call void @usevec(<3 x i14> [[SH]]) 952; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr <3 x i14> [[X]], splat (i14 11) 953; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw <3 x i14> [[SUM_SHIFT]] to <3 x i9> 954; CHECK-NEXT: ret <3 x i9> [[R1]] 955; 956 %sh = lshr <3 x i14> %x, <i14 6, i14 6, i14 6> 957 call void @usevec(<3 x i14> %sh) 958 %tr = trunc <3 x i14> %sh to <3 x i9> 959 %r = lshr <3 x i9> %tr, <i9 5, i9 5, i9 5> 960 ret <3 x i9> %r 961} 962 963define i12 @trunc_sandwich_min_shift1_use1(i32 %x) { 964; CHECK-LABEL: @trunc_sandwich_min_shift1_use1( 965; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 20 966; CHECK-NEXT: call void @use(i32 [[SH]]) 967; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 21 968; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12 969; CHECK-NEXT: ret i12 [[R1]] 970; 971 %sh = lshr i32 %x, 20 972 call void @use(i32 %sh) 973 %tr = trunc i32 %sh to i12 974 %r = lshr i12 %tr, 1 975 ret i12 %r 976} 977 978; negative test - trunc is bigger than first shift 979 980define i12 @trunc_sandwich_small_shift1_use1(i32 %x) { 981; CHECK-LABEL: @trunc_sandwich_small_shift1_use1( 982; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 19 983; CHECK-NEXT: call void @use(i32 [[SH]]) 984; CHECK-NEXT: [[TR:%.*]] = trunc i32 [[SH]] to i12 985; CHECK-NEXT: [[R:%.*]] = lshr i12 [[TR]], 1 986; CHECK-NEXT: ret i12 [[R]] 987; 988 %sh = lshr i32 %x, 19 989 call void @use(i32 %sh) 990 %tr = trunc i32 %sh to i12 991 %r = lshr i12 %tr, 1 992 ret i12 %r 993} 994 995define i12 @trunc_sandwich_max_sum_shift_use1(i32 %x) { 996; CHECK-LABEL: @trunc_sandwich_max_sum_shift_use1( 997; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 20 998; CHECK-NEXT: call void @use(i32 [[SH]]) 999; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 31 1000; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12 1001; CHECK-NEXT: ret i12 [[R1]] 1002; 1003 %sh = lshr i32 %x, 20 1004 call void @use(i32 %sh) 1005 %tr = trunc i32 %sh to i12 1006 %r = lshr i12 %tr, 11 1007 ret i12 %r 1008} 1009 1010define i12 @trunc_sandwich_max_sum_shift2_use1(i32 %x) { 1011; CHECK-LABEL: @trunc_sandwich_max_sum_shift2_use1( 1012; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 30 1013; CHECK-NEXT: call void @use(i32 [[SH]]) 1014; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 31 1015; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12 1016; CHECK-NEXT: ret i12 [[R1]] 1017; 1018 %sh = lshr i32 %x, 30 1019 call void @use(i32 %sh) 1020 %tr = trunc i32 %sh to i12 1021 %r = lshr i12 %tr, 1 1022 ret i12 %r 1023} 1024 1025; negative test - but overshift is simplified to zero by another fold 1026 1027define i12 @trunc_sandwich_big_sum_shift1_use1(i32 %x) { 1028; CHECK-LABEL: @trunc_sandwich_big_sum_shift1_use1( 1029; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 21 1030; CHECK-NEXT: call void @use(i32 [[SH]]) 1031; CHECK-NEXT: ret i12 0 1032; 1033 %sh = lshr i32 %x, 21 1034 call void @use(i32 %sh) 1035 %tr = trunc i32 %sh to i12 1036 %r = lshr i12 %tr, 11 1037 ret i12 %r 1038} 1039 1040; negative test - but overshift is simplified to zero by another fold 1041 1042define i12 @trunc_sandwich_big_sum_shift2_use1(i32 %x) { 1043; CHECK-LABEL: @trunc_sandwich_big_sum_shift2_use1( 1044; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 31 1045; CHECK-NEXT: call void @use(i32 [[SH]]) 1046; CHECK-NEXT: ret i12 0 1047; 1048 %sh = lshr i32 %x, 31 1049 call void @use(i32 %sh) 1050 %tr = trunc i32 %sh to i12 1051 %r = lshr i12 %tr, 1 1052 ret i12 %r 1053} 1054 1055define i16 @lshr_sext_i1_to_i16(i1 %a) { 1056; CHECK-LABEL: @lshr_sext_i1_to_i16( 1057; CHECK-NEXT: [[LSHR:%.*]] = select i1 [[A:%.*]], i16 4095, i16 0 1058; CHECK-NEXT: ret i16 [[LSHR]] 1059; 1060 %sext = sext i1 %a to i16 1061 %lshr = lshr i16 %sext, 4 1062 ret i16 %lshr 1063} 1064 1065define i128 @lshr_sext_i1_to_i128(i1 %a) { 1066; CHECK-LABEL: @lshr_sext_i1_to_i128( 1067; CHECK-NEXT: [[LSHR:%.*]] = select i1 [[A:%.*]], i128 77371252455336267181195263, i128 0 1068; CHECK-NEXT: ret i128 [[LSHR]] 1069; 1070 %sext = sext i1 %a to i128 1071 %lshr = lshr i128 %sext, 42 1072 ret i128 %lshr 1073} 1074 1075define i32 @lshr_sext_i1_to_i32_use(i1 %a) { 1076; CHECK-LABEL: @lshr_sext_i1_to_i32_use( 1077; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[A:%.*]] to i32 1078; CHECK-NEXT: call void @use(i32 [[SEXT]]) 1079; CHECK-NEXT: [[LSHR:%.*]] = select i1 [[A]], i32 262143, i32 0 1080; CHECK-NEXT: ret i32 [[LSHR]] 1081; 1082 %sext = sext i1 %a to i32 1083 call void @use(i32 %sext) 1084 %lshr = lshr i32 %sext, 14 1085 ret i32 %lshr 1086} 1087 1088define <3 x i14> @lshr_sext_i1_to_i14_splat_vec_use1(<3 x i1> %a) { 1089; CHECK-LABEL: @lshr_sext_i1_to_i14_splat_vec_use1( 1090; CHECK-NEXT: [[SEXT:%.*]] = sext <3 x i1> [[A:%.*]] to <3 x i14> 1091; CHECK-NEXT: call void @usevec(<3 x i14> [[SEXT]]) 1092; CHECK-NEXT: [[LSHR:%.*]] = select <3 x i1> [[A]], <3 x i14> splat (i14 1023), <3 x i14> zeroinitializer 1093; CHECK-NEXT: ret <3 x i14> [[LSHR]] 1094; 1095 %sext = sext <3 x i1> %a to <3 x i14> 1096 call void @usevec(<3 x i14> %sext) 1097 %lshr = lshr <3 x i14> %sext, <i14 4, i14 4, i14 4> 1098 ret <3 x i14> %lshr 1099} 1100 1101define i1 @icmp_ule(i32 %x, i32 %y) { 1102; CHECK-LABEL: @icmp_ule( 1103; CHECK-NEXT: ret i1 true 1104; 1105 %x.shifted = lshr i32 %x, %y 1106 %cmp = icmp ule i32 %x.shifted, %x 1107 ret i1 %cmp 1108} 1109 1110define i1 @icmp_ult(i32 %x, i32 %y) { 1111; CHECK-LABEL: @icmp_ult( 1112; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 1113; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X_SHIFTED]], [[X]] 1114; CHECK-NEXT: ret i1 [[CMP]] 1115; 1116 %x.shifted = lshr i32 %x, %y 1117 %cmp = icmp ult i32 %x.shifted, %x 1118 ret i1 %cmp 1119} 1120 1121define i1 @icmp_eq(i32 %x, i32 %y) { 1122; CHECK-LABEL: @icmp_eq( 1123; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 1124; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X_SHIFTED]], [[X]] 1125; CHECK-NEXT: ret i1 [[CMP]] 1126; 1127 %x.shifted = lshr i32 %x, %y 1128 %cmp = icmp eq i32 %x.shifted, %x 1129 ret i1 %cmp 1130} 1131 1132define i1 @icmp_ne(i32 %x, i32 %y) { 1133; CHECK-LABEL: @icmp_ne( 1134; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 1135; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X_SHIFTED]], [[X]] 1136; CHECK-NEXT: ret i1 [[CMP]] 1137; 1138 %x.shifted = lshr i32 %x, %y 1139 %cmp = icmp ne i32 %x.shifted, %x 1140 ret i1 %cmp 1141} 1142 1143define i1 @icmp_ugt(i32 %x, i32 %y) { 1144; CHECK-LABEL: @icmp_ugt( 1145; CHECK-NEXT: ret i1 false 1146; 1147 %x.shifted = lshr i32 %x, %y 1148 %cmp = icmp ugt i32 %x.shifted, %x 1149 ret i1 %cmp 1150} 1151 1152define i1 @icmp_uge(i32 %x, i32 %y) { 1153; CHECK-LABEL: @icmp_uge( 1154; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 1155; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[X_SHIFTED]], [[X]] 1156; CHECK-NEXT: ret i1 [[CMP]] 1157; 1158 %x.shifted = lshr i32 %x, %y 1159 %cmp = icmp uge i32 %x.shifted, %x 1160 ret i1 %cmp 1161} 1162 1163define i1 @icmp_sle(i32 %x, i32 %y) { 1164; CHECK-LABEL: @icmp_sle( 1165; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 1166; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[X_SHIFTED]], [[X]] 1167; CHECK-NEXT: ret i1 [[CMP]] 1168; 1169 %x.shifted = lshr i32 %x, %y 1170 %cmp = icmp sle i32 %x.shifted, %x 1171 ret i1 %cmp 1172} 1173 1174define i1 @icmp_slt(i32 %x, i32 %y) { 1175; CHECK-LABEL: @icmp_slt( 1176; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 1177; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X_SHIFTED]], [[X]] 1178; CHECK-NEXT: ret i1 [[CMP]] 1179; 1180 %x.shifted = lshr i32 %x, %y 1181 %cmp = icmp slt i32 %x.shifted, %x 1182 ret i1 %cmp 1183} 1184 1185define i1 @icmp_sgt(i32 %x, i32 %y) { 1186; CHECK-LABEL: @icmp_sgt( 1187; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 1188; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X_SHIFTED]], [[X]] 1189; CHECK-NEXT: ret i1 [[CMP]] 1190; 1191 %x.shifted = lshr i32 %x, %y 1192 %cmp = icmp sgt i32 %x.shifted, %x 1193 ret i1 %cmp 1194} 1195 1196define i1 @icmp_sge(i32 %x, i32 %y) { 1197; CHECK-LABEL: @icmp_sge( 1198; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 1199; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X_SHIFTED]], [[X]] 1200; CHECK-NEXT: ret i1 [[CMP]] 1201; 1202 %x.shifted = lshr i32 %x, %y 1203 %cmp = icmp sge i32 %x.shifted, %x 1204 ret i1 %cmp 1205} 1206 1207define i32 @narrow_bswap(i16 %x) { 1208; CHECK-LABEL: @narrow_bswap( 1209; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.bswap.i16(i16 [[X:%.*]]) 1210; CHECK-NEXT: [[S:%.*]] = zext i16 [[TMP1]] to i32 1211; CHECK-NEXT: ret i32 [[S]] 1212; 1213 %z = zext i16 %x to i32 1214 %b = call i32 @llvm.bswap.i32(i32 %z) 1215 %s = lshr i32 %b, 16 1216 ret i32 %s 1217} 1218 1219define i128 @narrow_bswap_extra_wide(i16 %x) { 1220; CHECK-LABEL: @narrow_bswap_extra_wide( 1221; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.bswap.i16(i16 [[X:%.*]]) 1222; CHECK-NEXT: [[S:%.*]] = zext i16 [[TMP1]] to i128 1223; CHECK-NEXT: ret i128 [[S]] 1224; 1225 %z = zext i16 %x to i128 1226 %b = call i128 @llvm.bswap.i128(i128 %z) 1227 %s = lshr i128 %b, 112 1228 ret i128 %s 1229} 1230 1231define i32 @narrow_bswap_undershift(i16 %x) { 1232; CHECK-LABEL: @narrow_bswap_undershift( 1233; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.bswap.i16(i16 [[X:%.*]]) 1234; CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[TMP1]] to i32 1235; CHECK-NEXT: [[S:%.*]] = shl nuw nsw i32 [[TMP2]], 7 1236; CHECK-NEXT: ret i32 [[S]] 1237; 1238 %z = zext i16 %x to i32 1239 %b = call i32 @llvm.bswap.i32(i32 %z) 1240 %s = lshr i32 %b, 9 1241 ret i32 %s 1242} 1243 1244define <2 x i64> @narrow_bswap_splat(<2 x i16> %x) { 1245; CHECK-LABEL: @narrow_bswap_splat( 1246; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i16> @llvm.bswap.v2i16(<2 x i16> [[X:%.*]]) 1247; CHECK-NEXT: [[S:%.*]] = zext <2 x i16> [[TMP1]] to <2 x i64> 1248; CHECK-NEXT: ret <2 x i64> [[S]] 1249; 1250 %z = zext <2 x i16> %x to <2 x i64> 1251 %b = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> %z) 1252 %s = lshr <2 x i64> %b, <i64 48, i64 48> 1253 ret <2 x i64> %s 1254} 1255 1256define <2 x i64> @narrow_bswap_splat_poison_elt(<2 x i16> %x) { 1257; CHECK-LABEL: @narrow_bswap_splat_poison_elt( 1258; CHECK-NEXT: [[Z:%.*]] = zext <2 x i16> [[X:%.*]] to <2 x i64> 1259; CHECK-NEXT: [[B:%.*]] = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> [[Z]]) 1260; CHECK-NEXT: [[S:%.*]] = lshr exact <2 x i64> [[B]], <i64 48, i64 poison> 1261; CHECK-NEXT: ret <2 x i64> [[S]] 1262; 1263 %z = zext <2 x i16> %x to <2 x i64> 1264 %b = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> %z) 1265 %s = lshr <2 x i64> %b, <i64 48, i64 poison> 1266 ret <2 x i64> %s 1267} 1268 1269define <2 x i64> @narrow_bswap_overshift(<2 x i32> %x) { 1270; CHECK-LABEL: @narrow_bswap_overshift( 1271; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.bswap.v2i32(<2 x i32> [[X:%.*]]) 1272; CHECK-NEXT: [[TMP2:%.*]] = lshr <2 x i32> [[TMP1]], splat (i32 16) 1273; CHECK-NEXT: [[S:%.*]] = zext nneg <2 x i32> [[TMP2]] to <2 x i64> 1274; CHECK-NEXT: ret <2 x i64> [[S]] 1275; 1276 %z = zext <2 x i32> %x to <2 x i64> 1277 %b = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> %z) 1278 %s = lshr <2 x i64> %b, <i64 48, i64 48> 1279 ret <2 x i64> %s 1280} 1281 1282define i128 @narrow_bswap_overshift2(i96 %x) { 1283; CHECK-LABEL: @narrow_bswap_overshift2( 1284; CHECK-NEXT: [[TMP1:%.*]] = call i96 @llvm.bswap.i96(i96 [[X:%.*]]) 1285; CHECK-NEXT: [[TMP2:%.*]] = lshr i96 [[TMP1]], 29 1286; CHECK-NEXT: [[S:%.*]] = zext nneg i96 [[TMP2]] to i128 1287; CHECK-NEXT: ret i128 [[S]] 1288; 1289 %z = zext i96 %x to i128 1290 %b = call i128 @llvm.bswap.i128(i128 %z) 1291 %s = lshr i128 %b, 61 1292 ret i128 %s 1293} 1294 1295; negative test - can't make a bswap with an odd number of bytes 1296 1297define i32 @not_narrow_bswap(i24 %x) { 1298; CHECK-LABEL: @not_narrow_bswap( 1299; CHECK-NEXT: [[Z:%.*]] = zext i24 [[X:%.*]] to i32 1300; CHECK-NEXT: [[B:%.*]] = call i32 @llvm.bswap.i32(i32 [[Z]]) 1301; CHECK-NEXT: [[R:%.*]] = lshr exact i32 [[B]], 8 1302; CHECK-NEXT: ret i32 [[R]] 1303; 1304 %z = zext i24 %x to i32 1305 %b = call i32 @llvm.bswap.i32(i32 %z) 1306 %r = lshr i32 %b, 8 1307 ret i32 %r 1308} 1309 1310define i8 @not_signbit(i8 %x) { 1311; CHECK-LABEL: @not_signbit( 1312; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1 1313; CHECK-NEXT: [[R:%.*]] = zext i1 [[ISNOTNEG]] to i8 1314; CHECK-NEXT: ret i8 [[R]] 1315; 1316 %a = xor i8 %x, -1 1317 %r = lshr i8 %a, 7 1318 ret i8 %r 1319} 1320 1321define <2 x i6> @not_signbit_vec(<2 x i6> %x) { 1322; CHECK-LABEL: @not_signbit_vec( 1323; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt <2 x i6> [[X:%.*]], splat (i6 -1) 1324; CHECK-NEXT: [[R:%.*]] = zext <2 x i1> [[ISNOTNEG]] to <2 x i6> 1325; CHECK-NEXT: ret <2 x i6> [[R]] 1326; 1327 %a = xor <2 x i6> %x, <i6 -1, i6 poison> 1328 %r = lshr <2 x i6> %a, <i6 5, i6 poison> 1329 ret <2 x i6> %r 1330} 1331 1332define i8 @not_signbit_alt_xor(i8 %x) { 1333; CHECK-LABEL: @not_signbit_alt_xor( 1334; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1 1335; CHECK-NEXT: [[R:%.*]] = zext i1 [[ISNOTNEG]] to i8 1336; CHECK-NEXT: ret i8 [[R]] 1337; 1338 %a = xor i8 %x, -2 1339 %r = lshr i8 %a, 7 1340 ret i8 %r 1341} 1342 1343define i8 @not_not_signbit(i8 %x) { 1344; CHECK-LABEL: @not_not_signbit( 1345; CHECK-NEXT: [[A:%.*]] = xor i8 [[X:%.*]], -1 1346; CHECK-NEXT: [[R:%.*]] = lshr i8 [[A]], 6 1347; CHECK-NEXT: ret i8 [[R]] 1348; 1349 %a = xor i8 %x, -1 1350 %r = lshr i8 %a, 6 1351 ret i8 %r 1352} 1353 1354define i32 @not_signbit_use(i32 %x) { 1355; CHECK-LABEL: @not_signbit_use( 1356; CHECK-NEXT: [[A:%.*]] = xor i32 [[X:%.*]], -1 1357; CHECK-NEXT: call void @use(i32 [[A]]) 1358; CHECK-NEXT: [[R:%.*]] = lshr i32 [[A]], 31 1359; CHECK-NEXT: ret i32 [[R]] 1360; 1361 %a = xor i32 %x, -1 1362 call void @use(i32 %a) 1363 %r = lshr i32 %a, 31 1364 ret i32 %r 1365} 1366 1367define i32 @not_signbit_zext(i16 %x) { 1368; CHECK-LABEL: @not_signbit_zext( 1369; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i16 [[X:%.*]], -1 1370; CHECK-NEXT: [[R2:%.*]] = zext i1 [[ISNOTNEG]] to i32 1371; CHECK-NEXT: ret i32 [[R2]] 1372; 1373 %a = xor i16 %x, -1 1374 %r = lshr i16 %a, 15 1375 %r2 = zext i16 %r to i32 1376 ret i32 %r2 1377} 1378 1379define i8 @not_signbit_trunc(i16 %x) { 1380; CHECK-LABEL: @not_signbit_trunc( 1381; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i16 [[X:%.*]], -1 1382; CHECK-NEXT: [[R2:%.*]] = zext i1 [[ISNOTNEG]] to i8 1383; CHECK-NEXT: ret i8 [[R2]] 1384; 1385 %a = xor i16 %x, -1 1386 %r = lshr i16 %a, 15 1387 %r2 = trunc i16 %r to i8 1388 ret i8 %r2 1389} 1390 1391define i2 @bool_add_lshr(i1 %a, i1 %b) { 1392; CHECK-LABEL: @bool_add_lshr( 1393; CHECK-NEXT: [[LSHR1:%.*]] = and i1 [[A:%.*]], [[B:%.*]] 1394; CHECK-NEXT: [[LSHR:%.*]] = zext i1 [[LSHR1]] to i2 1395; CHECK-NEXT: ret i2 [[LSHR]] 1396; 1397 %zext.a = zext i1 %a to i2 1398 %zext.b = zext i1 %b to i2 1399 %add = add i2 %zext.a, %zext.b 1400 %lshr = lshr i2 %add, 1 1401 ret i2 %lshr 1402} 1403 1404; negative test - need bools 1405 1406define i4 @not_bool_add_lshr(i2 %a, i2 %b) { 1407; CHECK-LABEL: @not_bool_add_lshr( 1408; CHECK-NEXT: [[TMP1:%.*]] = xor i2 [[A:%.*]], -1 1409; CHECK-NEXT: [[ADD_NARROWED_OVERFLOW:%.*]] = icmp ugt i2 [[B:%.*]], [[TMP1]] 1410; CHECK-NEXT: [[LSHR:%.*]] = zext i1 [[ADD_NARROWED_OVERFLOW]] to i4 1411; CHECK-NEXT: ret i4 [[LSHR]] 1412; 1413 %zext.a = zext i2 %a to i4 1414 %zext.b = zext i2 %b to i4 1415 %add = add i4 %zext.a, %zext.b 1416 %lshr = lshr i4 %add, 2 1417 ret i4 %lshr 1418} 1419 1420; TODO: This could be sext(and a, b). 1421 1422define i2 @bool_add_ashr(i1 %a, i1 %b) { 1423; CHECK-LABEL: @bool_add_ashr( 1424; CHECK-NEXT: [[ZEXT_A:%.*]] = zext i1 [[A:%.*]] to i2 1425; CHECK-NEXT: [[ZEXT_B:%.*]] = zext i1 [[B:%.*]] to i2 1426; CHECK-NEXT: [[ADD:%.*]] = add nuw i2 [[ZEXT_A]], [[ZEXT_B]] 1427; CHECK-NEXT: [[ASHR:%.*]] = ashr i2 [[ADD]], 1 1428; CHECK-NEXT: ret i2 [[ASHR]] 1429; 1430 %zext.a = zext i1 %a to i2 1431 %zext.b = zext i1 %b to i2 1432 %add = add i2 %zext.a, %zext.b 1433 %ashr = ashr i2 %add, 1 1434 ret i2 %ashr 1435} 1436 1437define <2 x i8> @bool_add_lshr_vec(<2 x i1> %a, <2 x i1> %b) { 1438; CHECK-LABEL: @bool_add_lshr_vec( 1439; CHECK-NEXT: [[LSHR1:%.*]] = and <2 x i1> [[A:%.*]], [[B:%.*]] 1440; CHECK-NEXT: [[LSHR:%.*]] = zext <2 x i1> [[LSHR1]] to <2 x i8> 1441; CHECK-NEXT: ret <2 x i8> [[LSHR]] 1442; 1443 %zext.a = zext <2 x i1> %a to <2 x i8> 1444 %zext.b = zext <2 x i1> %b to <2 x i8> 1445 %add = add <2 x i8> %zext.a, %zext.b 1446 %lshr = lshr <2 x i8> %add, <i8 1, i8 1> 1447 ret <2 x i8> %lshr 1448} 1449 1450define i32 @bool_add_lshr_uses(i1 %a, i1 %b) { 1451; CHECK-LABEL: @bool_add_lshr_uses( 1452; CHECK-NEXT: [[ZEXT_A:%.*]] = zext i1 [[A:%.*]] to i32 1453; CHECK-NEXT: call void @use(i32 [[ZEXT_A]]) 1454; CHECK-NEXT: [[ZEXT_B:%.*]] = zext i1 [[B:%.*]] to i32 1455; CHECK-NEXT: call void @use(i32 [[ZEXT_B]]) 1456; CHECK-NEXT: [[LSHR:%.*]] = and i32 [[ZEXT_A]], [[ZEXT_B]] 1457; CHECK-NEXT: ret i32 [[LSHR]] 1458; 1459 %zext.a = zext i1 %a to i32 1460 call void @use(i32 %zext.a) 1461 %zext.b = zext i1 %b to i32 1462 call void @use(i32 %zext.b) 1463 %add = add i32 %zext.a, %zext.b 1464 %lshr = lshr i32 %add, 1 1465 ret i32 %lshr 1466} 1467 1468define i32 @bool_add_lshr_uses2(i1 %a, i1 %b) { 1469; CHECK-LABEL: @bool_add_lshr_uses2( 1470; CHECK-NEXT: [[ZEXT_A:%.*]] = zext i1 [[A:%.*]] to i32 1471; CHECK-NEXT: [[ZEXT_B:%.*]] = zext i1 [[B:%.*]] to i32 1472; CHECK-NEXT: call void @use(i32 [[ZEXT_B]]) 1473; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[ZEXT_A]], [[ZEXT_B]] 1474; CHECK-NEXT: call void @use(i32 [[ADD]]) 1475; CHECK-NEXT: [[LSHR:%.*]] = and i32 [[ZEXT_A]], [[ZEXT_B]] 1476; CHECK-NEXT: ret i32 [[LSHR]] 1477; 1478 %zext.a = zext i1 %a to i32 1479 %zext.b = zext i1 %b to i32 1480 call void @use(i32 %zext.b) 1481 %add = add i32 %zext.a, %zext.b 1482 call void @use(i32 %add) 1483 %lshr = lshr i32 %add, 1 1484 ret i32 %lshr 1485} 1486 1487; negative test - too many extra uses 1488 1489define i32 @bool_add_lshr_uses3(i1 %a, i1 %b) { 1490; CHECK-LABEL: @bool_add_lshr_uses3( 1491; CHECK-NEXT: [[ZEXT_A:%.*]] = zext i1 [[A:%.*]] to i32 1492; CHECK-NEXT: call void @use(i32 [[ZEXT_A]]) 1493; CHECK-NEXT: [[ZEXT_B:%.*]] = zext i1 [[B:%.*]] to i32 1494; CHECK-NEXT: call void @use(i32 [[ZEXT_B]]) 1495; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[ZEXT_A]], [[ZEXT_B]] 1496; CHECK-NEXT: call void @use(i32 [[ADD]]) 1497; CHECK-NEXT: [[LSHR:%.*]] = and i32 [[ZEXT_A]], [[ZEXT_B]] 1498; CHECK-NEXT: ret i32 [[LSHR]] 1499; 1500 %zext.a = zext i1 %a to i32 1501 call void @use(i32 %zext.a) 1502 %zext.b = zext i1 %b to i32 1503 call void @use(i32 %zext.b) 1504 %add = add i32 %zext.a, %zext.b 1505 call void @use(i32 %add) 1506 %lshr = lshr i32 %add, 1 1507 ret i32 %lshr 1508} 1509 1510; negative test 1511 1512define <2 x i8> @bool_add_lshr_vec_wrong_shift_amt(<2 x i1> %a, <2 x i1> %b) { 1513; CHECK-LABEL: @bool_add_lshr_vec_wrong_shift_amt( 1514; CHECK-NEXT: [[ZEXT_A:%.*]] = zext <2 x i1> [[A:%.*]] to <2 x i8> 1515; CHECK-NEXT: [[ZEXT_B:%.*]] = zext <2 x i1> [[B:%.*]] to <2 x i8> 1516; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw <2 x i8> [[ZEXT_A]], [[ZEXT_B]] 1517; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i8> [[ADD]], <i8 1, i8 2> 1518; CHECK-NEXT: ret <2 x i8> [[LSHR]] 1519; 1520 %zext.a = zext <2 x i1> %a to <2 x i8> 1521 %zext.b = zext <2 x i1> %b to <2 x i8> 1522 %add = add <2 x i8> %zext.a, %zext.b 1523 %lshr = lshr <2 x i8> %add, <i8 1, i8 2> 1524 ret <2 x i8> %lshr 1525} 1526 1527define i32 @lowbits_of_lshr_mul(i64 %x) { 1528; CHECK-LABEL: @lowbits_of_lshr_mul( 1529; CHECK-NEXT: entry: 1530; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[X:%.*]] to i32 1531; CHECK-NEXT: [[CONV:%.*]] = mul i32 [[TMP0]], 15 1532; CHECK-NEXT: ret i32 [[CONV]] 1533; 1534entry: 1535 %mul = mul i64 %x, 64424509440 1536 %shift = lshr i64 %mul, 32 1537 %conv = trunc i64 %shift to i32 1538 ret i32 %conv 1539} 1540 1541define i32 @lowbits_of_lshr_mul_mask(i32 %x) { 1542; CHECK-LABEL: @lowbits_of_lshr_mul_mask( 1543; CHECK-NEXT: entry: 1544; CHECK-NEXT: [[TMP0:%.*]] = mul i32 [[X:%.*]], 1600 1545; CHECK-NEXT: [[CONV:%.*]] = and i32 [[TMP0]], 32704 1546; CHECK-NEXT: ret i32 [[CONV]] 1547; 1548entry: 1549 %mul = mul i32 %x, 104857600 1550 %shift = lshr i32 %mul, 16 1551 %conv = and i32 %shift, 32767 1552 ret i32 %conv 1553} 1554 1555; Negative tests 1556 1557define i32 @lowbits_of_lshr_mul_mask_multiuse(i32 %x) { 1558; CHECK-LABEL: @lowbits_of_lshr_mul_mask_multiuse( 1559; CHECK-NEXT: entry: 1560; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], 104857600 1561; CHECK-NEXT: call void @use(i32 [[MUL]]) 1562; CHECK-NEXT: [[SHIFT:%.*]] = lshr exact i32 [[MUL]], 16 1563; CHECK-NEXT: [[CONV:%.*]] = and i32 [[SHIFT]], 32704 1564; CHECK-NEXT: ret i32 [[CONV]] 1565; 1566entry: 1567 %mul = mul i32 %x, 104857600 1568 call void @use(i32 %mul) 1569 %shift = lshr i32 %mul, 16 1570 %conv = and i32 %shift, 32767 1571 ret i32 %conv 1572} 1573 1574define i32 @lowbits_of_lshr_mul_mask_indivisible(i32 %x) { 1575; CHECK-LABEL: @lowbits_of_lshr_mul_mask_indivisible( 1576; CHECK-NEXT: entry: 1577; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], 25600 1578; CHECK-NEXT: [[SHIFT:%.*]] = lshr i32 [[MUL]], 16 1579; CHECK-NEXT: [[CONV:%.*]] = and i32 [[SHIFT]], 32767 1580; CHECK-NEXT: ret i32 [[CONV]] 1581; 1582entry: 1583 %mul = mul i32 %x, 25600 1584 %shift = lshr i32 %mul, 16 1585 %conv = and i32 %shift, 32767 1586 ret i32 %conv 1587} 1588