diff --git a/llvm/test/CodeGen/RISCV/rv32zpn-bitreverse.ll b/llvm/test/CodeGen/RISCV/rv32zpn-bitreverse.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rv32zpn-bitreverse.ll @@ -0,0 +1,400 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+experimental-b -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV32IB +; RUN: llc -mtriple=riscv32 -mattr=+experimental-p -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV32IP +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zpn -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV32IPN +; RUN: llc -mtriple=riscv32 -mattr=+experimental-b,+experimental-p -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV32IBP + +declare i8 @llvm.bitreverse.i8(i8) +declare i16 @llvm.bitreverse.i16(i16) +declare i32 @llvm.bitreverse.i32(i32) +declare i64 @llvm.bitreverse.i64(i64) + +define zeroext i8 @bitreverse_i8(i8 zeroext %a) nounwind { +; RV32IB-LABEL: bitreverse_i8: +; RV32IB: # %bb.0: +; RV32IB-NEXT: rev.b a0, a0 +; RV32IB-NEXT: ret +; +; RV32IP-LABEL: bitreverse_i8: +; RV32IP: # %bb.0: +; RV32IP-NEXT: srli a1, a0, 4 +; RV32IP-NEXT: andi a0, a0, 15 +; RV32IP-NEXT: slli a0, a0, 4 +; RV32IP-NEXT: or a0, a1, a0 +; RV32IP-NEXT: andi a1, a0, 51 +; RV32IP-NEXT: slli a1, a1, 2 +; RV32IP-NEXT: andi a0, a0, 204 +; RV32IP-NEXT: srli a0, a0, 2 +; RV32IP-NEXT: or a0, a0, a1 +; RV32IP-NEXT: andi a1, a0, 85 +; RV32IP-NEXT: slli a1, a1, 1 +; RV32IP-NEXT: andi a0, a0, 170 +; RV32IP-NEXT: srli a0, a0, 1 +; RV32IP-NEXT: or a0, a0, a1 +; RV32IP-NEXT: ret +; +; RV32IPN-LABEL: bitreverse_i8: +; RV32IPN: # %bb.0: +; RV32IPN-NEXT: srli a1, a0, 4 +; RV32IPN-NEXT: andi a0, a0, 15 +; RV32IPN-NEXT: slli a0, a0, 4 +; RV32IPN-NEXT: or a0, a1, a0 +; RV32IPN-NEXT: andi a1, a0, 51 +; RV32IPN-NEXT: slli a1, a1, 2 +; RV32IPN-NEXT: andi a0, a0, 204 +; RV32IPN-NEXT: srli a0, a0, 2 +; RV32IPN-NEXT: or a0, a0, a1 +; RV32IPN-NEXT: andi a1, a0, 85 +; RV32IPN-NEXT: slli a1, a1, 1 +; RV32IPN-NEXT: andi a0, a0, 170 +; RV32IPN-NEXT: srli a0, a0, 1 +; RV32IPN-NEXT: or a0, a0, a1 +; RV32IPN-NEXT: ret +; +; RV32IBP-LABEL: bitreverse_i8: +; RV32IBP: # %bb.0: +; RV32IBP-NEXT: rev.b a0, a0 +; RV32IBP-NEXT: ret + %ret = tail call i8 @llvm.bitreverse.i8(i8 %a) + ret i8 %ret +} + +define zeroext i16 @bitreverse_i16(i16 zeroext %a) nounwind { +; RV32IB-LABEL: bitreverse_i16: +; RV32IB: # %bb.0: +; RV32IB-NEXT: rev.h a0, a0 +; RV32IB-NEXT: ret +; +; RV32IP-LABEL: bitreverse_i16: +; RV32IP: # %bb.0: +; RV32IP-NEXT: srli a1, a0, 8 +; RV32IP-NEXT: slli a0, a0, 8 +; RV32IP-NEXT: or a0, a0, a1 +; RV32IP-NEXT: lui a1, 1 +; RV32IP-NEXT: addi a1, a1, -241 +; RV32IP-NEXT: and a1, a0, a1 +; RV32IP-NEXT: slli a1, a1, 4 +; RV32IP-NEXT: lui a2, 15 +; RV32IP-NEXT: addi a2, a2, 240 +; RV32IP-NEXT: and a0, a0, a2 +; RV32IP-NEXT: srli a0, a0, 4 +; RV32IP-NEXT: or a0, a0, a1 +; RV32IP-NEXT: lui a1, 3 +; RV32IP-NEXT: addi a1, a1, 819 +; RV32IP-NEXT: and a1, a0, a1 +; RV32IP-NEXT: slli a1, a1, 2 +; RV32IP-NEXT: lui a2, 13 +; RV32IP-NEXT: addi a2, a2, -820 +; RV32IP-NEXT: and a0, a0, a2 +; RV32IP-NEXT: srli a0, a0, 2 +; RV32IP-NEXT: or a0, a0, a1 +; RV32IP-NEXT: lui a1, 5 +; RV32IP-NEXT: addi a1, a1, 1365 +; RV32IP-NEXT: and a1, a0, a1 +; RV32IP-NEXT: slli a1, a1, 1 +; RV32IP-NEXT: lui a2, 11 +; RV32IP-NEXT: addi a2, a2, -1366 +; RV32IP-NEXT: and a0, a0, a2 +; RV32IP-NEXT: srli a0, a0, 1 +; RV32IP-NEXT: or a0, a0, a1 +; RV32IP-NEXT: ret +; +; RV32IPN-LABEL: bitreverse_i16: +; RV32IPN: # %bb.0: +; RV32IPN-NEXT: srli a1, a0, 8 +; RV32IPN-NEXT: slli a0, a0, 8 +; RV32IPN-NEXT: or a0, a0, a1 +; RV32IPN-NEXT: lui a1, 1 +; RV32IPN-NEXT: addi a1, a1, -241 +; RV32IPN-NEXT: and a1, a0, a1 +; RV32IPN-NEXT: slli a1, a1, 4 +; RV32IPN-NEXT: lui a2, 15 +; RV32IPN-NEXT: addi a2, a2, 240 +; RV32IPN-NEXT: and a0, a0, a2 +; RV32IPN-NEXT: srli a0, a0, 4 +; RV32IPN-NEXT: or a0, a0, a1 +; RV32IPN-NEXT: lui a1, 3 +; RV32IPN-NEXT: addi a1, a1, 819 +; RV32IPN-NEXT: and a1, a0, a1 +; RV32IPN-NEXT: slli a1, a1, 2 +; RV32IPN-NEXT: lui a2, 13 +; RV32IPN-NEXT: addi a2, a2, -820 +; RV32IPN-NEXT: and a0, a0, a2 +; RV32IPN-NEXT: srli a0, a0, 2 +; RV32IPN-NEXT: or a0, a0, a1 +; RV32IPN-NEXT: lui a1, 5 +; RV32IPN-NEXT: addi a1, a1, 1365 +; RV32IPN-NEXT: and a1, a0, a1 +; RV32IPN-NEXT: slli a1, a1, 1 +; RV32IPN-NEXT: lui a2, 11 +; RV32IPN-NEXT: addi a2, a2, -1366 +; RV32IPN-NEXT: and a0, a0, a2 +; RV32IPN-NEXT: srli a0, a0, 1 +; RV32IPN-NEXT: or a0, a0, a1 +; RV32IPN-NEXT: ret +; +; RV32IBP-LABEL: bitreverse_i16: +; RV32IBP: # %bb.0: +; RV32IBP-NEXT: rev.h a0, a0 +; RV32IBP-NEXT: ret + %ret = tail call i16 @llvm.bitreverse.i16(i16 %a) + ret i16 %ret +} + +define i32 @bitreverse_i32(i32 %a) nounwind { +; RV32IB-LABEL: bitreverse_i32: +; RV32IB: # %bb.0: +; RV32IB-NEXT: rev a0, a0 +; RV32IB-NEXT: ret +; +; RV32IP-LABEL: bitreverse_i32: +; RV32IP: # %bb.0: +; RV32IP-NEXT: srli a1, a0, 8 +; RV32IP-NEXT: lui a2, 16 +; RV32IP-NEXT: addi a2, a2, -256 +; RV32IP-NEXT: and a1, a1, a2 +; RV32IP-NEXT: srli a2, a0, 24 +; RV32IP-NEXT: or a1, a1, a2 +; RV32IP-NEXT: slli a2, a0, 8 +; RV32IP-NEXT: lui a3, 4080 +; RV32IP-NEXT: and a2, a2, a3 +; RV32IP-NEXT: slli a0, a0, 24 +; RV32IP-NEXT: or a0, a0, a2 +; RV32IP-NEXT: or a0, a0, a1 +; RV32IP-NEXT: lui a1, 61681 +; RV32IP-NEXT: addi a1, a1, -241 +; RV32IP-NEXT: and a1, a0, a1 +; RV32IP-NEXT: slli a1, a1, 4 +; RV32IP-NEXT: lui a2, 986895 +; RV32IP-NEXT: addi a2, a2, 240 +; RV32IP-NEXT: and a0, a0, a2 +; RV32IP-NEXT: srli a0, a0, 4 +; RV32IP-NEXT: or a0, a0, a1 +; RV32IP-NEXT: lui a1, 209715 +; RV32IP-NEXT: addi a1, a1, 819 +; RV32IP-NEXT: and a1, a0, a1 +; RV32IP-NEXT: slli a1, a1, 2 +; RV32IP-NEXT: lui a2, 838861 +; RV32IP-NEXT: addi a2, a2, -820 +; RV32IP-NEXT: and a0, a0, a2 +; RV32IP-NEXT: srli a0, a0, 2 +; RV32IP-NEXT: or a0, a0, a1 +; RV32IP-NEXT: lui a1, 349525 +; RV32IP-NEXT: addi a1, a1, 1365 +; RV32IP-NEXT: and a1, a0, a1 +; RV32IP-NEXT: slli a1, a1, 1 +; RV32IP-NEXT: lui a2, 699051 +; RV32IP-NEXT: addi a2, a2, -1366 +; RV32IP-NEXT: and a0, a0, a2 +; RV32IP-NEXT: srli a0, a0, 1 +; RV32IP-NEXT: or a0, a0, a1 +; RV32IP-NEXT: ret +; +; RV32IPN-LABEL: bitreverse_i32: +; RV32IPN: # %bb.0: +; RV32IPN-NEXT: srli a1, a0, 8 +; RV32IPN-NEXT: lui a2, 16 +; RV32IPN-NEXT: addi a2, a2, -256 +; RV32IPN-NEXT: and a1, a1, a2 +; RV32IPN-NEXT: srli a2, a0, 24 +; RV32IPN-NEXT: or a1, a1, a2 +; RV32IPN-NEXT: slli a2, a0, 8 +; RV32IPN-NEXT: lui a3, 4080 +; RV32IPN-NEXT: and a2, a2, a3 +; RV32IPN-NEXT: slli a0, a0, 24 +; RV32IPN-NEXT: or a0, a0, a2 +; RV32IPN-NEXT: or a0, a0, a1 +; RV32IPN-NEXT: lui a1, 61681 +; RV32IPN-NEXT: addi a1, a1, -241 +; RV32IPN-NEXT: and a1, a0, a1 +; RV32IPN-NEXT: slli a1, a1, 4 +; RV32IPN-NEXT: lui a2, 986895 +; RV32IPN-NEXT: addi a2, a2, 240 +; RV32IPN-NEXT: and a0, a0, a2 +; RV32IPN-NEXT: srli a0, a0, 4 +; RV32IPN-NEXT: or a0, a0, a1 +; RV32IPN-NEXT: lui a1, 209715 +; RV32IPN-NEXT: addi a1, a1, 819 +; RV32IPN-NEXT: and a1, a0, a1 +; RV32IPN-NEXT: slli a1, a1, 2 +; RV32IPN-NEXT: lui a2, 838861 +; RV32IPN-NEXT: addi a2, a2, -820 +; RV32IPN-NEXT: and a0, a0, a2 +; RV32IPN-NEXT: srli a0, a0, 2 +; RV32IPN-NEXT: or a0, a0, a1 +; RV32IPN-NEXT: lui a1, 349525 +; RV32IPN-NEXT: addi a1, a1, 1365 +; RV32IPN-NEXT: and a1, a0, a1 +; RV32IPN-NEXT: slli a1, a1, 1 +; RV32IPN-NEXT: lui a2, 699051 +; RV32IPN-NEXT: addi a2, a2, -1366 +; RV32IPN-NEXT: and a0, a0, a2 +; RV32IPN-NEXT: srli a0, a0, 1 +; RV32IPN-NEXT: or a0, a0, a1 +; RV32IPN-NEXT: ret +; +; RV32IBP-LABEL: bitreverse_i32: +; RV32IBP: # %bb.0: +; RV32IBP-NEXT: rev a0, a0 +; RV32IBP-NEXT: ret + %ret = tail call i32 @llvm.bitreverse.i32(i32 %a) + ret i32 %ret +} + +define i64 @bitreverse_i64(i64 %a) nounwind { +; RV32IB-LABEL: bitreverse_i64: +; RV32IB: # %bb.0: +; RV32IB-NEXT: rev a2, a1 +; RV32IB-NEXT: rev a1, a0 +; RV32IB-NEXT: mv a0, a2 +; RV32IB-NEXT: ret +; +; RV32IP-LABEL: bitreverse_i64: +; RV32IP: # %bb.0: +; RV32IP-NEXT: srli a2, a1, 8 +; RV32IP-NEXT: lui a3, 16 +; RV32IP-NEXT: addi t0, a3, -256 +; RV32IP-NEXT: and a2, a2, t0 +; RV32IP-NEXT: srli a4, a1, 24 +; RV32IP-NEXT: or a2, a2, a4 +; RV32IP-NEXT: slli a4, a1, 8 +; RV32IP-NEXT: lui a6, 4080 +; RV32IP-NEXT: and a4, a4, a6 +; RV32IP-NEXT: slli a1, a1, 24 +; RV32IP-NEXT: or a1, a1, a4 +; RV32IP-NEXT: or a1, a1, a2 +; RV32IP-NEXT: lui a2, 61681 +; RV32IP-NEXT: addi t1, a2, -241 +; RV32IP-NEXT: and a2, a1, t1 +; RV32IP-NEXT: slli a2, a2, 4 +; RV32IP-NEXT: lui a5, 986895 +; RV32IP-NEXT: addi t2, a5, 240 +; RV32IP-NEXT: and a1, a1, t2 +; RV32IP-NEXT: srli a1, a1, 4 +; RV32IP-NEXT: or a1, a1, a2 +; RV32IP-NEXT: lui a2, 209715 +; RV32IP-NEXT: addi t3, a2, 819 +; RV32IP-NEXT: and a3, a1, t3 +; RV32IP-NEXT: slli a3, a3, 2 +; RV32IP-NEXT: lui a4, 838861 +; RV32IP-NEXT: addi a4, a4, -820 +; RV32IP-NEXT: and a1, a1, a4 +; RV32IP-NEXT: srli a1, a1, 2 +; RV32IP-NEXT: or a1, a1, a3 +; RV32IP-NEXT: lui a3, 349525 +; RV32IP-NEXT: addi a3, a3, 1365 +; RV32IP-NEXT: and a5, a1, a3 +; RV32IP-NEXT: slli a5, a5, 1 +; RV32IP-NEXT: lui a2, 699051 +; RV32IP-NEXT: addi a2, a2, -1366 +; RV32IP-NEXT: and a1, a1, a2 +; RV32IP-NEXT: srli a1, a1, 1 +; RV32IP-NEXT: or a7, a1, a5 +; RV32IP-NEXT: srli a1, a0, 8 +; RV32IP-NEXT: and a1, a1, t0 +; RV32IP-NEXT: srli a5, a0, 24 +; RV32IP-NEXT: or a1, a1, a5 +; RV32IP-NEXT: slli a5, a0, 8 +; RV32IP-NEXT: and a5, a5, a6 +; RV32IP-NEXT: slli a0, a0, 24 +; RV32IP-NEXT: or a0, a0, a5 +; RV32IP-NEXT: or a0, a0, a1 +; RV32IP-NEXT: and a1, a0, t1 +; RV32IP-NEXT: slli a1, a1, 4 +; RV32IP-NEXT: and a0, a0, t2 +; RV32IP-NEXT: srli a0, a0, 4 +; RV32IP-NEXT: or a0, a0, a1 +; RV32IP-NEXT: and a1, a0, t3 +; RV32IP-NEXT: slli a1, a1, 2 +; RV32IP-NEXT: and a0, a0, a4 +; RV32IP-NEXT: srli a0, a0, 2 +; RV32IP-NEXT: or a0, a0, a1 +; RV32IP-NEXT: and a1, a0, a3 +; RV32IP-NEXT: slli a1, a1, 1 +; RV32IP-NEXT: and a0, a0, a2 +; RV32IP-NEXT: srli a0, a0, 1 +; RV32IP-NEXT: or a1, a0, a1 +; RV32IP-NEXT: mv a0, a7 +; RV32IP-NEXT: ret +; +; RV32IPN-LABEL: bitreverse_i64: +; RV32IPN: # %bb.0: +; RV32IPN-NEXT: srli a2, a1, 8 +; RV32IPN-NEXT: lui a3, 16 +; RV32IPN-NEXT: addi t0, a3, -256 +; RV32IPN-NEXT: and a2, a2, t0 +; RV32IPN-NEXT: srli a4, a1, 24 +; RV32IPN-NEXT: or a2, a2, a4 +; RV32IPN-NEXT: slli a4, a1, 8 +; RV32IPN-NEXT: lui a6, 4080 +; RV32IPN-NEXT: and a4, a4, a6 +; RV32IPN-NEXT: slli a1, a1, 24 +; RV32IPN-NEXT: or a1, a1, a4 +; RV32IPN-NEXT: or a1, a1, a2 +; RV32IPN-NEXT: lui a2, 61681 +; RV32IPN-NEXT: addi t1, a2, -241 +; RV32IPN-NEXT: and a2, a1, t1 +; RV32IPN-NEXT: slli a2, a2, 4 +; RV32IPN-NEXT: lui a5, 986895 +; RV32IPN-NEXT: addi t2, a5, 240 +; RV32IPN-NEXT: and a1, a1, t2 +; RV32IPN-NEXT: srli a1, a1, 4 +; RV32IPN-NEXT: or a1, a1, a2 +; RV32IPN-NEXT: lui a2, 209715 +; RV32IPN-NEXT: addi t3, a2, 819 +; RV32IPN-NEXT: and a3, a1, t3 +; RV32IPN-NEXT: slli a3, a3, 2 +; RV32IPN-NEXT: lui a4, 838861 +; RV32IPN-NEXT: addi a4, a4, -820 +; RV32IPN-NEXT: and a1, a1, a4 +; RV32IPN-NEXT: srli a1, a1, 2 +; RV32IPN-NEXT: or a1, a1, a3 +; RV32IPN-NEXT: lui a3, 349525 +; RV32IPN-NEXT: addi a3, a3, 1365 +; RV32IPN-NEXT: and a5, a1, a3 +; RV32IPN-NEXT: slli a5, a5, 1 +; RV32IPN-NEXT: lui a2, 699051 +; RV32IPN-NEXT: addi a2, a2, -1366 +; RV32IPN-NEXT: and a1, a1, a2 +; RV32IPN-NEXT: srli a1, a1, 1 +; RV32IPN-NEXT: or a7, a1, a5 +; RV32IPN-NEXT: srli a1, a0, 8 +; RV32IPN-NEXT: and a1, a1, t0 +; RV32IPN-NEXT: srli a5, a0, 24 +; RV32IPN-NEXT: or a1, a1, a5 +; RV32IPN-NEXT: slli a5, a0, 8 +; RV32IPN-NEXT: and a5, a5, a6 +; RV32IPN-NEXT: slli a0, a0, 24 +; RV32IPN-NEXT: or a0, a0, a5 +; RV32IPN-NEXT: or a0, a0, a1 +; RV32IPN-NEXT: and a1, a0, t1 +; RV32IPN-NEXT: slli a1, a1, 4 +; RV32IPN-NEXT: and a0, a0, t2 +; RV32IPN-NEXT: srli a0, a0, 4 +; RV32IPN-NEXT: or a0, a0, a1 +; RV32IPN-NEXT: and a1, a0, t3 +; RV32IPN-NEXT: slli a1, a1, 2 +; RV32IPN-NEXT: and a0, a0, a4 +; RV32IPN-NEXT: srli a0, a0, 2 +; RV32IPN-NEXT: or a0, a0, a1 +; RV32IPN-NEXT: and a1, a0, a3 +; RV32IPN-NEXT: slli a1, a1, 1 +; RV32IPN-NEXT: and a0, a0, a2 +; RV32IPN-NEXT: srli a0, a0, 1 +; RV32IPN-NEXT: or a1, a0, a1 +; RV32IPN-NEXT: mv a0, a7 +; RV32IPN-NEXT: ret +; +; RV32IBP-LABEL: bitreverse_i64: +; RV32IBP: # %bb.0: +; RV32IBP-NEXT: rev a2, a1 +; RV32IBP-NEXT: rev a1, a0 +; RV32IBP-NEXT: mv a0, a2 +; RV32IBP-NEXT: ret + %ret = tail call i64 @llvm.bitreverse.i64(i64 %a) + ret i64 %ret +} diff --git a/llvm/test/CodeGen/RISCV/rv32zpn-bswap.ll b/llvm/test/CodeGen/RISCV/rv32zpn-bswap.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rv32zpn-bswap.ll @@ -0,0 +1,163 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+experimental-b -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV32IB +; RUN: llc -mtriple=riscv32 -mattr=+experimental-p -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV32IP +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zpn -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV32IPN +; RUN: llc -mtriple=riscv32 -mattr=+experimental-b,+experimental-p -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV32IBP + +declare i16 @llvm.bswap.i16(i16) +declare i32 @llvm.bswap.i32(i32) +declare i64 @llvm.bswap.i64(i64) + +define zeroext i16 @bswap_i16(i16 zeroext %a) nounwind { +; RV32IB-LABEL: bswap_i16: +; RV32IB: # %bb.0: +; RV32IB-NEXT: rev8.h a0, a0 +; RV32IB-NEXT: ret +; +; RV32IP-LABEL: bswap_i16: +; RV32IP: # %bb.0: +; RV32IP-NEXT: srli a1, a0, 8 +; RV32IP-NEXT: slli a0, a0, 8 +; RV32IP-NEXT: or a0, a0, a1 +; RV32IP-NEXT: lui a1, 16 +; RV32IP-NEXT: addi a1, a1, -1 +; RV32IP-NEXT: and a0, a0, a1 +; RV32IP-NEXT: ret +; +; RV32IPN-LABEL: bswap_i16: +; RV32IPN: # %bb.0: +; RV32IPN-NEXT: srli a1, a0, 8 +; RV32IPN-NEXT: slli a0, a0, 8 +; RV32IPN-NEXT: or a0, a0, a1 +; RV32IPN-NEXT: lui a1, 16 +; RV32IPN-NEXT: addi a1, a1, -1 +; RV32IPN-NEXT: and a0, a0, a1 +; RV32IPN-NEXT: ret +; +; RV32IBP-LABEL: bswap_i16: +; RV32IBP: # %bb.0: +; RV32IBP-NEXT: rev8.h a0, a0 +; RV32IBP-NEXT: ret + %ret = tail call i16 @llvm.bswap.i16(i16 %a) + ret i16 %ret +} + +define i32 @bswap_i32(i32 %a) nounwind { +; RV32IB-LABEL: bswap_i32: +; RV32IB: # %bb.0: +; RV32IB-NEXT: rev8 a0, a0 +; RV32IB-NEXT: ret +; +; RV32IP-LABEL: bswap_i32: +; RV32IP: # %bb.0: +; RV32IP-NEXT: srli a1, a0, 8 +; RV32IP-NEXT: lui a2, 16 +; RV32IP-NEXT: addi a2, a2, -256 +; RV32IP-NEXT: and a1, a1, a2 +; RV32IP-NEXT: srli a2, a0, 24 +; RV32IP-NEXT: or a1, a1, a2 +; RV32IP-NEXT: slli a2, a0, 8 +; RV32IP-NEXT: lui a3, 4080 +; RV32IP-NEXT: and a2, a2, a3 +; RV32IP-NEXT: slli a0, a0, 24 +; RV32IP-NEXT: or a0, a0, a2 +; RV32IP-NEXT: or a0, a0, a1 +; RV32IP-NEXT: ret +; +; RV32IPN-LABEL: bswap_i32: +; RV32IPN: # %bb.0: +; RV32IPN-NEXT: srli a1, a0, 8 +; RV32IPN-NEXT: lui a2, 16 +; RV32IPN-NEXT: addi a2, a2, -256 +; RV32IPN-NEXT: and a1, a1, a2 +; RV32IPN-NEXT: srli a2, a0, 24 +; RV32IPN-NEXT: or a1, a1, a2 +; RV32IPN-NEXT: slli a2, a0, 8 +; RV32IPN-NEXT: lui a3, 4080 +; RV32IPN-NEXT: and a2, a2, a3 +; RV32IPN-NEXT: slli a0, a0, 24 +; RV32IPN-NEXT: or a0, a0, a2 +; RV32IPN-NEXT: or a0, a0, a1 +; RV32IPN-NEXT: ret +; +; RV32IBP-LABEL: bswap_i32: +; RV32IBP: # %bb.0: +; RV32IBP-NEXT: rev8 a0, a0 +; RV32IBP-NEXT: ret + %ret = tail call i32 @llvm.bswap.i32(i32 %a) + ret i32 %ret +} + +define i64 @bswap_i64(i64 %a) nounwind { +; RV32IB-LABEL: bswap_i64: +; RV32IB: # %bb.0: +; RV32IB-NEXT: rev8 a2, a1 +; RV32IB-NEXT: rev8 a1, a0 +; RV32IB-NEXT: mv a0, a2 +; RV32IB-NEXT: ret +; +; RV32IP-LABEL: bswap_i64: +; RV32IP: # %bb.0: +; RV32IP-NEXT: srli a2, a1, 8 +; RV32IP-NEXT: lui a3, 16 +; RV32IP-NEXT: addi a3, a3, -256 +; RV32IP-NEXT: and a2, a2, a3 +; RV32IP-NEXT: srli a4, a1, 24 +; RV32IP-NEXT: or a2, a2, a4 +; RV32IP-NEXT: slli a4, a1, 8 +; RV32IP-NEXT: lui a5, 4080 +; RV32IP-NEXT: and a4, a4, a5 +; RV32IP-NEXT: slli a1, a1, 24 +; RV32IP-NEXT: or a1, a1, a4 +; RV32IP-NEXT: or a2, a1, a2 +; RV32IP-NEXT: srli a1, a0, 8 +; RV32IP-NEXT: and a1, a1, a3 +; RV32IP-NEXT: srli a3, a0, 24 +; RV32IP-NEXT: or a1, a1, a3 +; RV32IP-NEXT: slli a3, a0, 8 +; RV32IP-NEXT: and a3, a3, a5 +; RV32IP-NEXT: slli a0, a0, 24 +; RV32IP-NEXT: or a0, a0, a3 +; RV32IP-NEXT: or a1, a0, a1 +; RV32IP-NEXT: mv a0, a2 +; RV32IP-NEXT: ret +; +; RV32IPN-LABEL: bswap_i64: +; RV32IPN: # %bb.0: +; RV32IPN-NEXT: srli a2, a1, 8 +; RV32IPN-NEXT: lui a3, 16 +; RV32IPN-NEXT: addi a3, a3, -256 +; RV32IPN-NEXT: and a2, a2, a3 +; RV32IPN-NEXT: srli a4, a1, 24 +; RV32IPN-NEXT: or a2, a2, a4 +; RV32IPN-NEXT: slli a4, a1, 8 +; RV32IPN-NEXT: lui a5, 4080 +; RV32IPN-NEXT: and a4, a4, a5 +; RV32IPN-NEXT: slli a1, a1, 24 +; RV32IPN-NEXT: or a1, a1, a4 +; RV32IPN-NEXT: or a2, a1, a2 +; RV32IPN-NEXT: srli a1, a0, 8 +; RV32IPN-NEXT: and a1, a1, a3 +; RV32IPN-NEXT: srli a3, a0, 24 +; RV32IPN-NEXT: or a1, a1, a3 +; RV32IPN-NEXT: slli a3, a0, 8 +; RV32IPN-NEXT: and a3, a3, a5 +; RV32IPN-NEXT: slli a0, a0, 24 +; RV32IPN-NEXT: or a0, a0, a3 +; RV32IPN-NEXT: or a1, a0, a1 +; RV32IPN-NEXT: mv a0, a2 +; RV32IPN-NEXT: ret +; +; RV32IBP-LABEL: bswap_i64: +; RV32IBP: # %bb.0: +; RV32IBP-NEXT: rev8 a2, a1 +; RV32IBP-NEXT: rev8 a1, a0 +; RV32IBP-NEXT: mv a0, a2 +; RV32IBP-NEXT: ret + %ret = tail call i64 @llvm.bswap.i64(i64 %a) + ret i64 %ret +} diff --git a/llvm/test/CodeGen/RISCV/rv64zpn-bitreverse.ll b/llvm/test/CodeGen/RISCV/rv64zpn-bitreverse.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rv64zpn-bitreverse.ll @@ -0,0 +1,568 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv64 -mattr=+experimental-b -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV64IB +; RUN: llc -mtriple=riscv64 -mattr=+experimental-p -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV64IP +; RUN: llc -mtriple=riscv64 -mattr=+experimental-zpn -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV64IPN +; RUN: llc -mtriple=riscv64 -mattr=+experimental-b,+experimental-p -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV64IBP + +declare i8 @llvm.bitreverse.i8(i8) +declare i16 @llvm.bitreverse.i16(i16) +declare i32 @llvm.bitreverse.i32(i32) +declare i64 @llvm.bitreverse.i64(i64) + +define zeroext i8 @bitreverse_i8(i8 zeroext %a) nounwind { +; RV64IB-LABEL: bitreverse_i8: +; RV64IB: # %bb.0: +; RV64IB-NEXT: greviw a0, a0, 7 +; RV64IB-NEXT: ret +; +; RV64IP-LABEL: bitreverse_i8: +; RV64IP: # %bb.0: +; RV64IP-NEXT: srli a1, a0, 4 +; RV64IP-NEXT: andi a0, a0, 15 +; RV64IP-NEXT: slli a0, a0, 4 +; RV64IP-NEXT: or a0, a1, a0 +; RV64IP-NEXT: andi a1, a0, 51 +; RV64IP-NEXT: slli a1, a1, 2 +; RV64IP-NEXT: andi a0, a0, 204 +; RV64IP-NEXT: srli a0, a0, 2 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: andi a1, a0, 85 +; RV64IP-NEXT: slli a1, a1, 1 +; RV64IP-NEXT: andi a0, a0, 170 +; RV64IP-NEXT: srli a0, a0, 1 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: ret +; +; RV64IPN-LABEL: bitreverse_i8: +; RV64IPN: # %bb.0: +; RV64IPN-NEXT: srli a1, a0, 4 +; RV64IPN-NEXT: andi a0, a0, 15 +; RV64IPN-NEXT: slli a0, a0, 4 +; RV64IPN-NEXT: or a0, a1, a0 +; RV64IPN-NEXT: andi a1, a0, 51 +; RV64IPN-NEXT: slli a1, a1, 2 +; RV64IPN-NEXT: andi a0, a0, 204 +; RV64IPN-NEXT: srli a0, a0, 2 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: andi a1, a0, 85 +; RV64IPN-NEXT: slli a1, a1, 1 +; RV64IPN-NEXT: andi a0, a0, 170 +; RV64IPN-NEXT: srli a0, a0, 1 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: ret +; +; RV64IBP-LABEL: bitreverse_i8: +; RV64IBP: # %bb.0: +; RV64IBP-NEXT: greviw a0, a0, 7 +; RV64IBP-NEXT: ret + %ret = tail call i8 @llvm.bitreverse.i8(i8 %a) + ret i8 %ret +} + +define zeroext i16 @bitreverse_i16(i16 zeroext %a) nounwind { +; RV64IB-LABEL: bitreverse_i16: +; RV64IB: # %bb.0: +; RV64IB-NEXT: greviw a0, a0, 15 +; RV64IB-NEXT: ret +; +; RV64IP-LABEL: bitreverse_i16: +; RV64IP: # %bb.0: +; RV64IP-NEXT: srli a1, a0, 8 +; RV64IP-NEXT: slli a0, a0, 8 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: lui a1, 1 +; RV64IP-NEXT: addiw a1, a1, -241 +; RV64IP-NEXT: and a1, a0, a1 +; RV64IP-NEXT: slli a1, a1, 4 +; RV64IP-NEXT: lui a2, 15 +; RV64IP-NEXT: addiw a2, a2, 240 +; RV64IP-NEXT: and a0, a0, a2 +; RV64IP-NEXT: srli a0, a0, 4 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: lui a1, 3 +; RV64IP-NEXT: addiw a1, a1, 819 +; RV64IP-NEXT: and a1, a0, a1 +; RV64IP-NEXT: slli a1, a1, 2 +; RV64IP-NEXT: lui a2, 13 +; RV64IP-NEXT: addiw a2, a2, -820 +; RV64IP-NEXT: and a0, a0, a2 +; RV64IP-NEXT: srli a0, a0, 2 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: lui a1, 5 +; RV64IP-NEXT: addiw a1, a1, 1365 +; RV64IP-NEXT: and a1, a0, a1 +; RV64IP-NEXT: slli a1, a1, 1 +; RV64IP-NEXT: lui a2, 11 +; RV64IP-NEXT: addiw a2, a2, -1366 +; RV64IP-NEXT: and a0, a0, a2 +; RV64IP-NEXT: srli a0, a0, 1 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: ret +; +; RV64IPN-LABEL: bitreverse_i16: +; RV64IPN: # %bb.0: +; RV64IPN-NEXT: srli a1, a0, 8 +; RV64IPN-NEXT: slli a0, a0, 8 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: lui a1, 1 +; RV64IPN-NEXT: addiw a1, a1, -241 +; RV64IPN-NEXT: and a1, a0, a1 +; RV64IPN-NEXT: slli a1, a1, 4 +; RV64IPN-NEXT: lui a2, 15 +; RV64IPN-NEXT: addiw a2, a2, 240 +; RV64IPN-NEXT: and a0, a0, a2 +; RV64IPN-NEXT: srli a0, a0, 4 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: lui a1, 3 +; RV64IPN-NEXT: addiw a1, a1, 819 +; RV64IPN-NEXT: and a1, a0, a1 +; RV64IPN-NEXT: slli a1, a1, 2 +; RV64IPN-NEXT: lui a2, 13 +; RV64IPN-NEXT: addiw a2, a2, -820 +; RV64IPN-NEXT: and a0, a0, a2 +; RV64IPN-NEXT: srli a0, a0, 2 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: lui a1, 5 +; RV64IPN-NEXT: addiw a1, a1, 1365 +; RV64IPN-NEXT: and a1, a0, a1 +; RV64IPN-NEXT: slli a1, a1, 1 +; RV64IPN-NEXT: lui a2, 11 +; RV64IPN-NEXT: addiw a2, a2, -1366 +; RV64IPN-NEXT: and a0, a0, a2 +; RV64IPN-NEXT: srli a0, a0, 1 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: ret +; +; RV64IBP-LABEL: bitreverse_i16: +; RV64IBP: # %bb.0: +; RV64IBP-NEXT: greviw a0, a0, 15 +; RV64IBP-NEXT: ret + %ret = tail call i16 @llvm.bitreverse.i16(i16 %a) + ret i16 %ret +} + +define signext i32 @bitreverse_i32(i32 signext %a) nounwind { +; RV64IB-LABEL: bitreverse_i32: +; RV64IB: # %bb.0: +; RV64IB-NEXT: greviw a0, a0, 31 +; RV64IB-NEXT: ret +; +; RV64IP-LABEL: bitreverse_i32: +; RV64IP: # %bb.0: +; RV64IP-NEXT: srliw a1, a0, 8 +; RV64IP-NEXT: lui a2, 16 +; RV64IP-NEXT: addiw a2, a2, -256 +; RV64IP-NEXT: and a1, a1, a2 +; RV64IP-NEXT: srliw a2, a0, 24 +; RV64IP-NEXT: or a1, a1, a2 +; RV64IP-NEXT: slli a2, a0, 8 +; RV64IP-NEXT: lui a3, 4080 +; RV64IP-NEXT: and a2, a2, a3 +; RV64IP-NEXT: slli a0, a0, 24 +; RV64IP-NEXT: or a0, a0, a2 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: lui a1, 61681 +; RV64IP-NEXT: addiw a1, a1, -241 +; RV64IP-NEXT: and a1, a0, a1 +; RV64IP-NEXT: slli a1, a1, 4 +; RV64IP-NEXT: lui a2, 241 +; RV64IP-NEXT: addiw a2, a2, -241 +; RV64IP-NEXT: slli a2, a2, 12 +; RV64IP-NEXT: addi a2, a2, 240 +; RV64IP-NEXT: and a0, a0, a2 +; RV64IP-NEXT: srli a0, a0, 4 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: lui a1, 209715 +; RV64IP-NEXT: addiw a1, a1, 819 +; RV64IP-NEXT: and a1, a0, a1 +; RV64IP-NEXT: slli a1, a1, 2 +; RV64IP-NEXT: lui a2, 838861 +; RV64IP-NEXT: addiw a2, a2, -820 +; RV64IP-NEXT: and a0, a0, a2 +; RV64IP-NEXT: srli a0, a0, 2 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: lui a1, 349525 +; RV64IP-NEXT: addiw a1, a1, 1365 +; RV64IP-NEXT: and a1, a0, a1 +; RV64IP-NEXT: slli a1, a1, 1 +; RV64IP-NEXT: lui a2, 699051 +; RV64IP-NEXT: addiw a2, a2, -1366 +; RV64IP-NEXT: and a0, a0, a2 +; RV64IP-NEXT: srli a0, a0, 1 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: sext.w a0, a0 +; RV64IP-NEXT: ret +; +; RV64IPN-LABEL: bitreverse_i32: +; RV64IPN: # %bb.0: +; RV64IPN-NEXT: srliw a1, a0, 8 +; RV64IPN-NEXT: lui a2, 16 +; RV64IPN-NEXT: addiw a2, a2, -256 +; RV64IPN-NEXT: and a1, a1, a2 +; RV64IPN-NEXT: srliw a2, a0, 24 +; RV64IPN-NEXT: or a1, a1, a2 +; RV64IPN-NEXT: slli a2, a0, 8 +; RV64IPN-NEXT: lui a3, 4080 +; RV64IPN-NEXT: and a2, a2, a3 +; RV64IPN-NEXT: slli a0, a0, 24 +; RV64IPN-NEXT: or a0, a0, a2 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: lui a1, 61681 +; RV64IPN-NEXT: addiw a1, a1, -241 +; RV64IPN-NEXT: and a1, a0, a1 +; RV64IPN-NEXT: slli a1, a1, 4 +; RV64IPN-NEXT: lui a2, 241 +; RV64IPN-NEXT: addiw a2, a2, -241 +; RV64IPN-NEXT: slli a2, a2, 12 +; RV64IPN-NEXT: addi a2, a2, 240 +; RV64IPN-NEXT: and a0, a0, a2 +; RV64IPN-NEXT: srli a0, a0, 4 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: lui a1, 209715 +; RV64IPN-NEXT: addiw a1, a1, 819 +; RV64IPN-NEXT: and a1, a0, a1 +; RV64IPN-NEXT: slli a1, a1, 2 +; RV64IPN-NEXT: lui a2, 838861 +; RV64IPN-NEXT: addiw a2, a2, -820 +; RV64IPN-NEXT: and a0, a0, a2 +; RV64IPN-NEXT: srli a0, a0, 2 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: lui a1, 349525 +; RV64IPN-NEXT: addiw a1, a1, 1365 +; RV64IPN-NEXT: and a1, a0, a1 +; RV64IPN-NEXT: slli a1, a1, 1 +; RV64IPN-NEXT: lui a2, 699051 +; RV64IPN-NEXT: addiw a2, a2, -1366 +; RV64IPN-NEXT: and a0, a0, a2 +; RV64IPN-NEXT: srli a0, a0, 1 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: sext.w a0, a0 +; RV64IPN-NEXT: ret +; +; RV64IBP-LABEL: bitreverse_i32: +; RV64IBP: # %bb.0: +; RV64IBP-NEXT: greviw a0, a0, 31 +; RV64IBP-NEXT: ret + %ret = tail call i32 @llvm.bitreverse.i32(i32 %a) + ret i32 %ret +} + +; Similar to bitreverse32 but the result is not sign extended. +define void @bitreverse_i32_nosext(i32 signext %a, i32* %x) nounwind { +; RV64IB-LABEL: bitreverse_i32_nosext: +; RV64IB: # %bb.0: +; RV64IB-NEXT: greviw a0, a0, 31 +; RV64IB-NEXT: sw a0, 0(a1) +; RV64IB-NEXT: ret +; +; RV64IP-LABEL: bitreverse_i32_nosext: +; RV64IP: # %bb.0: +; RV64IP-NEXT: srliw a2, a0, 8 +; RV64IP-NEXT: lui a3, 16 +; RV64IP-NEXT: addiw a3, a3, -256 +; RV64IP-NEXT: and a2, a2, a3 +; RV64IP-NEXT: srliw a3, a0, 24 +; RV64IP-NEXT: or a2, a2, a3 +; RV64IP-NEXT: slli a3, a0, 8 +; RV64IP-NEXT: lui a4, 4080 +; RV64IP-NEXT: and a3, a3, a4 +; RV64IP-NEXT: slli a0, a0, 24 +; RV64IP-NEXT: or a0, a0, a3 +; RV64IP-NEXT: or a0, a0, a2 +; RV64IP-NEXT: lui a2, 61681 +; RV64IP-NEXT: addiw a2, a2, -241 +; RV64IP-NEXT: and a2, a0, a2 +; RV64IP-NEXT: slli a2, a2, 4 +; RV64IP-NEXT: lui a3, 241 +; RV64IP-NEXT: addiw a3, a3, -241 +; RV64IP-NEXT: slli a3, a3, 12 +; RV64IP-NEXT: addi a3, a3, 240 +; RV64IP-NEXT: and a0, a0, a3 +; RV64IP-NEXT: srli a0, a0, 4 +; RV64IP-NEXT: or a0, a0, a2 +; RV64IP-NEXT: lui a2, 209715 +; RV64IP-NEXT: addiw a2, a2, 819 +; RV64IP-NEXT: and a2, a0, a2 +; RV64IP-NEXT: slli a2, a2, 2 +; RV64IP-NEXT: lui a3, 838861 +; RV64IP-NEXT: addiw a3, a3, -820 +; RV64IP-NEXT: and a0, a0, a3 +; RV64IP-NEXT: srli a0, a0, 2 +; RV64IP-NEXT: or a0, a0, a2 +; RV64IP-NEXT: lui a2, 349525 +; RV64IP-NEXT: addiw a2, a2, 1365 +; RV64IP-NEXT: and a2, a0, a2 +; RV64IP-NEXT: slli a2, a2, 1 +; RV64IP-NEXT: lui a3, 699051 +; RV64IP-NEXT: addiw a3, a3, -1366 +; RV64IP-NEXT: and a0, a0, a3 +; RV64IP-NEXT: srli a0, a0, 1 +; RV64IP-NEXT: or a0, a0, a2 +; RV64IP-NEXT: sw a0, 0(a1) +; RV64IP-NEXT: ret +; +; RV64IPN-LABEL: bitreverse_i32_nosext: +; RV64IPN: # %bb.0: +; RV64IPN-NEXT: srliw a2, a0, 8 +; RV64IPN-NEXT: lui a3, 16 +; RV64IPN-NEXT: addiw a3, a3, -256 +; RV64IPN-NEXT: and a2, a2, a3 +; RV64IPN-NEXT: srliw a3, a0, 24 +; RV64IPN-NEXT: or a2, a2, a3 +; RV64IPN-NEXT: slli a3, a0, 8 +; RV64IPN-NEXT: lui a4, 4080 +; RV64IPN-NEXT: and a3, a3, a4 +; RV64IPN-NEXT: slli a0, a0, 24 +; RV64IPN-NEXT: or a0, a0, a3 +; RV64IPN-NEXT: or a0, a0, a2 +; RV64IPN-NEXT: lui a2, 61681 +; RV64IPN-NEXT: addiw a2, a2, -241 +; RV64IPN-NEXT: and a2, a0, a2 +; RV64IPN-NEXT: slli a2, a2, 4 +; RV64IPN-NEXT: lui a3, 241 +; RV64IPN-NEXT: addiw a3, a3, -241 +; RV64IPN-NEXT: slli a3, a3, 12 +; RV64IPN-NEXT: addi a3, a3, 240 +; RV64IPN-NEXT: and a0, a0, a3 +; RV64IPN-NEXT: srli a0, a0, 4 +; RV64IPN-NEXT: or a0, a0, a2 +; RV64IPN-NEXT: lui a2, 209715 +; RV64IPN-NEXT: addiw a2, a2, 819 +; RV64IPN-NEXT: and a2, a0, a2 +; RV64IPN-NEXT: slli a2, a2, 2 +; RV64IPN-NEXT: lui a3, 838861 +; RV64IPN-NEXT: addiw a3, a3, -820 +; RV64IPN-NEXT: and a0, a0, a3 +; RV64IPN-NEXT: srli a0, a0, 2 +; RV64IPN-NEXT: or a0, a0, a2 +; RV64IPN-NEXT: lui a2, 349525 +; RV64IPN-NEXT: addiw a2, a2, 1365 +; RV64IPN-NEXT: and a2, a0, a2 +; RV64IPN-NEXT: slli a2, a2, 1 +; RV64IPN-NEXT: lui a3, 699051 +; RV64IPN-NEXT: addiw a3, a3, -1366 +; RV64IPN-NEXT: and a0, a0, a3 +; RV64IPN-NEXT: srli a0, a0, 1 +; RV64IPN-NEXT: or a0, a0, a2 +; RV64IPN-NEXT: sw a0, 0(a1) +; RV64IPN-NEXT: ret +; +; RV64IBP-LABEL: bitreverse_i32_nosext: +; RV64IBP: # %bb.0: +; RV64IBP-NEXT: greviw a0, a0, 31 +; RV64IBP-NEXT: sw a0, 0(a1) +; RV64IBP-NEXT: ret + %ret = tail call i32 @llvm.bitreverse.i32(i32 %a) + store i32 %ret, i32* %x + ret void +} + +define i64 @bitreverse_i64(i64 %a) nounwind { +; RV64IB-LABEL: bitreverse_i64: +; RV64IB: # %bb.0: +; RV64IB-NEXT: rev a0, a0 +; RV64IB-NEXT: ret +; +; RV64IP-LABEL: bitreverse_i64: +; RV64IP: # %bb.0: +; RV64IP-NEXT: srli a1, a0, 24 +; RV64IP-NEXT: lui a2, 4080 +; RV64IP-NEXT: and a1, a1, a2 +; RV64IP-NEXT: srli a2, a0, 8 +; RV64IP-NEXT: addi a3, zero, 255 +; RV64IP-NEXT: slli a4, a3, 24 +; RV64IP-NEXT: and a2, a2, a4 +; RV64IP-NEXT: or a1, a2, a1 +; RV64IP-NEXT: srli a2, a0, 40 +; RV64IP-NEXT: lui a4, 16 +; RV64IP-NEXT: addiw a4, a4, -256 +; RV64IP-NEXT: and a2, a2, a4 +; RV64IP-NEXT: srli a4, a0, 56 +; RV64IP-NEXT: or a2, a2, a4 +; RV64IP-NEXT: or a1, a1, a2 +; RV64IP-NEXT: slli a2, a0, 8 +; RV64IP-NEXT: slli a4, a3, 32 +; RV64IP-NEXT: and a2, a2, a4 +; RV64IP-NEXT: slli a4, a0, 24 +; RV64IP-NEXT: slli a5, a3, 40 +; RV64IP-NEXT: and a4, a4, a5 +; RV64IP-NEXT: or a2, a4, a2 +; RV64IP-NEXT: slli a4, a0, 40 +; RV64IP-NEXT: slli a3, a3, 48 +; RV64IP-NEXT: and a3, a4, a3 +; RV64IP-NEXT: slli a0, a0, 56 +; RV64IP-NEXT: or a0, a0, a3 +; RV64IP-NEXT: or a0, a0, a2 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: lui a1, 3855 +; RV64IP-NEXT: addiw a1, a1, 241 +; RV64IP-NEXT: slli a1, a1, 12 +; RV64IP-NEXT: addi a1, a1, -241 +; RV64IP-NEXT: slli a1, a1, 12 +; RV64IP-NEXT: addi a1, a1, 241 +; RV64IP-NEXT: slli a1, a1, 12 +; RV64IP-NEXT: addi a1, a1, -241 +; RV64IP-NEXT: and a1, a0, a1 +; RV64IP-NEXT: slli a1, a1, 4 +; RV64IP-NEXT: lui a2, 1044721 +; RV64IP-NEXT: addiw a2, a2, -241 +; RV64IP-NEXT: slli a2, a2, 12 +; RV64IP-NEXT: addi a2, a2, 241 +; RV64IP-NEXT: slli a2, a2, 12 +; RV64IP-NEXT: addi a2, a2, -241 +; RV64IP-NEXT: slli a2, a2, 12 +; RV64IP-NEXT: addi a2, a2, 240 +; RV64IP-NEXT: and a0, a0, a2 +; RV64IP-NEXT: srli a0, a0, 4 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: lui a1, 13107 +; RV64IP-NEXT: addiw a1, a1, 819 +; RV64IP-NEXT: slli a1, a1, 12 +; RV64IP-NEXT: addi a1, a1, 819 +; RV64IP-NEXT: slli a1, a1, 12 +; RV64IP-NEXT: addi a1, a1, 819 +; RV64IP-NEXT: slli a1, a1, 12 +; RV64IP-NEXT: addi a1, a1, 819 +; RV64IP-NEXT: and a1, a0, a1 +; RV64IP-NEXT: slli a1, a1, 2 +; RV64IP-NEXT: lui a2, 1035469 +; RV64IP-NEXT: addiw a2, a2, -819 +; RV64IP-NEXT: slli a2, a2, 12 +; RV64IP-NEXT: addi a2, a2, -819 +; RV64IP-NEXT: slli a2, a2, 12 +; RV64IP-NEXT: addi a2, a2, -819 +; RV64IP-NEXT: slli a2, a2, 12 +; RV64IP-NEXT: addi a2, a2, -820 +; RV64IP-NEXT: and a0, a0, a2 +; RV64IP-NEXT: srli a0, a0, 2 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: lui a1, 21845 +; RV64IP-NEXT: addiw a1, a1, 1365 +; RV64IP-NEXT: slli a1, a1, 12 +; RV64IP-NEXT: addi a1, a1, 1365 +; RV64IP-NEXT: slli a1, a1, 12 +; RV64IP-NEXT: addi a1, a1, 1365 +; RV64IP-NEXT: slli a1, a1, 12 +; RV64IP-NEXT: addi a1, a1, 1365 +; RV64IP-NEXT: and a1, a0, a1 +; RV64IP-NEXT: slli a1, a1, 1 +; RV64IP-NEXT: lui a2, 1026731 +; RV64IP-NEXT: addiw a2, a2, -1365 +; RV64IP-NEXT: slli a2, a2, 12 +; RV64IP-NEXT: addi a2, a2, -1365 +; RV64IP-NEXT: slli a2, a2, 12 +; RV64IP-NEXT: addi a2, a2, -1365 +; RV64IP-NEXT: slli a2, a2, 12 +; RV64IP-NEXT: addi a2, a2, -1366 +; RV64IP-NEXT: and a0, a0, a2 +; RV64IP-NEXT: srli a0, a0, 1 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: ret +; +; RV64IPN-LABEL: bitreverse_i64: +; RV64IPN: # %bb.0: +; RV64IPN-NEXT: srli a1, a0, 24 +; RV64IPN-NEXT: lui a2, 4080 +; RV64IPN-NEXT: and a1, a1, a2 +; RV64IPN-NEXT: srli a2, a0, 8 +; RV64IPN-NEXT: addi a3, zero, 255 +; RV64IPN-NEXT: slli a4, a3, 24 +; RV64IPN-NEXT: and a2, a2, a4 +; RV64IPN-NEXT: or a1, a2, a1 +; RV64IPN-NEXT: srli a2, a0, 40 +; RV64IPN-NEXT: lui a4, 16 +; RV64IPN-NEXT: addiw a4, a4, -256 +; RV64IPN-NEXT: and a2, a2, a4 +; RV64IPN-NEXT: srli a4, a0, 56 +; RV64IPN-NEXT: or a2, a2, a4 +; RV64IPN-NEXT: or a1, a1, a2 +; RV64IPN-NEXT: slli a2, a0, 8 +; RV64IPN-NEXT: slli a4, a3, 32 +; RV64IPN-NEXT: and a2, a2, a4 +; RV64IPN-NEXT: slli a4, a0, 24 +; RV64IPN-NEXT: slli a5, a3, 40 +; RV64IPN-NEXT: and a4, a4, a5 +; RV64IPN-NEXT: or a2, a4, a2 +; RV64IPN-NEXT: slli a4, a0, 40 +; RV64IPN-NEXT: slli a3, a3, 48 +; RV64IPN-NEXT: and a3, a4, a3 +; RV64IPN-NEXT: slli a0, a0, 56 +; RV64IPN-NEXT: or a0, a0, a3 +; RV64IPN-NEXT: or a0, a0, a2 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: lui a1, 3855 +; RV64IPN-NEXT: addiw a1, a1, 241 +; RV64IPN-NEXT: slli a1, a1, 12 +; RV64IPN-NEXT: addi a1, a1, -241 +; RV64IPN-NEXT: slli a1, a1, 12 +; RV64IPN-NEXT: addi a1, a1, 241 +; RV64IPN-NEXT: slli a1, a1, 12 +; RV64IPN-NEXT: addi a1, a1, -241 +; RV64IPN-NEXT: and a1, a0, a1 +; RV64IPN-NEXT: slli a1, a1, 4 +; RV64IPN-NEXT: lui a2, 1044721 +; RV64IPN-NEXT: addiw a2, a2, -241 +; RV64IPN-NEXT: slli a2, a2, 12 +; RV64IPN-NEXT: addi a2, a2, 241 +; RV64IPN-NEXT: slli a2, a2, 12 +; RV64IPN-NEXT: addi a2, a2, -241 +; RV64IPN-NEXT: slli a2, a2, 12 +; RV64IPN-NEXT: addi a2, a2, 240 +; RV64IPN-NEXT: and a0, a0, a2 +; RV64IPN-NEXT: srli a0, a0, 4 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: lui a1, 13107 +; RV64IPN-NEXT: addiw a1, a1, 819 +; RV64IPN-NEXT: slli a1, a1, 12 +; RV64IPN-NEXT: addi a1, a1, 819 +; RV64IPN-NEXT: slli a1, a1, 12 +; RV64IPN-NEXT: addi a1, a1, 819 +; RV64IPN-NEXT: slli a1, a1, 12 +; RV64IPN-NEXT: addi a1, a1, 819 +; RV64IPN-NEXT: and a1, a0, a1 +; RV64IPN-NEXT: slli a1, a1, 2 +; RV64IPN-NEXT: lui a2, 1035469 +; RV64IPN-NEXT: addiw a2, a2, -819 +; RV64IPN-NEXT: slli a2, a2, 12 +; RV64IPN-NEXT: addi a2, a2, -819 +; RV64IPN-NEXT: slli a2, a2, 12 +; RV64IPN-NEXT: addi a2, a2, -819 +; RV64IPN-NEXT: slli a2, a2, 12 +; RV64IPN-NEXT: addi a2, a2, -820 +; RV64IPN-NEXT: and a0, a0, a2 +; RV64IPN-NEXT: srli a0, a0, 2 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: lui a1, 21845 +; RV64IPN-NEXT: addiw a1, a1, 1365 +; RV64IPN-NEXT: slli a1, a1, 12 +; RV64IPN-NEXT: addi a1, a1, 1365 +; RV64IPN-NEXT: slli a1, a1, 12 +; RV64IPN-NEXT: addi a1, a1, 1365 +; RV64IPN-NEXT: slli a1, a1, 12 +; RV64IPN-NEXT: addi a1, a1, 1365 +; RV64IPN-NEXT: and a1, a0, a1 +; RV64IPN-NEXT: slli a1, a1, 1 +; RV64IPN-NEXT: lui a2, 1026731 +; RV64IPN-NEXT: addiw a2, a2, -1365 +; RV64IPN-NEXT: slli a2, a2, 12 +; RV64IPN-NEXT: addi a2, a2, -1365 +; RV64IPN-NEXT: slli a2, a2, 12 +; RV64IPN-NEXT: addi a2, a2, -1365 +; RV64IPN-NEXT: slli a2, a2, 12 +; RV64IPN-NEXT: addi a2, a2, -1366 +; RV64IPN-NEXT: and a0, a0, a2 +; RV64IPN-NEXT: srli a0, a0, 1 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: ret +; +; RV64IBP-LABEL: bitreverse_i64: +; RV64IBP: # %bb.0: +; RV64IBP-NEXT: rev a0, a0 +; RV64IBP-NEXT: ret + %ret = tail call i64 @llvm.bitreverse.i64(i64 %a) + ret i64 %ret +} diff --git a/llvm/test/CodeGen/RISCV/rv64zpn-bswap.ll b/llvm/test/CodeGen/RISCV/rv64zpn-bswap.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rv64zpn-bswap.ll @@ -0,0 +1,227 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv64 -mattr=+experimental-b -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV64IB +; RUN: llc -mtriple=riscv64 -mattr=+experimental-p -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV64IP +; RUN: llc -mtriple=riscv64 -mattr=+experimental-zpn -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV64IPN +; RUN: llc -mtriple=riscv64 -mattr=+experimental-b,+experimental-p -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV64IBP + +declare i16 @llvm.bswap.i16(i16) +declare i32 @llvm.bswap.i32(i32) +declare i64 @llvm.bswap.i64(i64) + +define zeroext i16 @bswap_i16(i16 zeroext %a) nounwind { +; RV64IB-LABEL: bswap_i16: +; RV64IB: # %bb.0: +; RV64IB-NEXT: greviw a0, a0, 8 +; RV64IB-NEXT: ret +; +; RV64IP-LABEL: bswap_i16: +; RV64IP: # %bb.0: +; RV64IP-NEXT: srli a1, a0, 8 +; RV64IP-NEXT: slli a0, a0, 8 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: lui a1, 16 +; RV64IP-NEXT: addiw a1, a1, -1 +; RV64IP-NEXT: and a0, a0, a1 +; RV64IP-NEXT: ret +; +; RV64IPN-LABEL: bswap_i16: +; RV64IPN: # %bb.0: +; RV64IPN-NEXT: srli a1, a0, 8 +; RV64IPN-NEXT: slli a0, a0, 8 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: lui a1, 16 +; RV64IPN-NEXT: addiw a1, a1, -1 +; RV64IPN-NEXT: and a0, a0, a1 +; RV64IPN-NEXT: ret +; +; RV64IBP-LABEL: bswap_i16: +; RV64IBP: # %bb.0: +; RV64IBP-NEXT: greviw a0, a0, 8 +; RV64IBP-NEXT: ret + %ret = tail call i16 @llvm.bswap.i16(i16 %a) + ret i16 %ret +} + +define signext i32 @bswap_i32(i32 signext %a) nounwind { +; RV64IB-LABEL: bswap_i32: +; RV64IB: # %bb.0: +; RV64IB-NEXT: greviw a0, a0, 24 +; RV64IB-NEXT: ret +; +; RV64IP-LABEL: bswap_i32: +; RV64IP: # %bb.0: +; RV64IP-NEXT: srliw a1, a0, 8 +; RV64IP-NEXT: lui a2, 16 +; RV64IP-NEXT: addiw a2, a2, -256 +; RV64IP-NEXT: and a1, a1, a2 +; RV64IP-NEXT: srliw a2, a0, 24 +; RV64IP-NEXT: or a1, a1, a2 +; RV64IP-NEXT: slli a2, a0, 8 +; RV64IP-NEXT: lui a3, 4080 +; RV64IP-NEXT: and a2, a2, a3 +; RV64IP-NEXT: slli a0, a0, 24 +; RV64IP-NEXT: or a0, a0, a2 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: sext.w a0, a0 +; RV64IP-NEXT: ret +; +; RV64IPN-LABEL: bswap_i32: +; RV64IPN: # %bb.0: +; RV64IPN-NEXT: srliw a1, a0, 8 +; RV64IPN-NEXT: lui a2, 16 +; RV64IPN-NEXT: addiw a2, a2, -256 +; RV64IPN-NEXT: and a1, a1, a2 +; RV64IPN-NEXT: srliw a2, a0, 24 +; RV64IPN-NEXT: or a1, a1, a2 +; RV64IPN-NEXT: slli a2, a0, 8 +; RV64IPN-NEXT: lui a3, 4080 +; RV64IPN-NEXT: and a2, a2, a3 +; RV64IPN-NEXT: slli a0, a0, 24 +; RV64IPN-NEXT: or a0, a0, a2 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: sext.w a0, a0 +; RV64IPN-NEXT: ret +; +; RV64IBP-LABEL: bswap_i32: +; RV64IBP: # %bb.0: +; RV64IBP-NEXT: greviw a0, a0, 24 +; RV64IBP-NEXT: ret + %ret = tail call i32 @llvm.bswap.i32(i32 %a) + ret i32 %ret +} + +; Similar to bswap_i32 but the result is not sign extended. +define void @bswap_i32_nosext(i32 signext %a, i32* %x) nounwind { +; RV64IB-LABEL: bswap_i32_nosext: +; RV64IB: # %bb.0: +; RV64IB-NEXT: greviw a0, a0, 24 +; RV64IB-NEXT: sw a0, 0(a1) +; RV64IB-NEXT: ret +; +; RV64IP-LABEL: bswap_i32_nosext: +; RV64IP: # %bb.0: +; RV64IP-NEXT: srliw a2, a0, 8 +; RV64IP-NEXT: lui a3, 16 +; RV64IP-NEXT: addiw a3, a3, -256 +; RV64IP-NEXT: and a2, a2, a3 +; RV64IP-NEXT: srliw a3, a0, 24 +; RV64IP-NEXT: or a2, a2, a3 +; RV64IP-NEXT: slli a3, a0, 8 +; RV64IP-NEXT: lui a4, 4080 +; RV64IP-NEXT: and a3, a3, a4 +; RV64IP-NEXT: slli a0, a0, 24 +; RV64IP-NEXT: or a0, a0, a3 +; RV64IP-NEXT: or a0, a0, a2 +; RV64IP-NEXT: sw a0, 0(a1) +; RV64IP-NEXT: ret +; +; RV64IPN-LABEL: bswap_i32_nosext: +; RV64IPN: # %bb.0: +; RV64IPN-NEXT: srliw a2, a0, 8 +; RV64IPN-NEXT: lui a3, 16 +; RV64IPN-NEXT: addiw a3, a3, -256 +; RV64IPN-NEXT: and a2, a2, a3 +; RV64IPN-NEXT: srliw a3, a0, 24 +; RV64IPN-NEXT: or a2, a2, a3 +; RV64IPN-NEXT: slli a3, a0, 8 +; RV64IPN-NEXT: lui a4, 4080 +; RV64IPN-NEXT: and a3, a3, a4 +; RV64IPN-NEXT: slli a0, a0, 24 +; RV64IPN-NEXT: or a0, a0, a3 +; RV64IPN-NEXT: or a0, a0, a2 +; RV64IPN-NEXT: sw a0, 0(a1) +; RV64IPN-NEXT: ret +; +; RV64IBP-LABEL: bswap_i32_nosext: +; RV64IBP: # %bb.0: +; RV64IBP-NEXT: greviw a0, a0, 24 +; RV64IBP-NEXT: sw a0, 0(a1) +; RV64IBP-NEXT: ret + %ret = tail call i32 @llvm.bswap.i32(i32 %a) + store i32 %ret, i32* %x + ret void +} + +define i64 @bswap_i64(i64 %a) nounwind { +; RV64IB-LABEL: bswap_i64: +; RV64IB: # %bb.0: +; RV64IB-NEXT: rev8 a0, a0 +; RV64IB-NEXT: ret +; +; RV64IP-LABEL: bswap_i64: +; RV64IP: # %bb.0: +; RV64IP-NEXT: srli a1, a0, 24 +; RV64IP-NEXT: lui a2, 4080 +; RV64IP-NEXT: and a1, a1, a2 +; RV64IP-NEXT: srli a2, a0, 8 +; RV64IP-NEXT: addi a3, zero, 255 +; RV64IP-NEXT: slli a4, a3, 24 +; RV64IP-NEXT: and a2, a2, a4 +; RV64IP-NEXT: or a1, a2, a1 +; RV64IP-NEXT: srli a2, a0, 40 +; RV64IP-NEXT: lui a4, 16 +; RV64IP-NEXT: addiw a4, a4, -256 +; RV64IP-NEXT: and a2, a2, a4 +; RV64IP-NEXT: srli a4, a0, 56 +; RV64IP-NEXT: or a2, a2, a4 +; RV64IP-NEXT: or a1, a1, a2 +; RV64IP-NEXT: slli a2, a0, 8 +; RV64IP-NEXT: slli a4, a3, 32 +; RV64IP-NEXT: and a2, a2, a4 +; RV64IP-NEXT: slli a4, a0, 24 +; RV64IP-NEXT: slli a5, a3, 40 +; RV64IP-NEXT: and a4, a4, a5 +; RV64IP-NEXT: or a2, a4, a2 +; RV64IP-NEXT: slli a4, a0, 40 +; RV64IP-NEXT: slli a3, a3, 48 +; RV64IP-NEXT: and a3, a4, a3 +; RV64IP-NEXT: slli a0, a0, 56 +; RV64IP-NEXT: or a0, a0, a3 +; RV64IP-NEXT: or a0, a0, a2 +; RV64IP-NEXT: or a0, a0, a1 +; RV64IP-NEXT: ret +; +; RV64IPN-LABEL: bswap_i64: +; RV64IPN: # %bb.0: +; RV64IPN-NEXT: srli a1, a0, 24 +; RV64IPN-NEXT: lui a2, 4080 +; RV64IPN-NEXT: and a1, a1, a2 +; RV64IPN-NEXT: srli a2, a0, 8 +; RV64IPN-NEXT: addi a3, zero, 255 +; RV64IPN-NEXT: slli a4, a3, 24 +; RV64IPN-NEXT: and a2, a2, a4 +; RV64IPN-NEXT: or a1, a2, a1 +; RV64IPN-NEXT: srli a2, a0, 40 +; RV64IPN-NEXT: lui a4, 16 +; RV64IPN-NEXT: addiw a4, a4, -256 +; RV64IPN-NEXT: and a2, a2, a4 +; RV64IPN-NEXT: srli a4, a0, 56 +; RV64IPN-NEXT: or a2, a2, a4 +; RV64IPN-NEXT: or a1, a1, a2 +; RV64IPN-NEXT: slli a2, a0, 8 +; RV64IPN-NEXT: slli a4, a3, 32 +; RV64IPN-NEXT: and a2, a2, a4 +; RV64IPN-NEXT: slli a4, a0, 24 +; RV64IPN-NEXT: slli a5, a3, 40 +; RV64IPN-NEXT: and a4, a4, a5 +; RV64IPN-NEXT: or a2, a4, a2 +; RV64IPN-NEXT: slli a4, a0, 40 +; RV64IPN-NEXT: slli a3, a3, 48 +; RV64IPN-NEXT: and a3, a4, a3 +; RV64IPN-NEXT: slli a0, a0, 56 +; RV64IPN-NEXT: or a0, a0, a3 +; RV64IPN-NEXT: or a0, a0, a2 +; RV64IPN-NEXT: or a0, a0, a1 +; RV64IPN-NEXT: ret +; +; RV64IBP-LABEL: bswap_i64: +; RV64IBP: # %bb.0: +; RV64IBP-NEXT: rev8 a0, a0 +; RV64IBP-NEXT: ret + %ret = tail call i64 @llvm.bswap.i64(i64 %a) + ret i64 %ret +}