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; General case - all operands can be variables. 18 19define i16 @fshl_i16(i16 %x, i16 %y, i16 %z) { 20; CHECK-LABEL: fshl_i16: 21; CHECK: # %bb.0: 22; CHECK-NEXT: andi $1, $5, 65535 23; CHECK-NEXT: sll $2, $4, 16 24; CHECK-NEXT: or $1, $2, $1 25; CHECK-NEXT: andi $2, $6, 15 26; CHECK-NEXT: sllv $1, $1, $2 27; CHECK-NEXT: jr $ra 28; CHECK-NEXT: srl $2, $1, 16 29 %f = call i16 @llvm.fshl.i16(i16 %x, i16 %y, i16 %z) 30 ret i16 %f 31} 32 33define i32 @fshl_i32(i32 %x, i32 %y, i32 %z) { 34; CHECK-LABEL: fshl_i32: 35; CHECK: # %bb.0: 36; CHECK-NEXT: andi $1, $6, 31 37; CHECK-NEXT: sllv $1, $4, $1 38; CHECK-NEXT: srl $2, $5, 1 39; CHECK-NEXT: not $3, $6 40; CHECK-NEXT: andi $3, $3, 31 41; CHECK-NEXT: srlv $2, $2, $3 42; CHECK-NEXT: jr $ra 43; CHECK-NEXT: or $2, $1, $2 44 %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %z) 45 ret i32 %f 46} 47 48; Verify that weird types are minimally supported. 49declare i37 @llvm.fshl.i37(i37, i37, i37) 50define i37 @fshl_i37(i37 %x, i37 %y, i37 %z) { 51; CHECK-BE-LABEL: fshl_i37: 52; CHECK-BE: # %bb.0: 53; CHECK-BE-NEXT: addiu $sp, $sp, -40 54; CHECK-BE-NEXT: .cfi_def_cfa_offset 40 55; CHECK-BE-NEXT: sw $ra, 36($sp) # 4-byte Folded Spill 56; CHECK-BE-NEXT: sw $19, 32($sp) # 4-byte Folded Spill 57; CHECK-BE-NEXT: sw $18, 28($sp) # 4-byte Folded Spill 58; CHECK-BE-NEXT: sw $17, 24($sp) # 4-byte Folded Spill 59; CHECK-BE-NEXT: sw $16, 20($sp) # 4-byte Folded Spill 60; CHECK-BE-NEXT: .cfi_offset 31, -4 61; CHECK-BE-NEXT: .cfi_offset 19, -8 62; CHECK-BE-NEXT: .cfi_offset 18, -12 63; CHECK-BE-NEXT: .cfi_offset 17, -16 64; CHECK-BE-NEXT: .cfi_offset 16, -20 65; CHECK-BE-NEXT: move $16, $7 66; CHECK-BE-NEXT: move $17, $6 67; CHECK-BE-NEXT: move $18, $5 68; CHECK-BE-NEXT: move $19, $4 69; CHECK-BE-NEXT: lw $4, 56($sp) 70; CHECK-BE-NEXT: lw $5, 60($sp) 71; CHECK-BE-NEXT: addiu $6, $zero, 0 72; CHECK-BE-NEXT: jal __umoddi3 73; CHECK-BE-NEXT: addiu $7, $zero, 37 74; CHECK-BE-NEXT: not $1, $3 75; CHECK-BE-NEXT: andi $2, $3, 63 76; CHECK-BE-NEXT: not $4, $2 77; CHECK-BE-NEXT: srl $5, $18, 1 78; CHECK-BE-NEXT: sllv $6, $19, $2 79; CHECK-BE-NEXT: srlv $4, $5, $4 80; CHECK-BE-NEXT: andi $5, $1, 63 81; CHECK-BE-NEXT: srl $7, $16, 5 82; CHECK-BE-NEXT: sll $8, $17, 27 83; CHECK-BE-NEXT: or $7, $8, $7 84; CHECK-BE-NEXT: srl $8, $7, 1 85; CHECK-BE-NEXT: srlv $9, $8, $5 86; CHECK-BE-NEXT: andi $1, $1, 32 87; CHECK-BE-NEXT: move $10, $9 88; CHECK-BE-NEXT: movn $10, $zero, $1 89; CHECK-BE-NEXT: or $4, $6, $4 90; CHECK-BE-NEXT: sllv $6, $18, $2 91; CHECK-BE-NEXT: andi $3, $3, 32 92; CHECK-BE-NEXT: movn $4, $6, $3 93; CHECK-BE-NEXT: sll $7, $7, 31 94; CHECK-BE-NEXT: sll $2, $16, 27 95; CHECK-BE-NEXT: srl $11, $2, 1 96; CHECK-BE-NEXT: or $2, $4, $10 97; CHECK-BE-NEXT: movn $6, $zero, $3 98; CHECK-BE-NEXT: or $3, $11, $7 99; CHECK-BE-NEXT: srlv $3, $3, $5 100; CHECK-BE-NEXT: not $4, $5 101; CHECK-BE-NEXT: sll $5, $8, 1 102; CHECK-BE-NEXT: sllv $4, $5, $4 103; CHECK-BE-NEXT: or $3, $4, $3 104; CHECK-BE-NEXT: movn $3, $9, $1 105; CHECK-BE-NEXT: or $3, $6, $3 106; CHECK-BE-NEXT: lw $16, 20($sp) # 4-byte Folded Reload 107; CHECK-BE-NEXT: lw $17, 24($sp) # 4-byte Folded Reload 108; CHECK-BE-NEXT: lw $18, 28($sp) # 4-byte Folded Reload 109; CHECK-BE-NEXT: lw $19, 32($sp) # 4-byte Folded Reload 110; CHECK-BE-NEXT: lw $ra, 36($sp) # 4-byte Folded Reload 111; CHECK-BE-NEXT: jr $ra 112; CHECK-BE-NEXT: addiu $sp, $sp, 40 113; 114; CHECK-LE-LABEL: fshl_i37: 115; CHECK-LE: # %bb.0: 116; CHECK-LE-NEXT: addiu $sp, $sp, -40 117; CHECK-LE-NEXT: .cfi_def_cfa_offset 40 118; CHECK-LE-NEXT: sw $ra, 36($sp) # 4-byte Folded Spill 119; CHECK-LE-NEXT: sw $19, 32($sp) # 4-byte Folded Spill 120; CHECK-LE-NEXT: sw $18, 28($sp) # 4-byte Folded Spill 121; CHECK-LE-NEXT: sw $17, 24($sp) # 4-byte Folded Spill 122; CHECK-LE-NEXT: sw $16, 20($sp) # 4-byte Folded Spill 123; CHECK-LE-NEXT: .cfi_offset 31, -4 124; CHECK-LE-NEXT: .cfi_offset 19, -8 125; CHECK-LE-NEXT: .cfi_offset 18, -12 126; CHECK-LE-NEXT: .cfi_offset 17, -16 127; CHECK-LE-NEXT: .cfi_offset 16, -20 128; CHECK-LE-NEXT: move $16, $7 129; CHECK-LE-NEXT: move $17, $6 130; CHECK-LE-NEXT: move $18, $5 131; CHECK-LE-NEXT: move $19, $4 132; CHECK-LE-NEXT: lw $4, 56($sp) 133; CHECK-LE-NEXT: lw $5, 60($sp) 134; CHECK-LE-NEXT: addiu $6, $zero, 37 135; CHECK-LE-NEXT: jal __umoddi3 136; CHECK-LE-NEXT: addiu $7, $zero, 0 137; CHECK-LE-NEXT: not $1, $2 138; CHECK-LE-NEXT: andi $3, $2, 63 139; CHECK-LE-NEXT: not $4, $3 140; CHECK-LE-NEXT: srl $5, $19, 1 141; CHECK-LE-NEXT: sllv $6, $18, $3 142; CHECK-LE-NEXT: srlv $4, $5, $4 143; CHECK-LE-NEXT: andi $5, $1, 63 144; CHECK-LE-NEXT: srl $7, $17, 5 145; CHECK-LE-NEXT: sll $8, $16, 27 146; CHECK-LE-NEXT: or $7, $8, $7 147; CHECK-LE-NEXT: srl $8, $7, 1 148; CHECK-LE-NEXT: srlv $9, $8, $5 149; CHECK-LE-NEXT: andi $1, $1, 32 150; CHECK-LE-NEXT: move $10, $9 151; CHECK-LE-NEXT: movn $10, $zero, $1 152; CHECK-LE-NEXT: or $4, $6, $4 153; CHECK-LE-NEXT: sllv $6, $19, $3 154; CHECK-LE-NEXT: andi $2, $2, 32 155; CHECK-LE-NEXT: movn $4, $6, $2 156; CHECK-LE-NEXT: sll $7, $7, 31 157; CHECK-LE-NEXT: sll $3, $17, 27 158; CHECK-LE-NEXT: srl $11, $3, 1 159; CHECK-LE-NEXT: or $3, $4, $10 160; CHECK-LE-NEXT: movn $6, $zero, $2 161; CHECK-LE-NEXT: or $2, $11, $7 162; CHECK-LE-NEXT: srlv $2, $2, $5 163; CHECK-LE-NEXT: not $4, $5 164; CHECK-LE-NEXT: sll $5, $8, 1 165; CHECK-LE-NEXT: sllv $4, $5, $4 166; CHECK-LE-NEXT: or $2, $4, $2 167; CHECK-LE-NEXT: movn $2, $9, $1 168; CHECK-LE-NEXT: or $2, $6, $2 169; CHECK-LE-NEXT: lw $16, 20($sp) # 4-byte Folded Reload 170; CHECK-LE-NEXT: lw $17, 24($sp) # 4-byte Folded Reload 171; CHECK-LE-NEXT: lw $18, 28($sp) # 4-byte Folded Reload 172; CHECK-LE-NEXT: lw $19, 32($sp) # 4-byte Folded Reload 173; CHECK-LE-NEXT: lw $ra, 36($sp) # 4-byte Folded Reload 174; CHECK-LE-NEXT: jr $ra 175; CHECK-LE-NEXT: addiu $sp, $sp, 40 176 %f = call i37 @llvm.fshl.i37(i37 %x, i37 %y, i37 %z) 177 ret i37 %f 178} 179 180; extract(concat(0b1110000, 0b1111111) << 2) = 0b1000011 181 182declare i7 @llvm.fshl.i7(i7, i7, i7) 183define i7 @fshl_i7_const_fold() { 184; CHECK-LABEL: fshl_i7_const_fold: 185; CHECK: # %bb.0: 186; CHECK-NEXT: jr $ra 187; CHECK-NEXT: addiu $2, $zero, 67 188 %f = call i7 @llvm.fshl.i7(i7 112, i7 127, i7 2) 189 ret i7 %f 190} 191 192define i8 @fshl_i8_const_fold_overshift_1() { 193; CHECK-LABEL: fshl_i8_const_fold_overshift_1: 194; CHECK: # %bb.0: 195; CHECK-NEXT: jr $ra 196; CHECK-NEXT: addiu $2, $zero, 128 197 %f = call i8 @llvm.fshl.i8(i8 255, i8 0, i8 15) 198 ret i8 %f 199} 200 201define i8 @fshl_i8_const_fold_overshift_2() { 202; CHECK-LABEL: fshl_i8_const_fold_overshift_2: 203; CHECK: # %bb.0: 204; CHECK-NEXT: jr $ra 205; CHECK-NEXT: addiu $2, $zero, 120 206 %f = call i8 @llvm.fshl.i8(i8 15, i8 15, i8 11) 207 ret i8 %f 208} 209 210define i8 @fshl_i8_const_fold_overshift_3() { 211; CHECK-LABEL: fshl_i8_const_fold_overshift_3: 212; CHECK: # %bb.0: 213; CHECK-NEXT: jr $ra 214; CHECK-NEXT: addiu $2, $zero, 0 215 %f = call i8 @llvm.fshl.i8(i8 0, i8 225, i8 8) 216 ret i8 %f 217} 218 219; With constant shift amount, this is 'extr'. 220 221define i32 @fshl_i32_const_shift(i32 %x, i32 %y) { 222; CHECK-LABEL: fshl_i32_const_shift: 223; CHECK: # %bb.0: 224; CHECK-NEXT: srl $1, $5, 23 225; CHECK-NEXT: sll $2, $4, 9 226; CHECK-NEXT: jr $ra 227; CHECK-NEXT: or $2, $2, $1 228 %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 9) 229 ret i32 %f 230} 231 232; Check modulo math on shift amount. 233 234define i32 @fshl_i32_const_overshift(i32 %x, i32 %y) { 235; CHECK-LABEL: fshl_i32_const_overshift: 236; CHECK: # %bb.0: 237; CHECK-NEXT: srl $1, $5, 23 238; CHECK-NEXT: sll $2, $4, 9 239; CHECK-NEXT: jr $ra 240; CHECK-NEXT: or $2, $2, $1 241 %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 41) 242 ret i32 %f 243} 244 245; 64-bit should also work. 246 247define i64 @fshl_i64_const_overshift(i64 %x, i64 %y) { 248; CHECK-BE-LABEL: fshl_i64_const_overshift: 249; CHECK-BE: # %bb.0: 250; CHECK-BE-NEXT: srl $1, $6, 23 251; CHECK-BE-NEXT: sll $2, $5, 9 252; CHECK-BE-NEXT: or $2, $2, $1 253; CHECK-BE-NEXT: sll $1, $6, 9 254; CHECK-BE-NEXT: srl $3, $7, 23 255; CHECK-BE-NEXT: jr $ra 256; CHECK-BE-NEXT: or $3, $3, $1 257; 258; CHECK-LE-LABEL: fshl_i64_const_overshift: 259; CHECK-LE: # %bb.0: 260; CHECK-LE-NEXT: sll $1, $7, 9 261; CHECK-LE-NEXT: srl $2, $6, 23 262; CHECK-LE-NEXT: or $2, $2, $1 263; CHECK-LE-NEXT: srl $1, $7, 23 264; CHECK-LE-NEXT: sll $3, $4, 9 265; CHECK-LE-NEXT: jr $ra 266; CHECK-LE-NEXT: or $3, $3, $1 267 %f = call i64 @llvm.fshl.i64(i64 %x, i64 %y, i64 105) 268 ret i64 %f 269} 270 271; This should work without any node-specific logic. 272 273define i8 @fshl_i8_const_fold() { 274; CHECK-LABEL: fshl_i8_const_fold: 275; CHECK: # %bb.0: 276; CHECK-NEXT: jr $ra 277; CHECK-NEXT: addiu $2, $zero, 128 278 %f = call i8 @llvm.fshl.i8(i8 255, i8 0, i8 7) 279 ret i8 %f 280} 281 282; Repeat everything for funnel shift right. 283 284; General case - all operands can be variables. 285 286define i16 @fshr_i16(i16 %x, i16 %y, i16 %z) { 287; CHECK-LABEL: fshr_i16: 288; CHECK: # %bb.0: 289; CHECK-NEXT: andi $1, $5, 65535 290; CHECK-NEXT: sll $2, $4, 16 291; CHECK-NEXT: or $1, $2, $1 292; CHECK-NEXT: andi $2, $6, 15 293; CHECK-NEXT: jr $ra 294; CHECK-NEXT: srlv $2, $1, $2 295 %f = call i16 @llvm.fshr.i16(i16 %x, i16 %y, i16 %z) 296 ret i16 %f 297} 298 299define i32 @fshr_i32(i32 %x, i32 %y, i32 %z) { 300; CHECK-LABEL: fshr_i32: 301; CHECK: # %bb.0: 302; CHECK-NEXT: andi $1, $6, 31 303; CHECK-NEXT: srlv $1, $5, $1 304; CHECK-NEXT: sll $2, $4, 1 305; CHECK-NEXT: not $3, $6 306; CHECK-NEXT: andi $3, $3, 31 307; CHECK-NEXT: sllv $2, $2, $3 308; CHECK-NEXT: jr $ra 309; CHECK-NEXT: or $2, $2, $1 310 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %z) 311 ret i32 %f 312} 313 314; Verify that weird types are minimally supported. 315declare i37 @llvm.fshr.i37(i37, i37, i37) 316define i37 @fshr_i37(i37 %x, i37 %y, i37 %z) { 317; CHECK-BE-LABEL: fshr_i37: 318; CHECK-BE: # %bb.0: 319; CHECK-BE-NEXT: addiu $sp, $sp, -40 320; CHECK-BE-NEXT: .cfi_def_cfa_offset 40 321; CHECK-BE-NEXT: sw $ra, 36($sp) # 4-byte Folded Spill 322; CHECK-BE-NEXT: sw $19, 32($sp) # 4-byte Folded Spill 323; CHECK-BE-NEXT: sw $18, 28($sp) # 4-byte Folded Spill 324; CHECK-BE-NEXT: sw $17, 24($sp) # 4-byte Folded Spill 325; CHECK-BE-NEXT: sw $16, 20($sp) # 4-byte Folded Spill 326; CHECK-BE-NEXT: .cfi_offset 31, -4 327; CHECK-BE-NEXT: .cfi_offset 19, -8 328; CHECK-BE-NEXT: .cfi_offset 18, -12 329; CHECK-BE-NEXT: .cfi_offset 17, -16 330; CHECK-BE-NEXT: .cfi_offset 16, -20 331; CHECK-BE-NEXT: move $16, $7 332; CHECK-BE-NEXT: move $17, $6 333; CHECK-BE-NEXT: move $18, $5 334; CHECK-BE-NEXT: move $19, $4 335; CHECK-BE-NEXT: lw $4, 56($sp) 336; CHECK-BE-NEXT: lw $5, 60($sp) 337; CHECK-BE-NEXT: addiu $6, $zero, 0 338; CHECK-BE-NEXT: jal __umoddi3 339; CHECK-BE-NEXT: addiu $7, $zero, 37 340; CHECK-BE-NEXT: addiu $1, $3, 27 341; CHECK-BE-NEXT: andi $2, $1, 63 342; CHECK-BE-NEXT: not $3, $2 343; CHECK-BE-NEXT: srl $4, $16, 5 344; CHECK-BE-NEXT: sll $5, $17, 27 345; CHECK-BE-NEXT: or $4, $5, $4 346; CHECK-BE-NEXT: sll $5, $4, 1 347; CHECK-BE-NEXT: sll $6, $16, 27 348; CHECK-BE-NEXT: srlv $6, $6, $2 349; CHECK-BE-NEXT: sllv $3, $5, $3 350; CHECK-BE-NEXT: not $5, $1 351; CHECK-BE-NEXT: andi $7, $5, 63 352; CHECK-BE-NEXT: sll $8, $18, 1 353; CHECK-BE-NEXT: sllv $8, $8, $7 354; CHECK-BE-NEXT: andi $5, $5, 32 355; CHECK-BE-NEXT: move $9, $8 356; CHECK-BE-NEXT: movn $9, $zero, $5 357; CHECK-BE-NEXT: or $3, $3, $6 358; CHECK-BE-NEXT: srlv $2, $4, $2 359; CHECK-BE-NEXT: andi $1, $1, 32 360; CHECK-BE-NEXT: movn $3, $2, $1 361; CHECK-BE-NEXT: srl $4, $18, 31 362; CHECK-BE-NEXT: sll $6, $19, 1 363; CHECK-BE-NEXT: or $4, $6, $4 364; CHECK-BE-NEXT: or $3, $9, $3 365; CHECK-BE-NEXT: movn $2, $zero, $1 366; CHECK-BE-NEXT: sllv $1, $4, $7 367; CHECK-BE-NEXT: not $4, $7 368; CHECK-BE-NEXT: lui $6, 32767 369; CHECK-BE-NEXT: ori $6, $6, 65535 370; CHECK-BE-NEXT: and $6, $18, $6 371; CHECK-BE-NEXT: srlv $4, $6, $4 372; CHECK-BE-NEXT: or $1, $1, $4 373; CHECK-BE-NEXT: movn $1, $8, $5 374; CHECK-BE-NEXT: or $2, $1, $2 375; CHECK-BE-NEXT: lw $16, 20($sp) # 4-byte Folded Reload 376; CHECK-BE-NEXT: lw $17, 24($sp) # 4-byte Folded Reload 377; CHECK-BE-NEXT: lw $18, 28($sp) # 4-byte Folded Reload 378; CHECK-BE-NEXT: lw $19, 32($sp) # 4-byte Folded Reload 379; CHECK-BE-NEXT: lw $ra, 36($sp) # 4-byte Folded Reload 380; CHECK-BE-NEXT: jr $ra 381; CHECK-BE-NEXT: addiu $sp, $sp, 40 382; 383; CHECK-LE-LABEL: fshr_i37: 384; CHECK-LE: # %bb.0: 385; CHECK-LE-NEXT: addiu $sp, $sp, -40 386; CHECK-LE-NEXT: .cfi_def_cfa_offset 40 387; CHECK-LE-NEXT: sw $ra, 36($sp) # 4-byte Folded Spill 388; CHECK-LE-NEXT: sw $19, 32($sp) # 4-byte Folded Spill 389; CHECK-LE-NEXT: sw $18, 28($sp) # 4-byte Folded Spill 390; CHECK-LE-NEXT: sw $17, 24($sp) # 4-byte Folded Spill 391; CHECK-LE-NEXT: sw $16, 20($sp) # 4-byte Folded Spill 392; CHECK-LE-NEXT: .cfi_offset 31, -4 393; CHECK-LE-NEXT: .cfi_offset 19, -8 394; CHECK-LE-NEXT: .cfi_offset 18, -12 395; CHECK-LE-NEXT: .cfi_offset 17, -16 396; CHECK-LE-NEXT: .cfi_offset 16, -20 397; CHECK-LE-NEXT: move $16, $7 398; CHECK-LE-NEXT: move $17, $6 399; CHECK-LE-NEXT: move $18, $5 400; CHECK-LE-NEXT: move $19, $4 401; CHECK-LE-NEXT: lw $4, 56($sp) 402; CHECK-LE-NEXT: lw $5, 60($sp) 403; CHECK-LE-NEXT: addiu $6, $zero, 37 404; CHECK-LE-NEXT: jal __umoddi3 405; CHECK-LE-NEXT: addiu $7, $zero, 0 406; CHECK-LE-NEXT: addiu $1, $2, 27 407; CHECK-LE-NEXT: andi $2, $1, 63 408; CHECK-LE-NEXT: not $3, $2 409; CHECK-LE-NEXT: srl $4, $17, 5 410; CHECK-LE-NEXT: sll $5, $16, 27 411; CHECK-LE-NEXT: or $4, $5, $4 412; CHECK-LE-NEXT: sll $5, $4, 1 413; CHECK-LE-NEXT: sll $6, $17, 27 414; CHECK-LE-NEXT: srlv $6, $6, $2 415; CHECK-LE-NEXT: sllv $3, $5, $3 416; CHECK-LE-NEXT: not $5, $1 417; CHECK-LE-NEXT: andi $7, $5, 63 418; CHECK-LE-NEXT: sll $8, $19, 1 419; CHECK-LE-NEXT: sllv $8, $8, $7 420; CHECK-LE-NEXT: andi $5, $5, 32 421; CHECK-LE-NEXT: move $9, $8 422; CHECK-LE-NEXT: movn $9, $zero, $5 423; CHECK-LE-NEXT: or $3, $3, $6 424; CHECK-LE-NEXT: srlv $4, $4, $2 425; CHECK-LE-NEXT: andi $1, $1, 32 426; CHECK-LE-NEXT: movn $3, $4, $1 427; CHECK-LE-NEXT: srl $2, $19, 31 428; CHECK-LE-NEXT: sll $6, $18, 1 429; CHECK-LE-NEXT: or $6, $6, $2 430; CHECK-LE-NEXT: or $2, $9, $3 431; CHECK-LE-NEXT: movn $4, $zero, $1 432; CHECK-LE-NEXT: sllv $1, $6, $7 433; CHECK-LE-NEXT: not $3, $7 434; CHECK-LE-NEXT: lui $6, 32767 435; CHECK-LE-NEXT: ori $6, $6, 65535 436; CHECK-LE-NEXT: and $6, $19, $6 437; CHECK-LE-NEXT: srlv $3, $6, $3 438; CHECK-LE-NEXT: or $1, $1, $3 439; CHECK-LE-NEXT: movn $1, $8, $5 440; CHECK-LE-NEXT: or $3, $1, $4 441; CHECK-LE-NEXT: lw $16, 20($sp) # 4-byte Folded Reload 442; CHECK-LE-NEXT: lw $17, 24($sp) # 4-byte Folded Reload 443; CHECK-LE-NEXT: lw $18, 28($sp) # 4-byte Folded Reload 444; CHECK-LE-NEXT: lw $19, 32($sp) # 4-byte Folded Reload 445; CHECK-LE-NEXT: lw $ra, 36($sp) # 4-byte Folded Reload 446; CHECK-LE-NEXT: jr $ra 447; CHECK-LE-NEXT: addiu $sp, $sp, 40 448 %f = call i37 @llvm.fshr.i37(i37 %x, i37 %y, i37 %z) 449 ret i37 %f 450} 451 452; extract(concat(0b1110000, 0b1111111) >> 2) = 0b0011111 453 454declare i7 @llvm.fshr.i7(i7, i7, i7) 455define i7 @fshr_i7_const_fold() { 456; CHECK-LABEL: fshr_i7_const_fold: 457; CHECK: # %bb.0: 458; CHECK-NEXT: jr $ra 459; CHECK-NEXT: addiu $2, $zero, 31 460 %f = call i7 @llvm.fshr.i7(i7 112, i7 127, i7 2) 461 ret i7 %f 462} 463 464define i8 @fshr_i8_const_fold_overshift_1() { 465; CHECK-LABEL: fshr_i8_const_fold_overshift_1: 466; CHECK: # %bb.0: 467; CHECK-NEXT: jr $ra 468; CHECK-NEXT: addiu $2, $zero, 254 469 %f = call i8 @llvm.fshr.i8(i8 255, i8 0, i8 15) 470 ret i8 %f 471} 472 473define i8 @fshr_i8_const_fold_overshift_2() { 474; CHECK-LABEL: fshr_i8_const_fold_overshift_2: 475; CHECK: # %bb.0: 476; CHECK-NEXT: jr $ra 477; CHECK-NEXT: addiu $2, $zero, 225 478 %f = call i8 @llvm.fshr.i8(i8 15, i8 15, i8 11) 479 ret i8 %f 480} 481 482define i8 @fshr_i8_const_fold_overshift_3() { 483; CHECK-LABEL: fshr_i8_const_fold_overshift_3: 484; CHECK: # %bb.0: 485; CHECK-NEXT: jr $ra 486; CHECK-NEXT: addiu $2, $zero, 255 487 %f = call i8 @llvm.fshr.i8(i8 0, i8 255, i8 8) 488 ret i8 %f 489} 490 491; With constant shift amount, this is 'extr'. 492 493define i32 @fshr_i32_const_shift(i32 %x, i32 %y) { 494; CHECK-LABEL: fshr_i32_const_shift: 495; CHECK: # %bb.0: 496; CHECK-NEXT: srl $1, $5, 9 497; CHECK-NEXT: sll $2, $4, 23 498; CHECK-NEXT: jr $ra 499; CHECK-NEXT: or $2, $2, $1 500 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 9) 501 ret i32 %f 502} 503 504; Check modulo math on shift amount. 41-32=9. 505 506define i32 @fshr_i32_const_overshift(i32 %x, i32 %y) { 507; CHECK-LABEL: fshr_i32_const_overshift: 508; CHECK: # %bb.0: 509; CHECK-NEXT: srl $1, $5, 9 510; CHECK-NEXT: sll $2, $4, 23 511; CHECK-NEXT: jr $ra 512; CHECK-NEXT: or $2, $2, $1 513 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 41) 514 ret i32 %f 515} 516 517; 64-bit should also work. 105-64 = 41. 518 519define i64 @fshr_i64_const_overshift(i64 %x, i64 %y) { 520; CHECK-BE-LABEL: fshr_i64_const_overshift: 521; CHECK-BE: # %bb.0: 522; CHECK-BE-NEXT: srl $1, $5, 9 523; CHECK-BE-NEXT: sll $2, $4, 23 524; CHECK-BE-NEXT: or $2, $2, $1 525; CHECK-BE-NEXT: srl $1, $6, 9 526; CHECK-BE-NEXT: sll $3, $5, 23 527; CHECK-BE-NEXT: jr $ra 528; CHECK-BE-NEXT: or $3, $3, $1 529; 530; CHECK-LE-LABEL: fshr_i64_const_overshift: 531; CHECK-LE: # %bb.0: 532; CHECK-LE-NEXT: srl $1, $7, 9 533; CHECK-LE-NEXT: sll $2, $4, 23 534; CHECK-LE-NEXT: or $2, $2, $1 535; CHECK-LE-NEXT: srl $1, $4, 9 536; CHECK-LE-NEXT: sll $3, $5, 23 537; CHECK-LE-NEXT: jr $ra 538; CHECK-LE-NEXT: or $3, $3, $1 539 %f = call i64 @llvm.fshr.i64(i64 %x, i64 %y, i64 105) 540 ret i64 %f 541} 542 543; This should work without any node-specific logic. 544 545define i8 @fshr_i8_const_fold() { 546; CHECK-LABEL: fshr_i8_const_fold: 547; CHECK: # %bb.0: 548; CHECK-NEXT: jr $ra 549; CHECK-NEXT: addiu $2, $zero, 254 550 %f = call i8 @llvm.fshr.i8(i8 255, i8 0, i8 7) 551 ret i8 %f 552} 553 554define i32 @fshl_i32_shift_by_bitwidth(i32 %x, i32 %y) { 555; CHECK-LABEL: fshl_i32_shift_by_bitwidth: 556; CHECK: # %bb.0: 557; CHECK-NEXT: jr $ra 558; CHECK-NEXT: move $2, $4 559 %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 32) 560 ret i32 %f 561} 562 563define i32 @fshr_i32_shift_by_bitwidth(i32 %x, i32 %y) { 564; CHECK-LABEL: fshr_i32_shift_by_bitwidth: 565; CHECK: # %bb.0: 566; CHECK-NEXT: jr $ra 567; CHECK-NEXT: move $2, $5 568 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 32) 569 ret i32 %f 570} 571 572define <4 x i32> @fshl_v4i32_shift_by_bitwidth(<4 x i32> %x, <4 x i32> %y) { 573; CHECK-LABEL: fshl_v4i32_shift_by_bitwidth: 574; CHECK: # %bb.0: 575; CHECK-NEXT: move $2, $4 576; CHECK-NEXT: move $3, $5 577; CHECK-NEXT: move $4, $6 578; CHECK-NEXT: jr $ra 579; CHECK-NEXT: move $5, $7 580 %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %y, <4 x i32> <i32 32, i32 32, i32 32, i32 32>) 581 ret <4 x i32> %f 582} 583 584define <4 x i32> @fshr_v4i32_shift_by_bitwidth(<4 x i32> %x, <4 x i32> %y) { 585; CHECK-LABEL: fshr_v4i32_shift_by_bitwidth: 586; CHECK: # %bb.0: 587; CHECK-NEXT: lw $5, 28($sp) 588; CHECK-NEXT: lw $4, 24($sp) 589; CHECK-NEXT: lw $3, 20($sp) 590; CHECK-NEXT: lw $2, 16($sp) 591; CHECK-NEXT: jr $ra 592; CHECK-NEXT: nop 593 %f = call <4 x i32> @llvm.fshr.v4i32(<4 x i32> %x, <4 x i32> %y, <4 x i32> <i32 32, i32 32, i32 32, i32 32>) 594 ret <4 x i32> %f 595} 596 597