1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" 4 5; Instcombine should be able to eliminate all of these ext casts. 6 7declare void @use(i32) 8declare void @use_vec(<2 x i32>) 9 10define i64 @test1(i64 %a) { 11; CHECK-LABEL: @test1( 12; CHECK-NEXT: [[B:%.*]] = trunc i64 [[A:%.*]] to i32 13; CHECK-NEXT: [[C:%.*]] = and i64 [[A]], 15 14; CHECK-NEXT: call void @use(i32 [[B]]) 15; CHECK-NEXT: ret i64 [[C]] 16; 17 %b = trunc i64 %a to i32 18 %c = and i32 %b, 15 19 %d = zext i32 %c to i64 20 call void @use(i32 %b) 21 ret i64 %d 22} 23 24define <2 x i64> @test1_vec(<2 x i64> %a) { 25; CHECK-LABEL: @test1_vec( 26; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32> 27; CHECK-NEXT: [[D:%.*]] = and <2 x i64> [[A]], splat (i64 15) 28; CHECK-NEXT: call void @use_vec(<2 x i32> [[B]]) 29; CHECK-NEXT: ret <2 x i64> [[D]] 30; 31 %b = trunc <2 x i64> %a to <2 x i32> 32 %c = and <2 x i32> %b, <i32 15, i32 15> 33 %d = zext <2 x i32> %c to <2 x i64> 34 call void @use_vec(<2 x i32> %b) 35 ret <2 x i64> %d 36} 37 38define <2 x i64> @test1_vec_nonuniform(<2 x i64> %a) { 39; CHECK-LABEL: @test1_vec_nonuniform( 40; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32> 41; CHECK-NEXT: [[D:%.*]] = and <2 x i64> [[A]], <i64 15, i64 7> 42; CHECK-NEXT: call void @use_vec(<2 x i32> [[B]]) 43; CHECK-NEXT: ret <2 x i64> [[D]] 44; 45 %b = trunc <2 x i64> %a to <2 x i32> 46 %c = and <2 x i32> %b, <i32 15, i32 7> 47 %d = zext <2 x i32> %c to <2 x i64> 48 call void @use_vec(<2 x i32> %b) 49 ret <2 x i64> %d 50} 51 52define <2 x i64> @test1_vec_poison(<2 x i64> %a) { 53; CHECK-LABEL: @test1_vec_poison( 54; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32> 55; CHECK-NEXT: [[D:%.*]] = and <2 x i64> [[A]], <i64 15, i64 poison> 56; CHECK-NEXT: call void @use_vec(<2 x i32> [[B]]) 57; CHECK-NEXT: ret <2 x i64> [[D]] 58; 59 %b = trunc <2 x i64> %a to <2 x i32> 60 %c = and <2 x i32> %b, <i32 15, i32 poison> 61 %d = zext <2 x i32> %c to <2 x i64> 62 call void @use_vec(<2 x i32> %b) 63 ret <2 x i64> %d 64} 65 66define i64 @test2(i64 %a) { 67; CHECK-LABEL: @test2( 68; CHECK-NEXT: [[B:%.*]] = trunc i64 [[A:%.*]] to i32 69; CHECK-NEXT: [[D1:%.*]] = shl i64 [[A]], 36 70; CHECK-NEXT: [[D:%.*]] = ashr exact i64 [[D1]], 36 71; CHECK-NEXT: call void @use(i32 [[B]]) 72; CHECK-NEXT: ret i64 [[D]] 73; 74 %b = trunc i64 %a to i32 75 %c = shl i32 %b, 4 76 %q = ashr i32 %c, 4 77 %d = sext i32 %q to i64 78 call void @use(i32 %b) 79 ret i64 %d 80} 81 82define <2 x i64> @test2_vec(<2 x i64> %a) { 83; CHECK-LABEL: @test2_vec( 84; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32> 85; CHECK-NEXT: [[D1:%.*]] = shl <2 x i64> [[A]], splat (i64 36) 86; CHECK-NEXT: [[D:%.*]] = ashr exact <2 x i64> [[D1]], splat (i64 36) 87; CHECK-NEXT: call void @use_vec(<2 x i32> [[B]]) 88; CHECK-NEXT: ret <2 x i64> [[D]] 89; 90 %b = trunc <2 x i64> %a to <2 x i32> 91 %c = shl <2 x i32> %b, <i32 4, i32 4> 92 %q = ashr <2 x i32> %c, <i32 4, i32 4> 93 %d = sext <2 x i32> %q to <2 x i64> 94 call void @use_vec(<2 x i32> %b) 95 ret <2 x i64> %d 96} 97 98define <2 x i64> @test2_vec_nonuniform(<2 x i64> %a) { 99; CHECK-LABEL: @test2_vec_nonuniform( 100; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32> 101; CHECK-NEXT: [[D1:%.*]] = shl <2 x i64> [[A]], <i64 36, i64 37> 102; CHECK-NEXT: [[D:%.*]] = ashr exact <2 x i64> [[D1]], <i64 36, i64 37> 103; CHECK-NEXT: call void @use_vec(<2 x i32> [[B]]) 104; CHECK-NEXT: ret <2 x i64> [[D]] 105; 106 %b = trunc <2 x i64> %a to <2 x i32> 107 %c = shl <2 x i32> %b, <i32 4, i32 5> 108 %q = ashr <2 x i32> %c, <i32 4, i32 5> 109 %d = sext <2 x i32> %q to <2 x i64> 110 call void @use_vec(<2 x i32> %b) 111 ret <2 x i64> %d 112} 113 114define <2 x i64> @test2_vec_poison(<2 x i64> %a) { 115; CHECK-LABEL: @test2_vec_poison( 116; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32> 117; CHECK-NEXT: [[D1:%.*]] = shl <2 x i64> [[A]], <i64 36, i64 poison> 118; CHECK-NEXT: [[D:%.*]] = ashr exact <2 x i64> [[D1]], <i64 36, i64 poison> 119; CHECK-NEXT: call void @use_vec(<2 x i32> [[B]]) 120; CHECK-NEXT: ret <2 x i64> [[D]] 121; 122 %b = trunc <2 x i64> %a to <2 x i32> 123 %c = shl <2 x i32> %b, <i32 4, i32 poison> 124 %q = ashr <2 x i32> %c, <i32 4, i32 poison> 125 %d = sext <2 x i32> %q to <2 x i64> 126 call void @use_vec(<2 x i32> %b) 127 ret <2 x i64> %d 128} 129 130define i64 @test3(i64 %a) { 131; CHECK-LABEL: @test3( 132; CHECK-NEXT: [[B:%.*]] = trunc i64 [[A:%.*]] to i32 133; CHECK-NEXT: [[C:%.*]] = and i64 [[A]], 8 134; CHECK-NEXT: call void @use(i32 [[B]]) 135; CHECK-NEXT: ret i64 [[C]] 136; 137 %b = trunc i64 %a to i32 138 %c = and i32 %b, 8 139 %d = zext i32 %c to i64 140 call void @use(i32 %b) 141 ret i64 %d 142} 143 144define i64 @test4(i64 %a) { 145; CHECK-LABEL: @test4( 146; CHECK-NEXT: [[B:%.*]] = trunc i64 [[A:%.*]] to i32 147; CHECK-NEXT: [[C:%.*]] = and i64 [[A]], 8 148; CHECK-NEXT: [[X:%.*]] = xor i64 [[C]], 8 149; CHECK-NEXT: call void @use(i32 [[B]]) 150; CHECK-NEXT: ret i64 [[X]] 151; 152 %b = trunc i64 %a to i32 153 %c = and i32 %b, 8 154 %x = xor i32 %c, 8 155 %d = zext i32 %x to i64 156 call void @use(i32 %b) 157 ret i64 %d 158} 159 160define i32 @test5(i32 %A) { 161; CHECK-LABEL: @test5( 162; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[A:%.*]], 16 163; CHECK-NEXT: ret i32 [[TMP1]] 164; 165 %B = zext i32 %A to i128 166 %C = lshr i128 %B, 16 167 %D = trunc i128 %C to i32 168 ret i32 %D 169} 170 171define i32 @test6(i64 %A) { 172; CHECK-LABEL: @test6( 173; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[A:%.*]], 32 174; CHECK-NEXT: [[D:%.*]] = trunc nuw i64 [[TMP1]] to i32 175; CHECK-NEXT: ret i32 [[D]] 176; 177 %B = zext i64 %A to i128 178 %C = lshr i128 %B, 32 179 %D = trunc i128 %C to i32 180 ret i32 %D 181} 182 183; Test case where 'ashr' demanded bits does not contain any of the high bits, 184; but does contain sign bits, where the sign bit is not known to be zero. 185define i16 @ashr_mul_sign_bits(i8 %X, i8 %Y) { 186; CHECK-LABEL: @ashr_mul_sign_bits( 187; CHECK-NEXT: [[A:%.*]] = sext i8 [[X:%.*]] to i16 188; CHECK-NEXT: [[B:%.*]] = sext i8 [[Y:%.*]] to i16 189; CHECK-NEXT: [[C:%.*]] = mul nsw i16 [[A]], [[B]] 190; CHECK-NEXT: [[D:%.*]] = ashr i16 [[C]], 3 191; CHECK-NEXT: ret i16 [[D]] 192; 193 %A = sext i8 %X to i32 194 %B = sext i8 %Y to i32 195 %C = mul i32 %A, %B 196 %D = ashr i32 %C, 3 197 %E = trunc i32 %D to i16 198 ret i16 %E 199} 200 201define i16 @ashr_mul(i8 %X, i8 %Y) { 202; CHECK-LABEL: @ashr_mul( 203; CHECK-NEXT: [[A:%.*]] = sext i8 [[X:%.*]] to i16 204; CHECK-NEXT: [[B:%.*]] = sext i8 [[Y:%.*]] to i16 205; CHECK-NEXT: [[C:%.*]] = mul nsw i16 [[A]], [[B]] 206; CHECK-NEXT: [[D:%.*]] = ashr i16 [[C]], 8 207; CHECK-NEXT: ret i16 [[D]] 208; 209 %A = sext i8 %X to i20 210 %B = sext i8 %Y to i20 211 %C = mul i20 %A, %B 212 %D = ashr i20 %C, 8 213 %E = trunc i20 %D to i16 214 ret i16 %E 215} 216 217define i32 @trunc_ashr(i32 %X) { 218; CHECK-LABEL: @trunc_ashr( 219; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8 220; CHECK-NEXT: [[C:%.*]] = or i32 [[TMP1]], -8388608 221; CHECK-NEXT: ret i32 [[C]] 222; 223 %A = zext i32 %X to i36 224 %B = or i36 %A, -2147483648 ; 0xF80000000 225 %C = ashr i36 %B, 8 226 %T = trunc i36 %C to i32 227 ret i32 %T 228} 229 230define <2 x i32> @trunc_ashr_vec(<2 x i32> %X) { 231; CHECK-LABEL: @trunc_ashr_vec( 232; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], splat (i32 8) 233; CHECK-NEXT: [[C:%.*]] = or <2 x i32> [[TMP1]], splat (i32 -8388608) 234; CHECK-NEXT: ret <2 x i32> [[C]] 235; 236 %A = zext <2 x i32> %X to <2 x i36> 237 %B = or <2 x i36> %A, <i36 -2147483648, i36 -2147483648> ; 0xF80000000 238 %C = ashr <2 x i36> %B, <i36 8, i36 8> 239 %T = trunc <2 x i36> %C to <2 x i32> 240 ret <2 x i32> %T 241} 242 243define i92 @test7(i64 %A) { 244; CHECK-LABEL: @test7( 245; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[A:%.*]], 32 246; CHECK-NEXT: [[D:%.*]] = zext nneg i64 [[TMP1]] to i92 247; CHECK-NEXT: ret i92 [[D]] 248; 249 %B = zext i64 %A to i128 250 %C = lshr i128 %B, 32 251 %D = trunc i128 %C to i92 252 ret i92 %D 253} 254 255define i64 @test8(i32 %A, i32 %B) { 256; CHECK-LABEL: @test8( 257; CHECK-NEXT: [[C:%.*]] = zext i32 [[A:%.*]] to i64 258; CHECK-NEXT: [[D:%.*]] = zext i32 [[B:%.*]] to i64 259; CHECK-NEXT: [[E:%.*]] = shl nuw i64 [[D]], 32 260; CHECK-NEXT: [[F:%.*]] = or disjoint i64 [[E]], [[C]] 261; CHECK-NEXT: ret i64 [[F]] 262; 263 %C = zext i32 %A to i128 264 %D = zext i32 %B to i128 265 %E = shl i128 %D, 32 266 %F = or i128 %E, %C 267 %G = trunc i128 %F to i64 268 ret i64 %G 269} 270 271define <2 x i64> @test8_vec(<2 x i32> %A, <2 x i32> %B) { 272; CHECK-LABEL: @test8_vec( 273; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64> 274; CHECK-NEXT: [[D:%.*]] = zext <2 x i32> [[B:%.*]] to <2 x i64> 275; CHECK-NEXT: [[E:%.*]] = shl nuw <2 x i64> [[D]], splat (i64 32) 276; CHECK-NEXT: [[F:%.*]] = or disjoint <2 x i64> [[E]], [[C]] 277; CHECK-NEXT: ret <2 x i64> [[F]] 278; 279 %C = zext <2 x i32> %A to <2 x i128> 280 %D = zext <2 x i32> %B to <2 x i128> 281 %E = shl <2 x i128> %D, <i128 32, i128 32> 282 %F = or <2 x i128> %E, %C 283 %G = trunc <2 x i128> %F to <2 x i64> 284 ret <2 x i64> %G 285} 286 287define <2 x i64> @test8_vec_nonuniform(<2 x i32> %A, <2 x i32> %B) { 288; CHECK-LABEL: @test8_vec_nonuniform( 289; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64> 290; CHECK-NEXT: [[D:%.*]] = zext <2 x i32> [[B:%.*]] to <2 x i64> 291; CHECK-NEXT: [[E:%.*]] = shl <2 x i64> [[D]], <i64 32, i64 48> 292; CHECK-NEXT: [[F:%.*]] = or disjoint <2 x i64> [[E]], [[C]] 293; CHECK-NEXT: ret <2 x i64> [[F]] 294; 295 %C = zext <2 x i32> %A to <2 x i128> 296 %D = zext <2 x i32> %B to <2 x i128> 297 %E = shl <2 x i128> %D, <i128 32, i128 48> 298 %F = or <2 x i128> %E, %C 299 %G = trunc <2 x i128> %F to <2 x i64> 300 ret <2 x i64> %G 301} 302 303define <2 x i64> @test8_vec_poison(<2 x i32> %A, <2 x i32> %B) { 304; CHECK-LABEL: @test8_vec_poison( 305; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64> 306; CHECK-NEXT: [[D:%.*]] = zext <2 x i32> [[B:%.*]] to <2 x i64> 307; CHECK-NEXT: [[E:%.*]] = shl nuw <2 x i64> [[D]], <i64 32, i64 poison> 308; CHECK-NEXT: [[G:%.*]] = or disjoint <2 x i64> [[E]], [[C]] 309; CHECK-NEXT: ret <2 x i64> [[G]] 310; 311 %C = zext <2 x i32> %A to <2 x i128> 312 %D = zext <2 x i32> %B to <2 x i128> 313 %E = shl <2 x i128> %D, <i128 32, i128 poison> 314 %F = or <2 x i128> %E, %C 315 %G = trunc <2 x i128> %F to <2 x i64> 316 ret <2 x i64> %G 317} 318 319define i8 @test9(i32 %X) { 320; CHECK-LABEL: @test9( 321; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i8 322; CHECK-NEXT: [[Z:%.*]] = and i8 [[TMP1]], 42 323; CHECK-NEXT: ret i8 [[Z]] 324; 325 %Y = and i32 %X, 42 326 %Z = trunc i32 %Y to i8 327 ret i8 %Z 328} 329 330; rdar://8808586 331define i8 @test10(i32 %X) { 332; CHECK-LABEL: @test10( 333; CHECK-NEXT: [[Y:%.*]] = trunc i32 [[X:%.*]] to i8 334; CHECK-NEXT: [[Z:%.*]] = and i8 [[Y]], 42 335; CHECK-NEXT: ret i8 [[Z]] 336; 337 %Y = trunc i32 %X to i8 338 %Z = and i8 %Y, 42 339 ret i8 %Z 340} 341 342define i64 @test11(i32 %A, i32 %B) { 343; CHECK-LABEL: @test11( 344; CHECK-NEXT: [[C:%.*]] = zext i32 [[A:%.*]] to i64 345; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[B:%.*]], 31 346; CHECK-NEXT: [[E:%.*]] = zext nneg i32 [[TMP1]] to i64 347; CHECK-NEXT: [[F:%.*]] = shl nuw nsw i64 [[C]], [[E]] 348; CHECK-NEXT: ret i64 [[F]] 349; 350 %C = zext i32 %A to i128 351 %D = zext i32 %B to i128 352 %E = and i128 %D, 31 353 %F = shl i128 %C, %E 354 %G = trunc i128 %F to i64 355 ret i64 %G 356} 357 358define <2 x i64> @test11_vec(<2 x i32> %A, <2 x i32> %B) { 359; CHECK-LABEL: @test11_vec( 360; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64> 361; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], splat (i32 31) 362; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64> 363; CHECK-NEXT: [[F:%.*]] = shl nuw nsw <2 x i64> [[C]], [[E]] 364; CHECK-NEXT: ret <2 x i64> [[F]] 365; 366 %C = zext <2 x i32> %A to <2 x i128> 367 %D = zext <2 x i32> %B to <2 x i128> 368 %E = and <2 x i128> %D, <i128 31, i128 31> 369 %F = shl <2 x i128> %C, %E 370 %G = trunc <2 x i128> %F to <2 x i64> 371 ret <2 x i64> %G 372} 373 374define <2 x i64> @test11_vec_nonuniform(<2 x i32> %A, <2 x i32> %B) { 375; CHECK-LABEL: @test11_vec_nonuniform( 376; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64> 377; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 15> 378; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64> 379; CHECK-NEXT: [[F:%.*]] = shl nuw nsw <2 x i64> [[C]], [[E]] 380; CHECK-NEXT: ret <2 x i64> [[F]] 381; 382 %C = zext <2 x i32> %A to <2 x i128> 383 %D = zext <2 x i32> %B to <2 x i128> 384 %E = and <2 x i128> %D, <i128 31, i128 15> 385 %F = shl <2 x i128> %C, %E 386 %G = trunc <2 x i128> %F to <2 x i64> 387 ret <2 x i64> %G 388} 389 390define <2 x i64> @test11_vec_poison(<2 x i32> %A, <2 x i32> %B) { 391; CHECK-LABEL: @test11_vec_poison( 392; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64> 393; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 poison> 394; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64> 395; CHECK-NEXT: [[G:%.*]] = shl nuw nsw <2 x i64> [[C]], [[E]] 396; CHECK-NEXT: ret <2 x i64> [[G]] 397; 398 %C = zext <2 x i32> %A to <2 x i128> 399 %D = zext <2 x i32> %B to <2 x i128> 400 %E = and <2 x i128> %D, <i128 31, i128 poison> 401 %F = shl <2 x i128> %C, %E 402 %G = trunc <2 x i128> %F to <2 x i64> 403 ret <2 x i64> %G 404} 405 406define i64 @test12(i32 %A, i32 %B) { 407; CHECK-LABEL: @test12( 408; CHECK-NEXT: [[C:%.*]] = zext i32 [[A:%.*]] to i64 409; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[B:%.*]], 31 410; CHECK-NEXT: [[E:%.*]] = zext nneg i32 [[TMP1]] to i64 411; CHECK-NEXT: [[F:%.*]] = lshr i64 [[C]], [[E]] 412; CHECK-NEXT: ret i64 [[F]] 413; 414 %C = zext i32 %A to i128 415 %D = zext i32 %B to i128 416 %E = and i128 %D, 31 417 %F = lshr i128 %C, %E 418 %G = trunc i128 %F to i64 419 ret i64 %G 420} 421 422define <2 x i64> @test12_vec(<2 x i32> %A, <2 x i32> %B) { 423; CHECK-LABEL: @test12_vec( 424; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64> 425; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], splat (i32 31) 426; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64> 427; CHECK-NEXT: [[F:%.*]] = lshr <2 x i64> [[C]], [[E]] 428; CHECK-NEXT: ret <2 x i64> [[F]] 429; 430 %C = zext <2 x i32> %A to <2 x i128> 431 %D = zext <2 x i32> %B to <2 x i128> 432 %E = and <2 x i128> %D, <i128 31, i128 31> 433 %F = lshr <2 x i128> %C, %E 434 %G = trunc <2 x i128> %F to <2 x i64> 435 ret <2 x i64> %G 436} 437 438define <2 x i64> @test12_vec_nonuniform(<2 x i32> %A, <2 x i32> %B) { 439; CHECK-LABEL: @test12_vec_nonuniform( 440; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64> 441; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 15> 442; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64> 443; CHECK-NEXT: [[F:%.*]] = lshr <2 x i64> [[C]], [[E]] 444; CHECK-NEXT: ret <2 x i64> [[F]] 445; 446 %C = zext <2 x i32> %A to <2 x i128> 447 %D = zext <2 x i32> %B to <2 x i128> 448 %E = and <2 x i128> %D, <i128 31, i128 15> 449 %F = lshr <2 x i128> %C, %E 450 %G = trunc <2 x i128> %F to <2 x i64> 451 ret <2 x i64> %G 452} 453 454define <2 x i64> @test12_vec_poison(<2 x i32> %A, <2 x i32> %B) { 455; CHECK-LABEL: @test12_vec_poison( 456; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64> 457; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 poison> 458; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64> 459; CHECK-NEXT: [[G:%.*]] = lshr <2 x i64> [[C]], [[E]] 460; CHECK-NEXT: ret <2 x i64> [[G]] 461; 462 %C = zext <2 x i32> %A to <2 x i128> 463 %D = zext <2 x i32> %B to <2 x i128> 464 %E = and <2 x i128> %D, <i128 31, i128 poison> 465 %F = lshr <2 x i128> %C, %E 466 %G = trunc <2 x i128> %F to <2 x i64> 467 ret <2 x i64> %G 468} 469 470define i64 @test13(i32 %A, i32 %B) { 471; CHECK-LABEL: @test13( 472; CHECK-NEXT: [[C:%.*]] = sext i32 [[A:%.*]] to i64 473; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[B:%.*]], 31 474; CHECK-NEXT: [[E:%.*]] = zext nneg i32 [[TMP1]] to i64 475; CHECK-NEXT: [[F:%.*]] = ashr i64 [[C]], [[E]] 476; CHECK-NEXT: ret i64 [[F]] 477; 478 %C = sext i32 %A to i128 479 %D = zext i32 %B to i128 480 %E = and i128 %D, 31 481 %F = ashr i128 %C, %E 482 %G = trunc i128 %F to i64 483 ret i64 %G 484} 485 486define <2 x i64> @test13_vec(<2 x i32> %A, <2 x i32> %B) { 487; CHECK-LABEL: @test13_vec( 488; CHECK-NEXT: [[C:%.*]] = sext <2 x i32> [[A:%.*]] to <2 x i64> 489; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], splat (i32 31) 490; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64> 491; CHECK-NEXT: [[F:%.*]] = ashr <2 x i64> [[C]], [[E]] 492; CHECK-NEXT: ret <2 x i64> [[F]] 493; 494 %C = sext <2 x i32> %A to <2 x i128> 495 %D = zext <2 x i32> %B to <2 x i128> 496 %E = and <2 x i128> %D, <i128 31, i128 31> 497 %F = ashr <2 x i128> %C, %E 498 %G = trunc <2 x i128> %F to <2 x i64> 499 ret <2 x i64> %G 500} 501 502define <2 x i64> @test13_vec_nonuniform(<2 x i32> %A, <2 x i32> %B) { 503; CHECK-LABEL: @test13_vec_nonuniform( 504; CHECK-NEXT: [[C:%.*]] = sext <2 x i32> [[A:%.*]] to <2 x i64> 505; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 15> 506; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64> 507; CHECK-NEXT: [[F:%.*]] = ashr <2 x i64> [[C]], [[E]] 508; CHECK-NEXT: ret <2 x i64> [[F]] 509; 510 %C = sext <2 x i32> %A to <2 x i128> 511 %D = zext <2 x i32> %B to <2 x i128> 512 %E = and <2 x i128> %D, <i128 31, i128 15> 513 %F = ashr <2 x i128> %C, %E 514 %G = trunc <2 x i128> %F to <2 x i64> 515 ret <2 x i64> %G 516} 517 518define <2 x i64> @test13_vec_poison(<2 x i32> %A, <2 x i32> %B) { 519; CHECK-LABEL: @test13_vec_poison( 520; CHECK-NEXT: [[C:%.*]] = sext <2 x i32> [[A:%.*]] to <2 x i64> 521; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 poison> 522; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64> 523; CHECK-NEXT: [[G:%.*]] = ashr <2 x i64> [[C]], [[E]] 524; CHECK-NEXT: ret <2 x i64> [[G]] 525; 526 %C = sext <2 x i32> %A to <2 x i128> 527 %D = zext <2 x i32> %B to <2 x i128> 528 %E = and <2 x i128> %D, <i128 31, i128 poison> 529 %F = ashr <2 x i128> %C, %E 530 %G = trunc <2 x i128> %F to <2 x i64> 531 ret <2 x i64> %G 532} 533 534; PR25543 535; https://llvm.org/bugs/show_bug.cgi?id=25543 536; This is an extractelement. 537 538define i32 @trunc_bitcast1(<4 x i32> %v) { 539; CHECK-LABEL: @trunc_bitcast1( 540; CHECK-NEXT: [[EXT:%.*]] = extractelement <4 x i32> [[V:%.*]], i64 1 541; CHECK-NEXT: ret i32 [[EXT]] 542; 543 %bc = bitcast <4 x i32> %v to i128 544 %shr = lshr i128 %bc, 32 545 %ext = trunc i128 %shr to i32 546 ret i32 %ext 547} 548 549; A bitcast may still be required. 550 551define i32 @trunc_bitcast2(<2 x i64> %v) { 552; CHECK-LABEL: @trunc_bitcast2( 553; CHECK-NEXT: [[BC1:%.*]] = bitcast <2 x i64> [[V:%.*]] to <4 x i32> 554; CHECK-NEXT: [[EXT:%.*]] = extractelement <4 x i32> [[BC1]], i64 2 555; CHECK-NEXT: ret i32 [[EXT]] 556; 557 %bc = bitcast <2 x i64> %v to i128 558 %shr = lshr i128 %bc, 64 559 %ext = trunc i128 %shr to i32 560 ret i32 %ext 561} 562 563; The right shift is optional. 564 565define i32 @trunc_bitcast3(<4 x i32> %v) { 566; CHECK-LABEL: @trunc_bitcast3( 567; CHECK-NEXT: [[EXT:%.*]] = extractelement <4 x i32> [[V:%.*]], i64 0 568; CHECK-NEXT: ret i32 [[EXT]] 569; 570 %bc = bitcast <4 x i32> %v to i128 571 %ext = trunc i128 %bc to i32 572 ret i32 %ext 573} 574 575define i32 @trunc_shl_31_i32_i64(i64 %val) { 576; CHECK-LABEL: @trunc_shl_31_i32_i64( 577; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32 578; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31 579; CHECK-NEXT: ret i32 [[TRUNC]] 580; 581 %shl = shl i64 %val, 31 582 %trunc = trunc i64 %shl to i32 583 ret i32 %trunc 584} 585 586define i32 @trunc_shl_nsw_31_i32_i64(i64 %val) { 587; CHECK-LABEL: @trunc_shl_nsw_31_i32_i64( 588; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32 589; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31 590; CHECK-NEXT: ret i32 [[TRUNC]] 591; 592 %shl = shl nsw i64 %val, 31 593 %trunc = trunc i64 %shl to i32 594 ret i32 %trunc 595} 596 597define i32 @trunc_shl_nuw_31_i32_i64(i64 %val) { 598; CHECK-LABEL: @trunc_shl_nuw_31_i32_i64( 599; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32 600; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31 601; CHECK-NEXT: ret i32 [[TRUNC]] 602; 603 %shl = shl nuw i64 %val, 31 604 %trunc = trunc i64 %shl to i32 605 ret i32 %trunc 606} 607 608define i32 @trunc_shl_nsw_nuw_31_i32_i64(i64 %val) { 609; CHECK-LABEL: @trunc_shl_nsw_nuw_31_i32_i64( 610; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32 611; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31 612; CHECK-NEXT: ret i32 [[TRUNC]] 613; 614 %shl = shl nsw nuw i64 %val, 31 615 %trunc = trunc i64 %shl to i32 616 ret i32 %trunc 617} 618 619define i16 @trunc_shl_15_i16_i64(i64 %val) { 620; CHECK-LABEL: @trunc_shl_15_i16_i64( 621; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i16 622; CHECK-NEXT: [[TRUNC:%.*]] = shl i16 [[VAL_TR]], 15 623; CHECK-NEXT: ret i16 [[TRUNC]] 624; 625 %shl = shl i64 %val, 15 626 %trunc = trunc i64 %shl to i16 627 ret i16 %trunc 628} 629 630define i16 @trunc_shl_15_i16_i32(i32 %val) { 631; CHECK-LABEL: @trunc_shl_15_i16_i32( 632; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i32 [[VAL:%.*]] to i16 633; CHECK-NEXT: [[TRUNC:%.*]] = shl i16 [[VAL_TR]], 15 634; CHECK-NEXT: ret i16 [[TRUNC]] 635; 636 %shl = shl i32 %val, 15 637 %trunc = trunc i32 %shl to i16 638 ret i16 %trunc 639} 640 641define i8 @trunc_shl_7_i8_i64(i64 %val) { 642; CHECK-LABEL: @trunc_shl_7_i8_i64( 643; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i8 644; CHECK-NEXT: [[TRUNC:%.*]] = shl i8 [[VAL_TR]], 7 645; CHECK-NEXT: ret i8 [[TRUNC]] 646; 647 %shl = shl i64 %val, 7 648 %trunc = trunc i64 %shl to i8 649 ret i8 %trunc 650} 651 652define i2 @trunc_shl_1_i2_i64(i64 %val) { 653; CHECK-LABEL: @trunc_shl_1_i2_i64( 654; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[VAL:%.*]], 1 655; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[SHL]] to i2 656; CHECK-NEXT: ret i2 [[TRUNC]] 657; 658 %shl = shl i64 %val, 1 659 %trunc = trunc i64 %shl to i2 660 ret i2 %trunc 661} 662 663define i32 @trunc_shl_1_i32_i64(i64 %val) { 664; CHECK-LABEL: @trunc_shl_1_i32_i64( 665; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32 666; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 1 667; CHECK-NEXT: ret i32 [[TRUNC]] 668; 669 %shl = shl i64 %val, 1 670 %trunc = trunc i64 %shl to i32 671 ret i32 %trunc 672} 673 674define i32 @trunc_shl_16_i32_i64(i64 %val) { 675; CHECK-LABEL: @trunc_shl_16_i32_i64( 676; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32 677; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 16 678; CHECK-NEXT: ret i32 [[TRUNC]] 679; 680 %shl = shl i64 %val, 16 681 %trunc = trunc i64 %shl to i32 682 ret i32 %trunc 683} 684 685define i32 @trunc_shl_33_i32_i64(i64 %val) { 686; CHECK-LABEL: @trunc_shl_33_i32_i64( 687; CHECK-NEXT: ret i32 0 688; 689 %shl = shl i64 %val, 33 690 %trunc = trunc i64 %shl to i32 691 ret i32 %trunc 692} 693 694define i32 @trunc_shl_32_i32_i64(i64 %val) { 695; CHECK-LABEL: @trunc_shl_32_i32_i64( 696; CHECK-NEXT: ret i32 0 697; 698 %shl = shl i64 %val, 32 699 %trunc = trunc i64 %shl to i32 700 ret i32 %trunc 701} 702 703; Should be able to handle vectors 704define <2 x i32> @trunc_shl_16_v2i32_v2i64(<2 x i64> %val) { 705; CHECK-LABEL: @trunc_shl_16_v2i32_v2i64( 706; CHECK-NEXT: [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32> 707; CHECK-NEXT: [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], splat (i32 16) 708; CHECK-NEXT: ret <2 x i32> [[TRUNC]] 709; 710 %shl = shl <2 x i64> %val, <i64 16, i64 16> 711 %trunc = trunc <2 x i64> %shl to <2 x i32> 712 ret <2 x i32> %trunc 713} 714 715define <2 x i32> @trunc_shl_nosplat_v2i32_v2i64(<2 x i64> %val) { 716; CHECK-LABEL: @trunc_shl_nosplat_v2i32_v2i64( 717; CHECK-NEXT: [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32> 718; CHECK-NEXT: [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], <i32 15, i32 16> 719; CHECK-NEXT: ret <2 x i32> [[TRUNC]] 720; 721 %shl = shl <2 x i64> %val, <i64 15, i64 16> 722 %trunc = trunc <2 x i64> %shl to <2 x i32> 723 ret <2 x i32> %trunc 724} 725 726define void @trunc_shl_31_i32_i64_multi_use(i64 %val, ptr addrspace(1) %ptr0, ptr addrspace(1) %ptr1) { 727; CHECK-LABEL: @trunc_shl_31_i32_i64_multi_use( 728; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[VAL:%.*]], 31 729; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[SHL]] to i32 730; CHECK-NEXT: store volatile i32 [[TRUNC]], ptr addrspace(1) [[PTR0:%.*]], align 4 731; CHECK-NEXT: store volatile i64 [[SHL]], ptr addrspace(1) [[PTR1:%.*]], align 8 732; CHECK-NEXT: ret void 733; 734 %shl = shl i64 %val, 31 735 %trunc = trunc i64 %shl to i32 736 store volatile i32 %trunc, ptr addrspace(1) %ptr0 737 store volatile i64 %shl, ptr addrspace(1) %ptr1 738 ret void 739} 740 741define i32 @trunc_shl_lshr_infloop(i64 %arg) { 742; CHECK-LABEL: @trunc_shl_lshr_infloop( 743; CHECK-NEXT: [[ARG_TR:%.*]] = trunc i64 [[ARG:%.*]] to i32 744; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[ARG_TR]], 1 745; CHECK-NEXT: [[C:%.*]] = and i32 [[TMP1]], -4 746; CHECK-NEXT: ret i32 [[C]] 747; 748 %A = lshr i64 %arg, 1 749 %B = shl i64 %A, 2 750 %C = trunc i64 %B to i32 751 ret i32 %C 752} 753 754define <2 x i32> @trunc_shl_v2i32_v2i64_uniform(<2 x i64> %val) { 755; CHECK-LABEL: @trunc_shl_v2i32_v2i64_uniform( 756; CHECK-NEXT: [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32> 757; CHECK-NEXT: [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], splat (i32 31) 758; CHECK-NEXT: ret <2 x i32> [[TRUNC]] 759; 760 %shl = shl <2 x i64> %val, <i64 31, i64 31> 761 %trunc = trunc <2 x i64> %shl to <2 x i32> 762 ret <2 x i32> %trunc 763} 764 765define <2 x i32> @trunc_shl_v2i32_v2i64_poison(<2 x i64> %val) { 766; CHECK-LABEL: @trunc_shl_v2i32_v2i64_poison( 767; CHECK-NEXT: [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32> 768; CHECK-NEXT: [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], <i32 31, i32 poison> 769; CHECK-NEXT: ret <2 x i32> [[TRUNC]] 770; 771 %shl = shl <2 x i64> %val, <i64 31, i64 poison> 772 %trunc = trunc <2 x i64> %shl to <2 x i32> 773 ret <2 x i32> %trunc 774} 775 776define <2 x i32> @trunc_shl_v2i32_v2i64_nonuniform(<2 x i64> %val) { 777; CHECK-LABEL: @trunc_shl_v2i32_v2i64_nonuniform( 778; CHECK-NEXT: [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32> 779; CHECK-NEXT: [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], <i32 31, i32 12> 780; CHECK-NEXT: ret <2 x i32> [[TRUNC]] 781; 782 %shl = shl <2 x i64> %val, <i64 31, i64 12> 783 %trunc = trunc <2 x i64> %shl to <2 x i32> 784 ret <2 x i32> %trunc 785} 786 787define <2 x i32> @trunc_shl_v2i32_v2i64_outofrange(<2 x i64> %val) { 788; CHECK-LABEL: @trunc_shl_v2i32_v2i64_outofrange( 789; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i64> [[VAL:%.*]], <i64 31, i64 33> 790; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i64> [[SHL]] to <2 x i32> 791; CHECK-NEXT: ret <2 x i32> [[TRUNC]] 792; 793 %shl = shl <2 x i64> %val, <i64 31, i64 33> 794 %trunc = trunc <2 x i64> %shl to <2 x i32> 795 ret <2 x i32> %trunc 796} 797 798define i32 @trunc_shl_ashr_infloop(i64 %arg) { 799; CHECK-LABEL: @trunc_shl_ashr_infloop( 800; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[ARG:%.*]], 1 801; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32 802; CHECK-NEXT: [[C:%.*]] = and i32 [[TMP2]], -4 803; CHECK-NEXT: ret i32 [[C]] 804; 805 %A = ashr i64 %arg, 3 806 %B = shl i64 %A, 2 807 %C = trunc i64 %B to i32 808 ret i32 %C 809} 810 811define i32 @trunc_shl_shl_infloop(i64 %arg) { 812; CHECK-LABEL: @trunc_shl_shl_infloop( 813; CHECK-NEXT: [[ARG_TR:%.*]] = trunc i64 [[ARG:%.*]] to i32 814; CHECK-NEXT: [[C:%.*]] = shl i32 [[ARG_TR]], 3 815; CHECK-NEXT: ret i32 [[C]] 816; 817 %A = shl i64 %arg, 1 818 %B = shl i64 %A, 2 819 %C = trunc i64 %B to i32 820 ret i32 %C 821} 822 823define i32 @trunc_shl_lshr_var(i64 %arg, i64 %val) { 824; CHECK-LABEL: @trunc_shl_lshr_var( 825; CHECK-NEXT: [[A:%.*]] = lshr i64 [[ARG:%.*]], [[VAL:%.*]] 826; CHECK-NEXT: [[A_TR:%.*]] = trunc i64 [[A]] to i32 827; CHECK-NEXT: [[C:%.*]] = shl i32 [[A_TR]], 2 828; CHECK-NEXT: ret i32 [[C]] 829; 830 %A = lshr i64 %arg, %val 831 %B = shl i64 %A, 2 832 %C = trunc i64 %B to i32 833 ret i32 %C 834} 835 836define i32 @trunc_shl_ashr_var(i64 %arg, i64 %val) { 837; CHECK-LABEL: @trunc_shl_ashr_var( 838; CHECK-NEXT: [[A:%.*]] = ashr i64 [[ARG:%.*]], [[VAL:%.*]] 839; CHECK-NEXT: [[A_TR:%.*]] = trunc i64 [[A]] to i32 840; CHECK-NEXT: [[C:%.*]] = shl i32 [[A_TR]], 2 841; CHECK-NEXT: ret i32 [[C]] 842; 843 %A = ashr i64 %arg, %val 844 %B = shl i64 %A, 2 845 %C = trunc i64 %B to i32 846 ret i32 %C 847} 848 849define i32 @trunc_shl_shl_var(i64 %arg, i64 %val) { 850; CHECK-LABEL: @trunc_shl_shl_var( 851; CHECK-NEXT: [[A:%.*]] = shl i64 [[ARG:%.*]], [[VAL:%.*]] 852; CHECK-NEXT: [[A_TR:%.*]] = trunc i64 [[A]] to i32 853; CHECK-NEXT: [[C:%.*]] = shl i32 [[A_TR]], 2 854; CHECK-NEXT: ret i32 [[C]] 855; 856 %A = shl i64 %arg, %val 857 %B = shl i64 %A, 2 858 %C = trunc i64 %B to i32 859 ret i32 %C 860} 861 862define <8 x i16> @trunc_shl_v8i15_v8i32_15(<8 x i32> %a) { 863; CHECK-LABEL: @trunc_shl_v8i15_v8i32_15( 864; CHECK-NEXT: [[A_TR:%.*]] = trunc <8 x i32> [[A:%.*]] to <8 x i16> 865; CHECK-NEXT: [[CONV:%.*]] = shl <8 x i16> [[A_TR]], splat (i16 15) 866; CHECK-NEXT: ret <8 x i16> [[CONV]] 867; 868 %shl = shl <8 x i32> %a, <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15> 869 %conv = trunc <8 x i32> %shl to <8 x i16> 870 ret <8 x i16> %conv 871} 872 873define <8 x i16> @trunc_shl_v8i16_v8i32_16(<8 x i32> %a) { 874; CHECK-LABEL: @trunc_shl_v8i16_v8i32_16( 875; CHECK-NEXT: ret <8 x i16> zeroinitializer 876; 877 %shl = shl <8 x i32> %a, <i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16> 878 %conv = trunc <8 x i32> %shl to <8 x i16> 879 ret <8 x i16> %conv 880} 881 882define <8 x i16> @trunc_shl_v8i16_v8i32_17(<8 x i32> %a) { 883; CHECK-LABEL: @trunc_shl_v8i16_v8i32_17( 884; CHECK-NEXT: ret <8 x i16> zeroinitializer 885; 886 %shl = shl <8 x i32> %a, <i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17> 887 %conv = trunc <8 x i32> %shl to <8 x i16> 888 ret <8 x i16> %conv 889} 890 891define <8 x i16> @trunc_shl_v8i16_v8i32_4(<8 x i32> %a) { 892; CHECK-LABEL: @trunc_shl_v8i16_v8i32_4( 893; CHECK-NEXT: [[A_TR:%.*]] = trunc <8 x i32> [[A:%.*]] to <8 x i16> 894; CHECK-NEXT: [[CONV:%.*]] = shl <8 x i16> [[A_TR]], splat (i16 4) 895; CHECK-NEXT: ret <8 x i16> [[CONV]] 896; 897 %shl = shl <8 x i32> %a, <i32 4, i32 4, i32 4, i32 4, i32 4, i32 4, i32 4, i32 4> 898 %conv = trunc <8 x i32> %shl to <8 x i16> 899 ret <8 x i16> %conv 900} 901 902; Although the mask is the same value, we don't create a shuffle for types that the backend may not be able to handle: 903; trunc (shuffle X, C, Mask) --> shuffle (trunc X), C', Mask 904 905define <4 x i8> @wide_shuf(<4 x i32> %x) { 906; CHECK-LABEL: @wide_shuf( 907; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> <i32 poison, i32 3634, i32 90, i32 poison>, <4 x i32> <i32 1, i32 5, i32 6, i32 2> 908; CHECK-NEXT: [[TRUNC:%.*]] = trunc <4 x i32> [[SHUF]] to <4 x i8> 909; CHECK-NEXT: ret <4 x i8> [[TRUNC]] 910; 911 %shuf = shufflevector <4 x i32> %x, <4 x i32> <i32 35, i32 3634, i32 90, i32 -1>, <4 x i32> <i32 1, i32 5, i32 6, i32 2> 912 %trunc = trunc <4 x i32> %shuf to <4 x i8> 913 ret <4 x i8> %trunc 914} 915 916; trunc (shuffle X, poison, SplatMask) --> shuffle (trunc X), poison, SplatMask 917 918define <4 x i8> @wide_splat1(<4 x i32> %x) { 919; CHECK-LABEL: @wide_splat1( 920; CHECK-NEXT: [[TMP1:%.*]] = trunc <4 x i32> [[X:%.*]] to <4 x i8> 921; CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2> 922; CHECK-NEXT: ret <4 x i8> [[TRUNC]] 923; 924 %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2> 925 %trunc = trunc <4 x i32> %shuf to <4 x i8> 926 ret <4 x i8> %trunc 927} 928 929; Test weird types. 930; trunc (shuffle X, poison, SplatMask) --> shuffle (trunc X), poison, SplatMask 931 932define <3 x i31> @wide_splat2(<3 x i33> %x) { 933; CHECK-LABEL: @wide_splat2( 934; CHECK-NEXT: [[TMP1:%.*]] = trunc <3 x i33> [[X:%.*]] to <3 x i31> 935; CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <3 x i31> [[TMP1]], <3 x i31> poison, <3 x i32> <i32 1, i32 1, i32 1> 936; CHECK-NEXT: ret <3 x i31> [[TRUNC]] 937; 938 %shuf = shufflevector <3 x i33> %x, <3 x i33> poison, <3 x i32> <i32 1, i32 1, i32 1> 939 %trunc = trunc <3 x i33> %shuf to <3 x i31> 940 ret <3 x i31> %trunc 941} 942 943; FIXME: 944; trunc (shuffle X, poison, SplatMask) --> shuffle (trunc X), poison, SplatMask 945; A mask with poison elements should still be considered a splat mask. 946 947define <3 x i31> @wide_splat3(<3 x i33> %x) { 948; CHECK-LABEL: @wide_splat3( 949; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <3 x i33> [[X:%.*]], <3 x i33> poison, <3 x i32> <i32 poison, i32 1, i32 1> 950; CHECK-NEXT: [[TRUNC:%.*]] = trunc <3 x i33> [[SHUF]] to <3 x i31> 951; CHECK-NEXT: ret <3 x i31> [[TRUNC]] 952; 953 %shuf = shufflevector <3 x i33> %x, <3 x i33> poison, <3 x i32> <i32 poison, i32 1, i32 1> 954 %trunc = trunc <3 x i33> %shuf to <3 x i31> 955 ret <3 x i31> %trunc 956} 957 958; TODO: The shuffle extends the length of the input vector. Should we shrink this? 959 960define <8 x i8> @wide_lengthening_splat(<4 x i16> %v) { 961; CHECK-LABEL: @wide_lengthening_splat( 962; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i16> [[V:%.*]], <4 x i16> poison, <8 x i32> zeroinitializer 963; CHECK-NEXT: [[TR:%.*]] = trunc <8 x i16> [[SHUF]] to <8 x i8> 964; CHECK-NEXT: ret <8 x i8> [[TR]] 965; 966 %shuf = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> zeroinitializer 967 %tr = trunc <8 x i16> %shuf to <8 x i8> 968 ret <8 x i8> %tr 969} 970 971define <2 x i8> @narrow_add_vec_constant(<2 x i32> %x) { 972; CHECK-LABEL: @narrow_add_vec_constant( 973; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[X:%.*]] to <2 x i8> 974; CHECK-NEXT: [[TR:%.*]] = add <2 x i8> [[TMP1]], <i8 0, i8 127> 975; CHECK-NEXT: ret <2 x i8> [[TR]] 976; 977 %add = add <2 x i32> %x, <i32 256, i32 -129> 978 %tr = trunc <2 x i32> %add to <2 x i8> 979 ret <2 x i8> %tr 980} 981 982define <2 x i8> @narrow_mul_vec_constant(<2 x i32> %x) { 983; CHECK-LABEL: @narrow_mul_vec_constant( 984; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[X:%.*]] to <2 x i8> 985; CHECK-NEXT: [[TR:%.*]] = mul <2 x i8> [[TMP1]], <i8 0, i8 127> 986; CHECK-NEXT: ret <2 x i8> [[TR]] 987; 988 %add = mul <2 x i32> %x, <i32 256, i32 -129> 989 %tr = trunc <2 x i32> %add to <2 x i8> 990 ret <2 x i8> %tr 991} 992 993define <2 x i8> @narrow_sub_vec_constant(<2 x i32> %x) { 994; CHECK-LABEL: @narrow_sub_vec_constant( 995; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[X:%.*]] to <2 x i8> 996; CHECK-NEXT: [[TR:%.*]] = sub <2 x i8> <i8 0, i8 127>, [[TMP1]] 997; CHECK-NEXT: ret <2 x i8> [[TR]] 998; 999 %sub = sub <2 x i32> <i32 256, i32 -129>, %x 1000 %tr = trunc <2 x i32> %sub to <2 x i8> 1001 ret <2 x i8> %tr 1002} 1003 1004; If the select is narrowed based on the target's datalayout, we allow more optimizations. 1005 1006define i16 @PR44545(i32 %t0, i32 %data) { 1007; CHECK-LABEL: @PR44545( 1008; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[DATA:%.*]], 0 1009; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[T0:%.*]] to i16 1010; CHECK-NEXT: [[SUB:%.*]] = select i1 [[ISZERO]], i16 -1, i16 [[TMP1]] 1011; CHECK-NEXT: ret i16 [[SUB]] 1012; 1013 %t1 = add nuw nsw i32 %t0, 1 1014 %iszero = icmp eq i32 %data, 0 1015 %ffs = select i1 %iszero, i32 0, i32 %t1 1016 %cast = trunc i32 %ffs to i16 1017 %sub = add nsw i16 %cast, -1 1018 ret i16 %sub 1019} 1020