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 a2, a0, 1 23; RV32I-NEXT: sltu a0, a2, a0 24; RV32I-NEXT: add a1, a1, a0 25; RV32I-NEXT: mv a0, a2 26; RV32I-NEXT: ret 27 %1 = add i64 %a, 1 28 ret i64 %1 29} 30 31define i64 @slti(i64 %a) nounwind { 32; RV64I-LABEL: slti: 33; RV64I: # %bb.0: 34; RV64I-NEXT: slti a0, a0, 2 35; RV64I-NEXT: ret 36; 37; RV32I-LABEL: slti: 38; RV32I: # %bb.0: 39; RV32I-NEXT: beqz a1, .LBB1_2 40; RV32I-NEXT: # %bb.1: 41; RV32I-NEXT: slti a0, a1, 0 42; RV32I-NEXT: mv a1, zero 43; RV32I-NEXT: ret 44; RV32I-NEXT: .LBB1_2: 45; RV32I-NEXT: sltiu a0, a0, 2 46; RV32I-NEXT: mv a1, zero 47; RV32I-NEXT: ret 48 %1 = icmp slt i64 %a, 2 49 %2 = zext i1 %1 to i64 50 ret i64 %2 51} 52 53define i64 @sltiu(i64 %a) nounwind { 54; RV64I-LABEL: sltiu: 55; RV64I: # %bb.0: 56; RV64I-NEXT: sltiu a0, a0, 3 57; RV64I-NEXT: ret 58; 59; RV32I-LABEL: sltiu: 60; RV32I: # %bb.0: 61; RV32I-NEXT: beqz a1, .LBB2_2 62; RV32I-NEXT: # %bb.1: 63; RV32I-NEXT: mv a0, zero 64; RV32I-NEXT: mv a1, zero 65; RV32I-NEXT: ret 66; RV32I-NEXT: .LBB2_2: 67; RV32I-NEXT: sltiu a0, a0, 3 68; RV32I-NEXT: mv a1, zero 69; RV32I-NEXT: ret 70 %1 = icmp ult i64 %a, 3 71 %2 = zext i1 %1 to i64 72 ret i64 %2 73} 74 75define i64 @xori(i64 %a) nounwind { 76; RV64I-LABEL: xori: 77; RV64I: # %bb.0: 78; RV64I-NEXT: xori a0, a0, 4 79; RV64I-NEXT: ret 80; 81; RV32I-LABEL: xori: 82; RV32I: # %bb.0: 83; RV32I-NEXT: xori a0, a0, 4 84; RV32I-NEXT: ret 85 %1 = xor i64 %a, 4 86 ret i64 %1 87} 88 89define i64 @ori(i64 %a) nounwind { 90; RV64I-LABEL: ori: 91; RV64I: # %bb.0: 92; RV64I-NEXT: ori a0, a0, 5 93; RV64I-NEXT: ret 94; 95; RV32I-LABEL: ori: 96; RV32I: # %bb.0: 97; RV32I-NEXT: ori a0, a0, 5 98; RV32I-NEXT: ret 99 %1 = or i64 %a, 5 100 ret i64 %1 101} 102 103define i64 @andi(i64 %a) nounwind { 104; RV64I-LABEL: andi: 105; RV64I: # %bb.0: 106; RV64I-NEXT: andi a0, a0, 6 107; RV64I-NEXT: ret 108; 109; RV32I-LABEL: andi: 110; RV32I: # %bb.0: 111; RV32I-NEXT: andi a0, a0, 6 112; RV32I-NEXT: mv a1, zero 113; RV32I-NEXT: ret 114 %1 = and i64 %a, 6 115 ret i64 %1 116} 117 118define i64 @slli(i64 %a) nounwind { 119; RV64I-LABEL: slli: 120; RV64I: # %bb.0: 121; RV64I-NEXT: slli a0, a0, 7 122; RV64I-NEXT: ret 123; 124; RV32I-LABEL: slli: 125; RV32I: # %bb.0: 126; RV32I-NEXT: srli a2, a0, 25 127; RV32I-NEXT: slli a1, a1, 7 128; RV32I-NEXT: or a1, a1, a2 129; RV32I-NEXT: slli a0, a0, 7 130; RV32I-NEXT: ret 131 %1 = shl i64 %a, 7 132 ret i64 %1 133} 134 135define i64 @srli(i64 %a) nounwind { 136; RV64I-LABEL: srli: 137; RV64I: # %bb.0: 138; RV64I-NEXT: srli a0, a0, 8 139; RV64I-NEXT: ret 140; 141; RV32I-LABEL: srli: 142; RV32I: # %bb.0: 143; RV32I-NEXT: slli a2, a1, 24 144; RV32I-NEXT: srli a0, a0, 8 145; RV32I-NEXT: or a0, a0, a2 146; RV32I-NEXT: srli a1, a1, 8 147; RV32I-NEXT: ret 148 %1 = lshr i64 %a, 8 149 ret i64 %1 150} 151 152define i64 @srai(i64 %a) nounwind { 153; RV64I-LABEL: srai: 154; RV64I: # %bb.0: 155; RV64I-NEXT: srai a0, a0, 9 156; RV64I-NEXT: ret 157; 158; RV32I-LABEL: srai: 159; RV32I: # %bb.0: 160; RV32I-NEXT: slli a2, a1, 23 161; RV32I-NEXT: srli a0, a0, 9 162; RV32I-NEXT: or a0, a0, a2 163; RV32I-NEXT: srai a1, a1, 9 164; RV32I-NEXT: ret 165 %1 = ashr i64 %a, 9 166 ret i64 %1 167} 168 169; Register-register instructions 170 171define i64 @add(i64 %a, i64 %b) nounwind { 172; RV64I-LABEL: add: 173; RV64I: # %bb.0: 174; RV64I-NEXT: add a0, a0, a1 175; RV64I-NEXT: ret 176; 177; RV32I-LABEL: add: 178; RV32I: # %bb.0: 179; RV32I-NEXT: add a1, a1, a3 180; RV32I-NEXT: add a2, a0, a2 181; RV32I-NEXT: sltu a0, a2, a0 182; RV32I-NEXT: add a1, a1, a0 183; RV32I-NEXT: mv a0, a2 184; RV32I-NEXT: ret 185 %1 = add i64 %a, %b 186 ret i64 %1 187} 188 189define i64 @sub(i64 %a, i64 %b) nounwind { 190; RV64I-LABEL: sub: 191; RV64I: # %bb.0: 192; RV64I-NEXT: sub a0, a0, a1 193; RV64I-NEXT: ret 194; 195; RV32I-LABEL: sub: 196; RV32I: # %bb.0: 197; RV32I-NEXT: sltu a4, a0, a2 198; RV32I-NEXT: sub a1, a1, a3 199; RV32I-NEXT: sub a1, a1, a4 200; RV32I-NEXT: sub a0, a0, a2 201; RV32I-NEXT: ret 202 %1 = sub i64 %a, %b 203 ret i64 %1 204} 205 206define i64 @sll(i64 %a, i64 %b) nounwind { 207; RV64I-LABEL: sll: 208; RV64I: # %bb.0: 209; RV64I-NEXT: sll a0, a0, a1 210; RV64I-NEXT: ret 211; 212; RV32I-LABEL: sll: 213; RV32I: # %bb.0: 214; RV32I-NEXT: addi a3, a2, -32 215; RV32I-NEXT: bltz a3, .LBB11_2 216; RV32I-NEXT: # %bb.1: 217; RV32I-NEXT: sll a1, a0, a3 218; RV32I-NEXT: mv a0, zero 219; RV32I-NEXT: ret 220; RV32I-NEXT: .LBB11_2: 221; RV32I-NEXT: sll a1, a1, a2 222; RV32I-NEXT: addi a3, zero, 31 223; RV32I-NEXT: sub a3, a3, a2 224; RV32I-NEXT: srli a4, a0, 1 225; RV32I-NEXT: srl a3, a4, a3 226; RV32I-NEXT: or a1, a1, a3 227; RV32I-NEXT: sll a0, a0, a2 228; RV32I-NEXT: ret 229 %1 = shl i64 %a, %b 230 ret i64 %1 231} 232 233define i64 @slt(i64 %a, i64 %b) nounwind { 234; RV64I-LABEL: slt: 235; RV64I: # %bb.0: 236; RV64I-NEXT: slt a0, a0, a1 237; RV64I-NEXT: ret 238; 239; RV32I-LABEL: slt: 240; RV32I: # %bb.0: 241; RV32I-NEXT: beq a1, a3, .LBB12_2 242; RV32I-NEXT: # %bb.1: 243; RV32I-NEXT: slt a0, a1, a3 244; RV32I-NEXT: mv a1, zero 245; RV32I-NEXT: ret 246; RV32I-NEXT: .LBB12_2: 247; RV32I-NEXT: sltu a0, a0, a2 248; RV32I-NEXT: mv a1, zero 249; RV32I-NEXT: ret 250 %1 = icmp slt i64 %a, %b 251 %2 = zext i1 %1 to i64 252 ret i64 %2 253} 254 255define i64 @sltu(i64 %a, i64 %b) nounwind { 256; RV64I-LABEL: sltu: 257; RV64I: # %bb.0: 258; RV64I-NEXT: sltu a0, a0, a1 259; RV64I-NEXT: ret 260; 261; RV32I-LABEL: sltu: 262; RV32I: # %bb.0: 263; RV32I-NEXT: beq a1, a3, .LBB13_2 264; RV32I-NEXT: # %bb.1: 265; RV32I-NEXT: sltu a0, a1, a3 266; RV32I-NEXT: mv a1, zero 267; RV32I-NEXT: ret 268; RV32I-NEXT: .LBB13_2: 269; RV32I-NEXT: sltu a0, a0, a2 270; RV32I-NEXT: mv a1, zero 271; RV32I-NEXT: ret 272 %1 = icmp ult i64 %a, %b 273 %2 = zext i1 %1 to i64 274 ret i64 %2 275} 276 277define i64 @xor(i64 %a, i64 %b) nounwind { 278; RV64I-LABEL: xor: 279; RV64I: # %bb.0: 280; RV64I-NEXT: xor a0, a0, a1 281; RV64I-NEXT: ret 282; 283; RV32I-LABEL: xor: 284; RV32I: # %bb.0: 285; RV32I-NEXT: xor a0, a0, a2 286; RV32I-NEXT: xor a1, a1, a3 287; RV32I-NEXT: ret 288 %1 = xor i64 %a, %b 289 ret i64 %1 290} 291 292define i64 @srl(i64 %a, i64 %b) nounwind { 293; RV64I-LABEL: srl: 294; RV64I: # %bb.0: 295; RV64I-NEXT: srl a0, a0, a1 296; RV64I-NEXT: ret 297; 298; RV32I-LABEL: srl: 299; RV32I: # %bb.0: 300; RV32I-NEXT: addi a3, a2, -32 301; RV32I-NEXT: bltz a3, .LBB15_2 302; RV32I-NEXT: # %bb.1: 303; RV32I-NEXT: srl a0, a1, a3 304; RV32I-NEXT: mv a1, zero 305; RV32I-NEXT: ret 306; RV32I-NEXT: .LBB15_2: 307; RV32I-NEXT: srl a0, a0, a2 308; RV32I-NEXT: addi a3, zero, 31 309; RV32I-NEXT: sub a3, a3, a2 310; RV32I-NEXT: slli a4, a1, 1 311; RV32I-NEXT: sll a3, a4, a3 312; RV32I-NEXT: or a0, a0, a3 313; RV32I-NEXT: srl a1, a1, a2 314; RV32I-NEXT: ret 315 %1 = lshr i64 %a, %b 316 ret i64 %1 317} 318 319define i64 @sra(i64 %a, i64 %b) nounwind { 320; RV64I-LABEL: sra: 321; RV64I: # %bb.0: 322; RV64I-NEXT: sra a0, a0, a1 323; RV64I-NEXT: ret 324; 325; RV32I-LABEL: sra: 326; RV32I: # %bb.0: 327; RV32I-NEXT: addi a3, a2, -32 328; RV32I-NEXT: bltz a3, .LBB16_2 329; RV32I-NEXT: # %bb.1: 330; RV32I-NEXT: sra a0, a1, a3 331; RV32I-NEXT: srai a1, a1, 31 332; RV32I-NEXT: ret 333; RV32I-NEXT: .LBB16_2: 334; RV32I-NEXT: srl a0, a0, a2 335; RV32I-NEXT: addi a3, zero, 31 336; RV32I-NEXT: sub a3, a3, a2 337; RV32I-NEXT: slli a4, a1, 1 338; RV32I-NEXT: sll a3, a4, a3 339; RV32I-NEXT: or a0, a0, a3 340; RV32I-NEXT: sra a1, a1, a2 341; RV32I-NEXT: ret 342 %1 = ashr i64 %a, %b 343 ret i64 %1 344} 345 346define i64 @or(i64 %a, i64 %b) nounwind { 347; RV64I-LABEL: or: 348; RV64I: # %bb.0: 349; RV64I-NEXT: or a0, a0, a1 350; RV64I-NEXT: ret 351; 352; RV32I-LABEL: or: 353; RV32I: # %bb.0: 354; RV32I-NEXT: or a0, a0, a2 355; RV32I-NEXT: or a1, a1, a3 356; RV32I-NEXT: ret 357 %1 = or i64 %a, %b 358 ret i64 %1 359} 360 361define i64 @and(i64 %a, i64 %b) nounwind { 362; RV64I-LABEL: and: 363; RV64I: # %bb.0: 364; RV64I-NEXT: and a0, a0, a1 365; RV64I-NEXT: ret 366; 367; RV32I-LABEL: and: 368; RV32I: # %bb.0: 369; RV32I-NEXT: and a0, a0, a2 370; RV32I-NEXT: and a1, a1, a3 371; RV32I-NEXT: ret 372 %1 = and i64 %a, %b 373 ret i64 %1 374} 375 376; RV64I-only instructions 377 378define signext i32 @addiw(i32 signext %a) nounwind { 379; RV64I-LABEL: addiw: 380; RV64I: # %bb.0: 381; RV64I-NEXT: addiw a0, a0, 123 382; RV64I-NEXT: ret 383; 384; RV32I-LABEL: addiw: 385; RV32I: # %bb.0: 386; RV32I-NEXT: addi a0, a0, 123 387; RV32I-NEXT: ret 388 %1 = add i32 %a, 123 389 ret i32 %1 390} 391 392define signext i32 @slliw(i32 signext %a) nounwind { 393; RV64I-LABEL: slliw: 394; RV64I: # %bb.0: 395; RV64I-NEXT: slliw a0, a0, 17 396; RV64I-NEXT: ret 397; 398; RV32I-LABEL: slliw: 399; RV32I: # %bb.0: 400; RV32I-NEXT: slli a0, a0, 17 401; RV32I-NEXT: ret 402 %1 = shl i32 %a, 17 403 ret i32 %1 404} 405 406define signext i32 @srliw(i32 %a) nounwind { 407; RV64I-LABEL: srliw: 408; RV64I: # %bb.0: 409; RV64I-NEXT: srliw a0, a0, 8 410; RV64I-NEXT: ret 411; 412; RV32I-LABEL: srliw: 413; RV32I: # %bb.0: 414; RV32I-NEXT: srli a0, a0, 8 415; RV32I-NEXT: ret 416 %1 = lshr i32 %a, 8 417 ret i32 %1 418} 419 420define signext i32 @sraiw(i32 %a) nounwind { 421; RV64I-LABEL: sraiw: 422; RV64I: # %bb.0: 423; RV64I-NEXT: sraiw a0, a0, 9 424; RV64I-NEXT: ret 425; 426; RV32I-LABEL: sraiw: 427; RV32I: # %bb.0: 428; RV32I-NEXT: srai a0, a0, 9 429; RV32I-NEXT: ret 430 %1 = ashr i32 %a, 9 431 ret i32 %1 432} 433 434define signext i32 @sextw(i32 zeroext %a) nounwind { 435; RV64I-LABEL: sextw: 436; RV64I: # %bb.0: 437; RV64I-NEXT: sext.w a0, a0 438; RV64I-NEXT: ret 439; 440; RV32I-LABEL: sextw: 441; RV32I: # %bb.0: 442; RV32I-NEXT: ret 443 ret i32 %a 444} 445 446define signext i32 @addw(i32 signext %a, i32 signext %b) nounwind { 447; RV64I-LABEL: addw: 448; RV64I: # %bb.0: 449; RV64I-NEXT: addw a0, a0, a1 450; RV64I-NEXT: ret 451; 452; RV32I-LABEL: addw: 453; RV32I: # %bb.0: 454; RV32I-NEXT: add a0, a0, a1 455; RV32I-NEXT: ret 456 %1 = add i32 %a, %b 457 ret i32 %1 458} 459 460define signext i32 @subw(i32 signext %a, i32 signext %b) nounwind { 461; RV64I-LABEL: subw: 462; RV64I: # %bb.0: 463; RV64I-NEXT: subw a0, a0, a1 464; RV64I-NEXT: ret 465; 466; RV32I-LABEL: subw: 467; RV32I: # %bb.0: 468; RV32I-NEXT: sub a0, a0, a1 469; RV32I-NEXT: ret 470 %1 = sub i32 %a, %b 471 ret i32 %1 472} 473 474define signext i32 @sllw(i32 signext %a, i32 zeroext %b) nounwind { 475; RV64I-LABEL: sllw: 476; RV64I: # %bb.0: 477; RV64I-NEXT: sllw a0, a0, a1 478; RV64I-NEXT: ret 479; 480; RV32I-LABEL: sllw: 481; RV32I: # %bb.0: 482; RV32I-NEXT: sll a0, a0, a1 483; RV32I-NEXT: ret 484 %1 = shl i32 %a, %b 485 ret i32 %1 486} 487 488define signext i32 @srlw(i32 signext %a, i32 zeroext %b) nounwind { 489; RV64I-LABEL: srlw: 490; RV64I: # %bb.0: 491; RV64I-NEXT: srlw a0, a0, a1 492; RV64I-NEXT: ret 493; 494; RV32I-LABEL: srlw: 495; RV32I: # %bb.0: 496; RV32I-NEXT: srl a0, a0, a1 497; RV32I-NEXT: ret 498 %1 = lshr i32 %a, %b 499 ret i32 %1 500} 501 502define signext i32 @sraw(i64 %a, i32 zeroext %b) nounwind { 503; RV64I-LABEL: sraw: 504; RV64I: # %bb.0: 505; RV64I-NEXT: sraw a0, a0, a1 506; RV64I-NEXT: ret 507; 508; RV32I-LABEL: sraw: 509; RV32I: # %bb.0: 510; RV32I-NEXT: sra a0, a0, a2 511; RV32I-NEXT: ret 512 %1 = trunc i64 %a to i32 513 %2 = ashr i32 %1, %b 514 ret i32 %2 515} 516