| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,380 @@ | ||
| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | ||
| ; RUN: llc -mtriple=riscv32 -mattr=+m -global-isel -verify-machineinstrs < %s \ | ||
| ; RUN: | FileCheck %s --check-prefix=RV32IM | ||
| ; RUN: llc -mtriple=riscv64 -mattr=+m -global-isel -verify-machineinstrs < %s \ | ||
| ; RUN: | FileCheck %s --check-prefix=RV64IM | ||
|
|
||
| ; Extends to 32 bits exhaustively tested for add only. | ||
|
|
||
| define i8 @add_i8(i8 %a, i8 %b) { | ||
| ; RV32IM-LABEL: add_i8: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: add a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: add_i8: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: addw a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = add i8 %a, %b | ||
| ret i8 %0 | ||
| } | ||
|
|
||
| define i32 @add_i8_signext_i32(i8 %a, i8 %b) { | ||
| ; RV32IM-LABEL: add_i8_signext_i32: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: slli a0, a0, 24 | ||
| ; RV32IM-NEXT: srai a0, a0, 24 | ||
| ; RV32IM-NEXT: slli a1, a1, 24 | ||
| ; RV32IM-NEXT: srai a1, a1, 24 | ||
| ; RV32IM-NEXT: add a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: add_i8_signext_i32: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: li a2, 24 | ||
| ; RV64IM-NEXT: sllw a0, a0, a2 | ||
| ; RV64IM-NEXT: sraw a0, a0, a2 | ||
| ; RV64IM-NEXT: sllw a1, a1, a2 | ||
| ; RV64IM-NEXT: sraw a1, a1, a2 | ||
| ; RV64IM-NEXT: addw a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = sext i8 %a to i32 | ||
| %1 = sext i8 %b to i32 | ||
| %2 = add i32 %0, %1 | ||
| ret i32 %2 | ||
| } | ||
|
|
||
| define i32 @add_i8_zeroext_i32(i8 %a, i8 %b) { | ||
| ; RV32IM-LABEL: add_i8_zeroext_i32: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: andi a0, a0, 255 | ||
| ; RV32IM-NEXT: andi a1, a1, 255 | ||
| ; RV32IM-NEXT: add a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: add_i8_zeroext_i32: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: andi a0, a0, 255 | ||
| ; RV64IM-NEXT: andi a1, a1, 255 | ||
| ; RV64IM-NEXT: addw a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = zext i8 %a to i32 | ||
| %1 = zext i8 %b to i32 | ||
| %2 = add i32 %0, %1 | ||
| ret i32 %2 | ||
| } | ||
|
|
||
| ; TODO: Handle G_IMPLICIT_DEF, which is needed to have i8 -> i64 extends working | ||
| ; on RV32. | ||
|
|
||
| define i32 @add_i32(i32 %a, i32 %b) { | ||
| ; RV32IM-LABEL: add_i32: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: add a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: add_i32: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: addw a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = add i32 %a, %b | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| define i32 @sub_i32(i32 %a, i32 %b) { | ||
| ; RV32IM-LABEL: sub_i32: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: sub a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: sub_i32: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: subw a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = sub i32 %a, %b | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| define i32 @shl_i32(i32 %a, i32 %b) { | ||
| ; RV32IM-LABEL: shl_i32: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: sll a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: shl_i32: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: sllw a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = shl i32 %a, %b | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| define i32 @ashr_i32(i32 %a, i32 %b) { | ||
| ; RV32IM-LABEL: ashr_i32: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: sra a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: ashr_i32: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: sraw a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = ashr i32 %a, %b | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| define i32 @lshr_i32(i32 %a, i32 %b) { | ||
| ; RV32IM-LABEL: lshr_i32: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: srl a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: lshr_i32: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: srlw a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = lshr i32 %a, %b | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| define i32 @and_i32(i32 %a, i32 %b) { | ||
| ; RV32IM-LABEL: and_i32: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: and a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: and_i32: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: and a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = and i32 %a, %b | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| define i32 @or_i32(i32 %a, i32 %b) { | ||
| ; RV32IM-LABEL: or_i32: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: or a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: or_i32: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: or a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = or i32 %a, %b | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| define i32 @xor_i32(i32 %a, i32 %b) { | ||
| ; RV32IM-LABEL: xor_i32: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: xor a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: xor_i32: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: xor a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = xor i32 %a, %b | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| define i32 @mul_i32(i32 %a, i32 %b) { | ||
| ; RV32IM-LABEL: mul_i32: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: mul a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: mul_i32: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: mulw a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = mul i32 %a, %b | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| define i32 @sdiv_i32(i32 %a, i32 %b) { | ||
| ; RV32IM-LABEL: sdiv_i32: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: div a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: sdiv_i32: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: divw a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = sdiv i32 %a, %b | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| define i32 @srem_i32(i32 %a, i32 %b) { | ||
| ; RV32IM-LABEL: srem_i32: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: rem a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: srem_i32: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: remw a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = srem i32 %a, %b | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| define i32 @udiv_i32(i32 %a, i32 %b) { | ||
| ; RV32IM-LABEL: udiv_i32: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: divu a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: udiv_i32: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: divuw a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = udiv i32 %a, %b | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| define i32 @urem_i32(i32 %a, i32 %b) { | ||
| ; RV32IM-LABEL: urem_i32: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: remu a0, a0, a1 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: urem_i32: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: remuw a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = urem i32 %a, %b | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| define i64 @add_i64(i64 %a, i64 %b) { | ||
| ; RV32IM-LABEL: add_i64: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: add a0, a0, a2 | ||
| ; RV32IM-NEXT: sltu a2, a0, a2 | ||
| ; RV32IM-NEXT: add a1, a1, a3 | ||
| ; RV32IM-NEXT: andi a2, a2, 1 | ||
| ; RV32IM-NEXT: add a1, a1, a2 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: add_i64: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: add a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = add i64 %a, %b | ||
| ret i64 %0 | ||
| } | ||
|
|
||
| define i64 @sub_i64(i64 %a, i64 %b) { | ||
| ; RV32IM-LABEL: sub_i64: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: sub a4, a0, a2 | ||
| ; RV32IM-NEXT: sltu a0, a0, a2 | ||
| ; RV32IM-NEXT: sub a1, a1, a3 | ||
| ; RV32IM-NEXT: andi a0, a0, 1 | ||
| ; RV32IM-NEXT: sub a1, a1, a0 | ||
| ; RV32IM-NEXT: mv a0, a4 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: sub_i64: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: sub a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = sub i64 %a, %b | ||
| ret i64 %0 | ||
| } | ||
|
|
||
| ; TODO: Handle G_SELECT, which is needed to have i64 shifts working on RV32. | ||
|
|
||
| define i64 @and_i64(i64 %a, i64 %b) { | ||
| ; RV32IM-LABEL: and_i64: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: and a0, a0, a2 | ||
| ; RV32IM-NEXT: and a1, a1, a3 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: and_i64: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: and a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = and i64 %a, %b | ||
| ret i64 %0 | ||
| } | ||
|
|
||
| define i64 @or_i64(i64 %a, i64 %b) { | ||
| ; RV32IM-LABEL: or_i64: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: or a0, a0, a2 | ||
| ; RV32IM-NEXT: or a1, a1, a3 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: or_i64: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: or a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = or i64 %a, %b | ||
| ret i64 %0 | ||
| } | ||
|
|
||
| define i64 @xor_i64(i64 %a, i64 %b) { | ||
| ; RV32IM-LABEL: xor_i64: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: xor a0, a0, a2 | ||
| ; RV32IM-NEXT: xor a1, a1, a3 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: xor_i64: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: xor a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = xor i64 %a, %b | ||
| ret i64 %0 | ||
| } | ||
|
|
||
| define i64 @mul_i64(i64 %a, i64 %b) { | ||
| ; RV32IM-LABEL: mul_i64: | ||
| ; RV32IM: # %bb.0: # %entry | ||
| ; RV32IM-NEXT: mul a4, a0, a2 | ||
| ; RV32IM-NEXT: mul a1, a1, a2 | ||
| ; RV32IM-NEXT: mul a3, a0, a3 | ||
| ; RV32IM-NEXT: mulhu a0, a0, a2 | ||
| ; RV32IM-NEXT: add a1, a1, a3 | ||
| ; RV32IM-NEXT: add a1, a1, a0 | ||
| ; RV32IM-NEXT: mv a0, a4 | ||
| ; RV32IM-NEXT: ret | ||
| ; | ||
| ; RV64IM-LABEL: mul_i64: | ||
| ; RV64IM: # %bb.0: # %entry | ||
| ; RV64IM-NEXT: mul a0, a0, a1 | ||
| ; RV64IM-NEXT: ret | ||
| entry: | ||
| %0 = mul i64 %a, %b | ||
| ret i64 %0 | ||
| } | ||
|
|
||
| ; TODO: Handle G_SDIV, G_SREM, G_UDIV, G_UREM for i64 on RV32. Likely will be | ||
| ; dispatched to a libcall? |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,164 @@ | ||
| # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py | ||
| # RUN: llc -march=riscv32 -mattr=+m -run-pass=instruction-select -simplify-mir -verify-machineinstrs %s -o - \ | ||
| # RUN: | FileCheck -check-prefix=RV32I %s | ||
|
|
||
| --- | ||
| name: mul_i32 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11 | ||
| ; RV32I-LABEL: name: mul_i32 | ||
| ; RV32I: liveins: $x10, $x11 | ||
| ; RV32I-NEXT: {{ $}} | ||
| ; RV32I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV32I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV32I-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[COPY]], [[COPY1]] | ||
| ; RV32I-NEXT: $x10 = COPY [[MUL]] | ||
| ; RV32I-NEXT: PseudoRET implicit $x10 | ||
| %0:gprb(s32) = COPY $x10 | ||
| %1:gprb(s32) = COPY $x11 | ||
| %2:gprb(s32) = G_MUL %0, %1 | ||
| $x10 = COPY %2(s32) | ||
| PseudoRET implicit $x10 | ||
| ... | ||
| --- | ||
| name: sdiv_i32 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11 | ||
| ; RV32I-LABEL: name: sdiv_i32 | ||
| ; RV32I: liveins: $x10, $x11 | ||
| ; RV32I-NEXT: {{ $}} | ||
| ; RV32I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV32I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV32I-NEXT: [[DIV:%[0-9]+]]:gpr = DIV [[COPY]], [[COPY1]] | ||
| ; RV32I-NEXT: $x10 = COPY [[DIV]] | ||
| ; RV32I-NEXT: PseudoRET implicit $x10 | ||
| %0:gprb(s32) = COPY $x10 | ||
| %1:gprb(s32) = COPY $x11 | ||
| %2:gprb(s32) = G_SDIV %0, %1 | ||
| $x10 = COPY %2(s32) | ||
| PseudoRET implicit $x10 | ||
| ... | ||
| --- | ||
| name: srem_i32 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11 | ||
| ; RV32I-LABEL: name: srem_i32 | ||
| ; RV32I: liveins: $x10, $x11 | ||
| ; RV32I-NEXT: {{ $}} | ||
| ; RV32I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV32I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV32I-NEXT: [[REM:%[0-9]+]]:gpr = REM [[COPY]], [[COPY1]] | ||
| ; RV32I-NEXT: $x10 = COPY [[REM]] | ||
| ; RV32I-NEXT: PseudoRET implicit $x10 | ||
| %0:gprb(s32) = COPY $x10 | ||
| %1:gprb(s32) = COPY $x11 | ||
| %2:gprb(s32) = G_SREM %0, %1 | ||
| $x10 = COPY %2(s32) | ||
| PseudoRET implicit $x10 | ||
| ... | ||
| --- | ||
| name: udiv_i32 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11 | ||
| ; RV32I-LABEL: name: udiv_i32 | ||
| ; RV32I: liveins: $x10, $x11 | ||
| ; RV32I-NEXT: {{ $}} | ||
| ; RV32I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV32I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV32I-NEXT: [[DIVU:%[0-9]+]]:gpr = DIVU [[COPY]], [[COPY1]] | ||
| ; RV32I-NEXT: $x10 = COPY [[DIVU]] | ||
| ; RV32I-NEXT: PseudoRET implicit $x10 | ||
| %0:gprb(s32) = COPY $x10 | ||
| %1:gprb(s32) = COPY $x11 | ||
| %2:gprb(s32) = G_UDIV %0, %1 | ||
| $x10 = COPY %2(s32) | ||
| PseudoRET implicit $x10 | ||
| ... | ||
| --- | ||
| name: urem_i32 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11 | ||
| ; RV32I-LABEL: name: urem_i32 | ||
| ; RV32I: liveins: $x10, $x11 | ||
| ; RV32I-NEXT: {{ $}} | ||
| ; RV32I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV32I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV32I-NEXT: [[REMU:%[0-9]+]]:gpr = REMU [[COPY]], [[COPY1]] | ||
| ; RV32I-NEXT: $x10 = COPY [[REMU]] | ||
| ; RV32I-NEXT: PseudoRET implicit $x10 | ||
| %0:gprb(s32) = COPY $x10 | ||
| %1:gprb(s32) = COPY $x11 | ||
| %2:gprb(s32) = G_UREM %0, %1 | ||
| $x10 = COPY %2(s32) | ||
| PseudoRET implicit $x10 | ||
| ... | ||
| --- | ||
| name: mul_i64 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11, $x12, $x13 | ||
| ; RV32I-LABEL: name: mul_i64 | ||
| ; RV32I: liveins: $x10, $x11, $x12, $x13 | ||
| ; RV32I-NEXT: {{ $}} | ||
| ; RV32I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV32I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV32I-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12 | ||
| ; RV32I-NEXT: [[COPY3:%[0-9]+]]:gpr = COPY $x13 | ||
| ; RV32I-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[COPY]], [[COPY2]] | ||
| ; RV32I-NEXT: [[MUL1:%[0-9]+]]:gpr = MUL [[COPY1]], [[COPY2]] | ||
| ; RV32I-NEXT: [[MUL2:%[0-9]+]]:gpr = MUL [[COPY]], [[COPY3]] | ||
| ; RV32I-NEXT: [[MULHU:%[0-9]+]]:gpr = MULHU [[COPY]], [[COPY2]] | ||
| ; RV32I-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[MUL1]], [[MUL2]] | ||
| ; RV32I-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[ADD]], [[MULHU]] | ||
| ; RV32I-NEXT: $x10 = COPY [[MUL]] | ||
| ; RV32I-NEXT: $x11 = COPY [[ADD1]] | ||
| ; RV32I-NEXT: PseudoRET implicit $x10, implicit $x11 | ||
| %0:gprb(s32) = COPY $x10 | ||
| %1:gprb(s32) = COPY $x11 | ||
| %2:gprb(s32) = COPY $x12 | ||
| %3:gprb(s32) = COPY $x13 | ||
| %4:gprb(s32) = G_MUL %0, %2 | ||
| %5:gprb(s32) = G_MUL %1, %2 | ||
| %6:gprb(s32) = G_MUL %0, %3 | ||
| %7:gprb(s32) = G_UMULH %0, %2 | ||
| %8:gprb(s32) = G_ADD %5, %6 | ||
| %9:gprb(s32) = G_ADD %8, %7 | ||
| $x10 = COPY %4(s32) | ||
| $x11 = COPY %9(s32) | ||
| PseudoRET implicit $x10, implicit $x11 | ||
| ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,299 @@ | ||
| # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py | ||
| # RUN: llc -march=riscv64 -mattr=+m -run-pass=instruction-select -simplify-mir -verify-machineinstrs %s -o - \ | ||
| # RUN: | FileCheck -check-prefix=RV64I %s | ||
|
|
||
| --- | ||
| name: mul_i32 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11 | ||
| ; RV64I-LABEL: name: mul_i32 | ||
| ; RV64I: liveins: $x10, $x11 | ||
| ; RV64I-NEXT: {{ $}} | ||
| ; RV64I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV64I-NEXT: [[MULW:%[0-9]+]]:gpr = MULW [[COPY]], [[COPY1]] | ||
| ; RV64I-NEXT: $x10 = COPY [[MULW]] | ||
| ; RV64I-NEXT: PseudoRET implicit $x10 | ||
| %0:gprb(s64) = COPY $x10 | ||
| %1:gprb(s32) = G_TRUNC %0(s64) | ||
| %2:gprb(s64) = COPY $x11 | ||
| %3:gprb(s32) = G_TRUNC %2(s64) | ||
| %4:gprb(s32) = G_MUL %1, %3 | ||
| %5:gprb(s64) = G_ANYEXT %4(s32) | ||
| $x10 = COPY %5(s64) | ||
| PseudoRET implicit $x10 | ||
| ... | ||
| --- | ||
| name: sdiv_i32 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11 | ||
| ; RV64I-LABEL: name: sdiv_i32 | ||
| ; RV64I: liveins: $x10, $x11 | ||
| ; RV64I-NEXT: {{ $}} | ||
| ; RV64I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV64I-NEXT: [[DIVW:%[0-9]+]]:gpr = DIVW [[COPY]], [[COPY1]] | ||
| ; RV64I-NEXT: $x10 = COPY [[DIVW]] | ||
| ; RV64I-NEXT: PseudoRET implicit $x10 | ||
| %0:gprb(s64) = COPY $x10 | ||
| %1:gprb(s32) = G_TRUNC %0(s64) | ||
| %2:gprb(s64) = COPY $x11 | ||
| %3:gprb(s32) = G_TRUNC %2(s64) | ||
| %4:gprb(s32) = G_SDIV %1, %3 | ||
| %5:gprb(s64) = G_ANYEXT %4(s32) | ||
| $x10 = COPY %5(s64) | ||
| PseudoRET implicit $x10 | ||
| ... | ||
| --- | ||
| name: srem_i32 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11 | ||
| ; RV64I-LABEL: name: srem_i32 | ||
| ; RV64I: liveins: $x10, $x11 | ||
| ; RV64I-NEXT: {{ $}} | ||
| ; RV64I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV64I-NEXT: [[REMW:%[0-9]+]]:gpr = REMW [[COPY]], [[COPY1]] | ||
| ; RV64I-NEXT: $x10 = COPY [[REMW]] | ||
| ; RV64I-NEXT: PseudoRET implicit $x10 | ||
| %0:gprb(s64) = COPY $x10 | ||
| %1:gprb(s32) = G_TRUNC %0(s64) | ||
| %2:gprb(s64) = COPY $x11 | ||
| %3:gprb(s32) = G_TRUNC %2(s64) | ||
| %4:gprb(s32) = G_SREM %1, %3 | ||
| %5:gprb(s64) = G_ANYEXT %4(s32) | ||
| $x10 = COPY %5(s64) | ||
| PseudoRET implicit $x10 | ||
| ... | ||
| --- | ||
| name: udiv_i32 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11 | ||
| ; RV64I-LABEL: name: udiv_i32 | ||
| ; RV64I: liveins: $x10, $x11 | ||
| ; RV64I-NEXT: {{ $}} | ||
| ; RV64I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV64I-NEXT: [[DIVUW:%[0-9]+]]:gpr = DIVUW [[COPY]], [[COPY1]] | ||
| ; RV64I-NEXT: $x10 = COPY [[DIVUW]] | ||
| ; RV64I-NEXT: PseudoRET implicit $x10 | ||
| %0:gprb(s64) = COPY $x10 | ||
| %1:gprb(s32) = G_TRUNC %0(s64) | ||
| %2:gprb(s64) = COPY $x11 | ||
| %3:gprb(s32) = G_TRUNC %2(s64) | ||
| %4:gprb(s32) = G_UDIV %1, %3 | ||
| %5:gprb(s64) = G_ANYEXT %4(s32) | ||
| $x10 = COPY %5(s64) | ||
| PseudoRET implicit $x10 | ||
| ... | ||
| --- | ||
| name: urem_i32 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11 | ||
| ; RV64I-LABEL: name: urem_i32 | ||
| ; RV64I: liveins: $x10, $x11 | ||
| ; RV64I-NEXT: {{ $}} | ||
| ; RV64I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV64I-NEXT: [[REMUW:%[0-9]+]]:gpr = REMUW [[COPY]], [[COPY1]] | ||
| ; RV64I-NEXT: $x10 = COPY [[REMUW]] | ||
| ; RV64I-NEXT: PseudoRET implicit $x10 | ||
| %0:gprb(s64) = COPY $x10 | ||
| %1:gprb(s32) = G_TRUNC %0(s64) | ||
| %2:gprb(s64) = COPY $x11 | ||
| %3:gprb(s32) = G_TRUNC %2(s64) | ||
| %4:gprb(s32) = G_UREM %1, %3 | ||
| %5:gprb(s64) = G_ANYEXT %4(s32) | ||
| $x10 = COPY %5(s64) | ||
| PseudoRET implicit $x10 | ||
| ... | ||
| --- | ||
| name: mul_i64 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11 | ||
| ; RV64I-LABEL: name: mul_i64 | ||
| ; RV64I: liveins: $x10, $x11 | ||
| ; RV64I-NEXT: {{ $}} | ||
| ; RV64I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV64I-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[COPY]], [[COPY1]] | ||
| ; RV64I-NEXT: $x10 = COPY [[MUL]] | ||
| ; RV64I-NEXT: PseudoRET implicit $x10 | ||
| %0:gprb(s64) = COPY $x10 | ||
| %1:gprb(s64) = COPY $x11 | ||
| %2:gprb(s64) = G_MUL %0, %1 | ||
| $x10 = COPY %2(s64) | ||
| PseudoRET implicit $x10 | ||
| ... | ||
| --- | ||
| name: sdiv_i64 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11 | ||
| ; RV64I-LABEL: name: sdiv_i64 | ||
| ; RV64I: liveins: $x10, $x11 | ||
| ; RV64I-NEXT: {{ $}} | ||
| ; RV64I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV64I-NEXT: [[DIV:%[0-9]+]]:gpr = DIV [[COPY]], [[COPY1]] | ||
| ; RV64I-NEXT: $x10 = COPY [[DIV]] | ||
| ; RV64I-NEXT: PseudoRET implicit $x10 | ||
| %0:gprb(s64) = COPY $x10 | ||
| %1:gprb(s64) = COPY $x11 | ||
| %2:gprb(s64) = G_SDIV %0, %1 | ||
| $x10 = COPY %2(s64) | ||
| PseudoRET implicit $x10 | ||
| ... | ||
| --- | ||
| name: srem_i64 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11 | ||
| ; RV64I-LABEL: name: srem_i64 | ||
| ; RV64I: liveins: $x10, $x11 | ||
| ; RV64I-NEXT: {{ $}} | ||
| ; RV64I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV64I-NEXT: [[REM:%[0-9]+]]:gpr = REM [[COPY]], [[COPY1]] | ||
| ; RV64I-NEXT: $x10 = COPY [[REM]] | ||
| ; RV64I-NEXT: PseudoRET implicit $x10 | ||
| %0:gprb(s64) = COPY $x10 | ||
| %1:gprb(s64) = COPY $x11 | ||
| %2:gprb(s64) = G_SREM %0, %1 | ||
| $x10 = COPY %2(s64) | ||
| PseudoRET implicit $x10 | ||
| ... | ||
| --- | ||
| name: udiv_i64 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11 | ||
| ; RV64I-LABEL: name: udiv_i64 | ||
| ; RV64I: liveins: $x10, $x11 | ||
| ; RV64I-NEXT: {{ $}} | ||
| ; RV64I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV64I-NEXT: [[DIVU:%[0-9]+]]:gpr = DIVU [[COPY]], [[COPY1]] | ||
| ; RV64I-NEXT: $x10 = COPY [[DIVU]] | ||
| ; RV64I-NEXT: PseudoRET implicit $x10 | ||
| %0:gprb(s64) = COPY $x10 | ||
| %1:gprb(s64) = COPY $x11 | ||
| %2:gprb(s64) = G_UDIV %0, %1 | ||
| $x10 = COPY %2(s64) | ||
| PseudoRET implicit $x10 | ||
| ... | ||
| --- | ||
| name: urem_i64 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11 | ||
| ; RV64I-LABEL: name: urem_i64 | ||
| ; RV64I: liveins: $x10, $x11 | ||
| ; RV64I-NEXT: {{ $}} | ||
| ; RV64I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV64I-NEXT: [[REMU:%[0-9]+]]:gpr = REMU [[COPY]], [[COPY1]] | ||
| ; RV64I-NEXT: $x10 = COPY [[REMU]] | ||
| ; RV64I-NEXT: PseudoRET implicit $x10 | ||
| %0:gprb(s64) = COPY $x10 | ||
| %1:gprb(s64) = COPY $x11 | ||
| %2:gprb(s64) = G_UREM %0, %1 | ||
| $x10 = COPY %2(s64) | ||
| PseudoRET implicit $x10 | ||
| ... | ||
| --- | ||
| name: mul_i128 | ||
| legalized: true | ||
| regBankSelected: true | ||
| tracksRegLiveness: true | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: $x10, $x11, $x12, $x13 | ||
| ; RV64I-LABEL: name: mul_i128 | ||
| ; RV64I: liveins: $x10, $x11, $x12, $x13 | ||
| ; RV64I-NEXT: {{ $}} | ||
| ; RV64I-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10 | ||
| ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11 | ||
| ; RV64I-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12 | ||
| ; RV64I-NEXT: [[COPY3:%[0-9]+]]:gpr = COPY $x13 | ||
| ; RV64I-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[COPY]], [[COPY2]] | ||
| ; RV64I-NEXT: [[MUL1:%[0-9]+]]:gpr = MUL [[COPY1]], [[COPY2]] | ||
| ; RV64I-NEXT: [[MUL2:%[0-9]+]]:gpr = MUL [[COPY]], [[COPY3]] | ||
| ; RV64I-NEXT: [[MULHU:%[0-9]+]]:gpr = MULHU [[COPY]], [[COPY2]] | ||
| ; RV64I-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[MUL1]], [[MUL2]] | ||
| ; RV64I-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[ADD]], [[MULHU]] | ||
| ; RV64I-NEXT: $x10 = COPY [[MUL]] | ||
| ; RV64I-NEXT: $x11 = COPY [[ADD1]] | ||
| ; RV64I-NEXT: PseudoRET implicit $x10, implicit $x11 | ||
| %0:gprb(s64) = COPY $x10 | ||
| %1:gprb(s64) = COPY $x11 | ||
| %2:gprb(s64) = COPY $x12 | ||
| %3:gprb(s64) = COPY $x13 | ||
| %4:gprb(s64) = G_MUL %0, %2 | ||
| %5:gprb(s64) = G_MUL %1, %2 | ||
| %6:gprb(s64) = G_MUL %0, %3 | ||
| %7:gprb(s64) = G_UMULH %0, %2 | ||
| %8:gprb(s64) = G_ADD %5, %6 | ||
| %9:gprb(s64) = G_ADD %8, %7 | ||
| $x10 = COPY %4(s64) | ||
| $x11 = COPY %9(s64) | ||
| PseudoRET implicit $x10, implicit $x11 | ||
| ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 | ||
| ; RUN: llc < %s -mtriple=riscv64 -mattr=+a | FileCheck %s | ||
|
|
||
| define ptr @cmpxchg_masked_and_branch1(ptr %ptr, i8 signext %cmp, i8 signext %val) nounwind { | ||
| ; CHECK-LABEL: cmpxchg_masked_and_branch1: | ||
| ; CHECK: # %bb.0: # %do_cmpxchg | ||
| ; CHECK-NEXT: andi a3, a0, -4 | ||
| ; CHECK-NEXT: slli a4, a0, 3 | ||
| ; CHECK-NEXT: li a5, 255 | ||
| ; CHECK-NEXT: sllw a5, a5, a4 | ||
| ; CHECK-NEXT: andi a1, a1, 255 | ||
| ; CHECK-NEXT: sllw a1, a1, a4 | ||
| ; CHECK-NEXT: andi a2, a2, 255 | ||
| ; CHECK-NEXT: sllw a2, a2, a4 | ||
| ; CHECK-NEXT: .LBB0_3: # %do_cmpxchg | ||
| ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 | ||
| ; CHECK-NEXT: lr.w.aqrl a4, (a3) | ||
| ; CHECK-NEXT: and a6, a4, a5 | ||
| ; CHECK-NEXT: bne a6, a1, .LBB0_5 | ||
| ; CHECK-NEXT: # %bb.4: # %do_cmpxchg | ||
| ; CHECK-NEXT: # in Loop: Header=BB0_3 Depth=1 | ||
| ; CHECK-NEXT: xor a6, a4, a2 | ||
| ; CHECK-NEXT: and a6, a6, a5 | ||
| ; CHECK-NEXT: xor a6, a4, a6 | ||
| ; CHECK-NEXT: sc.w.rl a6, a6, (a3) | ||
| ; CHECK-NEXT: bnez a6, .LBB0_3 | ||
| ; CHECK-NEXT: .LBB0_5: # %do_cmpxchg | ||
| ; CHECK-NEXT: and a2, a4, a5 | ||
| ; CHECK-NEXT: bne a1, a2, .LBB0_2 | ||
| ; CHECK-NEXT: # %bb.1: # %returnptr | ||
| ; CHECK-NEXT: xor a1, a1, a2 | ||
| ; CHECK-NEXT: snez a1, a1 | ||
| ; CHECK-NEXT: addi a1, a1, -1 | ||
| ; CHECK-NEXT: and a0, a1, a0 | ||
| ; CHECK-NEXT: ret | ||
| ; CHECK-NEXT: .LBB0_2: # %exit | ||
| ; CHECK-NEXT: li a0, 0 | ||
| ; CHECK-NEXT: ret | ||
| do_cmpxchg: | ||
| %0 = cmpxchg ptr %ptr, i8 %cmp, i8 %val seq_cst seq_cst | ||
| %1 = extractvalue { i8, i1 } %0, 1 | ||
| %2 = select i1 %1, ptr %ptr, ptr null | ||
| br i1 %1, label %returnptr, label %exit | ||
| returnptr: | ||
| ret ptr %2 | ||
| exit: | ||
| ret ptr null | ||
| } |