1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -mattr=+m -global-isel -verify-machineinstrs < %s \ 3; RUN: -riscv-enable-copy-propagation=false | FileCheck %s --check-prefix=RV32IM 4; RUN: llc -mtriple=riscv64 -mattr=+m -global-isel -verify-machineinstrs < %s \ 5; RUN: -riscv-enable-copy-propagation=false | FileCheck %s --check-prefix=RV64IM 6 7; Extends to 32 bits exhaustively tested for add only. 8 9define i8 @add_i8(i8 %a, i8 %b) { 10; RV32IM-LABEL: add_i8: 11; RV32IM: # %bb.0: # %entry 12; RV32IM-NEXT: add a0, a0, a1 13; RV32IM-NEXT: ret 14; 15; RV64IM-LABEL: add_i8: 16; RV64IM: # %bb.0: # %entry 17; RV64IM-NEXT: add a0, a0, a1 18; RV64IM-NEXT: ret 19entry: 20 %0 = add i8 %a, %b 21 ret i8 %0 22} 23 24define i32 @add_i8_signext_i32(i8 %a, i8 %b) { 25; RV32IM-LABEL: add_i8_signext_i32: 26; RV32IM: # %bb.0: # %entry 27; RV32IM-NEXT: slli a0, a0, 24 28; RV32IM-NEXT: slli a1, a1, 24 29; RV32IM-NEXT: srai a0, a0, 24 30; RV32IM-NEXT: srai a1, a1, 24 31; RV32IM-NEXT: add a0, a0, a1 32; RV32IM-NEXT: ret 33; 34; RV64IM-LABEL: add_i8_signext_i32: 35; RV64IM: # %bb.0: # %entry 36; RV64IM-NEXT: slli a0, a0, 56 37; RV64IM-NEXT: slli a1, a1, 56 38; RV64IM-NEXT: srai a0, a0, 56 39; RV64IM-NEXT: srai a1, a1, 56 40; RV64IM-NEXT: addw a0, a0, a1 41; RV64IM-NEXT: ret 42entry: 43 %0 = sext i8 %a to i32 44 %1 = sext i8 %b to i32 45 %2 = add i32 %0, %1 46 ret i32 %2 47} 48 49define i32 @add_i8_zeroext_i32(i8 %a, i8 %b) { 50; RV32IM-LABEL: add_i8_zeroext_i32: 51; RV32IM: # %bb.0: # %entry 52; RV32IM-NEXT: andi a0, a0, 255 53; RV32IM-NEXT: andi a1, a1, 255 54; RV32IM-NEXT: add a0, a0, a1 55; RV32IM-NEXT: ret 56; 57; RV64IM-LABEL: add_i8_zeroext_i32: 58; RV64IM: # %bb.0: # %entry 59; RV64IM-NEXT: andi a0, a0, 255 60; RV64IM-NEXT: andi a1, a1, 255 61; RV64IM-NEXT: addw a0, a0, a1 62; RV64IM-NEXT: ret 63entry: 64 %0 = zext i8 %a to i32 65 %1 = zext i8 %b to i32 66 %2 = add i32 %0, %1 67 ret i32 %2 68} 69 70; TODO: Handle G_IMPLICIT_DEF, which is needed to have i8 -> i64 extends working 71; on RV32. 72 73define i32 @add_i32(i32 %a, i32 %b) { 74; RV32IM-LABEL: add_i32: 75; RV32IM: # %bb.0: # %entry 76; RV32IM-NEXT: add a0, a0, a1 77; RV32IM-NEXT: ret 78; 79; RV64IM-LABEL: add_i32: 80; RV64IM: # %bb.0: # %entry 81; RV64IM-NEXT: addw a0, a0, a1 82; RV64IM-NEXT: ret 83entry: 84 %0 = add i32 %a, %b 85 ret i32 %0 86} 87 88define i32 @addi_i32(i32 %a) { 89; RV32IM-LABEL: addi_i32: 90; RV32IM: # %bb.0: # %entry 91; RV32IM-NEXT: addi a0, a0, 1234 92; RV32IM-NEXT: ret 93; 94; RV64IM-LABEL: addi_i32: 95; RV64IM: # %bb.0: # %entry 96; RV64IM-NEXT: addiw a0, a0, 1234 97; RV64IM-NEXT: ret 98entry: 99 %0 = add i32 %a, 1234 100 ret i32 %0 101} 102 103define i32 @sub_i32(i32 %a, i32 %b) { 104; RV32IM-LABEL: sub_i32: 105; RV32IM: # %bb.0: # %entry 106; RV32IM-NEXT: sub a0, a0, a1 107; RV32IM-NEXT: ret 108; 109; RV64IM-LABEL: sub_i32: 110; RV64IM: # %bb.0: # %entry 111; RV64IM-NEXT: subw a0, a0, a1 112; RV64IM-NEXT: ret 113entry: 114 %0 = sub i32 %a, %b 115 ret i32 %0 116} 117 118define i32 @subi_i32(i32 %a) { 119; RV32IM-LABEL: subi_i32: 120; RV32IM: # %bb.0: # %entry 121; RV32IM-NEXT: addi a0, a0, -1234 122; RV32IM-NEXT: ret 123; 124; RV64IM-LABEL: subi_i32: 125; RV64IM: # %bb.0: # %entry 126; RV64IM-NEXT: addiw a0, a0, -1234 127; RV64IM-NEXT: ret 128entry: 129 %0 = sub i32 %a, 1234 130 ret i32 %0 131} 132 133define i32 @neg_i32(i32 %a) { 134; RV32IM-LABEL: neg_i32: 135; RV32IM: # %bb.0: # %entry 136; RV32IM-NEXT: neg a0, a0 137; RV32IM-NEXT: ret 138; 139; RV64IM-LABEL: neg_i32: 140; RV64IM: # %bb.0: # %entry 141; RV64IM-NEXT: negw a0, a0 142; RV64IM-NEXT: ret 143entry: 144 %0 = sub i32 0, %a 145 ret i32 %0 146} 147 148define i32 @sll_i32(i32 %a, i32 %b) { 149; RV32IM-LABEL: sll_i32: 150; RV32IM: # %bb.0: # %entry 151; RV32IM-NEXT: sll a0, a0, a1 152; RV32IM-NEXT: ret 153; 154; RV64IM-LABEL: sll_i32: 155; RV64IM: # %bb.0: # %entry 156; RV64IM-NEXT: sllw a0, a0, a1 157; RV64IM-NEXT: ret 158entry: 159 %0 = shl i32 %a, %b 160 ret i32 %0 161} 162 163define i32 @slli_i32(i32 %a) { 164; RV32IM-LABEL: slli_i32: 165; RV32IM: # %bb.0: # %entry 166; RV32IM-NEXT: slli a0, a0, 11 167; RV32IM-NEXT: ret 168; 169; RV64IM-LABEL: slli_i32: 170; RV64IM: # %bb.0: # %entry 171; RV64IM-NEXT: slli a0, a0, 11 172; RV64IM-NEXT: ret 173entry: 174 %0 = shl i32 %a, 11 175 ret i32 %0 176} 177 178define i32 @sra_i32(i32 %a, i32 %b) { 179; RV32IM-LABEL: sra_i32: 180; RV32IM: # %bb.0: # %entry 181; RV32IM-NEXT: sra a0, a0, a1 182; RV32IM-NEXT: ret 183; 184; RV64IM-LABEL: sra_i32: 185; RV64IM: # %bb.0: # %entry 186; RV64IM-NEXT: sraw a0, a0, a1 187; RV64IM-NEXT: ret 188entry: 189 %0 = ashr i32 %a, %b 190 ret i32 %0 191} 192 193define i32 @srai_i32(i32 %a) { 194; RV32IM-LABEL: srai_i32: 195; RV32IM: # %bb.0: # %entry 196; RV32IM-NEXT: srai a0, a0, 17 197; RV32IM-NEXT: ret 198; 199; RV64IM-LABEL: srai_i32: 200; RV64IM: # %bb.0: # %entry 201; RV64IM-NEXT: sraiw a0, a0, 17 202; RV64IM-NEXT: ret 203entry: 204 %0 = ashr i32 %a, 17 205 ret i32 %0 206} 207 208define i32 @srl_i32(i32 %a, i32 %b) { 209; RV32IM-LABEL: srl_i32: 210; RV32IM: # %bb.0: # %entry 211; RV32IM-NEXT: srl a0, a0, a1 212; RV32IM-NEXT: ret 213; 214; RV64IM-LABEL: srl_i32: 215; RV64IM: # %bb.0: # %entry 216; RV64IM-NEXT: srlw a0, a0, a1 217; RV64IM-NEXT: ret 218entry: 219 %0 = lshr i32 %a, %b 220 ret i32 %0 221} 222 223define i32 @srli_i32(i32 %a, i32 %b) { 224; RV32IM-LABEL: srli_i32: 225; RV32IM: # %bb.0: # %entry 226; RV32IM-NEXT: srli a0, a0, 23 227; RV32IM-NEXT: ret 228; 229; RV64IM-LABEL: srli_i32: 230; RV64IM: # %bb.0: # %entry 231; RV64IM-NEXT: srliw a0, a0, 23 232; RV64IM-NEXT: ret 233entry: 234 %0 = lshr i32 %a, 23 235 ret i32 %0 236} 237 238define i32 @and_i32(i32 %a, i32 %b) { 239; RV32IM-LABEL: and_i32: 240; RV32IM: # %bb.0: # %entry 241; RV32IM-NEXT: and a0, a0, a1 242; RV32IM-NEXT: ret 243; 244; RV64IM-LABEL: and_i32: 245; RV64IM: # %bb.0: # %entry 246; RV64IM-NEXT: and a0, a0, a1 247; RV64IM-NEXT: ret 248entry: 249 %0 = and i32 %a, %b 250 ret i32 %0 251} 252 253define i32 @andi_i32(i32 %a) { 254; RV32IM-LABEL: andi_i32: 255; RV32IM: # %bb.0: # %entry 256; RV32IM-NEXT: andi a0, a0, 1234 257; RV32IM-NEXT: ret 258; 259; RV64IM-LABEL: andi_i32: 260; RV64IM: # %bb.0: # %entry 261; RV64IM-NEXT: andi a0, a0, 1234 262; RV64IM-NEXT: ret 263entry: 264 %0 = and i32 %a, 1234 265 ret i32 %0 266} 267 268define i32 @or_i32(i32 %a, i32 %b) { 269; RV32IM-LABEL: or_i32: 270; RV32IM: # %bb.0: # %entry 271; RV32IM-NEXT: or a0, a0, a1 272; RV32IM-NEXT: ret 273; 274; RV64IM-LABEL: or_i32: 275; RV64IM: # %bb.0: # %entry 276; RV64IM-NEXT: or a0, a0, a1 277; RV64IM-NEXT: ret 278entry: 279 %0 = or i32 %a, %b 280 ret i32 %0 281} 282 283define i32 @ori_i32(i32 %a) { 284; RV32IM-LABEL: ori_i32: 285; RV32IM: # %bb.0: # %entry 286; RV32IM-NEXT: ori a0, a0, 1234 287; RV32IM-NEXT: ret 288; 289; RV64IM-LABEL: ori_i32: 290; RV64IM: # %bb.0: # %entry 291; RV64IM-NEXT: ori a0, a0, 1234 292; RV64IM-NEXT: ret 293entry: 294 %0 = or i32 %a, 1234 295 ret i32 %0 296} 297 298define i32 @xor_i32(i32 %a, i32 %b) { 299; RV32IM-LABEL: xor_i32: 300; RV32IM: # %bb.0: # %entry 301; RV32IM-NEXT: xor a0, a0, a1 302; RV32IM-NEXT: ret 303; 304; RV64IM-LABEL: xor_i32: 305; RV64IM: # %bb.0: # %entry 306; RV64IM-NEXT: xor a0, a0, a1 307; RV64IM-NEXT: ret 308entry: 309 %0 = xor i32 %a, %b 310 ret i32 %0 311} 312 313define i32 @xori_i32(i32 %a, i32 %b) { 314; RV32IM-LABEL: xori_i32: 315; RV32IM: # %bb.0: # %entry 316; RV32IM-NEXT: xori a0, a0, 1234 317; RV32IM-NEXT: ret 318; 319; RV64IM-LABEL: xori_i32: 320; RV64IM: # %bb.0: # %entry 321; RV64IM-NEXT: xori a0, a0, 1234 322; RV64IM-NEXT: ret 323entry: 324 %0 = xor i32 %a, 1234 325 ret i32 %0 326} 327 328define i32 @mul_i32(i32 %a, i32 %b) { 329; RV32IM-LABEL: mul_i32: 330; RV32IM: # %bb.0: # %entry 331; RV32IM-NEXT: mul a0, a0, a1 332; RV32IM-NEXT: ret 333; 334; RV64IM-LABEL: mul_i32: 335; RV64IM: # %bb.0: # %entry 336; RV64IM-NEXT: mul a0, a0, a1 337; RV64IM-NEXT: ret 338entry: 339 %0 = mul i32 %a, %b 340 ret i32 %0 341} 342 343define i32 @sdiv_i32(i32 %a, i32 %b) { 344; RV32IM-LABEL: sdiv_i32: 345; RV32IM: # %bb.0: # %entry 346; RV32IM-NEXT: div a0, a0, a1 347; RV32IM-NEXT: ret 348; 349; RV64IM-LABEL: sdiv_i32: 350; RV64IM: # %bb.0: # %entry 351; RV64IM-NEXT: divw a0, a0, a1 352; RV64IM-NEXT: ret 353entry: 354 %0 = sdiv i32 %a, %b 355 ret i32 %0 356} 357 358define i32 @srem_i32(i32 %a, i32 %b) { 359; RV32IM-LABEL: srem_i32: 360; RV32IM: # %bb.0: # %entry 361; RV32IM-NEXT: rem a0, a0, a1 362; RV32IM-NEXT: ret 363; 364; RV64IM-LABEL: srem_i32: 365; RV64IM: # %bb.0: # %entry 366; RV64IM-NEXT: remw a0, a0, a1 367; RV64IM-NEXT: ret 368entry: 369 %0 = srem i32 %a, %b 370 ret i32 %0 371} 372 373define i32 @udiv_i32(i32 %a, i32 %b) { 374; RV32IM-LABEL: udiv_i32: 375; RV32IM: # %bb.0: # %entry 376; RV32IM-NEXT: divu a0, a0, a1 377; RV32IM-NEXT: ret 378; 379; RV64IM-LABEL: udiv_i32: 380; RV64IM: # %bb.0: # %entry 381; RV64IM-NEXT: divuw a0, a0, a1 382; RV64IM-NEXT: ret 383entry: 384 %0 = udiv i32 %a, %b 385 ret i32 %0 386} 387 388define i32 @urem_i32(i32 %a, i32 %b) { 389; RV32IM-LABEL: urem_i32: 390; RV32IM: # %bb.0: # %entry 391; RV32IM-NEXT: remu a0, a0, a1 392; RV32IM-NEXT: ret 393; 394; RV64IM-LABEL: urem_i32: 395; RV64IM: # %bb.0: # %entry 396; RV64IM-NEXT: remuw a0, a0, a1 397; RV64IM-NEXT: ret 398entry: 399 %0 = urem i32 %a, %b 400 ret i32 %0 401} 402 403define i64 @add_i64(i64 %a, i64 %b) { 404; RV32IM-LABEL: add_i64: 405; RV32IM: # %bb.0: # %entry 406; RV32IM-NEXT: add a0, a0, a2 407; RV32IM-NEXT: sltu a2, a0, a2 408; RV32IM-NEXT: add a1, a1, a3 409; RV32IM-NEXT: add a1, a1, a2 410; RV32IM-NEXT: ret 411; 412; RV64IM-LABEL: add_i64: 413; RV64IM: # %bb.0: # %entry 414; RV64IM-NEXT: add a0, a0, a1 415; RV64IM-NEXT: ret 416entry: 417 %0 = add i64 %a, %b 418 ret i64 %0 419} 420 421define i64 @addi_i64(i64 %a) { 422; RV32IM-LABEL: addi_i64: 423; RV32IM: # %bb.0: # %entry 424; RV32IM-NEXT: addi a0, a0, 1234 425; RV32IM-NEXT: sltiu a2, a0, 1234 426; RV32IM-NEXT: add a1, a1, a2 427; RV32IM-NEXT: ret 428; 429; RV64IM-LABEL: addi_i64: 430; RV64IM: # %bb.0: # %entry 431; RV64IM-NEXT: addi a0, a0, 1234 432; RV64IM-NEXT: ret 433entry: 434 %0 = add i64 %a, 1234 435 ret i64 %0 436} 437 438define i64 @sub_i64(i64 %a, i64 %b) { 439; RV32IM-LABEL: sub_i64: 440; RV32IM: # %bb.0: # %entry 441; RV32IM-NEXT: sub a4, a0, a2 442; RV32IM-NEXT: sltu a0, a0, a2 443; RV32IM-NEXT: sub a1, a1, a3 444; RV32IM-NEXT: sub a1, a1, a0 445; RV32IM-NEXT: mv a0, a4 446; RV32IM-NEXT: ret 447; 448; RV64IM-LABEL: sub_i64: 449; RV64IM: # %bb.0: # %entry 450; RV64IM-NEXT: sub a0, a0, a1 451; RV64IM-NEXT: ret 452entry: 453 %0 = sub i64 %a, %b 454 ret i64 %0 455} 456 457define i64 @subi_i64(i64 %a) { 458; RV32IM-LABEL: subi_i64: 459; RV32IM: # %bb.0: # %entry 460; RV32IM-NEXT: lui a2, 1048275 461; RV32IM-NEXT: addi a2, a2, -1548 462; RV32IM-NEXT: add a0, a0, a2 463; RV32IM-NEXT: sltu a2, a0, a2 464; RV32IM-NEXT: addi a1, a1, -1 465; RV32IM-NEXT: add a1, a1, a2 466; RV32IM-NEXT: ret 467; 468; RV64IM-LABEL: subi_i64: 469; RV64IM: # %bb.0: # %entry 470; RV64IM-NEXT: lui a1, 1048275 471; RV64IM-NEXT: addiw a1, a1, -1548 472; RV64IM-NEXT: add a0, a0, a1 473; RV64IM-NEXT: ret 474entry: 475 %0 = sub i64 %a, 1234444 476 ret i64 %0 477} 478 479define i64 @neg_i64(i64 %a) { 480; RV32IM-LABEL: neg_i64: 481; RV32IM: # %bb.0: # %entry 482; RV32IM-NEXT: neg a2, a0 483; RV32IM-NEXT: snez a0, a0 484; RV32IM-NEXT: neg a1, a1 485; RV32IM-NEXT: sub a1, a1, a0 486; RV32IM-NEXT: mv a0, a2 487; RV32IM-NEXT: ret 488; 489; RV64IM-LABEL: neg_i64: 490; RV64IM: # %bb.0: # %entry 491; RV64IM-NEXT: neg a0, a0 492; RV64IM-NEXT: ret 493entry: 494 %0 = sub i64 0, %a 495 ret i64 %0 496} 497 498; TODO: Handle G_SELECT, which is needed to have i64 shifts working on RV32. 499 500define i64 @and_i64(i64 %a, i64 %b) { 501; RV32IM-LABEL: and_i64: 502; RV32IM: # %bb.0: # %entry 503; RV32IM-NEXT: and a0, a0, a2 504; RV32IM-NEXT: and a1, a1, a3 505; RV32IM-NEXT: ret 506; 507; RV64IM-LABEL: and_i64: 508; RV64IM: # %bb.0: # %entry 509; RV64IM-NEXT: and a0, a0, a1 510; RV64IM-NEXT: ret 511entry: 512 %0 = and i64 %a, %b 513 ret i64 %0 514} 515 516define i64 @andi_i64(i64 %a) { 517; RV32IM-LABEL: andi_i64: 518; RV32IM: # %bb.0: # %entry 519; RV32IM-NEXT: andi a0, a0, 1234 520; RV32IM-NEXT: li a1, 0 521; RV32IM-NEXT: ret 522; 523; RV64IM-LABEL: andi_i64: 524; RV64IM: # %bb.0: # %entry 525; RV64IM-NEXT: andi a0, a0, 1234 526; RV64IM-NEXT: ret 527entry: 528 %0 = and i64 %a, 1234 529 ret i64 %0 530} 531 532define i64 @or_i64(i64 %a, i64 %b) { 533; RV32IM-LABEL: or_i64: 534; RV32IM: # %bb.0: # %entry 535; RV32IM-NEXT: or a0, a0, a2 536; RV32IM-NEXT: or a1, a1, a3 537; RV32IM-NEXT: ret 538; 539; RV64IM-LABEL: or_i64: 540; RV64IM: # %bb.0: # %entry 541; RV64IM-NEXT: or a0, a0, a1 542; RV64IM-NEXT: ret 543entry: 544 %0 = or i64 %a, %b 545 ret i64 %0 546} 547 548define i64 @ori_i64(i64 %a) { 549; RV32IM-LABEL: ori_i64: 550; RV32IM: # %bb.0: # %entry 551; RV32IM-NEXT: ori a0, a0, 1234 552; RV32IM-NEXT: ret 553; 554; RV64IM-LABEL: ori_i64: 555; RV64IM: # %bb.0: # %entry 556; RV64IM-NEXT: ori a0, a0, 1234 557; RV64IM-NEXT: ret 558entry: 559 %0 = or i64 %a, 1234 560 ret i64 %0 561} 562 563define i64 @xor_i64(i64 %a, i64 %b) { 564; RV32IM-LABEL: xor_i64: 565; RV32IM: # %bb.0: # %entry 566; RV32IM-NEXT: xor a0, a0, a2 567; RV32IM-NEXT: xor a1, a1, a3 568; RV32IM-NEXT: ret 569; 570; RV64IM-LABEL: xor_i64: 571; RV64IM: # %bb.0: # %entry 572; RV64IM-NEXT: xor a0, a0, a1 573; RV64IM-NEXT: ret 574entry: 575 %0 = xor i64 %a, %b 576 ret i64 %0 577} 578 579define i64 @xori_i64(i64 %a) { 580; RV32IM-LABEL: xori_i64: 581; RV32IM: # %bb.0: # %entry 582; RV32IM-NEXT: xori a0, a0, 1234 583; RV32IM-NEXT: ret 584; 585; RV64IM-LABEL: xori_i64: 586; RV64IM: # %bb.0: # %entry 587; RV64IM-NEXT: xori a0, a0, 1234 588; RV64IM-NEXT: ret 589entry: 590 %0 = xor i64 %a, 1234 591 ret i64 %0 592} 593 594define i64 @mul_i64(i64 %a, i64 %b) { 595; RV32IM-LABEL: mul_i64: 596; RV32IM: # %bb.0: # %entry 597; RV32IM-NEXT: mul a4, a0, a2 598; RV32IM-NEXT: mul a1, a1, a2 599; RV32IM-NEXT: mul a3, a0, a3 600; RV32IM-NEXT: mulhu a0, a0, a2 601; RV32IM-NEXT: add a1, a1, a3 602; RV32IM-NEXT: add a1, a1, a0 603; RV32IM-NEXT: mv a0, a4 604; RV32IM-NEXT: ret 605; 606; RV64IM-LABEL: mul_i64: 607; RV64IM: # %bb.0: # %entry 608; RV64IM-NEXT: mul a0, a0, a1 609; RV64IM-NEXT: ret 610entry: 611 %0 = mul i64 %a, %b 612 ret i64 %0 613} 614 615; TODO: Handle G_SDIV, G_SREM, G_UDIV, G_UREM for i64 on RV32. Likely will be 616; dispatched to a libcall? 617