380 changes: 380 additions & 0 deletions llvm/test/CodeGen/RISCV/GlobalISel/alu-roundtrip.ll
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?
480 changes: 480 additions & 0 deletions llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/alu-rv32.mir

Large diffs are not rendered by default.

621 changes: 621 additions & 0 deletions llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/alu-rv64.mir

Large diffs are not rendered by default.

164 changes: 164 additions & 0 deletions llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/alu_m-rv32.mir
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
...
299 changes: 299 additions & 0 deletions llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/alu_m-rv64.mir
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
...
48 changes: 48 additions & 0 deletions llvm/test/CodeGen/RISCV/pr65025.ll
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
}