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