1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; Check that instcombine rewrites multiply by a vector 5; of known constant power-of-2 elements with vector shift. 6 7define <4 x i8> @Zero_i8(<4 x i8> %InVec) { 8; CHECK-LABEL: @Zero_i8( 9; CHECK-NEXT: entry: 10; CHECK-NEXT: ret <4 x i8> zeroinitializer 11; 12entry: 13 %mul = mul <4 x i8> %InVec, <i8 0, i8 0, i8 0, i8 0> 14 ret <4 x i8> %mul 15} 16 17define <4 x i8> @Identity_i8(<4 x i8> %InVec) { 18; CHECK-LABEL: @Identity_i8( 19; CHECK-NEXT: entry: 20; CHECK-NEXT: ret <4 x i8> [[INVEC:%.*]] 21; 22entry: 23 %mul = mul <4 x i8> %InVec, <i8 1, i8 1, i8 1, i8 1> 24 ret <4 x i8> %mul 25} 26 27define <4 x i8> @AddToSelf_i8(<4 x i8> %InVec) { 28; CHECK-LABEL: @AddToSelf_i8( 29; CHECK-NEXT: entry: 30; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i8> [[INVEC:%.*]], <i8 1, i8 1, i8 1, i8 1> 31; CHECK-NEXT: ret <4 x i8> [[MUL]] 32; 33entry: 34 %mul = mul <4 x i8> %InVec, <i8 2, i8 2, i8 2, i8 2> 35 ret <4 x i8> %mul 36} 37 38define <4 x i8> @SplatPow2Test1_i8(<4 x i8> %InVec) { 39; CHECK-LABEL: @SplatPow2Test1_i8( 40; CHECK-NEXT: entry: 41; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i8> [[INVEC:%.*]], <i8 2, i8 2, i8 2, i8 2> 42; CHECK-NEXT: ret <4 x i8> [[MUL]] 43; 44entry: 45 %mul = mul <4 x i8> %InVec, <i8 4, i8 4, i8 4, i8 4> 46 ret <4 x i8> %mul 47} 48 49define <4 x i8> @SplatPow2Test2_i8(<4 x i8> %InVec) { 50; CHECK-LABEL: @SplatPow2Test2_i8( 51; CHECK-NEXT: entry: 52; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i8> [[INVEC:%.*]], <i8 3, i8 3, i8 3, i8 3> 53; CHECK-NEXT: ret <4 x i8> [[MUL]] 54; 55entry: 56 %mul = mul <4 x i8> %InVec, <i8 8, i8 8, i8 8, i8 8> 57 ret <4 x i8> %mul 58} 59 60define <4 x i8> @MulTest1_i8(<4 x i8> %InVec) { 61; CHECK-LABEL: @MulTest1_i8( 62; CHECK-NEXT: entry: 63; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i8> [[INVEC:%.*]], <i8 0, i8 1, i8 2, i8 3> 64; CHECK-NEXT: ret <4 x i8> [[MUL]] 65; 66entry: 67 %mul = mul <4 x i8> %InVec, <i8 1, i8 2, i8 4, i8 8> 68 ret <4 x i8> %mul 69} 70 71define <4 x i8> @MulTest2_i8(<4 x i8> %InVec) { 72; CHECK-LABEL: @MulTest2_i8( 73; CHECK-NEXT: entry: 74; CHECK-NEXT: [[MUL:%.*]] = mul <4 x i8> [[INVEC:%.*]], <i8 3, i8 3, i8 3, i8 3> 75; CHECK-NEXT: ret <4 x i8> [[MUL]] 76; 77entry: 78 %mul = mul <4 x i8> %InVec, <i8 3, i8 3, i8 3, i8 3> 79 ret <4 x i8> %mul 80} 81 82define <4 x i8> @MulTest3_i8(<4 x i8> %InVec) { 83; CHECK-LABEL: @MulTest3_i8( 84; CHECK-NEXT: entry: 85; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i8> [[INVEC:%.*]], <i8 2, i8 2, i8 1, i8 1> 86; CHECK-NEXT: ret <4 x i8> [[MUL]] 87; 88entry: 89 %mul = mul <4 x i8> %InVec, <i8 4, i8 4, i8 2, i8 2> 90 ret <4 x i8> %mul 91} 92 93define <4 x i8> @MulTest4_i8(<4 x i8> %InVec) { 94; CHECK-LABEL: @MulTest4_i8( 95; CHECK-NEXT: entry: 96; CHECK-NEXT: [[MUL:%.*]] = mul <4 x i8> [[INVEC:%.*]], <i8 4, i8 4, i8 0, i8 1> 97; CHECK-NEXT: ret <4 x i8> [[MUL]] 98; 99entry: 100 %mul = mul <4 x i8> %InVec, <i8 4, i8 4, i8 0, i8 1> 101 ret <4 x i8> %mul 102} 103 104define <4 x i16> @Zero_i16(<4 x i16> %InVec) { 105; CHECK-LABEL: @Zero_i16( 106; CHECK-NEXT: entry: 107; CHECK-NEXT: ret <4 x i16> zeroinitializer 108; 109entry: 110 %mul = mul <4 x i16> %InVec, <i16 0, i16 0, i16 0, i16 0> 111 ret <4 x i16> %mul 112} 113 114define <4 x i16> @Identity_i16(<4 x i16> %InVec) { 115; CHECK-LABEL: @Identity_i16( 116; CHECK-NEXT: entry: 117; CHECK-NEXT: ret <4 x i16> [[INVEC:%.*]] 118; 119entry: 120 %mul = mul <4 x i16> %InVec, <i16 1, i16 1, i16 1, i16 1> 121 ret <4 x i16> %mul 122} 123 124define <4 x i16> @AddToSelf_i16(<4 x i16> %InVec) { 125; CHECK-LABEL: @AddToSelf_i16( 126; CHECK-NEXT: entry: 127; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i16> [[INVEC:%.*]], <i16 1, i16 1, i16 1, i16 1> 128; CHECK-NEXT: ret <4 x i16> [[MUL]] 129; 130entry: 131 %mul = mul <4 x i16> %InVec, <i16 2, i16 2, i16 2, i16 2> 132 ret <4 x i16> %mul 133} 134 135define <4 x i16> @SplatPow2Test1_i16(<4 x i16> %InVec) { 136; CHECK-LABEL: @SplatPow2Test1_i16( 137; CHECK-NEXT: entry: 138; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i16> [[INVEC:%.*]], <i16 2, i16 2, i16 2, i16 2> 139; CHECK-NEXT: ret <4 x i16> [[MUL]] 140; 141entry: 142 %mul = mul <4 x i16> %InVec, <i16 4, i16 4, i16 4, i16 4> 143 ret <4 x i16> %mul 144} 145 146define <4 x i16> @SplatPow2Test2_i16(<4 x i16> %InVec) { 147; CHECK-LABEL: @SplatPow2Test2_i16( 148; CHECK-NEXT: entry: 149; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i16> [[INVEC:%.*]], <i16 3, i16 3, i16 3, i16 3> 150; CHECK-NEXT: ret <4 x i16> [[MUL]] 151; 152entry: 153 %mul = mul <4 x i16> %InVec, <i16 8, i16 8, i16 8, i16 8> 154 ret <4 x i16> %mul 155} 156 157define <4 x i16> @MulTest1_i16(<4 x i16> %InVec) { 158; CHECK-LABEL: @MulTest1_i16( 159; CHECK-NEXT: entry: 160; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i16> [[INVEC:%.*]], <i16 0, i16 1, i16 2, i16 3> 161; CHECK-NEXT: ret <4 x i16> [[MUL]] 162; 163entry: 164 %mul = mul <4 x i16> %InVec, <i16 1, i16 2, i16 4, i16 8> 165 ret <4 x i16> %mul 166} 167 168define <4 x i16> @MulTest2_i16(<4 x i16> %InVec) { 169; CHECK-LABEL: @MulTest2_i16( 170; CHECK-NEXT: entry: 171; CHECK-NEXT: [[MUL:%.*]] = mul <4 x i16> [[INVEC:%.*]], <i16 3, i16 3, i16 3, i16 3> 172; CHECK-NEXT: ret <4 x i16> [[MUL]] 173; 174entry: 175 %mul = mul <4 x i16> %InVec, <i16 3, i16 3, i16 3, i16 3> 176 ret <4 x i16> %mul 177} 178 179define <4 x i16> @MulTest3_i16(<4 x i16> %InVec) { 180; CHECK-LABEL: @MulTest3_i16( 181; CHECK-NEXT: entry: 182; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i16> [[INVEC:%.*]], <i16 2, i16 2, i16 1, i16 1> 183; CHECK-NEXT: ret <4 x i16> [[MUL]] 184; 185entry: 186 %mul = mul <4 x i16> %InVec, <i16 4, i16 4, i16 2, i16 2> 187 ret <4 x i16> %mul 188} 189 190define <4 x i16> @MulTest4_i16(<4 x i16> %InVec) { 191; CHECK-LABEL: @MulTest4_i16( 192; CHECK-NEXT: entry: 193; CHECK-NEXT: [[MUL:%.*]] = mul <4 x i16> [[INVEC:%.*]], <i16 4, i16 4, i16 0, i16 2> 194; CHECK-NEXT: ret <4 x i16> [[MUL]] 195; 196entry: 197 %mul = mul <4 x i16> %InVec, <i16 4, i16 4, i16 0, i16 2> 198 ret <4 x i16> %mul 199} 200 201define <4 x i32> @Zero_i32(<4 x i32> %InVec) { 202; CHECK-LABEL: @Zero_i32( 203; CHECK-NEXT: entry: 204; CHECK-NEXT: ret <4 x i32> zeroinitializer 205; 206entry: 207 %mul = mul <4 x i32> %InVec, <i32 0, i32 0, i32 0, i32 0> 208 ret <4 x i32> %mul 209} 210 211define <4 x i32> @Identity_i32(<4 x i32> %InVec) { 212; CHECK-LABEL: @Identity_i32( 213; CHECK-NEXT: entry: 214; CHECK-NEXT: ret <4 x i32> [[INVEC:%.*]] 215; 216entry: 217 %mul = mul <4 x i32> %InVec, <i32 1, i32 1, i32 1, i32 1> 218 ret <4 x i32> %mul 219} 220 221define <4 x i32> @AddToSelf_i32(<4 x i32> %InVec) { 222; CHECK-LABEL: @AddToSelf_i32( 223; CHECK-NEXT: entry: 224; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i32> [[INVEC:%.*]], <i32 1, i32 1, i32 1, i32 1> 225; CHECK-NEXT: ret <4 x i32> [[MUL]] 226; 227entry: 228 %mul = mul <4 x i32> %InVec, <i32 2, i32 2, i32 2, i32 2> 229 ret <4 x i32> %mul 230} 231 232define <4 x i32> @SplatPow2Test1_i32(<4 x i32> %InVec) { 233; CHECK-LABEL: @SplatPow2Test1_i32( 234; CHECK-NEXT: entry: 235; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i32> [[INVEC:%.*]], <i32 2, i32 2, i32 2, i32 2> 236; CHECK-NEXT: ret <4 x i32> [[MUL]] 237; 238entry: 239 %mul = mul <4 x i32> %InVec, <i32 4, i32 4, i32 4, i32 4> 240 ret <4 x i32> %mul 241} 242 243define <4 x i32> @SplatPow2Test2_i32(<4 x i32> %InVec) { 244; CHECK-LABEL: @SplatPow2Test2_i32( 245; CHECK-NEXT: entry: 246; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i32> [[INVEC:%.*]], <i32 3, i32 3, i32 3, i32 3> 247; CHECK-NEXT: ret <4 x i32> [[MUL]] 248; 249entry: 250 %mul = mul <4 x i32> %InVec, <i32 8, i32 8, i32 8, i32 8> 251 ret <4 x i32> %mul 252} 253 254define <4 x i32> @MulTest1_i32(<4 x i32> %InVec) { 255; CHECK-LABEL: @MulTest1_i32( 256; CHECK-NEXT: entry: 257; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i32> [[INVEC:%.*]], <i32 0, i32 1, i32 2, i32 3> 258; CHECK-NEXT: ret <4 x i32> [[MUL]] 259; 260entry: 261 %mul = mul <4 x i32> %InVec, <i32 1, i32 2, i32 4, i32 8> 262 ret <4 x i32> %mul 263} 264 265define <4 x i32> @MulTest2_i32(<4 x i32> %InVec) { 266; CHECK-LABEL: @MulTest2_i32( 267; CHECK-NEXT: entry: 268; CHECK-NEXT: [[MUL:%.*]] = mul <4 x i32> [[INVEC:%.*]], <i32 3, i32 3, i32 3, i32 3> 269; CHECK-NEXT: ret <4 x i32> [[MUL]] 270; 271entry: 272 %mul = mul <4 x i32> %InVec, <i32 3, i32 3, i32 3, i32 3> 273 ret <4 x i32> %mul 274} 275 276define <4 x i32> @MulTest3_i32(<4 x i32> %InVec) { 277; CHECK-LABEL: @MulTest3_i32( 278; CHECK-NEXT: entry: 279; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i32> [[INVEC:%.*]], <i32 2, i32 2, i32 1, i32 1> 280; CHECK-NEXT: ret <4 x i32> [[MUL]] 281; 282entry: 283 %mul = mul <4 x i32> %InVec, <i32 4, i32 4, i32 2, i32 2> 284 ret <4 x i32> %mul 285} 286 287define <4 x i32> @MulTest4_i32(<4 x i32> %InVec) { 288; CHECK-LABEL: @MulTest4_i32( 289; CHECK-NEXT: entry: 290; CHECK-NEXT: [[MUL:%.*]] = mul <4 x i32> [[INVEC:%.*]], <i32 4, i32 4, i32 0, i32 1> 291; CHECK-NEXT: ret <4 x i32> [[MUL]] 292; 293entry: 294 %mul = mul <4 x i32> %InVec, <i32 4, i32 4, i32 0, i32 1> 295 ret <4 x i32> %mul 296} 297 298define <4 x i64> @Zero_i64(<4 x i64> %InVec) { 299; CHECK-LABEL: @Zero_i64( 300; CHECK-NEXT: entry: 301; CHECK-NEXT: ret <4 x i64> zeroinitializer 302; 303entry: 304 %mul = mul <4 x i64> %InVec, <i64 0, i64 0, i64 0, i64 0> 305 ret <4 x i64> %mul 306} 307 308define <4 x i64> @Identity_i64(<4 x i64> %InVec) { 309; CHECK-LABEL: @Identity_i64( 310; CHECK-NEXT: entry: 311; CHECK-NEXT: ret <4 x i64> [[INVEC:%.*]] 312; 313entry: 314 %mul = mul <4 x i64> %InVec, <i64 1, i64 1, i64 1, i64 1> 315 ret <4 x i64> %mul 316} 317 318define <4 x i64> @AddToSelf_i64(<4 x i64> %InVec) { 319; CHECK-LABEL: @AddToSelf_i64( 320; CHECK-NEXT: entry: 321; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i64> [[INVEC:%.*]], <i64 1, i64 1, i64 1, i64 1> 322; CHECK-NEXT: ret <4 x i64> [[MUL]] 323; 324entry: 325 %mul = mul <4 x i64> %InVec, <i64 2, i64 2, i64 2, i64 2> 326 ret <4 x i64> %mul 327} 328 329define <4 x i64> @SplatPow2Test1_i64(<4 x i64> %InVec) { 330; CHECK-LABEL: @SplatPow2Test1_i64( 331; CHECK-NEXT: entry: 332; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i64> [[INVEC:%.*]], <i64 2, i64 2, i64 2, i64 2> 333; CHECK-NEXT: ret <4 x i64> [[MUL]] 334; 335entry: 336 %mul = mul <4 x i64> %InVec, <i64 4, i64 4, i64 4, i64 4> 337 ret <4 x i64> %mul 338} 339 340define <4 x i64> @SplatPow2Test2_i64(<4 x i64> %InVec) { 341; CHECK-LABEL: @SplatPow2Test2_i64( 342; CHECK-NEXT: entry: 343; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i64> [[INVEC:%.*]], <i64 3, i64 3, i64 3, i64 3> 344; CHECK-NEXT: ret <4 x i64> [[MUL]] 345; 346entry: 347 %mul = mul <4 x i64> %InVec, <i64 8, i64 8, i64 8, i64 8> 348 ret <4 x i64> %mul 349} 350 351define <4 x i64> @MulTest1_i64(<4 x i64> %InVec) { 352; CHECK-LABEL: @MulTest1_i64( 353; CHECK-NEXT: entry: 354; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i64> [[INVEC:%.*]], <i64 0, i64 1, i64 2, i64 3> 355; CHECK-NEXT: ret <4 x i64> [[MUL]] 356; 357entry: 358 %mul = mul <4 x i64> %InVec, <i64 1, i64 2, i64 4, i64 8> 359 ret <4 x i64> %mul 360} 361 362define <4 x i64> @MulTest2_i64(<4 x i64> %InVec) { 363; CHECK-LABEL: @MulTest2_i64( 364; CHECK-NEXT: entry: 365; CHECK-NEXT: [[MUL:%.*]] = mul <4 x i64> [[INVEC:%.*]], <i64 3, i64 3, i64 3, i64 3> 366; CHECK-NEXT: ret <4 x i64> [[MUL]] 367; 368entry: 369 %mul = mul <4 x i64> %InVec, <i64 3, i64 3, i64 3, i64 3> 370 ret <4 x i64> %mul 371} 372 373define <4 x i64> @MulTest3_i64(<4 x i64> %InVec) { 374; CHECK-LABEL: @MulTest3_i64( 375; CHECK-NEXT: entry: 376; CHECK-NEXT: [[MUL:%.*]] = shl <4 x i64> [[INVEC:%.*]], <i64 2, i64 2, i64 1, i64 1> 377; CHECK-NEXT: ret <4 x i64> [[MUL]] 378; 379entry: 380 %mul = mul <4 x i64> %InVec, <i64 4, i64 4, i64 2, i64 2> 381 ret <4 x i64> %mul 382} 383 384define <4 x i64> @MulTest4_i64(<4 x i64> %InVec) { 385; CHECK-LABEL: @MulTest4_i64( 386; CHECK-NEXT: entry: 387; CHECK-NEXT: [[MUL:%.*]] = mul <4 x i64> [[INVEC:%.*]], <i64 4, i64 4, i64 0, i64 1> 388; CHECK-NEXT: ret <4 x i64> [[MUL]] 389; 390entry: 391 %mul = mul <4 x i64> %InVec, <i64 4, i64 4, i64 0, i64 1> 392 ret <4 x i64> %mul 393} 394 395; Test also that the following rewriting rule works with vectors 396; of integers as well: 397; ((X << C1)*C2) == (X * (C2 << C1)) 398 399define <4 x i8> @ShiftMulTest1(<4 x i8> %InVec) { 400; CHECK-LABEL: @ShiftMulTest1( 401; CHECK-NEXT: entry: 402; CHECK-NEXT: [[MUL:%.*]] = mul <4 x i8> [[INVEC:%.*]], <i8 12, i8 12, i8 12, i8 12> 403; CHECK-NEXT: ret <4 x i8> [[MUL]] 404; 405entry: 406 %shl = shl <4 x i8> %InVec, <i8 2, i8 2, i8 2, i8 2> 407 %mul = mul <4 x i8> %shl, <i8 3, i8 3, i8 3, i8 3> 408 ret <4 x i8> %mul 409} 410 411define <4 x i16> @ShiftMulTest2(<4 x i16> %InVec) { 412; CHECK-LABEL: @ShiftMulTest2( 413; CHECK-NEXT: entry: 414; CHECK-NEXT: [[MUL:%.*]] = mul <4 x i16> [[INVEC:%.*]], <i16 12, i16 12, i16 12, i16 12> 415; CHECK-NEXT: ret <4 x i16> [[MUL]] 416; 417entry: 418 %shl = shl <4 x i16> %InVec, <i16 2, i16 2, i16 2, i16 2> 419 %mul = mul <4 x i16> %shl, <i16 3, i16 3, i16 3, i16 3> 420 ret <4 x i16> %mul 421} 422 423define <4 x i32> @ShiftMulTest3(<4 x i32> %InVec) { 424; CHECK-LABEL: @ShiftMulTest3( 425; CHECK-NEXT: entry: 426; CHECK-NEXT: [[MUL:%.*]] = mul <4 x i32> [[INVEC:%.*]], <i32 12, i32 12, i32 12, i32 12> 427; CHECK-NEXT: ret <4 x i32> [[MUL]] 428; 429entry: 430 %shl = shl <4 x i32> %InVec, <i32 2, i32 2, i32 2, i32 2> 431 %mul = mul <4 x i32> %shl, <i32 3, i32 3, i32 3, i32 3> 432 ret <4 x i32> %mul 433} 434 435define <4 x i64> @ShiftMulTest4(<4 x i64> %InVec) { 436; CHECK-LABEL: @ShiftMulTest4( 437; CHECK-NEXT: entry: 438; CHECK-NEXT: [[MUL:%.*]] = mul <4 x i64> [[INVEC:%.*]], <i64 12, i64 12, i64 12, i64 12> 439; CHECK-NEXT: ret <4 x i64> [[MUL]] 440; 441entry: 442 %shl = shl <4 x i64> %InVec, <i64 2, i64 2, i64 2, i64 2> 443 %mul = mul <4 x i64> %shl, <i64 3, i64 3, i64 3, i64 3> 444 ret <4 x i64> %mul 445} 446