1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=mips-linux-gnu -march=mips -mcpu=mips32 | FileCheck %s --check-prefixes=CHECK,CHECK-BE 3; RUN: llc < %s -mtriple=mipsel-linux-gnu -march=mipsel -mcpu=mips32 | FileCheck %s --check-prefixes=CHECK,CHECK-LE 4 5declare i8 @llvm.fshl.i8(i8, i8, i8) 6declare i16 @llvm.fshl.i16(i16, i16, i16) 7declare i32 @llvm.fshl.i32(i32, i32, i32) 8declare i64 @llvm.fshl.i64(i64, i64, i64) 9declare <4 x i32> @llvm.fshl.v4i32(<4 x i32>, <4 x i32>, <4 x i32>) 10 11declare i8 @llvm.fshr.i8(i8, i8, i8) 12declare i16 @llvm.fshr.i16(i16, i16, i16) 13declare i32 @llvm.fshr.i32(i32, i32, i32) 14declare i64 @llvm.fshr.i64(i64, i64, i64) 15declare <4 x i32> @llvm.fshr.v4i32(<4 x i32>, <4 x i32>, <4 x i32>) 16 17; When first 2 operands match, it's a rotate. 18 19define i8 @rotl_i8_const_shift(i8 %x) { 20; CHECK-LABEL: rotl_i8_const_shift: 21; CHECK: # %bb.0: 22; CHECK-NEXT: sll $1, $4, 3 23; CHECK-NEXT: andi $2, $4, 224 24; CHECK-NEXT: srl $2, $2, 5 25; CHECK-NEXT: jr $ra 26; CHECK-NEXT: or $2, $1, $2 27 %f = call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 3) 28 ret i8 %f 29} 30 31define i64 @rotl_i64_const_shift(i64 %x) { 32; CHECK-LABEL: rotl_i64_const_shift: 33; CHECK: # %bb.0: 34; CHECK-NEXT: srl $1, $5, 29 35; CHECK-NEXT: sll $2, $4, 3 36; CHECK-NEXT: or $2, $2, $1 37; CHECK-NEXT: srl $1, $4, 29 38; CHECK-NEXT: sll $3, $5, 3 39; CHECK-NEXT: jr $ra 40; CHECK-NEXT: or $3, $3, $1 41 %f = call i64 @llvm.fshl.i64(i64 %x, i64 %x, i64 3) 42 ret i64 %f 43} 44 45; When first 2 operands match, it's a rotate (by variable amount). 46 47define i16 @rotl_i16(i16 %x, i16 %z) { 48; CHECK-LABEL: rotl_i16: 49; CHECK: # %bb.0: 50; CHECK-NEXT: andi $1, $5, 15 51; CHECK-NEXT: sllv $1, $4, $1 52; CHECK-NEXT: negu $2, $5 53; CHECK-NEXT: andi $2, $2, 15 54; CHECK-NEXT: andi $3, $4, 65535 55; CHECK-NEXT: srlv $2, $3, $2 56; CHECK-NEXT: jr $ra 57; CHECK-NEXT: or $2, $1, $2 58 %f = call i16 @llvm.fshl.i16(i16 %x, i16 %x, i16 %z) 59 ret i16 %f 60} 61 62define i32 @rotl_i32(i32 %x, i32 %z) { 63; CHECK-LABEL: rotl_i32: 64; CHECK: # %bb.0: 65; CHECK-NEXT: andi $1, $5, 31 66; CHECK-NEXT: sllv $1, $4, $1 67; CHECK-NEXT: negu $2, $5 68; CHECK-NEXT: andi $2, $2, 31 69; CHECK-NEXT: srlv $2, $4, $2 70; CHECK-NEXT: jr $ra 71; CHECK-NEXT: or $2, $1, $2 72 %f = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %z) 73 ret i32 %f 74} 75 76define i64 @rotl_i64(i64 %x, i64 %z) { 77; CHECK-BE-LABEL: rotl_i64: 78; CHECK-BE: # %bb.0: 79; CHECK-BE-NEXT: srl $1, $7, 5 80; CHECK-BE-NEXT: andi $1, $1, 1 81; CHECK-BE-NEXT: move $3, $4 82; CHECK-BE-NEXT: movn $3, $5, $1 83; CHECK-BE-NEXT: andi $6, $7, 31 84; CHECK-BE-NEXT: sllv $2, $3, $6 85; CHECK-BE-NEXT: movn $5, $4, $1 86; CHECK-BE-NEXT: srl $1, $5, 1 87; CHECK-BE-NEXT: not $4, $7 88; CHECK-BE-NEXT: andi $4, $4, 31 89; CHECK-BE-NEXT: srlv $1, $1, $4 90; CHECK-BE-NEXT: or $2, $2, $1 91; CHECK-BE-NEXT: sllv $1, $5, $6 92; CHECK-BE-NEXT: srl $3, $3, 1 93; CHECK-BE-NEXT: srlv $3, $3, $4 94; CHECK-BE-NEXT: jr $ra 95; CHECK-BE-NEXT: or $3, $1, $3 96; 97; CHECK-LE-LABEL: rotl_i64: 98; CHECK-LE: # %bb.0: 99; CHECK-LE-NEXT: srl $1, $6, 5 100; CHECK-LE-NEXT: andi $1, $1, 1 101; CHECK-LE-NEXT: move $3, $4 102; CHECK-LE-NEXT: movn $3, $5, $1 103; CHECK-LE-NEXT: andi $7, $6, 31 104; CHECK-LE-NEXT: sllv $2, $3, $7 105; CHECK-LE-NEXT: movn $5, $4, $1 106; CHECK-LE-NEXT: srl $1, $5, 1 107; CHECK-LE-NEXT: not $4, $6 108; CHECK-LE-NEXT: andi $4, $4, 31 109; CHECK-LE-NEXT: srlv $1, $1, $4 110; CHECK-LE-NEXT: or $2, $2, $1 111; CHECK-LE-NEXT: sllv $1, $5, $7 112; CHECK-LE-NEXT: srl $3, $3, 1 113; CHECK-LE-NEXT: srlv $3, $3, $4 114; CHECK-LE-NEXT: jr $ra 115; CHECK-LE-NEXT: or $3, $1, $3 116 %f = call i64 @llvm.fshl.i64(i64 %x, i64 %x, i64 %z) 117 ret i64 %f 118} 119 120; Vector rotate. 121 122define <4 x i32> @rotl_v4i32(<4 x i32> %x, <4 x i32> %z) { 123; CHECK-LABEL: rotl_v4i32: 124; CHECK: # %bb.0: 125; CHECK-NEXT: lw $1, 24($sp) 126; CHECK-NEXT: negu $2, $1 127; CHECK-NEXT: lw $3, 20($sp) 128; CHECK-NEXT: negu $8, $3 129; CHECK-NEXT: andi $8, $8, 31 130; CHECK-NEXT: andi $2, $2, 31 131; CHECK-NEXT: andi $3, $3, 31 132; CHECK-NEXT: andi $1, $1, 31 133; CHECK-NEXT: lw $9, 16($sp) 134; CHECK-NEXT: sllv $1, $6, $1 135; CHECK-NEXT: srlv $6, $6, $2 136; CHECK-NEXT: sllv $3, $5, $3 137; CHECK-NEXT: srlv $5, $5, $8 138; CHECK-NEXT: andi $2, $9, 31 139; CHECK-NEXT: sllv $2, $4, $2 140; CHECK-NEXT: negu $8, $9 141; CHECK-NEXT: andi $8, $8, 31 142; CHECK-NEXT: srlv $4, $4, $8 143; CHECK-NEXT: lw $8, 28($sp) 144; CHECK-NEXT: or $2, $2, $4 145; CHECK-NEXT: or $3, $3, $5 146; CHECK-NEXT: or $4, $1, $6 147; CHECK-NEXT: andi $1, $8, 31 148; CHECK-NEXT: sllv $1, $7, $1 149; CHECK-NEXT: negu $5, $8 150; CHECK-NEXT: andi $5, $5, 31 151; CHECK-NEXT: srlv $5, $7, $5 152; CHECK-NEXT: jr $ra 153; CHECK-NEXT: or $5, $1, $5 154 %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> %z) 155 ret <4 x i32> %f 156} 157 158; Vector rotate by constant splat amount. 159 160define <4 x i32> @rotl_v4i32_rotl_const_shift(<4 x i32> %x) { 161; CHECK-LABEL: rotl_v4i32_rotl_const_shift: 162; CHECK: # %bb.0: 163; CHECK-NEXT: srl $1, $5, 29 164; CHECK-NEXT: sll $3, $5, 3 165; CHECK-NEXT: srl $2, $4, 29 166; CHECK-NEXT: sll $4, $4, 3 167; CHECK-NEXT: or $2, $4, $2 168; CHECK-NEXT: or $3, $3, $1 169; CHECK-NEXT: srl $1, $6, 29 170; CHECK-NEXT: sll $4, $6, 3 171; CHECK-NEXT: or $4, $4, $1 172; CHECK-NEXT: srl $1, $7, 29 173; CHECK-NEXT: sll $5, $7, 3 174; CHECK-NEXT: jr $ra 175; CHECK-NEXT: or $5, $5, $1 176 %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> <i32 3, i32 3, i32 3, i32 3>) 177 ret <4 x i32> %f 178} 179 180; Repeat everything for funnel shift right. 181 182; When first 2 operands match, it's a rotate. 183 184define i8 @rotr_i8_const_shift(i8 %x) { 185; CHECK-LABEL: rotr_i8_const_shift: 186; CHECK: # %bb.0: 187; CHECK-NEXT: sll $1, $4, 5 188; CHECK-NEXT: andi $2, $4, 248 189; CHECK-NEXT: srl $2, $2, 3 190; CHECK-NEXT: jr $ra 191; CHECK-NEXT: or $2, $2, $1 192 %f = call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 3) 193 ret i8 %f 194} 195 196define i32 @rotr_i32_const_shift(i32 %x) { 197; CHECK-LABEL: rotr_i32_const_shift: 198; CHECK: # %bb.0: 199; CHECK-NEXT: sll $1, $4, 29 200; CHECK-NEXT: srl $2, $4, 3 201; CHECK-NEXT: jr $ra 202; CHECK-NEXT: or $2, $2, $1 203 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 3) 204 ret i32 %f 205} 206 207; When first 2 operands match, it's a rotate (by variable amount). 208 209define i16 @rotr_i16(i16 %x, i16 %z) { 210; CHECK-LABEL: rotr_i16: 211; CHECK: # %bb.0: 212; CHECK-NEXT: andi $1, $5, 15 213; CHECK-NEXT: andi $2, $4, 65535 214; CHECK-NEXT: srlv $1, $2, $1 215; CHECK-NEXT: negu $2, $5 216; CHECK-NEXT: andi $2, $2, 15 217; CHECK-NEXT: sllv $2, $4, $2 218; CHECK-NEXT: jr $ra 219; CHECK-NEXT: or $2, $1, $2 220 %f = call i16 @llvm.fshr.i16(i16 %x, i16 %x, i16 %z) 221 ret i16 %f 222} 223 224define i32 @rotr_i32(i32 %x, i32 %z) { 225; CHECK-LABEL: rotr_i32: 226; CHECK: # %bb.0: 227; CHECK-NEXT: andi $1, $5, 31 228; CHECK-NEXT: srlv $1, $4, $1 229; CHECK-NEXT: negu $2, $5 230; CHECK-NEXT: andi $2, $2, 31 231; CHECK-NEXT: sllv $2, $4, $2 232; CHECK-NEXT: jr $ra 233; CHECK-NEXT: or $2, $1, $2 234 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %z) 235 ret i32 %f 236} 237 238define i64 @rotr_i64(i64 %x, i64 %z) { 239; CHECK-BE-LABEL: rotr_i64: 240; CHECK-BE: # %bb.0: 241; CHECK-BE-NEXT: andi $1, $7, 32 242; CHECK-BE-NEXT: move $3, $5 243; CHECK-BE-NEXT: movz $3, $4, $1 244; CHECK-BE-NEXT: andi $6, $7, 31 245; CHECK-BE-NEXT: srlv $2, $3, $6 246; CHECK-BE-NEXT: movz $4, $5, $1 247; CHECK-BE-NEXT: sll $1, $4, 1 248; CHECK-BE-NEXT: not $5, $7 249; CHECK-BE-NEXT: andi $5, $5, 31 250; CHECK-BE-NEXT: sllv $1, $1, $5 251; CHECK-BE-NEXT: or $2, $1, $2 252; CHECK-BE-NEXT: srlv $1, $4, $6 253; CHECK-BE-NEXT: sll $3, $3, 1 254; CHECK-BE-NEXT: sllv $3, $3, $5 255; CHECK-BE-NEXT: jr $ra 256; CHECK-BE-NEXT: or $3, $3, $1 257; 258; CHECK-LE-LABEL: rotr_i64: 259; CHECK-LE: # %bb.0: 260; CHECK-LE-NEXT: andi $1, $6, 32 261; CHECK-LE-NEXT: move $3, $5 262; CHECK-LE-NEXT: movz $3, $4, $1 263; CHECK-LE-NEXT: andi $7, $6, 31 264; CHECK-LE-NEXT: srlv $2, $3, $7 265; CHECK-LE-NEXT: movz $4, $5, $1 266; CHECK-LE-NEXT: sll $1, $4, 1 267; CHECK-LE-NEXT: not $5, $6 268; CHECK-LE-NEXT: andi $5, $5, 31 269; CHECK-LE-NEXT: sllv $1, $1, $5 270; CHECK-LE-NEXT: or $2, $1, $2 271; CHECK-LE-NEXT: srlv $1, $4, $7 272; CHECK-LE-NEXT: sll $3, $3, 1 273; CHECK-LE-NEXT: sllv $3, $3, $5 274; CHECK-LE-NEXT: jr $ra 275; CHECK-LE-NEXT: or $3, $3, $1 276 %f = call i64 @llvm.fshr.i64(i64 %x, i64 %x, i64 %z) 277 ret i64 %f 278} 279 280; Vector rotate. 281 282define <4 x i32> @rotr_v4i32(<4 x i32> %x, <4 x i32> %z) { 283; CHECK-LABEL: rotr_v4i32: 284; CHECK: # %bb.0: 285; CHECK-NEXT: lw $1, 24($sp) 286; CHECK-NEXT: negu $2, $1 287; CHECK-NEXT: lw $3, 20($sp) 288; CHECK-NEXT: negu $8, $3 289; CHECK-NEXT: andi $8, $8, 31 290; CHECK-NEXT: andi $2, $2, 31 291; CHECK-NEXT: andi $3, $3, 31 292; CHECK-NEXT: andi $1, $1, 31 293; CHECK-NEXT: lw $9, 16($sp) 294; CHECK-NEXT: srlv $1, $6, $1 295; CHECK-NEXT: sllv $6, $6, $2 296; CHECK-NEXT: srlv $3, $5, $3 297; CHECK-NEXT: sllv $5, $5, $8 298; CHECK-NEXT: andi $2, $9, 31 299; CHECK-NEXT: srlv $2, $4, $2 300; CHECK-NEXT: negu $8, $9 301; CHECK-NEXT: andi $8, $8, 31 302; CHECK-NEXT: sllv $4, $4, $8 303; CHECK-NEXT: lw $8, 28($sp) 304; CHECK-NEXT: or $2, $2, $4 305; CHECK-NEXT: or $3, $3, $5 306; CHECK-NEXT: or $4, $1, $6 307; CHECK-NEXT: andi $1, $8, 31 308; CHECK-NEXT: srlv $1, $7, $1 309; CHECK-NEXT: negu $5, $8 310; CHECK-NEXT: andi $5, $5, 31 311; CHECK-NEXT: sllv $5, $7, $5 312; CHECK-NEXT: jr $ra 313; CHECK-NEXT: or $5, $1, $5 314 %f = call <4 x i32> @llvm.fshr.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> %z) 315 ret <4 x i32> %f 316} 317 318; Vector rotate by constant splat amount. 319 320define <4 x i32> @rotr_v4i32_const_shift(<4 x i32> %x) { 321; CHECK-LABEL: rotr_v4i32_const_shift: 322; CHECK: # %bb.0: 323; CHECK-NEXT: sll $1, $5, 29 324; CHECK-NEXT: srl $3, $5, 3 325; CHECK-NEXT: sll $2, $4, 29 326; CHECK-NEXT: srl $4, $4, 3 327; CHECK-NEXT: or $2, $4, $2 328; CHECK-NEXT: or $3, $3, $1 329; CHECK-NEXT: sll $1, $6, 29 330; CHECK-NEXT: srl $4, $6, 3 331; CHECK-NEXT: or $4, $4, $1 332; CHECK-NEXT: sll $1, $7, 29 333; CHECK-NEXT: srl $5, $7, 3 334; CHECK-NEXT: jr $ra 335; CHECK-NEXT: or $5, $5, $1 336 %f = call <4 x i32> @llvm.fshr.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> <i32 3, i32 3, i32 3, i32 3>) 337 ret <4 x i32> %f 338} 339 340define i32 @rotl_i32_shift_by_bitwidth(i32 %x) { 341; CHECK-LABEL: rotl_i32_shift_by_bitwidth: 342; CHECK: # %bb.0: 343; CHECK-NEXT: jr $ra 344; CHECK-NEXT: move $2, $4 345 %f = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 32) 346 ret i32 %f 347} 348 349define i32 @rotr_i32_shift_by_bitwidth(i32 %x) { 350; CHECK-LABEL: rotr_i32_shift_by_bitwidth: 351; CHECK: # %bb.0: 352; CHECK-NEXT: jr $ra 353; CHECK-NEXT: move $2, $4 354 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 32) 355 ret i32 %f 356} 357 358define <4 x i32> @rotl_v4i32_shift_by_bitwidth(<4 x i32> %x) { 359; CHECK-LABEL: rotl_v4i32_shift_by_bitwidth: 360; CHECK: # %bb.0: 361; CHECK-NEXT: move $2, $4 362; CHECK-NEXT: move $3, $5 363; CHECK-NEXT: move $4, $6 364; CHECK-NEXT: jr $ra 365; CHECK-NEXT: move $5, $7 366 %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> <i32 32, i32 32, i32 32, i32 32>) 367 ret <4 x i32> %f 368} 369 370define <4 x i32> @rotr_v4i32_shift_by_bitwidth(<4 x i32> %x) { 371; CHECK-LABEL: rotr_v4i32_shift_by_bitwidth: 372; CHECK: # %bb.0: 373; CHECK-NEXT: move $2, $4 374; CHECK-NEXT: move $3, $5 375; CHECK-NEXT: move $4, $6 376; CHECK-NEXT: jr $ra 377; CHECK-NEXT: move $5, $7 378 %f = call <4 x i32> @llvm.fshr.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> <i32 32, i32 32, i32 32, i32 32>) 379 ret <4 x i32> %f 380} 381 382