Craig Topper 70289ea6f5 [RISCV][LegalizeTypes] Try to expand BSWAP before promoting if the promoted BSWAP would expand anyway.
If we're going to end up expanding anyway, we should do it early
so we don't create extra operations to handle the bytes added by
promotion.

This is helfpul on RISCV where we might have to promote i16 all
the way to i64.

Differential Revision: https://reviews.llvm.org/D95756
2021-01-31 14:33:29 -08:00

941 lines
25 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64I
; RUN: llc -mtriple=riscv64 -mattr=+experimental-b -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64IB
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbb -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64IBB
declare i32 @llvm.ctlz.i32(i32, i1)
define signext i32 @ctlz_i32(i32 signext %a) nounwind {
; RV64I-LABEL: ctlz_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: beqz a0, .LBB0_2
; RV64I-NEXT: # %bb.1: # %cond.false
; RV64I-NEXT: srliw a1, a0, 1
; RV64I-NEXT: slli a0, a0, 32
; RV64I-NEXT: srli a0, a0, 32
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: srli a1, a0, 2
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: srli a1, a0, 4
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: srli a1, a0, 8
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: srli a1, a0, 16
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: srli a1, a0, 32
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: srli a1, a0, 1
; RV64I-NEXT: lui a2, 21845
; RV64I-NEXT: addiw a2, a2, 1365
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 1365
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 1365
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 1365
; RV64I-NEXT: and a1, a1, a2
; RV64I-NEXT: sub a0, a0, a1
; RV64I-NEXT: lui a1, 13107
; RV64I-NEXT: addiw a1, a1, 819
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 819
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 819
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 819
; RV64I-NEXT: and a2, a0, a1
; RV64I-NEXT: srli a0, a0, 2
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: add a0, a2, a0
; RV64I-NEXT: srli a1, a0, 4
; RV64I-NEXT: add a0, a0, a1
; RV64I-NEXT: lui a1, 3855
; RV64I-NEXT: addiw a1, a1, 241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, -241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, -241
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: lui a1, 4112
; RV64I-NEXT: addiw a1, a1, 257
; RV64I-NEXT: slli a1, a1, 16
; RV64I-NEXT: addi a1, a1, 257
; RV64I-NEXT: slli a1, a1, 16
; RV64I-NEXT: addi a1, a1, 257
; RV64I-NEXT: call __muldi3@plt
; RV64I-NEXT: srli a0, a0, 56
; RV64I-NEXT: addi a0, a0, -32
; RV64I-NEXT: j .LBB0_3
; RV64I-NEXT: .LBB0_2:
; RV64I-NEXT: addi a0, zero, 32
; RV64I-NEXT: .LBB0_3: # %cond.end
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
;
; RV64IB-LABEL: ctlz_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: clzw a0, a0
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: ctlz_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: clzw a0, a0
; RV64IBB-NEXT: ret
%1 = call i32 @llvm.ctlz.i32(i32 %a, i1 false)
ret i32 %1
}
declare i64 @llvm.ctlz.i64(i64, i1)
define i64 @ctlz_i64(i64 %a) nounwind {
; RV64I-LABEL: ctlz_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: beqz a0, .LBB1_2
; RV64I-NEXT: # %bb.1: # %cond.false
; RV64I-NEXT: srli a1, a0, 1
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: srli a1, a0, 2
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: srli a1, a0, 4
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: srli a1, a0, 8
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: srli a1, a0, 16
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: srli a1, a0, 32
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: srli a1, a0, 1
; RV64I-NEXT: lui a2, 21845
; RV64I-NEXT: addiw a2, a2, 1365
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 1365
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 1365
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 1365
; RV64I-NEXT: and a1, a1, a2
; RV64I-NEXT: sub a0, a0, a1
; RV64I-NEXT: lui a1, 13107
; RV64I-NEXT: addiw a1, a1, 819
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 819
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 819
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 819
; RV64I-NEXT: and a2, a0, a1
; RV64I-NEXT: srli a0, a0, 2
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: add a0, a2, a0
; RV64I-NEXT: srli a1, a0, 4
; RV64I-NEXT: add a0, a0, a1
; RV64I-NEXT: lui a1, 3855
; RV64I-NEXT: addiw a1, a1, 241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, -241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, -241
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: lui a1, 4112
; RV64I-NEXT: addiw a1, a1, 257
; RV64I-NEXT: slli a1, a1, 16
; RV64I-NEXT: addi a1, a1, 257
; RV64I-NEXT: slli a1, a1, 16
; RV64I-NEXT: addi a1, a1, 257
; RV64I-NEXT: call __muldi3@plt
; RV64I-NEXT: srli a0, a0, 56
; RV64I-NEXT: j .LBB1_3
; RV64I-NEXT: .LBB1_2:
; RV64I-NEXT: addi a0, zero, 64
; RV64I-NEXT: .LBB1_3: # %cond.end
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
;
; RV64IB-LABEL: ctlz_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: clz a0, a0
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: ctlz_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: clz a0, a0
; RV64IBB-NEXT: ret
%1 = call i64 @llvm.ctlz.i64(i64 %a, i1 false)
ret i64 %1
}
declare i32 @llvm.cttz.i32(i32, i1)
define signext i32 @cttz_i32(i32 signext %a) nounwind {
; RV64I-LABEL: cttz_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: beqz a0, .LBB2_2
; RV64I-NEXT: # %bb.1: # %cond.false
; RV64I-NEXT: addi a1, a0, -1
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: srli a1, a0, 1
; RV64I-NEXT: lui a2, 21845
; RV64I-NEXT: addiw a2, a2, 1365
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 1365
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 1365
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 1365
; RV64I-NEXT: and a1, a1, a2
; RV64I-NEXT: sub a0, a0, a1
; RV64I-NEXT: lui a1, 13107
; RV64I-NEXT: addiw a1, a1, 819
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 819
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 819
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 819
; RV64I-NEXT: and a2, a0, a1
; RV64I-NEXT: srli a0, a0, 2
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: add a0, a2, a0
; RV64I-NEXT: srli a1, a0, 4
; RV64I-NEXT: add a0, a0, a1
; RV64I-NEXT: lui a1, 3855
; RV64I-NEXT: addiw a1, a1, 241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, -241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, -241
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: lui a1, 4112
; RV64I-NEXT: addiw a1, a1, 257
; RV64I-NEXT: slli a1, a1, 16
; RV64I-NEXT: addi a1, a1, 257
; RV64I-NEXT: slli a1, a1, 16
; RV64I-NEXT: addi a1, a1, 257
; RV64I-NEXT: call __muldi3@plt
; RV64I-NEXT: srli a0, a0, 56
; RV64I-NEXT: j .LBB2_3
; RV64I-NEXT: .LBB2_2:
; RV64I-NEXT: addi a0, zero, 32
; RV64I-NEXT: .LBB2_3: # %cond.end
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
;
; RV64IB-LABEL: cttz_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: ctzw a0, a0
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: cttz_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: ctzw a0, a0
; RV64IBB-NEXT: ret
%1 = call i32 @llvm.cttz.i32(i32 %a, i1 false)
ret i32 %1
}
declare i64 @llvm.cttz.i64(i64, i1)
define i64 @cttz_i64(i64 %a) nounwind {
; RV64I-LABEL: cttz_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: beqz a0, .LBB3_2
; RV64I-NEXT: # %bb.1: # %cond.false
; RV64I-NEXT: addi a1, a0, -1
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: srli a1, a0, 1
; RV64I-NEXT: lui a2, 21845
; RV64I-NEXT: addiw a2, a2, 1365
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 1365
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 1365
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 1365
; RV64I-NEXT: and a1, a1, a2
; RV64I-NEXT: sub a0, a0, a1
; RV64I-NEXT: lui a1, 13107
; RV64I-NEXT: addiw a1, a1, 819
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 819
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 819
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 819
; RV64I-NEXT: and a2, a0, a1
; RV64I-NEXT: srli a0, a0, 2
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: add a0, a2, a0
; RV64I-NEXT: srli a1, a0, 4
; RV64I-NEXT: add a0, a0, a1
; RV64I-NEXT: lui a1, 3855
; RV64I-NEXT: addiw a1, a1, 241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, -241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, -241
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: lui a1, 4112
; RV64I-NEXT: addiw a1, a1, 257
; RV64I-NEXT: slli a1, a1, 16
; RV64I-NEXT: addi a1, a1, 257
; RV64I-NEXT: slli a1, a1, 16
; RV64I-NEXT: addi a1, a1, 257
; RV64I-NEXT: call __muldi3@plt
; RV64I-NEXT: srli a0, a0, 56
; RV64I-NEXT: j .LBB3_3
; RV64I-NEXT: .LBB3_2:
; RV64I-NEXT: addi a0, zero, 64
; RV64I-NEXT: .LBB3_3: # %cond.end
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
;
; RV64IB-LABEL: cttz_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: ctz a0, a0
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: cttz_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: ctz a0, a0
; RV64IBB-NEXT: ret
%1 = call i64 @llvm.cttz.i64(i64 %a, i1 false)
ret i64 %1
}
declare i32 @llvm.ctpop.i32(i32)
define signext i32 @ctpop_i32(i32 signext %a) nounwind {
; RV64I-LABEL: ctpop_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: slli a1, a0, 32
; RV64I-NEXT: srli a1, a1, 32
; RV64I-NEXT: srliw a0, a0, 1
; RV64I-NEXT: lui a2, 349525
; RV64I-NEXT: addiw a2, a2, 1365
; RV64I-NEXT: and a0, a0, a2
; RV64I-NEXT: sub a0, a1, a0
; RV64I-NEXT: srli a1, a0, 2
; RV64I-NEXT: lui a2, 13107
; RV64I-NEXT: addiw a2, a2, 819
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 819
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 819
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 819
; RV64I-NEXT: and a1, a1, a2
; RV64I-NEXT: and a0, a0, a2
; RV64I-NEXT: add a0, a0, a1
; RV64I-NEXT: srli a1, a0, 4
; RV64I-NEXT: add a0, a0, a1
; RV64I-NEXT: lui a1, 3855
; RV64I-NEXT: addiw a1, a1, 241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, -241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, -241
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: lui a1, 4112
; RV64I-NEXT: addiw a1, a1, 257
; RV64I-NEXT: slli a1, a1, 16
; RV64I-NEXT: addi a1, a1, 257
; RV64I-NEXT: slli a1, a1, 16
; RV64I-NEXT: addi a1, a1, 257
; RV64I-NEXT: call __muldi3@plt
; RV64I-NEXT: srli a0, a0, 56
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
;
; RV64IB-LABEL: ctpop_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: cpopw a0, a0
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: ctpop_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: cpopw a0, a0
; RV64IBB-NEXT: ret
%1 = call i32 @llvm.ctpop.i32(i32 %a)
ret i32 %1
}
declare i64 @llvm.ctpop.i64(i64)
define i64 @ctpop_i64(i64 %a) nounwind {
; RV64I-LABEL: ctpop_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: srli a1, a0, 1
; RV64I-NEXT: lui a2, 21845
; RV64I-NEXT: addiw a2, a2, 1365
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 1365
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 1365
; RV64I-NEXT: slli a2, a2, 12
; RV64I-NEXT: addi a2, a2, 1365
; RV64I-NEXT: and a1, a1, a2
; RV64I-NEXT: sub a0, a0, a1
; RV64I-NEXT: lui a1, 13107
; RV64I-NEXT: addiw a1, a1, 819
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 819
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 819
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 819
; RV64I-NEXT: and a2, a0, a1
; RV64I-NEXT: srli a0, a0, 2
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: add a0, a2, a0
; RV64I-NEXT: srli a1, a0, 4
; RV64I-NEXT: add a0, a0, a1
; RV64I-NEXT: lui a1, 3855
; RV64I-NEXT: addiw a1, a1, 241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, -241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, 241
; RV64I-NEXT: slli a1, a1, 12
; RV64I-NEXT: addi a1, a1, -241
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: lui a1, 4112
; RV64I-NEXT: addiw a1, a1, 257
; RV64I-NEXT: slli a1, a1, 16
; RV64I-NEXT: addi a1, a1, 257
; RV64I-NEXT: slli a1, a1, 16
; RV64I-NEXT: addi a1, a1, 257
; RV64I-NEXT: call __muldi3@plt
; RV64I-NEXT: srli a0, a0, 56
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
;
; RV64IB-LABEL: ctpop_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: cpop a0, a0
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: ctpop_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: cpop a0, a0
; RV64IBB-NEXT: ret
%1 = call i64 @llvm.ctpop.i64(i64 %a)
ret i64 %1
}
define signext i32 @sextb_i32(i32 signext %a) nounwind {
; RV64I-LABEL: sextb_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: slli a0, a0, 56
; RV64I-NEXT: srai a0, a0, 56
; RV64I-NEXT: ret
;
; RV64IB-LABEL: sextb_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: sext.b a0, a0
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: sextb_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: sext.b a0, a0
; RV64IBB-NEXT: ret
%shl = shl i32 %a, 24
%shr = ashr exact i32 %shl, 24
ret i32 %shr
}
define i64 @sextb_i64(i64 %a) nounwind {
; RV64I-LABEL: sextb_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: slli a0, a0, 56
; RV64I-NEXT: srai a0, a0, 56
; RV64I-NEXT: ret
;
; RV64IB-LABEL: sextb_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: sext.b a0, a0
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: sextb_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: sext.b a0, a0
; RV64IBB-NEXT: ret
%shl = shl i64 %a, 56
%shr = ashr exact i64 %shl, 56
ret i64 %shr
}
define signext i32 @sexth_i32(i32 signext %a) nounwind {
; RV64I-LABEL: sexth_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: slli a0, a0, 48
; RV64I-NEXT: srai a0, a0, 48
; RV64I-NEXT: ret
;
; RV64IB-LABEL: sexth_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: sext.h a0, a0
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: sexth_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: sext.h a0, a0
; RV64IBB-NEXT: ret
%shl = shl i32 %a, 16
%shr = ashr exact i32 %shl, 16
ret i32 %shr
}
define i64 @sexth_i64(i64 %a) nounwind {
; RV64I-LABEL: sexth_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: slli a0, a0, 48
; RV64I-NEXT: srai a0, a0, 48
; RV64I-NEXT: ret
;
; RV64IB-LABEL: sexth_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: sext.h a0, a0
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: sexth_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: sext.h a0, a0
; RV64IBB-NEXT: ret
%shl = shl i64 %a, 48
%shr = ashr exact i64 %shl, 48
ret i64 %shr
}
define signext i32 @min_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: min_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: blt a0, a1, .LBB10_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
; RV64I-NEXT: .LBB10_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: min_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: min a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: min_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: min a0, a0, a1
; RV64IBB-NEXT: ret
%cmp = icmp slt i32 %a, %b
%cond = select i1 %cmp, i32 %a, i32 %b
ret i32 %cond
}
define i64 @min_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: min_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: blt a0, a1, .LBB11_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
; RV64I-NEXT: .LBB11_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: min_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: min a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: min_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: min a0, a0, a1
; RV64IBB-NEXT: ret
%cmp = icmp slt i64 %a, %b
%cond = select i1 %cmp, i64 %a, i64 %b
ret i64 %cond
}
define signext i32 @max_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: max_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: blt a1, a0, .LBB12_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
; RV64I-NEXT: .LBB12_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: max_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: max a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: max_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: max a0, a0, a1
; RV64IBB-NEXT: ret
%cmp = icmp sgt i32 %a, %b
%cond = select i1 %cmp, i32 %a, i32 %b
ret i32 %cond
}
define i64 @max_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: max_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: blt a1, a0, .LBB13_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
; RV64I-NEXT: .LBB13_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: max_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: max a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: max_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: max a0, a0, a1
; RV64IBB-NEXT: ret
%cmp = icmp sgt i64 %a, %b
%cond = select i1 %cmp, i64 %a, i64 %b
ret i64 %cond
}
define signext i32 @minu_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: minu_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: bltu a0, a1, .LBB14_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
; RV64I-NEXT: .LBB14_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: minu_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: minu a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: minu_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: minu a0, a0, a1
; RV64IBB-NEXT: ret
%cmp = icmp ult i32 %a, %b
%cond = select i1 %cmp, i32 %a, i32 %b
ret i32 %cond
}
define i64 @minu_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: minu_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: bltu a0, a1, .LBB15_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
; RV64I-NEXT: .LBB15_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: minu_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: minu a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: minu_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: minu a0, a0, a1
; RV64IBB-NEXT: ret
%cmp = icmp ult i64 %a, %b
%cond = select i1 %cmp, i64 %a, i64 %b
ret i64 %cond
}
define signext i32 @maxu_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: maxu_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: bltu a1, a0, .LBB16_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
; RV64I-NEXT: .LBB16_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: maxu_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: maxu a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: maxu_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: maxu a0, a0, a1
; RV64IBB-NEXT: ret
%cmp = icmp ugt i32 %a, %b
%cond = select i1 %cmp, i32 %a, i32 %b
ret i32 %cond
}
define i64 @maxu_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: maxu_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: bltu a1, a0, .LBB17_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
; RV64I-NEXT: .LBB17_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: maxu_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: maxu a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: maxu_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: maxu a0, a0, a1
; RV64IBB-NEXT: ret
%cmp = icmp ugt i64 %a, %b
%cond = select i1 %cmp, i64 %a, i64 %b
ret i64 %cond
}
declare i32 @llvm.abs.i32(i32, i1 immarg)
define i32 @abs_i32(i32 %x) {
; RV64I-LABEL: abs_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: srai a1, a0, 63
; RV64I-NEXT: add a0, a0, a1
; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: ret
;
; RV64IB-LABEL: abs_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: sext.w a0, a0
; RV64IB-NEXT: neg a1, a0
; RV64IB-NEXT: max a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: abs_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: sext.w a0, a0
; RV64IBB-NEXT: neg a1, a0
; RV64IBB-NEXT: max a0, a0, a1
; RV64IBB-NEXT: ret
%abs = tail call i32 @llvm.abs.i32(i32 %x, i1 true)
ret i32 %abs
}
declare i64 @llvm.abs.i64(i64, i1 immarg)
define i64 @abs_i64(i64 %x) {
; RV64I-LABEL: abs_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: srai a1, a0, 63
; RV64I-NEXT: add a0, a0, a1
; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: ret
;
; RV64IB-LABEL: abs_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: neg a1, a0
; RV64IB-NEXT: max a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: abs_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: neg a1, a0
; RV64IBB-NEXT: max a0, a0, a1
; RV64IBB-NEXT: ret
%abs = tail call i64 @llvm.abs.i64(i64 %x, i1 true)
ret i64 %abs
}
define i32 @zexth_i32(i32 %a) nounwind {
; RV64I-LABEL: zexth_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: lui a1, 16
; RV64I-NEXT: addiw a1, a1, -1
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: ret
;
; RV64IB-LABEL: zexth_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: zext.h a0, a0
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: zexth_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: zext.h a0, a0
; RV64IBB-NEXT: ret
%and = and i32 %a, 65535
ret i32 %and
}
define i64 @zexth_i64(i64 %a) nounwind {
; RV64I-LABEL: zexth_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: lui a1, 16
; RV64I-NEXT: addiw a1, a1, -1
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: ret
;
; RV64IB-LABEL: zexth_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: zext.h a0, a0
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: zexth_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: zext.h a0, a0
; RV64IBB-NEXT: ret
%and = and i64 %a, 65535
ret i64 %and
}
declare i32 @llvm.bswap.i32(i32)
define signext i32 @bswap_i32(i32 signext %a) nounwind {
; RV64I-LABEL: bswap_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: srliw a1, a0, 8
; RV64I-NEXT: lui a2, 16
; RV64I-NEXT: addiw a2, a2, -256
; RV64I-NEXT: and a1, a1, a2
; RV64I-NEXT: srliw a2, a0, 24
; RV64I-NEXT: or a1, a1, a2
; RV64I-NEXT: slli a2, a0, 8
; RV64I-NEXT: lui a3, 4080
; RV64I-NEXT: and a2, a2, a3
; RV64I-NEXT: slli a0, a0, 24
; RV64I-NEXT: or a0, a0, a2
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: bswap_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: greviw a0, a0, 24
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: bswap_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: rev8 a0, a0
; RV64IBB-NEXT: srai a0, a0, 32
; RV64IBB-NEXT: ret
%1 = tail call i32 @llvm.bswap.i32(i32 %a)
ret i32 %1
}
; Similar to bswap_i32 but the result is not sign extended.
define void @bswap_i32_nosext(i32 signext %a, i32* %x) nounwind {
; RV64I-LABEL: bswap_i32_nosext:
; RV64I: # %bb.0:
; RV64I-NEXT: srliw a2, a0, 8
; RV64I-NEXT: lui a3, 16
; RV64I-NEXT: addiw a3, a3, -256
; RV64I-NEXT: and a2, a2, a3
; RV64I-NEXT: srliw a3, a0, 24
; RV64I-NEXT: or a2, a2, a3
; RV64I-NEXT: slli a3, a0, 8
; RV64I-NEXT: lui a4, 4080
; RV64I-NEXT: and a3, a3, a4
; RV64I-NEXT: slli a0, a0, 24
; RV64I-NEXT: or a0, a0, a3
; RV64I-NEXT: or a0, a0, a2
; RV64I-NEXT: sw a0, 0(a1)
; RV64I-NEXT: ret
;
; RV64IB-LABEL: bswap_i32_nosext:
; RV64IB: # %bb.0:
; RV64IB-NEXT: greviw a0, a0, 24
; RV64IB-NEXT: sw a0, 0(a1)
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: bswap_i32_nosext:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: rev8 a0, a0
; RV64IBB-NEXT: srli a0, a0, 32
; RV64IBB-NEXT: sw a0, 0(a1)
; RV64IBB-NEXT: ret
%1 = tail call i32 @llvm.bswap.i32(i32 %a)
store i32 %1, i32* %x
ret void
}
declare i64 @llvm.bswap.i64(i64)
define i64 @bswap_i64(i64 %a) {
; RV64I-LABEL: bswap_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: srli a1, a0, 24
; RV64I-NEXT: lui a2, 4080
; RV64I-NEXT: and a1, a1, a2
; RV64I-NEXT: srli a2, a0, 8
; RV64I-NEXT: addi a3, zero, 255
; RV64I-NEXT: slli a4, a3, 24
; RV64I-NEXT: and a2, a2, a4
; RV64I-NEXT: or a1, a2, a1
; RV64I-NEXT: srli a2, a0, 40
; RV64I-NEXT: lui a4, 16
; RV64I-NEXT: addiw a4, a4, -256
; RV64I-NEXT: and a2, a2, a4
; RV64I-NEXT: srli a4, a0, 56
; RV64I-NEXT: or a2, a2, a4
; RV64I-NEXT: or a1, a1, a2
; RV64I-NEXT: slli a2, a0, 8
; RV64I-NEXT: slli a4, a3, 32
; RV64I-NEXT: and a2, a2, a4
; RV64I-NEXT: slli a4, a0, 24
; RV64I-NEXT: slli a5, a3, 40
; RV64I-NEXT: and a4, a4, a5
; RV64I-NEXT: or a2, a4, a2
; RV64I-NEXT: slli a4, a0, 40
; RV64I-NEXT: slli a3, a3, 48
; RV64I-NEXT: and a3, a4, a3
; RV64I-NEXT: slli a0, a0, 56
; RV64I-NEXT: or a0, a0, a3
; RV64I-NEXT: or a0, a0, a2
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: ret
;
; RV64IB-LABEL: bswap_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: rev8 a0, a0
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: bswap_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: rev8 a0, a0
; RV64IBB-NEXT: ret
%1 = call i64 @llvm.bswap.i64(i64 %a)
ret i64 %1
}