1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ 3; RUN: | FileCheck %s -check-prefix=RV64I 4; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ 5; RUN: | FileCheck %s -check-prefix=RV32I 6 7; These tests are each targeted at a particular RISC-V ALU instruction. Other 8; files in this folder exercise LLVM IR instructions that don't directly match a 9; RISC-V instruction. This file contains tests for the instructions common 10; between RV32I and RV64I as well as the *W instructions introduced in RV64I. 11 12; Register-immediate instructions 13 14define i64 @addi(i64 %a) nounwind { 15; RV64I-LABEL: addi: 16; RV64I: # %bb.0: 17; RV64I-NEXT: addi a0, a0, 1 18; RV64I-NEXT: ret 19; 20; RV32I-LABEL: addi: 21; RV32I: # %bb.0: 22; RV32I-NEXT: addi a0, a0, 1 23; RV32I-NEXT: seqz a2, a0 24; RV32I-NEXT: add a1, a1, a2 25; RV32I-NEXT: ret 26 %1 = add i64 %a, 1 27 ret i64 %1 28} 29 30define i64 @slti(i64 %a) nounwind { 31; RV64I-LABEL: slti: 32; RV64I: # %bb.0: 33; RV64I-NEXT: slti a0, a0, 2 34; RV64I-NEXT: ret 35; 36; RV32I-LABEL: slti: 37; RV32I: # %bb.0: 38; RV32I-NEXT: beqz a1, .LBB1_2 39; RV32I-NEXT: # %bb.1: 40; RV32I-NEXT: slti a0, a1, 0 41; RV32I-NEXT: li a1, 0 42; RV32I-NEXT: ret 43; RV32I-NEXT: .LBB1_2: 44; RV32I-NEXT: sltiu a0, a0, 2 45; RV32I-NEXT: li a1, 0 46; RV32I-NEXT: ret 47 %1 = icmp slt i64 %a, 2 48 %2 = zext i1 %1 to i64 49 ret i64 %2 50} 51 52define i64 @sltiu(i64 %a) nounwind { 53; RV64I-LABEL: sltiu: 54; RV64I: # %bb.0: 55; RV64I-NEXT: sltiu a0, a0, 3 56; RV64I-NEXT: ret 57; 58; RV32I-LABEL: sltiu: 59; RV32I: # %bb.0: 60; RV32I-NEXT: sltiu a0, a0, 3 61; RV32I-NEXT: seqz a1, a1 62; RV32I-NEXT: and a0, a1, a0 63; RV32I-NEXT: li a1, 0 64; RV32I-NEXT: ret 65 %1 = icmp ult i64 %a, 3 66 %2 = zext i1 %1 to i64 67 ret i64 %2 68} 69 70define i64 @xori(i64 %a) nounwind { 71; RV64I-LABEL: xori: 72; RV64I: # %bb.0: 73; RV64I-NEXT: xori a0, a0, 4 74; RV64I-NEXT: ret 75; 76; RV32I-LABEL: xori: 77; RV32I: # %bb.0: 78; RV32I-NEXT: xori a0, a0, 4 79; RV32I-NEXT: ret 80 %1 = xor i64 %a, 4 81 ret i64 %1 82} 83 84define i64 @ori(i64 %a) nounwind { 85; RV64I-LABEL: ori: 86; RV64I: # %bb.0: 87; RV64I-NEXT: ori a0, a0, 5 88; RV64I-NEXT: ret 89; 90; RV32I-LABEL: ori: 91; RV32I: # %bb.0: 92; RV32I-NEXT: ori a0, a0, 5 93; RV32I-NEXT: ret 94 %1 = or i64 %a, 5 95 ret i64 %1 96} 97 98define i64 @andi(i64 %a) nounwind { 99; RV64I-LABEL: andi: 100; RV64I: # %bb.0: 101; RV64I-NEXT: andi a0, a0, 6 102; RV64I-NEXT: ret 103; 104; RV32I-LABEL: andi: 105; RV32I: # %bb.0: 106; RV32I-NEXT: andi a0, a0, 6 107; RV32I-NEXT: li a1, 0 108; RV32I-NEXT: ret 109 %1 = and i64 %a, 6 110 ret i64 %1 111} 112 113define i64 @slli(i64 %a) nounwind { 114; RV64I-LABEL: slli: 115; RV64I: # %bb.0: 116; RV64I-NEXT: slli a0, a0, 7 117; RV64I-NEXT: ret 118; 119; RV32I-LABEL: slli: 120; RV32I: # %bb.0: 121; RV32I-NEXT: srli a2, a0, 25 122; RV32I-NEXT: slli a1, a1, 7 123; RV32I-NEXT: or a1, a1, a2 124; RV32I-NEXT: slli a0, a0, 7 125; RV32I-NEXT: ret 126 %1 = shl i64 %a, 7 127 ret i64 %1 128} 129 130define i64 @srli(i64 %a) nounwind { 131; RV64I-LABEL: srli: 132; RV64I: # %bb.0: 133; RV64I-NEXT: srli a0, a0, 8 134; RV64I-NEXT: ret 135; 136; RV32I-LABEL: srli: 137; RV32I: # %bb.0: 138; RV32I-NEXT: slli a2, a1, 24 139; RV32I-NEXT: srli a0, a0, 8 140; RV32I-NEXT: or a0, a0, a2 141; RV32I-NEXT: srli a1, a1, 8 142; RV32I-NEXT: ret 143 %1 = lshr i64 %a, 8 144 ret i64 %1 145} 146 147define i64 @srai(i64 %a) nounwind { 148; RV64I-LABEL: srai: 149; RV64I: # %bb.0: 150; RV64I-NEXT: srai a0, a0, 9 151; RV64I-NEXT: ret 152; 153; RV32I-LABEL: srai: 154; RV32I: # %bb.0: 155; RV32I-NEXT: slli a2, a1, 23 156; RV32I-NEXT: srli a0, a0, 9 157; RV32I-NEXT: or a0, a0, a2 158; RV32I-NEXT: srai a1, a1, 9 159; RV32I-NEXT: ret 160 %1 = ashr i64 %a, 9 161 ret i64 %1 162} 163 164; Register-register instructions 165 166define i64 @add(i64 %a, i64 %b) nounwind { 167; RV64I-LABEL: add: 168; RV64I: # %bb.0: 169; RV64I-NEXT: add a0, a0, a1 170; RV64I-NEXT: ret 171; 172; RV32I-LABEL: add: 173; RV32I: # %bb.0: 174; RV32I-NEXT: add a1, a1, a3 175; RV32I-NEXT: add a2, a0, a2 176; RV32I-NEXT: sltu a0, a2, a0 177; RV32I-NEXT: add a1, a1, a0 178; RV32I-NEXT: mv a0, a2 179; RV32I-NEXT: ret 180 %1 = add i64 %a, %b 181 ret i64 %1 182} 183 184define i64 @sub(i64 %a, i64 %b) nounwind { 185; RV64I-LABEL: sub: 186; RV64I: # %bb.0: 187; RV64I-NEXT: sub a0, a0, a1 188; RV64I-NEXT: ret 189; 190; RV32I-LABEL: sub: 191; RV32I: # %bb.0: 192; RV32I-NEXT: sltu a4, a0, a2 193; RV32I-NEXT: sub a1, a1, a3 194; RV32I-NEXT: sub a1, a1, a4 195; RV32I-NEXT: sub a0, a0, a2 196; RV32I-NEXT: ret 197 %1 = sub i64 %a, %b 198 ret i64 %1 199} 200 201define i64 @sll(i64 %a, i64 %b) nounwind { 202; RV64I-LABEL: sll: 203; RV64I: # %bb.0: 204; RV64I-NEXT: sll a0, a0, a1 205; RV64I-NEXT: ret 206; 207; RV32I-LABEL: sll: 208; RV32I: # %bb.0: 209; RV32I-NEXT: addi a4, a2, -32 210; RV32I-NEXT: sll a3, a0, a2 211; RV32I-NEXT: bltz a4, .LBB11_2 212; RV32I-NEXT: # %bb.1: 213; RV32I-NEXT: mv a1, a3 214; RV32I-NEXT: j .LBB11_3 215; RV32I-NEXT: .LBB11_2: 216; RV32I-NEXT: sll a1, a1, a2 217; RV32I-NEXT: not a2, a2 218; RV32I-NEXT: srli a0, a0, 1 219; RV32I-NEXT: srl a0, a0, a2 220; RV32I-NEXT: or a1, a1, a0 221; RV32I-NEXT: .LBB11_3: 222; RV32I-NEXT: srai a0, a4, 31 223; RV32I-NEXT: and a0, a0, a3 224; RV32I-NEXT: ret 225 %1 = shl i64 %a, %b 226 ret i64 %1 227} 228 229define i64 @slt(i64 %a, i64 %b) nounwind { 230; RV64I-LABEL: slt: 231; RV64I: # %bb.0: 232; RV64I-NEXT: slt a0, a0, a1 233; RV64I-NEXT: ret 234; 235; RV32I-LABEL: slt: 236; RV32I: # %bb.0: 237; RV32I-NEXT: beq a1, a3, .LBB12_2 238; RV32I-NEXT: # %bb.1: 239; RV32I-NEXT: slt a0, a1, a3 240; RV32I-NEXT: li a1, 0 241; RV32I-NEXT: ret 242; RV32I-NEXT: .LBB12_2: 243; RV32I-NEXT: sltu a0, a0, a2 244; RV32I-NEXT: li a1, 0 245; RV32I-NEXT: ret 246 %1 = icmp slt i64 %a, %b 247 %2 = zext i1 %1 to i64 248 ret i64 %2 249} 250 251define i64 @sltu(i64 %a, i64 %b) nounwind { 252; RV64I-LABEL: sltu: 253; RV64I: # %bb.0: 254; RV64I-NEXT: sltu a0, a0, a1 255; RV64I-NEXT: ret 256; 257; RV32I-LABEL: sltu: 258; RV32I: # %bb.0: 259; RV32I-NEXT: beq a1, a3, .LBB13_2 260; RV32I-NEXT: # %bb.1: 261; RV32I-NEXT: sltu a0, a1, a3 262; RV32I-NEXT: li a1, 0 263; RV32I-NEXT: ret 264; RV32I-NEXT: .LBB13_2: 265; RV32I-NEXT: sltu a0, a0, a2 266; RV32I-NEXT: li a1, 0 267; RV32I-NEXT: ret 268 %1 = icmp ult i64 %a, %b 269 %2 = zext i1 %1 to i64 270 ret i64 %2 271} 272 273define i64 @xor(i64 %a, i64 %b) nounwind { 274; RV64I-LABEL: xor: 275; RV64I: # %bb.0: 276; RV64I-NEXT: xor a0, a0, a1 277; RV64I-NEXT: ret 278; 279; RV32I-LABEL: xor: 280; RV32I: # %bb.0: 281; RV32I-NEXT: xor a0, a0, a2 282; RV32I-NEXT: xor a1, a1, a3 283; RV32I-NEXT: ret 284 %1 = xor i64 %a, %b 285 ret i64 %1 286} 287 288define i64 @srl(i64 %a, i64 %b) nounwind { 289; RV64I-LABEL: srl: 290; RV64I: # %bb.0: 291; RV64I-NEXT: srl a0, a0, a1 292; RV64I-NEXT: ret 293; 294; RV32I-LABEL: srl: 295; RV32I: # %bb.0: 296; RV32I-NEXT: addi a4, a2, -32 297; RV32I-NEXT: srl a3, a1, a2 298; RV32I-NEXT: bltz a4, .LBB15_2 299; RV32I-NEXT: # %bb.1: 300; RV32I-NEXT: mv a0, a3 301; RV32I-NEXT: j .LBB15_3 302; RV32I-NEXT: .LBB15_2: 303; RV32I-NEXT: srl a0, a0, a2 304; RV32I-NEXT: not a2, a2 305; RV32I-NEXT: slli a1, a1, 1 306; RV32I-NEXT: sll a1, a1, a2 307; RV32I-NEXT: or a0, a0, a1 308; RV32I-NEXT: .LBB15_3: 309; RV32I-NEXT: srai a1, a4, 31 310; RV32I-NEXT: and a1, a1, a3 311; RV32I-NEXT: ret 312 %1 = lshr i64 %a, %b 313 ret i64 %1 314} 315 316define i64 @sra(i64 %a, i64 %b) nounwind { 317; RV64I-LABEL: sra: 318; RV64I: # %bb.0: 319; RV64I-NEXT: sra a0, a0, a1 320; RV64I-NEXT: ret 321; 322; RV32I-LABEL: sra: 323; RV32I: # %bb.0: 324; RV32I-NEXT: mv a3, a1 325; RV32I-NEXT: addi a4, a2, -32 326; RV32I-NEXT: sra a1, a1, a2 327; RV32I-NEXT: bltz a4, .LBB16_2 328; RV32I-NEXT: # %bb.1: 329; RV32I-NEXT: srai a3, a3, 31 330; RV32I-NEXT: mv a0, a1 331; RV32I-NEXT: mv a1, a3 332; RV32I-NEXT: ret 333; RV32I-NEXT: .LBB16_2: 334; RV32I-NEXT: srl a0, a0, a2 335; RV32I-NEXT: not a2, a2 336; RV32I-NEXT: slli a3, a3, 1 337; RV32I-NEXT: sll a2, a3, a2 338; RV32I-NEXT: or a0, a0, a2 339; RV32I-NEXT: ret 340 %1 = ashr i64 %a, %b 341 ret i64 %1 342} 343 344define i64 @or(i64 %a, i64 %b) nounwind { 345; RV64I-LABEL: or: 346; RV64I: # %bb.0: 347; RV64I-NEXT: or a0, a0, a1 348; RV64I-NEXT: ret 349; 350; RV32I-LABEL: or: 351; RV32I: # %bb.0: 352; RV32I-NEXT: or a0, a0, a2 353; RV32I-NEXT: or a1, a1, a3 354; RV32I-NEXT: ret 355 %1 = or i64 %a, %b 356 ret i64 %1 357} 358 359define i64 @and(i64 %a, i64 %b) nounwind { 360; RV64I-LABEL: and: 361; RV64I: # %bb.0: 362; RV64I-NEXT: and a0, a0, a1 363; RV64I-NEXT: ret 364; 365; RV32I-LABEL: and: 366; RV32I: # %bb.0: 367; RV32I-NEXT: and a0, a0, a2 368; RV32I-NEXT: and a1, a1, a3 369; RV32I-NEXT: ret 370 %1 = and i64 %a, %b 371 ret i64 %1 372} 373 374; RV64I-only instructions 375 376define signext i32 @addiw(i32 signext %a) nounwind { 377; RV64I-LABEL: addiw: 378; RV64I: # %bb.0: 379; RV64I-NEXT: addiw a0, a0, 123 380; RV64I-NEXT: ret 381; 382; RV32I-LABEL: addiw: 383; RV32I: # %bb.0: 384; RV32I-NEXT: addi a0, a0, 123 385; RV32I-NEXT: ret 386 %1 = add i32 %a, 123 387 ret i32 %1 388} 389 390define signext i32 @slliw(i32 signext %a) nounwind { 391; RV64I-LABEL: slliw: 392; RV64I: # %bb.0: 393; RV64I-NEXT: slliw a0, a0, 17 394; RV64I-NEXT: ret 395; 396; RV32I-LABEL: slliw: 397; RV32I: # %bb.0: 398; RV32I-NEXT: slli a0, a0, 17 399; RV32I-NEXT: ret 400 %1 = shl i32 %a, 17 401 ret i32 %1 402} 403 404define signext i32 @srliw(i32 %a) nounwind { 405; RV64I-LABEL: srliw: 406; RV64I: # %bb.0: 407; RV64I-NEXT: srliw a0, a0, 8 408; RV64I-NEXT: ret 409; 410; RV32I-LABEL: srliw: 411; RV32I: # %bb.0: 412; RV32I-NEXT: srli a0, a0, 8 413; RV32I-NEXT: ret 414 %1 = lshr i32 %a, 8 415 ret i32 %1 416} 417 418define signext i32 @sraiw(i32 %a) nounwind { 419; RV64I-LABEL: sraiw: 420; RV64I: # %bb.0: 421; RV64I-NEXT: sraiw a0, a0, 9 422; RV64I-NEXT: ret 423; 424; RV32I-LABEL: sraiw: 425; RV32I: # %bb.0: 426; RV32I-NEXT: srai a0, a0, 9 427; RV32I-NEXT: ret 428 %1 = ashr i32 %a, 9 429 ret i32 %1 430} 431 432define i64 @sraiw_i64(i64 %a) nounwind { 433; RV64I-LABEL: sraiw_i64: 434; RV64I: # %bb.0: 435; RV64I-NEXT: sraiw a0, a0, 9 436; RV64I-NEXT: ret 437; 438; RV32I-LABEL: sraiw_i64: 439; RV32I: # %bb.0: 440; RV32I-NEXT: srai a2, a0, 9 441; RV32I-NEXT: srai a1, a0, 31 442; RV32I-NEXT: mv a0, a2 443; RV32I-NEXT: ret 444 %1 = shl i64 %a, 32 445 %2 = ashr i64 %1, 41 446 ret i64 %2 447} 448 449define signext i32 @sextw(i32 zeroext %a) nounwind { 450; RV64I-LABEL: sextw: 451; RV64I: # %bb.0: 452; RV64I-NEXT: sext.w a0, a0 453; RV64I-NEXT: ret 454; 455; RV32I-LABEL: sextw: 456; RV32I: # %bb.0: 457; RV32I-NEXT: ret 458 ret i32 %a 459} 460 461define signext i32 @addw(i32 signext %a, i32 signext %b) nounwind { 462; RV64I-LABEL: addw: 463; RV64I: # %bb.0: 464; RV64I-NEXT: addw a0, a0, a1 465; RV64I-NEXT: ret 466; 467; RV32I-LABEL: addw: 468; RV32I: # %bb.0: 469; RV32I-NEXT: add a0, a0, a1 470; RV32I-NEXT: ret 471 %1 = add i32 %a, %b 472 ret i32 %1 473} 474 475define signext i32 @subw(i32 signext %a, i32 signext %b) nounwind { 476; RV64I-LABEL: subw: 477; RV64I: # %bb.0: 478; RV64I-NEXT: subw a0, a0, a1 479; RV64I-NEXT: ret 480; 481; RV32I-LABEL: subw: 482; RV32I: # %bb.0: 483; RV32I-NEXT: sub a0, a0, a1 484; RV32I-NEXT: ret 485 %1 = sub i32 %a, %b 486 ret i32 %1 487} 488 489define signext i32 @sllw(i32 signext %a, i32 zeroext %b) nounwind { 490; RV64I-LABEL: sllw: 491; RV64I: # %bb.0: 492; RV64I-NEXT: sllw a0, a0, a1 493; RV64I-NEXT: ret 494; 495; RV32I-LABEL: sllw: 496; RV32I: # %bb.0: 497; RV32I-NEXT: sll a0, a0, a1 498; RV32I-NEXT: ret 499 %1 = shl i32 %a, %b 500 ret i32 %1 501} 502 503define signext i32 @srlw(i32 signext %a, i32 zeroext %b) nounwind { 504; RV64I-LABEL: srlw: 505; RV64I: # %bb.0: 506; RV64I-NEXT: srlw a0, a0, a1 507; RV64I-NEXT: ret 508; 509; RV32I-LABEL: srlw: 510; RV32I: # %bb.0: 511; RV32I-NEXT: srl a0, a0, a1 512; RV32I-NEXT: ret 513 %1 = lshr i32 %a, %b 514 ret i32 %1 515} 516 517define signext i32 @sraw(i64 %a, i32 zeroext %b) nounwind { 518; RV64I-LABEL: sraw: 519; RV64I: # %bb.0: 520; RV64I-NEXT: sraw a0, a0, a1 521; RV64I-NEXT: ret 522; 523; RV32I-LABEL: sraw: 524; RV32I: # %bb.0: 525; RV32I-NEXT: sra a0, a0, a2 526; RV32I-NEXT: ret 527 %1 = trunc i64 %a to i32 528 %2 = ashr i32 %1, %b 529 ret i32 %2 530} 531 532define i64 @add_hi_and_lo_negone(i64 %0) { 533; RV64I-LABEL: add_hi_and_lo_negone: 534; RV64I: # %bb.0: 535; RV64I-NEXT: addi a0, a0, -1 536; RV64I-NEXT: ret 537; 538; RV32I-LABEL: add_hi_and_lo_negone: 539; RV32I: # %bb.0: 540; RV32I-NEXT: seqz a2, a0 541; RV32I-NEXT: sub a1, a1, a2 542; RV32I-NEXT: addi a0, a0, -1 543; RV32I-NEXT: ret 544 %2 = add nsw i64 %0, -1 545 ret i64 %2 546} 547 548define i64 @add_hi_zero_lo_negone(i64 %0) { 549; RV64I-LABEL: add_hi_zero_lo_negone: 550; RV64I: # %bb.0: 551; RV64I-NEXT: li a1, -1 552; RV64I-NEXT: srli a1, a1, 32 553; RV64I-NEXT: add a0, a0, a1 554; RV64I-NEXT: ret 555; 556; RV32I-LABEL: add_hi_zero_lo_negone: 557; RV32I: # %bb.0: 558; RV32I-NEXT: snez a2, a0 559; RV32I-NEXT: add a1, a1, a2 560; RV32I-NEXT: addi a0, a0, -1 561; RV32I-NEXT: ret 562 %2 = add i64 %0, 4294967295 563 ret i64 %2 564} 565 566define i64 @add_lo_negone(i64 %0) { 567; RV64I-LABEL: add_lo_negone: 568; RV64I: # %bb.0: 569; RV64I-NEXT: li a1, -1 570; RV64I-NEXT: slli a1, a1, 32 571; RV64I-NEXT: addi a1, a1, -1 572; RV64I-NEXT: add a0, a0, a1 573; RV64I-NEXT: ret 574; 575; RV32I-LABEL: add_lo_negone: 576; RV32I: # %bb.0: 577; RV32I-NEXT: snez a2, a0 578; RV32I-NEXT: add a1, a1, a2 579; RV32I-NEXT: addi a1, a1, -2 580; RV32I-NEXT: addi a0, a0, -1 581; RV32I-NEXT: ret 582 %2 = add nsw i64 %0, -4294967297 583 ret i64 %2 584} 585 586define i64 @add_hi_one_lo_negone(i64 %0) { 587; RV64I-LABEL: add_hi_one_lo_negone: 588; RV64I: # %bb.0: 589; RV64I-NEXT: li a1, -1 590; RV64I-NEXT: srli a1, a1, 31 591; RV64I-NEXT: add a0, a0, a1 592; RV64I-NEXT: ret 593; 594; RV32I-LABEL: add_hi_one_lo_negone: 595; RV32I: # %bb.0: 596; RV32I-NEXT: snez a2, a0 597; RV32I-NEXT: add a1, a1, a2 598; RV32I-NEXT: addi a1, a1, 1 599; RV32I-NEXT: addi a0, a0, -1 600; RV32I-NEXT: ret 601 %2 = add nsw i64 %0, 8589934591 602 ret i64 %2 603} 604