[RISCV][CodeGen] Implement IR Intrinsic support for K extension

This revision implements IR Intrinsic support for RISCV Scalar Crypto extension according to the specification of version [[ https://github.com/riscv/riscv-crypto/releases/tag/v1.0.0-scalar | 1.0]]
Co-author:@ksyx & @VincentWu & @lihongliang & @achieveartificialintelligence

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D102310
This commit is contained in:
Wu Xinlong 2022-01-27 11:59:13 +08:00
parent 3bc152769d
commit 615d71d9a3
31 changed files with 1781 additions and 1326 deletions

View File

@ -88,9 +88,11 @@ let TargetPrefix = "riscv" in {
// Zbb
def int_riscv_orc_b : BitManipGPRIntrinsics;
// Zbc
// Zbc or Zbkc
def int_riscv_clmul : BitManipGPRGPRIntrinsics;
def int_riscv_clmulh : BitManipGPRGPRIntrinsics;
// Zbc
def int_riscv_clmulr : BitManipGPRGPRIntrinsics;
// Zbe
@ -123,6 +125,15 @@ let TargetPrefix = "riscv" in {
// Zbt
def int_riscv_fsl : BitManipGPRGPRGRIntrinsics;
def int_riscv_fsr : BitManipGPRGPRGRIntrinsics;
// Zbkb
def int_riscv_brev8 : BitManipGPRIntrinsics;
def int_riscv_zip : BitManipGPRIntrinsics;
def int_riscv_unzip : BitManipGPRIntrinsics;
// Zbkx
def int_riscv_xperm4 : BitManipGPRGPRIntrinsics;
def int_riscv_xperm8 : BitManipGPRGPRIntrinsics;
} // TargetPrefix = "riscv"
//===----------------------------------------------------------------------===//
@ -1453,3 +1464,92 @@ let TargetPrefix = "riscv" in {
llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>],
[NoCapture<ArgIndex<1>>, IntrWriteMem]>;
} // TargetPrefix = "riscv"
//===----------------------------------------------------------------------===//
// Scalar Cryptography
//
// These intrinsics will lower directly into the corresponding instructions
// added by the scalar cyptography extension, if the extension is present.
let TargetPrefix = "riscv" in {
class ScalarCryptoGprIntrinsicAny
: Intrinsic<[llvm_anyint_ty],
[LLVMMatchType<0>],
[IntrNoMem, IntrSpeculatable]>;
class ScalarCryptoByteSelect32
: Intrinsic<[llvm_i32_ty],
[llvm_i32_ty, llvm_i32_ty, llvm_i8_ty],
[IntrNoMem, IntrWillReturn, IntrSpeculatable,
ImmArg<ArgIndex<2>>]>;
class ScalarCryptoGprGprIntrinsic32
: Intrinsic<[llvm_i32_ty],
[llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, IntrWillReturn, IntrSpeculatable]>;
class ScalarCryptoGprGprIntrinsic64
: Intrinsic<[llvm_i64_ty],
[llvm_i64_ty, llvm_i64_ty],
[IntrNoMem, IntrWillReturn, IntrSpeculatable]>;
class ScalarCryptoGprIntrinsic64
: Intrinsic<[llvm_i64_ty],
[llvm_i64_ty],
[IntrNoMem, IntrWillReturn, IntrSpeculatable]>;
class ScalarCryptoByteSelectAny
: Intrinsic<[llvm_anyint_ty],
[LLVMMatchType<0>, LLVMMatchType<0>, llvm_i8_ty],
[IntrNoMem, IntrSpeculatable, IntrWillReturn,
ImmArg<ArgIndex<2>>, Returned<ArgIndex<0>>]>;
// Zknd
def int_riscv_aes32dsi : ScalarCryptoByteSelect32;
def int_riscv_aes32dsmi : ScalarCryptoByteSelect32;
def int_riscv_aes64ds : ScalarCryptoGprGprIntrinsic64;
def int_riscv_aes64dsm : ScalarCryptoGprGprIntrinsic64;
def int_riscv_aes64im : ScalarCryptoGprIntrinsic64;
// Zkne
def int_riscv_aes32esi : ScalarCryptoByteSelect32;
def int_riscv_aes32esmi : ScalarCryptoByteSelect32;
def int_riscv_aes64es : ScalarCryptoGprGprIntrinsic64;
def int_riscv_aes64esm : ScalarCryptoGprGprIntrinsic64;
// Zknd & Zkne
def int_riscv_aes64ks2 : ScalarCryptoGprGprIntrinsic64;
def int_riscv_aes64ks1i : Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty],
[IntrNoMem, IntrSpeculatable,
IntrWillReturn, ImmArg<ArgIndex<1>>]>;
// Zknh
def int_riscv_sha256sig0 : ScalarCryptoGprIntrinsicAny;
def int_riscv_sha256sig1 : ScalarCryptoGprIntrinsicAny;
def int_riscv_sha256sum0 : ScalarCryptoGprIntrinsicAny;
def int_riscv_sha256sum1 : ScalarCryptoGprIntrinsicAny;
def int_riscv_sha512sig0l : ScalarCryptoGprGprIntrinsic32;
def int_riscv_sha512sig0h : ScalarCryptoGprGprIntrinsic32;
def int_riscv_sha512sig1l : ScalarCryptoGprGprIntrinsic32;
def int_riscv_sha512sig1h : ScalarCryptoGprGprIntrinsic32;
def int_riscv_sha512sum0r : ScalarCryptoGprGprIntrinsic32;
def int_riscv_sha512sum1r : ScalarCryptoGprGprIntrinsic32;
def int_riscv_sha512sig0 : ScalarCryptoGprIntrinsic64;
def int_riscv_sha512sig1 : ScalarCryptoGprIntrinsic64;
def int_riscv_sha512sum0 : ScalarCryptoGprIntrinsic64;
def int_riscv_sha512sum1 : ScalarCryptoGprIntrinsic64;
// Zksed
def int_riscv_sm4ks : ScalarCryptoByteSelectAny;
def int_riscv_sm4ed : ScalarCryptoByteSelectAny;
// Zksh
def int_riscv_sm3p0 : ScalarCryptoGprIntrinsicAny;
def int_riscv_sm3p1 : ScalarCryptoGprIntrinsicAny;
} // TargetPrefix = "riscv"

View File

@ -169,6 +169,12 @@ def HasStdExtZbpOrZbkb
"'Zbp' (Permutation 'Zb' Instructions) or "
"'Zbkb' (Bitmanip instructions for Cryptography)">;
def HasStdExtZbbOrZbkb
: Predicate<"Subtarget->hasStdExtZbb() || Subtarget->hasStdExtZbkb()">,
AssemblerPredicate<(any_of FeatureStdExtZbb, FeatureStdExtZbkb),
"'Zbb' (Basic Bit-Manipulation) or "
"'Zbkb' (Bitmanip instructions for Cryptography)">;
def HasStdExtZbbOrZbpOrZbkb
: Predicate<"Subtarget->hasStdExtZbb() || Subtarget->hasStdExtZbp() || Subtarget->hasStdExtZbkb()">,
AssemblerPredicate<(any_of FeatureStdExtZbb, FeatureStdExtZbp, FeatureStdExtZbkb),

View File

@ -250,7 +250,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SRL_PARTS, XLenVT, Custom);
setOperationAction(ISD::SRA_PARTS, XLenVT, Custom);
if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbp()) {
if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbp() ||
Subtarget.hasStdExtZbkb()) {
if (Subtarget.is64Bit()) {
setOperationAction(ISD::ROTL, MVT::i32, Custom);
setOperationAction(ISD::ROTR, MVT::i32, Custom);
@ -278,7 +279,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
// With Zbb we have an XLen rev8 instruction, but not GREVI. So we'll
// pattern match it directly in isel.
setOperationAction(ISD::BSWAP, XLenVT,
Subtarget.hasStdExtZbb() ? Legal : Expand);
(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb())
? Legal
: Expand);
}
if (Subtarget.hasStdExtZbb()) {
@ -1232,7 +1235,8 @@ bool RISCVTargetLowering::hasAndNotCompare(SDValue Y) const {
if (VT.isVector())
return false;
return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbp()) &&
return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbp() ||
Subtarget.hasStdExtZbkb()) &&
!isa<ConstantSDNode>(Y);
}

View File

@ -794,16 +794,16 @@ def : InstAlias<"bext $rd, $rs1, $shamt",
// Codegen patterns
//===----------------------------------------------------------------------===//
let Predicates = [HasStdExtZbbOrZbp] in {
let Predicates = [HasStdExtZbbOrZbpOrZbkb] in {
def : Pat<(and GPR:$rs1, (not GPR:$rs2)), (ANDN GPR:$rs1, GPR:$rs2)>;
def : Pat<(or GPR:$rs1, (not GPR:$rs2)), (ORN GPR:$rs1, GPR:$rs2)>;
def : Pat<(xor GPR:$rs1, (not GPR:$rs2)), (XNOR GPR:$rs1, GPR:$rs2)>;
} // Predicates = [HasStdExtZbbOrZbp]
} // Predicates = [HasStdExtZbbOrZbpOrZbkb]
let Predicates = [HasStdExtZbbOrZbp] in {
let Predicates = [HasStdExtZbbOrZbpOrZbkb] in {
def : PatGprGpr<rotl, ROL>;
def : PatGprGpr<rotr, ROR>;
} // Predicates = [HasStdExtZbbOrZbp]
} // Predicates = [HasStdExtZbbOrZbpOrZbkb]
let Predicates = [HasStdExtZbs] in {
def : Pat<(and (not (shiftop<shl> 1, GPR:$rs2)), GPR:$rs1),
@ -854,7 +854,7 @@ def : Pat<(and GPR:$r, BCLRIANDIMask:$i),
// There's no encoding for roli in the the 'B' extension as it can be
// implemented with rori by negating the immediate.
let Predicates = [HasStdExtZbbOrZbp] in {
let Predicates = [HasStdExtZbbOrZbpOrZbkb] in {
def : PatGprImm<rotr, RORI, uimmlog2xlen>;
def : Pat<(rotl GPR:$rs1, uimmlog2xlen:$shamt),
(RORI GPR:$rs1, (ImmSubFromXLen uimmlog2xlen:$shamt))>;
@ -960,35 +960,38 @@ def : PatGprGpr<umin, MINU>;
def : PatGprGpr<umax, MAXU>;
} // Predicates = [HasStdExtZbb]
let Predicates = [HasStdExtZbb, IsRV32] in {
let Predicates = [HasStdExtZbbOrZbkb, IsRV32] in {
def : Pat<(i32 (bswap GPR:$rs1)), (REV8_RV32 GPR:$rs1)>;
} // Predicates = [HasStdExtZbb, IsRV32]
} // Predicates = [HasStdExtZbbOrZbkb, IsRV32]
let Predicates = [HasStdExtZbb, IsRV64] in {
let Predicates = [HasStdExtZbbOrZbkb, IsRV64] in {
def : Pat<(i64 (bswap GPR:$rs1)), (REV8_RV64 GPR:$rs1)>;
} // Predicates = [HasStdExtZbb, IsRV64]
} // Predicates = [HasStdExtZbbOrZbkb, IsRV64]
let Predicates = [HasStdExtZbp, IsRV32] in {
let Predicates = [HasStdExtZbpOrZbkb, IsRV32] in
def : Pat<(i32 (or (and GPR:$rs1, 0x0000FFFF), (shl GPR:$rs2, (i32 16)))),
(PACK GPR:$rs1, GPR:$rs2)>;
let Predicates = [HasStdExtZbp, IsRV32] in
def : Pat<(i32 (or (and GPR:$rs2, 0xFFFF0000), (srl GPR:$rs1, (i32 16)))),
(PACKU GPR:$rs1, GPR:$rs2)>;
}
let Predicates = [HasStdExtZbp, IsRV64] in {
let Predicates = [HasStdExtZbpOrZbkb, IsRV64] in
def : Pat<(i64 (or (and GPR:$rs1, 0x00000000FFFFFFFF), (shl GPR:$rs2, (i64 32)))),
(PACK GPR:$rs1, GPR:$rs2)>;
let Predicates = [HasStdExtZbp, IsRV64] in
def : Pat<(i64 (or (and GPR:$rs2, 0xFFFFFFFF00000000), (srl GPR:$rs1, (i64 32)))),
(PACKU GPR:$rs1, GPR:$rs2)>;
}
let Predicates = [HasStdExtZbp] in {
let Predicates = [HasStdExtZbpOrZbkb] in {
def : Pat<(or (and (shl GPR:$rs2, (XLenVT 8)), 0xFFFF),
(and GPR:$rs1, 0x00FF)),
(PACKH GPR:$rs1, GPR:$rs2)>;
def : Pat<(or (shl (and GPR:$rs2, 0x00FF), (XLenVT 8)),
(and GPR:$rs1, 0x00FF)),
(PACKH GPR:$rs1, GPR:$rs2)>;
}
} // Predicates = [HasStdExtZbpOrZbkb]
let Predicates = [HasStdExtZbbOrZbp, IsRV32] in
def : Pat<(i32 (and GPR:$rs, 0xFFFF)), (ZEXTH_RV32 GPR:$rs)>;
@ -1091,13 +1094,13 @@ def : Pat<(i64 (add (and (shl GPR:$rs1, (i64 3)), 0x7FFFFFFFF), non_imm12:$rs2))
(SH3ADDUW GPR:$rs1, GPR:$rs2)>;
} // Predicates = [HasStdExtZba, IsRV64]
let Predicates = [HasStdExtZbbOrZbp, IsRV64] in {
let Predicates = [HasStdExtZbbOrZbpOrZbkb, IsRV64] in {
def : PatGprGpr<riscv_rolw, ROLW>;
def : PatGprGpr<riscv_rorw, RORW>;
def : PatGprImm<riscv_rorw, RORIW, uimm5>;
def : Pat<(riscv_rolw GPR:$rs1, uimm5:$rs2),
(RORIW GPR:$rs1, (ImmSubFrom32 uimm5:$rs2))>;
} // Predicates = [HasStdExtZbbOrZbp, IsRV64]
} // Predicates = [HasStdExtZbbOrZbpOrZbkb, IsRV64]
let Predicates = [HasStdExtZbp, IsRV64] in {
def : Pat<(riscv_rorw (riscv_grevw GPR:$rs1, 24), 16), (GREVIW GPR:$rs1, 8)>;
@ -1129,7 +1132,7 @@ def : PatGpr<riscv_ctzw, CTZW>;
def : Pat<(i64 (ctpop (i64 (zexti32 (i64 GPR:$rs1))))), (CPOPW GPR:$rs1)>;
} // Predicates = [HasStdExtZbb, IsRV64]
let Predicates = [HasStdExtZbp, IsRV64] in {
let Predicates = [HasStdExtZbpOrZbkb, IsRV64] in {
def : Pat<(i64 (sext_inreg (or (shl GPR:$rs2, (i64 16)),
(and GPR:$rs1, 0x000000000000FFFF)),
i32)),
@ -1137,16 +1140,21 @@ def : Pat<(i64 (sext_inreg (or (shl GPR:$rs2, (i64 16)),
def : Pat<(i64 (or (sext_inreg (shl GPR:$rs2, (i64 16)), i32),
(and GPR:$rs1, 0x000000000000FFFF))),
(PACKW GPR:$rs1, GPR:$rs2)>;
}
let Predicates = [HasStdExtZbp, IsRV64] in
def : Pat<(i64 (or (and (assertsexti32 GPR:$rs2), 0xFFFFFFFFFFFF0000),
(srl (and GPR:$rs1, 0xFFFFFFFF), (i64 16)))),
(PACKUW GPR:$rs1, GPR:$rs2)>;
} // Predicates = [HasStdExtZbp, IsRV64]
let Predicates = [HasStdExtZbc] in {
let Predicates = [HasStdExtZbcOrZbkc] in {
def : PatGprGpr<int_riscv_clmul, CLMUL>;
def : PatGprGpr<int_riscv_clmulh, CLMULH>;
} // Predicates = [HasStdExtZbcOrZbkc]
let Predicates = [HasStdExtZbc] in
def : PatGprGpr<int_riscv_clmulr, CLMULR>;
} // Predicates = [HasStdExtZbc]
let Predicates = [HasStdExtZbe] in {
def : PatGprGpr<riscv_bcompress, BCOMPRESS>;
@ -1177,3 +1185,17 @@ def : PatGprGpr<riscv_bfp, BFP>;
let Predicates = [HasStdExtZbf, IsRV64] in
def : PatGprGpr<riscv_bfpw, BFPW>;
let Predicates = [HasStdExtZbkb] in {
def : PatGpr<int_riscv_brev8, BREV8>;
} // Predicates = [HasStdExtZbkb]
let Predicates = [HasStdExtZbkb, IsRV32] in {
def : PatGpr<int_riscv_zip, ZIP_RV32>;
def : PatGpr<int_riscv_unzip, UNZIP_RV32>;
} // Predicates = [HasStdExtZbkb, IsRV32]
let Predicates = [HasStdExtZbkx] in {
def : PatGprGpr<int_riscv_xperm4, XPERMN>;
def : PatGprGpr<int_riscv_xperm8, XPERMB>;
}

View File

@ -21,7 +21,7 @@ def RnumArg : AsmOperandClass {
let DiagnosticType = "InvalidRnumArg";
}
def rnum : Operand<XLenVT>, ImmLeaf<XLenVT, [{return (Imm >= 0 && Imm <= 10);}]> {
def rnum : Operand<i32>, TImmLeaf<i32, [{return (Imm >= 0 && Imm <= 10);}]> {
let ParserMatchClass = RnumArg;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeUImmOperand<4>";
@ -29,6 +29,13 @@ def rnum : Operand<XLenVT>, ImmLeaf<XLenVT, [{return (Imm >= 0 && Imm <= 10);}]>
let OperandNamespace = "RISCVOp";
}
def byteselect : Operand<i8>, TImmLeaf<i8, [{return isUInt<2>(Imm);}]> {
let ParserMatchClass = UImmAsmOperand<2>;
let DecoderMethod = "decodeUImmOperand<2>";
let OperandType = "OPERAND_UIMM2";
let OperandNamespace = "RISCVOp";
}
//===----------------------------------------------------------------------===//
// Instruction class templates
//===----------------------------------------------------------------------===//
@ -42,7 +49,7 @@ class RVKUnary<bits<12> imm12_in, bits<3> funct3, string opcodestr>
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVKByteSelect<bits<5> funct5, string opcodestr>
: RVInstR<{0b00, funct5}, 0b000, OPC_OP, (outs GPR:$rd),
(ins GPR:$rs1, GPR:$rs2, uimm2:$bs),
(ins GPR:$rs1, GPR:$rs2, byteselect:$bs),
opcodestr, "$rd, $rs1, $rs2, $bs">{
bits<2> bs;
let Inst{31-30} = bs;
@ -121,3 +128,76 @@ let Predicates = [HasStdExtZksh] in {
def SM3P0 : RVKUnary<0b000100001000, 0b001, "sm3p0">;
def SM3P1 : RVKUnary<0b000100001001, 0b001, "sm3p1">;
} // Predicates = [HasStdExtZksh]
//===----------------------------------------------------------------------===//
// Codegen patterns
//===----------------------------------------------------------------------===//
class PatGprGprByteSelect<SDPatternOperator OpNode, RVInst Inst>
: Pat<(OpNode GPR:$rs1, GPR:$rs2, i8:$imm),
(Inst GPR:$rs1, GPR:$rs2, byteselect:$imm)>;
// Zknd
let Predicates = [HasStdExtZknd, IsRV32] in {
def : PatGprGprByteSelect<int_riscv_aes32dsi, AES32DSI>;
def : PatGprGprByteSelect<int_riscv_aes32dsmi, AES32DSMI>;
} // Predicates = [HasStdExtZknd, IsRV32]
let Predicates = [HasStdExtZknd, IsRV64] in {
def : PatGprGpr<int_riscv_aes64ds, AES64DS>;
def : PatGprGpr<int_riscv_aes64dsm, AES64DSM>;
def : PatGpr<int_riscv_aes64im, AES64IM>;
} // Predicates = [HasStdExtZknd, IsRV64]
let Predicates = [HasStdExtZkndOrZkne, IsRV64] in {
def : PatGprGpr<int_riscv_aes64ks2, AES64KS2>;
def : Pat<(int_riscv_aes64ks1i GPR:$rs1, i32:$rnum),
(AES64KS1I GPR:$rs1, rnum:$rnum)>;
} // Predicates = [HasStdExtZkndOrZkne, IsRV64]
// Zkne
let Predicates = [HasStdExtZkne, IsRV32] in {
def : PatGprGprByteSelect<int_riscv_aes32esi, AES32ESI>;
def : PatGprGprByteSelect<int_riscv_aes32esmi, AES32ESMI>;
} // Predicates = [HasStdExtZkne, IsRV32]
let Predicates = [HasStdExtZkne, IsRV64] in {
def : PatGprGpr<int_riscv_aes64es, AES64ES>;
def : PatGprGpr<int_riscv_aes64esm, AES64ESM>;
} // Predicates = [HasStdExtZkne, IsRV64]
// Zknh
let Predicates = [HasStdExtZknh] in {
def : PatGpr<int_riscv_sha256sig0, SHA256SIG0>;
def : PatGpr<int_riscv_sha256sig1, SHA256SIG1>;
def : PatGpr<int_riscv_sha256sum0, SHA256SUM0>;
def : PatGpr<int_riscv_sha256sum1, SHA256SUM1>;
} // Predicates = [HasStdExtZknh]
let Predicates = [HasStdExtZknh, IsRV32] in {
def : PatGprGpr<int_riscv_sha512sig0l, SHA512SIG0L>;
def : PatGprGpr<int_riscv_sha512sig0h, SHA512SIG0H>;
def : PatGprGpr<int_riscv_sha512sig1l, SHA512SIG1L>;
def : PatGprGpr<int_riscv_sha512sig1h, SHA512SIG1H>;
def : PatGprGpr<int_riscv_sha512sum0r, SHA512SUM0R>;
def : PatGprGpr<int_riscv_sha512sum1r, SHA512SUM1R>;
} // Predicates = [HasStdExtZknh, IsRV32]
let Predicates = [HasStdExtZknh, IsRV64] in {
def : PatGpr<int_riscv_sha512sig0, SHA512SIG0>;
def : PatGpr<int_riscv_sha512sig1, SHA512SIG1>;
def : PatGpr<int_riscv_sha512sum0, SHA512SUM0>;
def : PatGpr<int_riscv_sha512sum1, SHA512SUM1>;
} // Predicates = [HasStdExtZknh, IsRV64]
// Zksed
let Predicates = [HasStdExtZksed] in {
def : PatGprGprByteSelect<int_riscv_sm4ks, SM4KS>;
def : PatGprGprByteSelect<int_riscv_sm4ed, SM4ED>;
} // Predicates = [HasStdExtZksed]
// Zksh
let Predicates = [HasStdExtZksh] in {
def : PatGpr<int_riscv_sm3p0, SM3P0>;
def : PatGpr<int_riscv_sm3p1, SM3P1>;
} // Predicates = [HasStdExtZksh]

View File

@ -0,0 +1,502 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefixes=RV32I
; RUN: llc -mtriple=riscv32 -mattr=+zbb -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefixes=RV32ZBB-ZBP-ZBKB
; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbp -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefixes=RV32ZBB-ZBP-ZBKB
; RUN: llc -mtriple=riscv32 -mattr=+zbkb -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefixes=RV32ZBB-ZBP-ZBKB
define i32 @andn_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: andn_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: not a1, a1
; RV32I-NEXT: and a0, a1, a0
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: andn_i32:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: andn a0, a0, a1
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%neg = xor i32 %b, -1
%and = and i32 %neg, %a
ret i32 %and
}
define i64 @andn_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: andn_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: not a3, a3
; RV32I-NEXT: not a2, a2
; RV32I-NEXT: and a0, a2, a0
; RV32I-NEXT: and a1, a3, a1
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: andn_i64:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: andn a0, a0, a2
; RV32ZBB-ZBP-ZBKB-NEXT: andn a1, a1, a3
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%neg = xor i64 %b, -1
%and = and i64 %neg, %a
ret i64 %and
}
define i32 @orn_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: orn_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: not a1, a1
; RV32I-NEXT: or a0, a1, a0
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: orn_i32:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: orn a0, a0, a1
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%neg = xor i32 %b, -1
%or = or i32 %neg, %a
ret i32 %or
}
define i64 @orn_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: orn_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: not a3, a3
; RV32I-NEXT: not a2, a2
; RV32I-NEXT: or a0, a2, a0
; RV32I-NEXT: or a1, a3, a1
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: orn_i64:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: orn a0, a0, a2
; RV32ZBB-ZBP-ZBKB-NEXT: orn a1, a1, a3
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%neg = xor i64 %b, -1
%or = or i64 %neg, %a
ret i64 %or
}
define i32 @xnor_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: xnor_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: xor a0, a0, a1
; RV32I-NEXT: not a0, a0
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: xnor_i32:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: xnor a0, a0, a1
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%neg = xor i32 %a, -1
%xor = xor i32 %neg, %b
ret i32 %xor
}
define i64 @xnor_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: xnor_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: xor a1, a1, a3
; RV32I-NEXT: xor a0, a0, a2
; RV32I-NEXT: not a0, a0
; RV32I-NEXT: not a1, a1
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: xnor_i64:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: xnor a0, a0, a2
; RV32ZBB-ZBP-ZBKB-NEXT: xnor a1, a1, a3
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%neg = xor i64 %a, -1
%xor = xor i64 %neg, %b
ret i64 %xor
}
declare i32 @llvm.fshl.i32(i32, i32, i32)
define i32 @rol_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: rol_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: sll a2, a0, a1
; RV32I-NEXT: neg a1, a1
; RV32I-NEXT: srl a0, a0, a1
; RV32I-NEXT: or a0, a2, a0
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: rol_i32:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: rol a0, a0, a1
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%or = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 %b)
ret i32 %or
}
; This test is presented here in case future expansions of the Bitmanip
; extensions introduce instructions suitable for this pattern.
declare i64 @llvm.fshl.i64(i64, i64, i64)
define i64 @rol_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: rol_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: srli a3, a2, 5
; RV32I-NEXT: andi a3, a3, 1
; RV32I-NEXT: mv a4, a1
; RV32I-NEXT: bnez a3, .LBB7_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: mv a4, a0
; RV32I-NEXT: .LBB7_2:
; RV32I-NEXT: sll a5, a4, a2
; RV32I-NEXT: bnez a3, .LBB7_4
; RV32I-NEXT: # %bb.3:
; RV32I-NEXT: mv a0, a1
; RV32I-NEXT: .LBB7_4:
; RV32I-NEXT: srli a1, a0, 1
; RV32I-NEXT: not a6, a2
; RV32I-NEXT: srl a1, a1, a6
; RV32I-NEXT: or a3, a5, a1
; RV32I-NEXT: sll a0, a0, a2
; RV32I-NEXT: srli a1, a4, 1
; RV32I-NEXT: srl a1, a1, a6
; RV32I-NEXT: or a1, a0, a1
; RV32I-NEXT: mv a0, a3
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: rol_i64:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: srli a3, a2, 5
; RV32ZBB-ZBP-ZBKB-NEXT: andi a3, a3, 1
; RV32ZBB-ZBP-ZBKB-NEXT: mv a4, a1
; RV32ZBB-ZBP-ZBKB-NEXT: bnez a3, .LBB7_2
; RV32ZBB-ZBP-ZBKB-NEXT: # %bb.1:
; RV32ZBB-ZBP-ZBKB-NEXT: mv a4, a0
; RV32ZBB-ZBP-ZBKB-NEXT: .LBB7_2:
; RV32ZBB-ZBP-ZBKB-NEXT: sll a5, a4, a2
; RV32ZBB-ZBP-ZBKB-NEXT: bnez a3, .LBB7_4
; RV32ZBB-ZBP-ZBKB-NEXT: # %bb.3:
; RV32ZBB-ZBP-ZBKB-NEXT: mv a0, a1
; RV32ZBB-ZBP-ZBKB-NEXT: .LBB7_4:
; RV32ZBB-ZBP-ZBKB-NEXT: srli a1, a0, 1
; RV32ZBB-ZBP-ZBKB-NEXT: not a6, a2
; RV32ZBB-ZBP-ZBKB-NEXT: srl a1, a1, a6
; RV32ZBB-ZBP-ZBKB-NEXT: or a3, a5, a1
; RV32ZBB-ZBP-ZBKB-NEXT: sll a0, a0, a2
; RV32ZBB-ZBP-ZBKB-NEXT: srli a1, a4, 1
; RV32ZBB-ZBP-ZBKB-NEXT: srl a1, a1, a6
; RV32ZBB-ZBP-ZBKB-NEXT: or a1, a0, a1
; RV32ZBB-ZBP-ZBKB-NEXT: mv a0, a3
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%or = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 %b)
ret i64 %or
}
declare i32 @llvm.fshr.i32(i32, i32, i32)
define i32 @ror_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: ror_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: srl a2, a0, a1
; RV32I-NEXT: neg a1, a1
; RV32I-NEXT: sll a0, a0, a1
; RV32I-NEXT: or a0, a2, a0
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: ror_i32:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: ror a0, a0, a1
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%or = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 %b)
ret i32 %or
}
; This test is presented here in case future expansions of the Bitmanip
; extensions introduce instructions suitable for this pattern.
declare i64 @llvm.fshr.i64(i64, i64, i64)
define i64 @ror_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: ror_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: andi a4, a2, 32
; RV32I-NEXT: mv a3, a0
; RV32I-NEXT: beqz a4, .LBB9_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: mv a3, a1
; RV32I-NEXT: .LBB9_2:
; RV32I-NEXT: srl a5, a3, a2
; RV32I-NEXT: beqz a4, .LBB9_4
; RV32I-NEXT: # %bb.3:
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: .LBB9_4:
; RV32I-NEXT: slli a0, a1, 1
; RV32I-NEXT: not a4, a2
; RV32I-NEXT: sll a0, a0, a4
; RV32I-NEXT: or a0, a0, a5
; RV32I-NEXT: srl a1, a1, a2
; RV32I-NEXT: slli a2, a3, 1
; RV32I-NEXT: sll a2, a2, a4
; RV32I-NEXT: or a1, a2, a1
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: ror_i64:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: andi a4, a2, 32
; RV32ZBB-ZBP-ZBKB-NEXT: mv a3, a0
; RV32ZBB-ZBP-ZBKB-NEXT: beqz a4, .LBB9_2
; RV32ZBB-ZBP-ZBKB-NEXT: # %bb.1:
; RV32ZBB-ZBP-ZBKB-NEXT: mv a3, a1
; RV32ZBB-ZBP-ZBKB-NEXT: .LBB9_2:
; RV32ZBB-ZBP-ZBKB-NEXT: srl a5, a3, a2
; RV32ZBB-ZBP-ZBKB-NEXT: beqz a4, .LBB9_4
; RV32ZBB-ZBP-ZBKB-NEXT: # %bb.3:
; RV32ZBB-ZBP-ZBKB-NEXT: mv a1, a0
; RV32ZBB-ZBP-ZBKB-NEXT: .LBB9_4:
; RV32ZBB-ZBP-ZBKB-NEXT: slli a0, a1, 1
; RV32ZBB-ZBP-ZBKB-NEXT: not a4, a2
; RV32ZBB-ZBP-ZBKB-NEXT: sll a0, a0, a4
; RV32ZBB-ZBP-ZBKB-NEXT: or a0, a0, a5
; RV32ZBB-ZBP-ZBKB-NEXT: srl a1, a1, a2
; RV32ZBB-ZBP-ZBKB-NEXT: slli a2, a3, 1
; RV32ZBB-ZBP-ZBKB-NEXT: sll a2, a2, a4
; RV32ZBB-ZBP-ZBKB-NEXT: or a1, a2, a1
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%or = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 %b)
ret i64 %or
}
define i32 @rori_i32_fshl(i32 %a) nounwind {
; RV32I-LABEL: rori_i32_fshl:
; RV32I: # %bb.0:
; RV32I-NEXT: srli a1, a0, 1
; RV32I-NEXT: slli a0, a0, 31
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: rori_i32_fshl:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: rori a0, a0, 1
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 31)
ret i32 %1
}
define i32 @rori_i32_fshr(i32 %a) nounwind {
; RV32I-LABEL: rori_i32_fshr:
; RV32I: # %bb.0:
; RV32I-NEXT: slli a1, a0, 1
; RV32I-NEXT: srli a0, a0, 31
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: rori_i32_fshr:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: rori a0, a0, 31
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 31)
ret i32 %1
}
define i64 @rori_i64(i64 %a) nounwind {
; RV32I-LABEL: rori_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: srli a2, a0, 1
; RV32I-NEXT: slli a3, a1, 31
; RV32I-NEXT: or a2, a3, a2
; RV32I-NEXT: srli a1, a1, 1
; RV32I-NEXT: slli a0, a0, 31
; RV32I-NEXT: or a1, a0, a1
; RV32I-NEXT: mv a0, a2
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: rori_i64:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: srli a2, a0, 1
; RV32ZBB-ZBP-ZBKB-NEXT: slli a3, a1, 31
; RV32ZBB-ZBP-ZBKB-NEXT: or a2, a3, a2
; RV32ZBB-ZBP-ZBKB-NEXT: srli a1, a1, 1
; RV32ZBB-ZBP-ZBKB-NEXT: slli a0, a0, 31
; RV32ZBB-ZBP-ZBKB-NEXT: or a1, a0, a1
; RV32ZBB-ZBP-ZBKB-NEXT: mv a0, a2
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 63)
ret i64 %1
}
define i64 @rori_i64_fshr(i64 %a) nounwind {
; RV32I-LABEL: rori_i64_fshr:
; RV32I: # %bb.0:
; RV32I-NEXT: srli a2, a1, 31
; RV32I-NEXT: slli a3, a0, 1
; RV32I-NEXT: or a2, a3, a2
; RV32I-NEXT: srli a0, a0, 31
; RV32I-NEXT: slli a1, a1, 1
; RV32I-NEXT: or a1, a1, a0
; RV32I-NEXT: mv a0, a2
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: rori_i64_fshr:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: srli a2, a1, 31
; RV32ZBB-ZBP-ZBKB-NEXT: slli a3, a0, 1
; RV32ZBB-ZBP-ZBKB-NEXT: or a2, a3, a2
; RV32ZBB-ZBP-ZBKB-NEXT: srli a0, a0, 31
; RV32ZBB-ZBP-ZBKB-NEXT: slli a1, a1, 1
; RV32ZBB-ZBP-ZBKB-NEXT: or a1, a1, a0
; RV32ZBB-ZBP-ZBKB-NEXT: mv a0, a2
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 63)
ret i64 %1
}
define i8 @srli_i8(i8 %a) nounwind {
; RV32I-LABEL: srli_i8:
; RV32I: # %bb.0:
; RV32I-NEXT: slli a0, a0, 24
; RV32I-NEXT: srli a0, a0, 30
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: srli_i8:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: slli a0, a0, 24
; RV32ZBB-ZBP-ZBKB-NEXT: srli a0, a0, 30
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%1 = lshr i8 %a, 6
ret i8 %1
}
; We could use sext.b+srai, but slli+srai offers more opportunities for
; comppressed instructions.
define i8 @srai_i8(i8 %a) nounwind {
; RV32I-LABEL: srai_i8:
; RV32I: # %bb.0:
; RV32I-NEXT: slli a0, a0, 24
; RV32I-NEXT: srai a0, a0, 29
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: srai_i8:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: slli a0, a0, 24
; RV32ZBB-ZBP-ZBKB-NEXT: srai a0, a0, 29
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%1 = ashr i8 %a, 5
ret i8 %1
}
; We could use zext.h+srli, but slli+srli offers more opportunities for
; comppressed instructions.
define i16 @srli_i16(i16 %a) nounwind {
; RV32I-LABEL: srli_i16:
; RV32I: # %bb.0:
; RV32I-NEXT: slli a0, a0, 16
; RV32I-NEXT: srli a0, a0, 22
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: srli_i16:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: slli a0, a0, 16
; RV32ZBB-ZBP-ZBKB-NEXT: srli a0, a0, 22
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%1 = lshr i16 %a, 6
ret i16 %1
}
; We could use sext.h+srai, but slli+srai offers more opportunities for
; comppressed instructions.
define i16 @srai_i16(i16 %a) nounwind {
; RV32I-LABEL: srai_i16:
; RV32I: # %bb.0:
; RV32I-NEXT: slli a0, a0, 16
; RV32I-NEXT: srai a0, a0, 25
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: srai_i16:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: slli a0, a0, 16
; RV32ZBB-ZBP-ZBKB-NEXT: srai a0, a0, 25
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%1 = ashr i16 %a, 9
ret i16 %1
}
define i1 @andn_seqz_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: andn_seqz_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: xor a0, a0, a1
; RV32I-NEXT: seqz a0, a0
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: andn_seqz_i32:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: andn a0, a1, a0
; RV32ZBB-ZBP-ZBKB-NEXT: seqz a0, a0
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%and = and i32 %a, %b
%cmpeq = icmp eq i32 %and, %b
ret i1 %cmpeq
}
define i1 @andn_seqz_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: andn_seqz_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: not a0, a0
; RV32I-NEXT: not a1, a1
; RV32I-NEXT: and a1, a1, a3
; RV32I-NEXT: and a0, a0, a2
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: seqz a0, a0
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: andn_seqz_i64:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: andn a1, a3, a1
; RV32ZBB-ZBP-ZBKB-NEXT: andn a0, a2, a0
; RV32ZBB-ZBP-ZBKB-NEXT: or a0, a0, a1
; RV32ZBB-ZBP-ZBKB-NEXT: seqz a0, a0
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%and = and i64 %a, %b
%cmpeq = icmp eq i64 %and, %b
ret i1 %cmpeq
}
define i1 @andn_snez_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: andn_snez_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: xor a0, a0, a1
; RV32I-NEXT: snez a0, a0
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: andn_snez_i32:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: andn a0, a1, a0
; RV32ZBB-ZBP-ZBKB-NEXT: snez a0, a0
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%and = and i32 %a, %b
%cmpeq = icmp ne i32 %and, %b
ret i1 %cmpeq
}
define i1 @andn_snez_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: andn_snez_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: not a0, a0
; RV32I-NEXT: not a1, a1
; RV32I-NEXT: and a1, a1, a3
; RV32I-NEXT: and a0, a0, a2
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: snez a0, a0
; RV32I-NEXT: ret
;
; RV32ZBB-ZBP-ZBKB-LABEL: andn_snez_i64:
; RV32ZBB-ZBP-ZBKB: # %bb.0:
; RV32ZBB-ZBP-ZBKB-NEXT: andn a1, a3, a1
; RV32ZBB-ZBP-ZBKB-NEXT: andn a0, a2, a0
; RV32ZBB-ZBP-ZBKB-NEXT: or a0, a0, a1
; RV32ZBB-ZBP-ZBKB-NEXT: snez a0, a0
; RV32ZBB-ZBP-ZBKB-NEXT: ret
%and = and i64 %a, %b
%cmpeq = icmp ne i64 %and, %b
ret i1 %cmpeq
}

View File

@ -1,675 +0,0 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32I
; RUN: llc -mtriple=riscv32 -mattr=+zbb -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32ZBB
; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbp -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32ZBP
define i32 @andn_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: andn_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: not a1, a1
; RV32I-NEXT: and a0, a1, a0
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: andn_i32:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: andn a0, a0, a1
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: andn_i32:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: andn a0, a0, a1
; RV32ZBP-NEXT: ret
%neg = xor i32 %b, -1
%and = and i32 %neg, %a
ret i32 %and
}
define i64 @andn_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: andn_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: not a3, a3
; RV32I-NEXT: not a2, a2
; RV32I-NEXT: and a0, a2, a0
; RV32I-NEXT: and a1, a3, a1
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: andn_i64:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: andn a0, a0, a2
; RV32ZBB-NEXT: andn a1, a1, a3
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: andn_i64:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: andn a0, a0, a2
; RV32ZBP-NEXT: andn a1, a1, a3
; RV32ZBP-NEXT: ret
%neg = xor i64 %b, -1
%and = and i64 %neg, %a
ret i64 %and
}
define i32 @orn_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: orn_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: not a1, a1
; RV32I-NEXT: or a0, a1, a0
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: orn_i32:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: orn a0, a0, a1
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: orn_i32:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: orn a0, a0, a1
; RV32ZBP-NEXT: ret
%neg = xor i32 %b, -1
%or = or i32 %neg, %a
ret i32 %or
}
define i64 @orn_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: orn_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: not a3, a3
; RV32I-NEXT: not a2, a2
; RV32I-NEXT: or a0, a2, a0
; RV32I-NEXT: or a1, a3, a1
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: orn_i64:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: orn a0, a0, a2
; RV32ZBB-NEXT: orn a1, a1, a3
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: orn_i64:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: orn a0, a0, a2
; RV32ZBP-NEXT: orn a1, a1, a3
; RV32ZBP-NEXT: ret
%neg = xor i64 %b, -1
%or = or i64 %neg, %a
ret i64 %or
}
define i32 @xnor_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: xnor_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: xor a0, a0, a1
; RV32I-NEXT: not a0, a0
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: xnor_i32:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: xnor a0, a0, a1
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: xnor_i32:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: xnor a0, a0, a1
; RV32ZBP-NEXT: ret
%neg = xor i32 %a, -1
%xor = xor i32 %neg, %b
ret i32 %xor
}
define i64 @xnor_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: xnor_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: xor a1, a1, a3
; RV32I-NEXT: xor a0, a0, a2
; RV32I-NEXT: not a0, a0
; RV32I-NEXT: not a1, a1
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: xnor_i64:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: xnor a0, a0, a2
; RV32ZBB-NEXT: xnor a1, a1, a3
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: xnor_i64:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: xnor a0, a0, a2
; RV32ZBP-NEXT: xnor a1, a1, a3
; RV32ZBP-NEXT: ret
%neg = xor i64 %a, -1
%xor = xor i64 %neg, %b
ret i64 %xor
}
declare i32 @llvm.fshl.i32(i32, i32, i32)
define i32 @rol_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: rol_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: sll a2, a0, a1
; RV32I-NEXT: neg a1, a1
; RV32I-NEXT: srl a0, a0, a1
; RV32I-NEXT: or a0, a2, a0
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: rol_i32:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: rol a0, a0, a1
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: rol_i32:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: rol a0, a0, a1
; RV32ZBP-NEXT: ret
%or = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 %b)
ret i32 %or
}
; This test is presented here in case future expansions of the Bitmanip
; extensions introduce instructions suitable for this pattern.
declare i64 @llvm.fshl.i64(i64, i64, i64)
define i64 @rol_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: rol_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: srli a3, a2, 5
; RV32I-NEXT: andi a3, a3, 1
; RV32I-NEXT: mv a4, a1
; RV32I-NEXT: bnez a3, .LBB7_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: mv a4, a0
; RV32I-NEXT: .LBB7_2:
; RV32I-NEXT: sll a5, a4, a2
; RV32I-NEXT: bnez a3, .LBB7_4
; RV32I-NEXT: # %bb.3:
; RV32I-NEXT: mv a0, a1
; RV32I-NEXT: .LBB7_4:
; RV32I-NEXT: srli a1, a0, 1
; RV32I-NEXT: not a6, a2
; RV32I-NEXT: srl a1, a1, a6
; RV32I-NEXT: or a3, a5, a1
; RV32I-NEXT: sll a0, a0, a2
; RV32I-NEXT: srli a1, a4, 1
; RV32I-NEXT: srl a1, a1, a6
; RV32I-NEXT: or a1, a0, a1
; RV32I-NEXT: mv a0, a3
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: rol_i64:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: srli a3, a2, 5
; RV32ZBB-NEXT: andi a3, a3, 1
; RV32ZBB-NEXT: mv a4, a1
; RV32ZBB-NEXT: bnez a3, .LBB7_2
; RV32ZBB-NEXT: # %bb.1:
; RV32ZBB-NEXT: mv a4, a0
; RV32ZBB-NEXT: .LBB7_2:
; RV32ZBB-NEXT: sll a5, a4, a2
; RV32ZBB-NEXT: bnez a3, .LBB7_4
; RV32ZBB-NEXT: # %bb.3:
; RV32ZBB-NEXT: mv a0, a1
; RV32ZBB-NEXT: .LBB7_4:
; RV32ZBB-NEXT: srli a1, a0, 1
; RV32ZBB-NEXT: not a6, a2
; RV32ZBB-NEXT: srl a1, a1, a6
; RV32ZBB-NEXT: or a3, a5, a1
; RV32ZBB-NEXT: sll a0, a0, a2
; RV32ZBB-NEXT: srli a1, a4, 1
; RV32ZBB-NEXT: srl a1, a1, a6
; RV32ZBB-NEXT: or a1, a0, a1
; RV32ZBB-NEXT: mv a0, a3
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: rol_i64:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: srli a3, a2, 5
; RV32ZBP-NEXT: andi a3, a3, 1
; RV32ZBP-NEXT: mv a4, a1
; RV32ZBP-NEXT: bnez a3, .LBB7_2
; RV32ZBP-NEXT: # %bb.1:
; RV32ZBP-NEXT: mv a4, a0
; RV32ZBP-NEXT: .LBB7_2:
; RV32ZBP-NEXT: sll a5, a4, a2
; RV32ZBP-NEXT: bnez a3, .LBB7_4
; RV32ZBP-NEXT: # %bb.3:
; RV32ZBP-NEXT: mv a0, a1
; RV32ZBP-NEXT: .LBB7_4:
; RV32ZBP-NEXT: srli a1, a0, 1
; RV32ZBP-NEXT: not a6, a2
; RV32ZBP-NEXT: srl a1, a1, a6
; RV32ZBP-NEXT: or a3, a5, a1
; RV32ZBP-NEXT: sll a0, a0, a2
; RV32ZBP-NEXT: srli a1, a4, 1
; RV32ZBP-NEXT: srl a1, a1, a6
; RV32ZBP-NEXT: or a1, a0, a1
; RV32ZBP-NEXT: mv a0, a3
; RV32ZBP-NEXT: ret
%or = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 %b)
ret i64 %or
}
declare i32 @llvm.fshr.i32(i32, i32, i32)
define i32 @ror_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: ror_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: srl a2, a0, a1
; RV32I-NEXT: neg a1, a1
; RV32I-NEXT: sll a0, a0, a1
; RV32I-NEXT: or a0, a2, a0
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: ror_i32:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: ror a0, a0, a1
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: ror_i32:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: ror a0, a0, a1
; RV32ZBP-NEXT: ret
%or = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 %b)
ret i32 %or
}
; This test is presented here in case future expansions of the Bitmanip
; extensions introduce instructions suitable for this pattern.
declare i64 @llvm.fshr.i64(i64, i64, i64)
define i64 @ror_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: ror_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: andi a4, a2, 32
; RV32I-NEXT: mv a3, a0
; RV32I-NEXT: beqz a4, .LBB9_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: mv a3, a1
; RV32I-NEXT: .LBB9_2:
; RV32I-NEXT: srl a5, a3, a2
; RV32I-NEXT: beqz a4, .LBB9_4
; RV32I-NEXT: # %bb.3:
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: .LBB9_4:
; RV32I-NEXT: slli a0, a1, 1
; RV32I-NEXT: not a4, a2
; RV32I-NEXT: sll a0, a0, a4
; RV32I-NEXT: or a0, a0, a5
; RV32I-NEXT: srl a1, a1, a2
; RV32I-NEXT: slli a2, a3, 1
; RV32I-NEXT: sll a2, a2, a4
; RV32I-NEXT: or a1, a2, a1
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: ror_i64:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: andi a4, a2, 32
; RV32ZBB-NEXT: mv a3, a0
; RV32ZBB-NEXT: beqz a4, .LBB9_2
; RV32ZBB-NEXT: # %bb.1:
; RV32ZBB-NEXT: mv a3, a1
; RV32ZBB-NEXT: .LBB9_2:
; RV32ZBB-NEXT: srl a5, a3, a2
; RV32ZBB-NEXT: beqz a4, .LBB9_4
; RV32ZBB-NEXT: # %bb.3:
; RV32ZBB-NEXT: mv a1, a0
; RV32ZBB-NEXT: .LBB9_4:
; RV32ZBB-NEXT: slli a0, a1, 1
; RV32ZBB-NEXT: not a4, a2
; RV32ZBB-NEXT: sll a0, a0, a4
; RV32ZBB-NEXT: or a0, a0, a5
; RV32ZBB-NEXT: srl a1, a1, a2
; RV32ZBB-NEXT: slli a2, a3, 1
; RV32ZBB-NEXT: sll a2, a2, a4
; RV32ZBB-NEXT: or a1, a2, a1
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: ror_i64:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: andi a4, a2, 32
; RV32ZBP-NEXT: mv a3, a0
; RV32ZBP-NEXT: beqz a4, .LBB9_2
; RV32ZBP-NEXT: # %bb.1:
; RV32ZBP-NEXT: mv a3, a1
; RV32ZBP-NEXT: .LBB9_2:
; RV32ZBP-NEXT: srl a5, a3, a2
; RV32ZBP-NEXT: beqz a4, .LBB9_4
; RV32ZBP-NEXT: # %bb.3:
; RV32ZBP-NEXT: mv a1, a0
; RV32ZBP-NEXT: .LBB9_4:
; RV32ZBP-NEXT: slli a0, a1, 1
; RV32ZBP-NEXT: not a4, a2
; RV32ZBP-NEXT: sll a0, a0, a4
; RV32ZBP-NEXT: or a0, a0, a5
; RV32ZBP-NEXT: srl a1, a1, a2
; RV32ZBP-NEXT: slli a2, a3, 1
; RV32ZBP-NEXT: sll a2, a2, a4
; RV32ZBP-NEXT: or a1, a2, a1
; RV32ZBP-NEXT: ret
%or = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 %b)
ret i64 %or
}
define i32 @rori_i32_fshl(i32 %a) nounwind {
; RV32I-LABEL: rori_i32_fshl:
; RV32I: # %bb.0:
; RV32I-NEXT: srli a1, a0, 1
; RV32I-NEXT: slli a0, a0, 31
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: rori_i32_fshl:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: rori a0, a0, 1
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: rori_i32_fshl:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: rori a0, a0, 1
; RV32ZBP-NEXT: ret
%1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 31)
ret i32 %1
}
define i32 @rori_i32_fshr(i32 %a) nounwind {
; RV32I-LABEL: rori_i32_fshr:
; RV32I: # %bb.0:
; RV32I-NEXT: slli a1, a0, 1
; RV32I-NEXT: srli a0, a0, 31
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: rori_i32_fshr:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: rori a0, a0, 31
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: rori_i32_fshr:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: rori a0, a0, 31
; RV32ZBP-NEXT: ret
%1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 31)
ret i32 %1
}
define i64 @rori_i64(i64 %a) nounwind {
; RV32I-LABEL: rori_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: srli a2, a0, 1
; RV32I-NEXT: slli a3, a1, 31
; RV32I-NEXT: or a2, a3, a2
; RV32I-NEXT: srli a1, a1, 1
; RV32I-NEXT: slli a0, a0, 31
; RV32I-NEXT: or a1, a0, a1
; RV32I-NEXT: mv a0, a2
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: rori_i64:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: srli a2, a0, 1
; RV32ZBB-NEXT: slli a3, a1, 31
; RV32ZBB-NEXT: or a2, a3, a2
; RV32ZBB-NEXT: srli a1, a1, 1
; RV32ZBB-NEXT: slli a0, a0, 31
; RV32ZBB-NEXT: or a1, a0, a1
; RV32ZBB-NEXT: mv a0, a2
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: rori_i64:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: srli a2, a0, 1
; RV32ZBP-NEXT: slli a3, a1, 31
; RV32ZBP-NEXT: or a2, a3, a2
; RV32ZBP-NEXT: srli a1, a1, 1
; RV32ZBP-NEXT: slli a0, a0, 31
; RV32ZBP-NEXT: or a1, a0, a1
; RV32ZBP-NEXT: mv a0, a2
; RV32ZBP-NEXT: ret
%1 = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 63)
ret i64 %1
}
define i64 @rori_i64_fshr(i64 %a) nounwind {
; RV32I-LABEL: rori_i64_fshr:
; RV32I: # %bb.0:
; RV32I-NEXT: srli a2, a1, 31
; RV32I-NEXT: slli a3, a0, 1
; RV32I-NEXT: or a2, a3, a2
; RV32I-NEXT: srli a0, a0, 31
; RV32I-NEXT: slli a1, a1, 1
; RV32I-NEXT: or a1, a1, a0
; RV32I-NEXT: mv a0, a2
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: rori_i64_fshr:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: srli a2, a1, 31
; RV32ZBB-NEXT: slli a3, a0, 1
; RV32ZBB-NEXT: or a2, a3, a2
; RV32ZBB-NEXT: srli a0, a0, 31
; RV32ZBB-NEXT: slli a1, a1, 1
; RV32ZBB-NEXT: or a1, a1, a0
; RV32ZBB-NEXT: mv a0, a2
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: rori_i64_fshr:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: srli a2, a1, 31
; RV32ZBP-NEXT: slli a3, a0, 1
; RV32ZBP-NEXT: or a2, a3, a2
; RV32ZBP-NEXT: srli a0, a0, 31
; RV32ZBP-NEXT: slli a1, a1, 1
; RV32ZBP-NEXT: or a1, a1, a0
; RV32ZBP-NEXT: mv a0, a2
; RV32ZBP-NEXT: ret
%1 = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 63)
ret i64 %1
}
define i8 @srli_i8(i8 %a) nounwind {
; RV32I-LABEL: srli_i8:
; RV32I: # %bb.0:
; RV32I-NEXT: slli a0, a0, 24
; RV32I-NEXT: srli a0, a0, 30
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: srli_i8:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: slli a0, a0, 24
; RV32ZBB-NEXT: srli a0, a0, 30
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: srli_i8:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: slli a0, a0, 24
; RV32ZBP-NEXT: srli a0, a0, 30
; RV32ZBP-NEXT: ret
%1 = lshr i8 %a, 6
ret i8 %1
}
; We could use sext.b+srai, but slli+srai offers more opportunities for
; comppressed instructions.
define i8 @srai_i8(i8 %a) nounwind {
; RV32I-LABEL: srai_i8:
; RV32I: # %bb.0:
; RV32I-NEXT: slli a0, a0, 24
; RV32I-NEXT: srai a0, a0, 29
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: srai_i8:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: slli a0, a0, 24
; RV32ZBB-NEXT: srai a0, a0, 29
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: srai_i8:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: slli a0, a0, 24
; RV32ZBP-NEXT: srai a0, a0, 29
; RV32ZBP-NEXT: ret
%1 = ashr i8 %a, 5
ret i8 %1
}
; We could use zext.h+srli, but slli+srli offers more opportunities for
; comppressed instructions.
define i16 @srli_i16(i16 %a) nounwind {
; RV32I-LABEL: srli_i16:
; RV32I: # %bb.0:
; RV32I-NEXT: slli a0, a0, 16
; RV32I-NEXT: srli a0, a0, 22
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: srli_i16:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: slli a0, a0, 16
; RV32ZBB-NEXT: srli a0, a0, 22
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: srli_i16:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: slli a0, a0, 16
; RV32ZBP-NEXT: srli a0, a0, 22
; RV32ZBP-NEXT: ret
%1 = lshr i16 %a, 6
ret i16 %1
}
; We could use sext.h+srai, but slli+srai offers more opportunities for
; comppressed instructions.
define i16 @srai_i16(i16 %a) nounwind {
; RV32I-LABEL: srai_i16:
; RV32I: # %bb.0:
; RV32I-NEXT: slli a0, a0, 16
; RV32I-NEXT: srai a0, a0, 25
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: srai_i16:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: slli a0, a0, 16
; RV32ZBB-NEXT: srai a0, a0, 25
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: srai_i16:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: slli a0, a0, 16
; RV32ZBP-NEXT: srai a0, a0, 25
; RV32ZBP-NEXT: ret
%1 = ashr i16 %a, 9
ret i16 %1
}
define i1 @andn_seqz_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: andn_seqz_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: xor a0, a0, a1
; RV32I-NEXT: seqz a0, a0
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: andn_seqz_i32:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: andn a0, a1, a0
; RV32ZBB-NEXT: seqz a0, a0
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: andn_seqz_i32:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: andn a0, a1, a0
; RV32ZBP-NEXT: seqz a0, a0
; RV32ZBP-NEXT: ret
%and = and i32 %a, %b
%cmpeq = icmp eq i32 %and, %b
ret i1 %cmpeq
}
define i1 @andn_seqz_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: andn_seqz_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: not a0, a0
; RV32I-NEXT: not a1, a1
; RV32I-NEXT: and a1, a1, a3
; RV32I-NEXT: and a0, a0, a2
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: seqz a0, a0
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: andn_seqz_i64:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: andn a1, a3, a1
; RV32ZBB-NEXT: andn a0, a2, a0
; RV32ZBB-NEXT: or a0, a0, a1
; RV32ZBB-NEXT: seqz a0, a0
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: andn_seqz_i64:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: andn a1, a3, a1
; RV32ZBP-NEXT: andn a0, a2, a0
; RV32ZBP-NEXT: or a0, a0, a1
; RV32ZBP-NEXT: seqz a0, a0
; RV32ZBP-NEXT: ret
%and = and i64 %a, %b
%cmpeq = icmp eq i64 %and, %b
ret i1 %cmpeq
}
define i1 @andn_snez_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: andn_snez_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: xor a0, a0, a1
; RV32I-NEXT: snez a0, a0
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: andn_snez_i32:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: andn a0, a1, a0
; RV32ZBB-NEXT: snez a0, a0
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: andn_snez_i32:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: andn a0, a1, a0
; RV32ZBP-NEXT: snez a0, a0
; RV32ZBP-NEXT: ret
%and = and i32 %a, %b
%cmpeq = icmp ne i32 %and, %b
ret i1 %cmpeq
}
define i1 @andn_snez_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: andn_snez_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: not a0, a0
; RV32I-NEXT: not a1, a1
; RV32I-NEXT: and a1, a1, a3
; RV32I-NEXT: and a0, a0, a2
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: snez a0, a0
; RV32I-NEXT: ret
;
; RV32ZBB-LABEL: andn_snez_i64:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: andn a1, a3, a1
; RV32ZBB-NEXT: andn a0, a2, a0
; RV32ZBB-NEXT: or a0, a0, a1
; RV32ZBB-NEXT: snez a0, a0
; RV32ZBB-NEXT: ret
;
; RV32ZBP-LABEL: andn_snez_i64:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: andn a1, a3, a1
; RV32ZBP-NEXT: andn a0, a2, a0
; RV32ZBP-NEXT: or a0, a0, a1
; RV32ZBP-NEXT: snez a0, a0
; RV32ZBP-NEXT: ret
%and = and i64 %a, %b
%cmpeq = icmp ne i64 %and, %b
ret i1 %cmpeq
}

View File

@ -2,28 +2,6 @@
; RUN: llc -mtriple=riscv32 -mattr=+zbc -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32ZBC
declare i32 @llvm.riscv.clmul.i32(i32 %a, i32 %b)
define i32 @clmul32(i32 %a, i32 %b) nounwind {
; RV32ZBC-LABEL: clmul32:
; RV32ZBC: # %bb.0:
; RV32ZBC-NEXT: clmul a0, a0, a1
; RV32ZBC-NEXT: ret
%tmp = call i32 @llvm.riscv.clmul.i32(i32 %a, i32 %b)
ret i32 %tmp
}
declare i32 @llvm.riscv.clmulh.i32(i32 %a, i32 %b)
define i32 @clmul32h(i32 %a, i32 %b) nounwind {
; RV32ZBC-LABEL: clmul32h:
; RV32ZBC: # %bb.0:
; RV32ZBC-NEXT: clmulh a0, a0, a1
; RV32ZBC-NEXT: ret
%tmp = call i32 @llvm.riscv.clmulh.i32(i32 %a, i32 %b)
ret i32 %tmp
}
declare i32 @llvm.riscv.clmulr.i32(i32 %a, i32 %b)
define i32 @clmul32r(i32 %a, i32 %b) nounwind {

View File

@ -0,0 +1,27 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -mattr=+zbc -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32ZBC-ZBKC
; RUN: llc -mtriple=riscv32 -mattr=+zbkc -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32ZBC-ZBKC
declare i32 @llvm.riscv.clmul.i32(i32 %a, i32 %b)
define i32 @clmul32(i32 %a, i32 %b) nounwind {
; RV32ZBC-ZBKC-LABEL: clmul32:
; RV32ZBC-ZBKC: # %bb.0:
; RV32ZBC-ZBKC-NEXT: clmul a0, a0, a1
; RV32ZBC-ZBKC-NEXT: ret
%tmp = call i32 @llvm.riscv.clmul.i32(i32 %a, i32 %b)
ret i32 %tmp
}
declare i32 @llvm.riscv.clmulh.i32(i32 %a, i32 %b)
define i32 @clmul32h(i32 %a, i32 %b) nounwind {
; RV32ZBC-ZBKC-LABEL: clmul32h:
; RV32ZBC-ZBKC: # %bb.0:
; RV32ZBC-ZBKC-NEXT: clmulh a0, a0, a1
; RV32ZBC-ZBKC-NEXT: ret
%tmp = call i32 @llvm.riscv.clmulh.i32(i32 %a, i32 %b)
ret i32 %tmp
}

View File

@ -0,0 +1,47 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -mattr=+zbkb -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32ZBKB
declare i32 @llvm.riscv.brev8(i32);
define i32 @brev8(i32 %a) nounwind {
; RV32ZBKB-LABEL: brev8:
; RV32ZBKB: # %bb.0:
; RV32ZBKB-NEXT: brev8 a0, a0
; RV32ZBKB-NEXT: ret
%val = call i32 @llvm.riscv.brev8(i32 %a)
ret i32 %val
}
declare i32 @llvm.bswap.i32(i32)
define i32 @rev8_i32(i32 %a) nounwind {
; RV32ZBKB-LABEL: rev8_i32:
; RV32ZBKB: # %bb.0:
; RV32ZBKB-NEXT: rev8 a0, a0
; RV32ZBKB-NEXT: ret
%1 = tail call i32 @llvm.bswap.i32(i32 %a)
ret i32 %1
}
declare i32 @llvm.riscv.zip(i32);
define i32 @zip(i32 %a) nounwind {
; RV32ZBKB-LABEL: zip:
; RV32ZBKB: # %bb.0:
; RV32ZBKB-NEXT: zip a0, a0
; RV32ZBKB-NEXT: ret
%val = call i32 @llvm.riscv.zip(i32 %a)
ret i32 %val
}
declare i32 @llvm.riscv.unzip(i32);
define i32 @unzip(i32 %a) nounwind {
; RV32ZBKB-LABEL: unzip:
; RV32ZBKB: # %bb.0:
; RV32ZBKB-NEXT: unzip a0, a0
; RV32ZBKB-NEXT: ret
%val = call i32 @llvm.riscv.unzip(i32 %a)
ret i32 %val
}

View File

@ -0,0 +1,24 @@
; RUN: llc -mtriple=riscv32 -mattr=+zbkx -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32ZBKX
declare i32 @llvm.riscv.xperm8.i32(i32 %a, i32 %b)
define i32 @xperm8(i32 %a, i32 %b) nounwind {
; RV32ZBKX-LABEL: xperm8:
; RV32ZBKX: # %bb.0:
; RV32ZBKX-NEXT: xperm8 a0, a0, a1
; RV32ZBKX-NEXT: ret
%tmp = call i32 @llvm.riscv.xperm8.i32(i32 %a, i32 %b)
ret i32 %tmp
}
declare i32 @llvm.riscv.xperm4.i32(i32 %a, i32 %b)
define i32 @xperm4(i32 %a, i32 %b) nounwind {
; RV32ZBKX-LABEL: xperm4:
; RV32ZBKX: # %bb.0:
; RV32ZBKX-NEXT: xperm4 a0, a0, a1
; RV32ZBKX-NEXT: ret
%tmp = call i32 @llvm.riscv.xperm4.i32(i32 %a, i32 %b)
ret i32 %tmp
}

View File

@ -0,0 +1,149 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32I
; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbp -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32ZBP-ZBKB
; RUN: llc -mtriple=riscv32 -mattr=+zbkb -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32ZBP-ZBKB
define i32 @pack_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: pack_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: slli a0, a0, 16
; RV32I-NEXT: srli a0, a0, 16
; RV32I-NEXT: slli a1, a1, 16
; RV32I-NEXT: or a0, a1, a0
; RV32I-NEXT: ret
%shl = and i32 %a, 65535
%shl1 = shl i32 %b, 16
%or = or i32 %shl1, %shl
ret i32 %or
}
; As we are not matching directly i64 code patterns on RV32 some i64 patterns
; don't have yet any matching bit manipulation instructions on RV32.
; This test is presented here in case future expansions of the Bitmanip
; extensions introduce instructions suitable for this pattern.
define i64 @pack_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: pack_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: mv a1, a2
; RV32I-NEXT: ret
;
; RV32ZBP-ZBKB-LABEL: pack_i64:
; RV32ZBP-ZBKB: # %bb.0:
; RV32ZBP-ZBKB-NEXT: mv a1, a2
; RV32ZBP-ZBKB-NEXT: ret
%shl = and i64 %a, 4294967295
%shl1 = shl i64 %b, 32
%or = or i64 %shl1, %shl
ret i64 %or
}
; As we are not matching directly i64 code patterns on RV32 some i64 patterns
; don't have yet any matching bit manipulation instructions on RV32.
; This test is presented here in case future expansions of the Bitmanip
; extensions introduce instructions suitable for this pattern.
define i64 @packu_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: packu_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: mv a0, a1
; RV32I-NEXT: mv a1, a3
; RV32I-NEXT: ret
;
; RV32ZBP-ZBKB-LABEL: packu_i64:
; RV32ZBP-ZBKB: # %bb.0:
; RV32ZBP-ZBKB-NEXT: mv a0, a1
; RV32ZBP-ZBKB-NEXT: mv a1, a3
; RV32ZBP-ZBKB-NEXT: ret
%shr = lshr i64 %a, 32
%shr1 = and i64 %b, -4294967296
%or = or i64 %shr1, %shr
ret i64 %or
}
define i32 @packh_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: packh_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: andi a0, a0, 255
; RV32I-NEXT: slli a1, a1, 24
; RV32I-NEXT: srli a1, a1, 16
; RV32I-NEXT: or a0, a1, a0
; RV32I-NEXT: ret
;
; RV32ZBP-ZBKB-LABEL: packh_i32:
; RV32ZBP-ZBKB: # %bb.0:
; RV32ZBP-ZBKB-NEXT: packh a0, a0, a1
; RV32ZBP-ZBKB-NEXT: ret
%and = and i32 %a, 255
%and1 = shl i32 %b, 8
%shl = and i32 %and1, 65280
%or = or i32 %shl, %and
ret i32 %or
}
define i32 @packh_i32_2(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: packh_i32_2:
; RV32I: # %bb.0:
; RV32I-NEXT: andi a0, a0, 255
; RV32I-NEXT: andi a1, a1, 255
; RV32I-NEXT: slli a1, a1, 8
; RV32I-NEXT: or a0, a1, a0
; RV32I-NEXT: ret
;
; RV32ZBP-ZBKB-LABEL: packh_i32_2:
; RV32ZBP-ZBKB: # %bb.0:
; RV32ZBP-ZBKB-NEXT: packh a0, a0, a1
; RV32ZBP-ZBKB-NEXT: ret
%and = and i32 %a, 255
%and1 = and i32 %b, 255
%shl = shl i32 %and1, 8
%or = or i32 %shl, %and
ret i32 %or
}
define i64 @packh_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: packh_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: andi a0, a0, 255
; RV32I-NEXT: slli a1, a2, 24
; RV32I-NEXT: srli a1, a1, 16
; RV32I-NEXT: or a0, a1, a0
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: ret
;
; RV32ZBP-ZBKB-LABEL: packh_i64:
; RV32ZBP-ZBKB: # %bb.0:
; RV32ZBP-ZBKB-NEXT: packh a0, a0, a2
; RV32ZBP-ZBKB-NEXT: li a1, 0
; RV32ZBP-ZBKB-NEXT: ret
%and = and i64 %a, 255
%and1 = shl i64 %b, 8
%shl = and i64 %and1, 65280
%or = or i64 %shl, %and
ret i64 %or
}
define i64 @packh_i64_2(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: packh_i64_2:
; RV32I: # %bb.0:
; RV32I-NEXT: andi a0, a0, 255
; RV32I-NEXT: andi a1, a2, 255
; RV32I-NEXT: slli a1, a1, 8
; RV32I-NEXT: or a0, a1, a0
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: ret
;
; RV32ZBP-ZBKB-LABEL: packh_i64_2:
; RV32ZBP-ZBKB: # %bb.0:
; RV32ZBP-ZBKB-NEXT: packh a0, a0, a2
; RV32ZBP-ZBKB-NEXT: li a1, 0
; RV32ZBP-ZBKB-NEXT: ret
%and = and i64 %a, 255
%and1 = and i64 %b, 255
%shl = shl i64 %and1, 8
%or = or i64 %shl, %and
ret i64 %or
}

View File

@ -2773,46 +2773,6 @@ define i64 @shfl8_i64(i64 %a, i64 %b) nounwind {
ret i64 %or3
}
define i32 @pack_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: pack_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: slli a0, a0, 16
; RV32I-NEXT: srli a0, a0, 16
; RV32I-NEXT: slli a1, a1, 16
; RV32I-NEXT: or a0, a1, a0
; RV32I-NEXT: ret
;
; RV32ZBP-LABEL: pack_i32:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: pack a0, a0, a1
; RV32ZBP-NEXT: ret
%shl = and i32 %a, 65535
%shl1 = shl i32 %b, 16
%or = or i32 %shl1, %shl
ret i32 %or
}
; As we are not matching directly i64 code patterns on RV32 some i64 patterns
; don't have yet any matching bit manipulation instructions on RV32.
; This test is presented here in case future expansions of the Bitmanip
; extensions introduce instructions suitable for this pattern.
define i64 @pack_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: pack_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: mv a1, a2
; RV32I-NEXT: ret
;
; RV32ZBP-LABEL: pack_i64:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: mv a1, a2
; RV32ZBP-NEXT: ret
%shl = and i64 %a, 4294967295
%shl1 = shl i64 %b, 32
%or = or i64 %shl1, %shl
ret i64 %or
}
define i32 @packu_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: packu_i32:
; RV32I: # %bb.0:
@ -2832,113 +2792,6 @@ define i32 @packu_i32(i32 %a, i32 %b) nounwind {
ret i32 %or
}
; As we are not matching directly i64 code patterns on RV32 some i64 patterns
; don't have yet any matching bit manipulation instructions on RV32.
; This test is presented here in case future expansions of the Bitmanip
; extensions introduce instructions suitable for this pattern.
define i64 @packu_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: packu_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: mv a0, a1
; RV32I-NEXT: mv a1, a3
; RV32I-NEXT: ret
;
; RV32ZBP-LABEL: packu_i64:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: mv a0, a1
; RV32ZBP-NEXT: mv a1, a3
; RV32ZBP-NEXT: ret
%shr = lshr i64 %a, 32
%shr1 = and i64 %b, -4294967296
%or = or i64 %shr1, %shr
ret i64 %or
}
define i32 @packh_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: packh_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: andi a0, a0, 255
; RV32I-NEXT: slli a1, a1, 24
; RV32I-NEXT: srli a1, a1, 16
; RV32I-NEXT: or a0, a1, a0
; RV32I-NEXT: ret
;
; RV32ZBP-LABEL: packh_i32:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: packh a0, a0, a1
; RV32ZBP-NEXT: ret
%and = and i32 %a, 255
%and1 = shl i32 %b, 8
%shl = and i32 %and1, 65280
%or = or i32 %shl, %and
ret i32 %or
}
define i32 @packh_i32_2(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: packh_i32_2:
; RV32I: # %bb.0:
; RV32I-NEXT: andi a0, a0, 255
; RV32I-NEXT: andi a1, a1, 255
; RV32I-NEXT: slli a1, a1, 8
; RV32I-NEXT: or a0, a1, a0
; RV32I-NEXT: ret
;
; RV32ZBP-LABEL: packh_i32_2:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: packh a0, a0, a1
; RV32ZBP-NEXT: ret
%and = and i32 %a, 255
%and1 = and i32 %b, 255
%shl = shl i32 %and1, 8
%or = or i32 %shl, %and
ret i32 %or
}
define i64 @packh_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: packh_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: andi a0, a0, 255
; RV32I-NEXT: slli a1, a2, 24
; RV32I-NEXT: srli a1, a1, 16
; RV32I-NEXT: or a0, a1, a0
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: ret
;
; RV32ZBP-LABEL: packh_i64:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: packh a0, a0, a2
; RV32ZBP-NEXT: li a1, 0
; RV32ZBP-NEXT: ret
%and = and i64 %a, 255
%and1 = shl i64 %b, 8
%shl = and i64 %and1, 65280
%or = or i64 %shl, %and
ret i64 %or
}
define i64 @packh_i64_2(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: packh_i64_2:
; RV32I: # %bb.0:
; RV32I-NEXT: andi a0, a0, 255
; RV32I-NEXT: andi a1, a2, 255
; RV32I-NEXT: slli a1, a1, 8
; RV32I-NEXT: or a0, a1, a0
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: ret
;
; RV32ZBP-LABEL: packh_i64_2:
; RV32ZBP: # %bb.0:
; RV32ZBP-NEXT: packh a0, a0, a2
; RV32ZBP-NEXT: li a1, 0
; RV32ZBP-NEXT: ret
%and = and i64 %a, 255
%and1 = and i64 %b, 255
%shl = shl i64 %and1, 8
%or = or i64 %shl, %and
ret i64 %or
}
define i32 @zexth_i32(i32 %a) nounwind {
; RV32I-LABEL: zexth_i32:
; RV32I: # %bb.0:

View File

@ -0,0 +1,25 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -mattr=+zknd -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32ZKND
declare i32 @llvm.riscv.aes32dsi(i32, i32, i8);
define i32 @aes32dsi(i32 %a, i32 %b) nounwind {
; RV32ZKND-LABEL: aes32dsi
; RV32ZKND: # %bb.0:
; RV32ZKND-NEXT: aes32dsi a0, a0, a1, 0
; RV32ZKND-NEXT: ret
%val = call i32 @llvm.riscv.aes32dsi(i32 %a, i32 %b, i8 0)
ret i32 %val
}
declare i32 @llvm.riscv.aes32dsmi(i32, i32, i8);
define i32 @aes32dsmi(i32 %a, i32 %b) nounwind {
; RV32ZKND-LABEL: aes32dsmi
; RV32ZKND: # %bb.0:
; RV32ZKND-NEXT: aes32dsmi a0, a0, a1, 1
; RV32ZKND-NEXT: ret
%val = call i32 @llvm.riscv.aes32dsmi(i32 %a, i32 %b, i8 1)
ret i32 %val
}

View File

@ -0,0 +1,25 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -mattr=+zkne -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32ZKNE
declare i32 @llvm.riscv.aes32esi(i32, i32, i8);
define i32 @aes32esi(i32 %a, i32 %b) nounwind {
; RV32ZKNE-LABEL: aes32esi
; RV32ZKNE: # %bb.0:
; RV32ZKNE-NEXT: aes32esi a0, a0, a1, 2
; RV32ZKNE-NEXT: ret
%val = call i32 @llvm.riscv.aes32esi(i32 %a, i32 %b, i8 2)
ret i32 %val
}
declare i32 @llvm.riscv.aes32esmi(i32, i32, i8);
define i32 @aes32esmi(i32 %a, i32 %b) nounwind {
; RV32ZKNE-LABEL: aes32esmi
; RV32ZKNE: # %bb.0:
; RV32ZKNE-NEXT: aes32esmi a0, a0, a1, 3
; RV32ZKNE-NEXT: ret
%val = call i32 @llvm.riscv.aes32esmi(i32 %a, i32 %b, i8 3)
ret i32 %val
}

View File

@ -0,0 +1,114 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -mattr=+zknh -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32ZKNH
declare i32 @llvm.riscv.sha256sig0.i32(i32);
define i32 @sha256sig0_i32(i32 %a) nounwind {
; RV32ZKNH-LABEL: sha256sig0_i32
; RV32ZKNH: # %bb.0:
; RV32ZKNH-NEXT: sha256sig0 a0, a0
; RV32ZKNH-NEXT: ret
%val = call i32 @llvm.riscv.sha256sig0.i32(i32 %a)
ret i32 %val
}
declare i32 @llvm.riscv.sha256sig1.i32(i32);
define i32 @sha256sig1_i32(i32 %a) nounwind {
; RV32ZKNH-LABEL: sha256sig1_i32
; RV32ZKNH: # %bb.0:
; RV32ZKNH-NEXT: sha256sig1 a0, a0
; RV32ZKNH-NEXT: ret
%val = call i32 @llvm.riscv.sha256sig1.i32(i32 %a)
ret i32 %val
}
declare i32 @llvm.riscv.sha256sum0.i32(i32);
define i32 @sha256sum0_i32(i32 %a) nounwind {
; RV32ZKNH-LABEL: sha256sum0_i32
; RV32ZKNH: # %bb.0:
; RV32ZKNH-NEXT: sha256sum0 a0, a0
; RV32ZKNH-NEXT: ret
%val = call i32 @llvm.riscv.sha256sum0.i32(i32 %a)
ret i32 %val
}
declare i32 @llvm.riscv.sha256sum1.i32(i32);
define i32 @sha256sum1_i32(i32 %a) nounwind {
; RV32ZKNH-LABEL: sha256sum1_i32
; RV32ZKNH: # %bb.0:
; RV32ZKNH-NEXT: sha256sum1 a0, a0
; RV32ZKNH-NEXT: ret
%val = call i32 @llvm.riscv.sha256sum1.i32(i32 %a)
ret i32 %val
}
declare i32 @llvm.riscv.sha512sig0l(i32, i32);
define i32 @sha512sig0l(i32 %a, i32 %b) nounwind {
; RV32ZKNH-LABEL: sha512sig0l
; RV32ZKNH: # %bb.0:
; RV32ZKNH-NEXT: sha512sig0l a0, a0, a1
; RV32ZKNH-NEXT: ret
%val = call i32 @llvm.riscv.sha512sig0l(i32 %a, i32 %b)
ret i32 %val
}
declare i32 @llvm.riscv.sha512sig0h(i32, i32);
define i32 @sha512sig0h(i32 %a, i32 %b) nounwind {
; RV32ZKNH-LABEL: sha512sig0h
; RV32ZKNH: # %bb.0:
; RV32ZKNH-NEXT: sha512sig0h a0, a0, a1
; RV32ZKNH-NEXT: ret
%val = call i32 @llvm.riscv.sha512sig0h(i32 %a, i32 %b)
ret i32 %val
}
declare i32 @llvm.riscv.sha512sig1l(i32, i32);
define i32 @sha512sig1l(i32 %a, i32 %b) nounwind {
; RV32ZKNH-LABEL: sha512sig1l
; RV32ZKNH: # %bb.0:
; RV32ZKNH-NEXT: sha512sig1l a0, a0, a1
; RV32ZKNH-NEXT: ret
%val = call i32 @llvm.riscv.sha512sig1l(i32 %a, i32 %b)
ret i32 %val
}
declare i32 @llvm.riscv.sha512sig1h(i32, i32);
define i32 @sha512sig1h(i32 %a, i32 %b) nounwind {
; RV32ZKNH-LABEL: sha512sig1h
; RV32ZKNH: # %bb.0:
; RV32ZKNH-NEXT: sha512sig1h a0, a0, a1
; RV32ZKNH-NEXT: ret
%val = call i32 @llvm.riscv.sha512sig1h(i32 %a, i32 %b)
ret i32 %val
}
declare i32 @llvm.riscv.sha512sum0r(i32, i32);
define i32 @sha512sum0r(i32 %a, i32 %b) nounwind {
; RV32ZKNH-LABEL: sha512sum0r
; RV32ZKNH: # %bb.0:
; RV32ZKNH-NEXT: sha512sum0r a0, a0, a1
; RV32ZKNH-NEXT: ret
%val = call i32 @llvm.riscv.sha512sum0r(i32 %a, i32 %b)
ret i32 %val
}
declare i32 @llvm.riscv.sha512sum1r(i32, i32);
define i32 @sha512sum1r(i32 %a, i32 %b) nounwind {
; RV32ZKNH-LABEL: sha512sum1r
; RV32ZKNH: # %bb.0:
; RV32ZKNH-NEXT: sha512sum1r a0, a0, a1
; RV32ZKNH-NEXT: ret
%val = call i32 @llvm.riscv.sha512sum1r(i32 %a, i32 %b)
ret i32 %val
}

View File

@ -0,0 +1,25 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -mattr=+zksed -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32ZKSED
declare i32 @llvm.riscv.sm4ks.i32(i32, i32, i8);
define i32 @sm4ks_i32(i32 %a, i32 %b) nounwind {
; RV32ZKSED-LABEL: sm4ks_i32:
; RV32ZKSED: # %bb.0:
; RV32ZKSED-NEXT: sm4ks a0, a0, a1, 2
; RV32ZKSED-NEXT: ret
%val = call i32 @llvm.riscv.sm4ks.i32(i32 %a, i32 %b, i8 2)
ret i32 %val
}
declare i32 @llvm.riscv.sm4ed.i32(i32, i32, i8);
define i32 @sm4ed_i32(i32 %a, i32 %b) nounwind {
; RV32ZKSED-LABEL: sm4ed_i32:
; RV32ZKSED: # %bb.0:
; RV32ZKSED-NEXT: sm4ed a0, a0, a1, 3
; RV32ZKSED-NEXT: ret
%val = call i32 @llvm.riscv.sm4ed.i32(i32 %a, i32 %b, i8 3)
ret i32 %val
}

View File

@ -0,0 +1,25 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -mattr=+zksh -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32ZKSH
declare i32 @llvm.riscv.sm3p0.i32(i32);
define i32 @sm3p0_i32(i32 %a) nounwind {
; RV32ZKSH-LABEL: sm3p0_i32:
; RV32ZKSH: # %bb.0:
; RV32ZKSH-NEXT: sm3p0 a0, a0
; RV32ZKSH-NEXT: ret
%val = call i32 @llvm.riscv.sm3p0.i32(i32 %a)
ret i32 %val
}
declare i32 @llvm.riscv.sm3p1.i32(i32);
define i32 @sm3p1_i32(i32 %a) nounwind {
; RV32ZKSH-LABEL: sm3p1_i32:
; RV32ZKSH: # %bb.0:
; RV32ZKSH-NEXT: sm3p1 a0, a0
; RV32ZKSH-NEXT: ret
%val = call i32 @llvm.riscv.sm3p1.i32(i32 %a)
ret i32 %val
}

View File

@ -1,10 +1,12 @@
; 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: | FileCheck %s -check-prefixes=RV64I
; RUN: llc -mtriple=riscv64 -mattr=+zbb -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZBB
; RUN: | FileCheck %s -check-prefixes=RV64ZBB-ZBP-ZBKB
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbp -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZBP
; RUN: | FileCheck %s -check-prefixes=RV64ZBB-ZBP-ZBKB
; RUN: llc -mtriple=riscv64 -mattr=+zbkb -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefixes=RV64ZBB-ZBP-ZBKB
define signext i32 @andn_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: andn_i32:
@ -13,15 +15,10 @@ define signext i32 @andn_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-NEXT: and a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: andn_i32:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: andn a0, a0, a1
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: andn_i32:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: andn a0, a0, a1
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: andn_i32:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: andn a0, a0, a1
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%neg = xor i32 %b, -1
%and = and i32 %neg, %a
ret i32 %and
@ -34,15 +31,10 @@ define i64 @andn_i64(i64 %a, i64 %b) nounwind {
; RV64I-NEXT: and a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: andn_i64:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: andn a0, a0, a1
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: andn_i64:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: andn a0, a0, a1
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: andn_i64:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: andn a0, a0, a1
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%neg = xor i64 %b, -1
%and = and i64 %neg, %a
ret i64 %and
@ -55,15 +47,10 @@ define signext i32 @orn_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: orn_i32:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: orn a0, a0, a1
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: orn_i32:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: orn a0, a0, a1
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: orn_i32:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: orn a0, a0, a1
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%neg = xor i32 %b, -1
%or = or i32 %neg, %a
ret i32 %or
@ -76,15 +63,10 @@ define i64 @orn_i64(i64 %a, i64 %b) nounwind {
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: orn_i64:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: orn a0, a0, a1
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: orn_i64:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: orn a0, a0, a1
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: orn_i64:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: orn a0, a0, a1
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%neg = xor i64 %b, -1
%or = or i64 %neg, %a
ret i64 %or
@ -97,15 +79,10 @@ define signext i32 @xnor_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: xnor_i32:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: xnor a0, a0, a1
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: xnor_i32:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: xnor a0, a0, a1
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: xnor_i32:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: xnor a0, a0, a1
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%neg = xor i32 %a, -1
%xor = xor i32 %neg, %b
ret i32 %xor
@ -118,15 +95,10 @@ define i64 @xnor_i64(i64 %a, i64 %b) nounwind {
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: xnor_i64:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: xnor a0, a0, a1
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: xnor_i64:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: xnor a0, a0, a1
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: xnor_i64:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: xnor a0, a0, a1
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%neg = xor i64 %a, -1
%xor = xor i64 %neg, %b
ret i64 %xor
@ -143,15 +115,10 @@ define signext i32 @rol_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-NEXT: or a0, a2, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: rol_i32:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: rolw a0, a0, a1
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: rol_i32:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: rolw a0, a0, a1
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: rol_i32:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: rolw a0, a0, a1
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 %b)
ret i32 %1
}
@ -167,17 +134,11 @@ define void @rol_i32_nosext(i32 signext %a, i32 signext %b, i32* %x) nounwind {
; RV64I-NEXT: sw a0, 0(a2)
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: rol_i32_nosext:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: rolw a0, a0, a1
; RV64ZBB-NEXT: sw a0, 0(a2)
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: rol_i32_nosext:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: rolw a0, a0, a1
; RV64ZBP-NEXT: sw a0, 0(a2)
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: rol_i32_nosext:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: rolw a0, a0, a1
; RV64ZBB-ZBP-ZBKB-NEXT: sw a0, 0(a2)
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 %b)
store i32 %1, i32* %x
ret void
@ -193,17 +154,11 @@ define signext i32 @rol_i32_neg_constant_rhs(i32 signext %a) nounwind {
; RV64I-NEXT: or a0, a2, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: rol_i32_neg_constant_rhs:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: li a1, -2
; RV64ZBB-NEXT: rolw a0, a1, a0
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: rol_i32_neg_constant_rhs:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: li a1, -2
; RV64ZBP-NEXT: rolw a0, a1, a0
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: rol_i32_neg_constant_rhs:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: li a1, -2
; RV64ZBB-ZBP-ZBKB-NEXT: rolw a0, a1, a0
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i32 @llvm.fshl.i32(i32 -2, i32 -2, i32 %a)
ret i32 %1
}
@ -219,15 +174,10 @@ define i64 @rol_i64(i64 %a, i64 %b) nounwind {
; RV64I-NEXT: or a0, a2, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: rol_i64:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: rol a0, a0, a1
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: rol_i64:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: rol a0, a0, a1
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: rol_i64:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: rol a0, a0, a1
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%or = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 %b)
ret i64 %or
}
@ -243,15 +193,10 @@ define signext i32 @ror_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-NEXT: or a0, a2, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: ror_i32:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: rorw a0, a0, a1
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: ror_i32:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: rorw a0, a0, a1
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: ror_i32:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: rorw a0, a0, a1
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 %b)
ret i32 %1
}
@ -267,17 +212,11 @@ define void @ror_i32_nosext(i32 signext %a, i32 signext %b, i32* %x) nounwind {
; RV64I-NEXT: sw a0, 0(a2)
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: ror_i32_nosext:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: rorw a0, a0, a1
; RV64ZBB-NEXT: sw a0, 0(a2)
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: ror_i32_nosext:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: rorw a0, a0, a1
; RV64ZBP-NEXT: sw a0, 0(a2)
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: ror_i32_nosext:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: rorw a0, a0, a1
; RV64ZBB-ZBP-ZBKB-NEXT: sw a0, 0(a2)
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 %b)
store i32 %1, i32* %x
ret void
@ -293,17 +232,11 @@ define signext i32 @ror_i32_neg_constant_rhs(i32 signext %a) nounwind {
; RV64I-NEXT: or a0, a2, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: ror_i32_neg_constant_rhs:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: li a1, -2
; RV64ZBB-NEXT: rorw a0, a1, a0
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: ror_i32_neg_constant_rhs:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: li a1, -2
; RV64ZBP-NEXT: rorw a0, a1, a0
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: ror_i32_neg_constant_rhs:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: li a1, -2
; RV64ZBB-ZBP-ZBKB-NEXT: rorw a0, a1, a0
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i32 @llvm.fshr.i32(i32 -2, i32 -2, i32 %a)
ret i32 %1
}
@ -319,15 +252,10 @@ define i64 @ror_i64(i64 %a, i64 %b) nounwind {
; RV64I-NEXT: or a0, a2, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: ror_i64:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: ror a0, a0, a1
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: ror_i64:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: ror a0, a0, a1
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: ror_i64:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: ror a0, a0, a1
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%or = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 %b)
ret i64 %or
}
@ -340,15 +268,10 @@ define signext i32 @rori_i32_fshl(i32 signext %a) nounwind {
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: rori_i32_fshl:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: roriw a0, a0, 1
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: rori_i32_fshl:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: roriw a0, a0, 1
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: rori_i32_fshl:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: roriw a0, a0, 1
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 31)
ret i32 %1
}
@ -363,17 +286,11 @@ define void @rori_i32_fshl_nosext(i32 signext %a, i32* %x) nounwind {
; RV64I-NEXT: sw a0, 0(a1)
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: rori_i32_fshl_nosext:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: roriw a0, a0, 1
; RV64ZBB-NEXT: sw a0, 0(a1)
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: rori_i32_fshl_nosext:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: roriw a0, a0, 1
; RV64ZBP-NEXT: sw a0, 0(a1)
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: rori_i32_fshl_nosext:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: roriw a0, a0, 1
; RV64ZBB-ZBP-ZBKB-NEXT: sw a0, 0(a1)
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 31)
store i32 %1, i32* %x
ret void
@ -387,15 +304,10 @@ define signext i32 @rori_i32_fshr(i32 signext %a) nounwind {
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: rori_i32_fshr:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: roriw a0, a0, 31
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: rori_i32_fshr:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: roriw a0, a0, 31
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: rori_i32_fshr:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: roriw a0, a0, 31
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 31)
ret i32 %1
}
@ -410,17 +322,11 @@ define void @rori_i32_fshr_nosext(i32 signext %a, i32* %x) nounwind {
; RV64I-NEXT: sw a0, 0(a1)
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: rori_i32_fshr_nosext:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: roriw a0, a0, 31
; RV64ZBB-NEXT: sw a0, 0(a1)
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: rori_i32_fshr_nosext:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: roriw a0, a0, 31
; RV64ZBP-NEXT: sw a0, 0(a1)
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: rori_i32_fshr_nosext:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: roriw a0, a0, 31
; RV64ZBB-ZBP-ZBKB-NEXT: sw a0, 0(a1)
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 31)
store i32 %1, i32* %x
ret void
@ -437,19 +343,12 @@ define signext i32 @not_rori_i32(i32 signext %x, i32 signext %y) nounwind {
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: not_rori_i32:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: slliw a0, a0, 31
; RV64ZBB-NEXT: srliw a1, a1, 1
; RV64ZBB-NEXT: or a0, a0, a1
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: not_rori_i32:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: slliw a0, a0, 31
; RV64ZBP-NEXT: srliw a1, a1, 1
; RV64ZBP-NEXT: or a0, a0, a1
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: not_rori_i32:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: slliw a0, a0, 31
; RV64ZBB-ZBP-ZBKB-NEXT: srliw a1, a1, 1
; RV64ZBB-ZBP-ZBKB-NEXT: or a0, a0, a1
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%a = shl i32 %x, 31
%b = lshr i32 %y, 1
%c = or i32 %a, %b
@ -470,25 +369,15 @@ define i64 @roriw_bug(i64 %x) nounwind {
; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: roriw_bug:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: slli a1, a0, 31
; RV64ZBB-NEXT: andi a0, a0, -2
; RV64ZBB-NEXT: srli a2, a0, 1
; RV64ZBB-NEXT: or a1, a1, a2
; RV64ZBB-NEXT: sext.w a1, a1
; RV64ZBB-NEXT: xor a0, a0, a1
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: roriw_bug:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: slli a1, a0, 31
; RV64ZBP-NEXT: andi a0, a0, -2
; RV64ZBP-NEXT: srli a2, a0, 1
; RV64ZBP-NEXT: or a1, a1, a2
; RV64ZBP-NEXT: sext.w a1, a1
; RV64ZBP-NEXT: xor a0, a0, a1
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: roriw_bug:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: slli a1, a0, 31
; RV64ZBB-ZBP-ZBKB-NEXT: andi a0, a0, -2
; RV64ZBB-ZBP-ZBKB-NEXT: srli a2, a0, 1
; RV64ZBB-ZBP-ZBKB-NEXT: or a1, a1, a2
; RV64ZBB-ZBP-ZBKB-NEXT: sext.w a1, a1
; RV64ZBB-ZBP-ZBKB-NEXT: xor a0, a0, a1
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%a = shl i64 %x, 31
%b = and i64 %x, 18446744073709551614
%c = lshr i64 %b, 1
@ -507,15 +396,10 @@ define i64 @rori_i64_fshl(i64 %a) nounwind {
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: rori_i64_fshl:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: rori a0, a0, 1
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: rori_i64_fshl:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: rori a0, a0, 1
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: rori_i64_fshl:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: rori a0, a0, 1
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 63)
ret i64 %1
}
@ -528,15 +412,10 @@ define i64 @rori_i64_fshr(i64 %a) nounwind {
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: rori_i64_fshr:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: rori a0, a0, 63
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: rori_i64_fshr:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: rori a0, a0, 63
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: rori_i64_fshr:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: rori a0, a0, 63
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 63)
ret i64 %1
}
@ -548,17 +427,11 @@ define i8 @srli_i8(i8 %a) nounwind {
; RV64I-NEXT: srli a0, a0, 62
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: srli_i8:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: slli a0, a0, 56
; RV64ZBB-NEXT: srli a0, a0, 62
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: srli_i8:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: slli a0, a0, 56
; RV64ZBP-NEXT: srli a0, a0, 62
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: srli_i8:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: slli a0, a0, 56
; RV64ZBB-ZBP-ZBKB-NEXT: srli a0, a0, 62
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = lshr i8 %a, 6
ret i8 %1
}
@ -572,17 +445,11 @@ define i8 @srai_i8(i8 %a) nounwind {
; RV64I-NEXT: srai a0, a0, 61
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: srai_i8:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: slli a0, a0, 56
; RV64ZBB-NEXT: srai a0, a0, 61
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: srai_i8:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: slli a0, a0, 56
; RV64ZBP-NEXT: srai a0, a0, 61
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: srai_i8:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: slli a0, a0, 56
; RV64ZBB-ZBP-ZBKB-NEXT: srai a0, a0, 61
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = ashr i8 %a, 5
ret i8 %1
}
@ -596,17 +463,11 @@ define i16 @srli_i16(i16 %a) nounwind {
; RV64I-NEXT: srli a0, a0, 54
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: srli_i16:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: slli a0, a0, 48
; RV64ZBB-NEXT: srli a0, a0, 54
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: srli_i16:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: slli a0, a0, 48
; RV64ZBP-NEXT: srli a0, a0, 54
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: srli_i16:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: slli a0, a0, 48
; RV64ZBB-ZBP-ZBKB-NEXT: srli a0, a0, 54
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = lshr i16 %a, 6
ret i16 %1
}
@ -620,17 +481,11 @@ define i16 @srai_i16(i16 %a) nounwind {
; RV64I-NEXT: srai a0, a0, 57
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: srai_i16:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: slli a0, a0, 48
; RV64ZBB-NEXT: srai a0, a0, 57
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: srai_i16:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: slli a0, a0, 48
; RV64ZBP-NEXT: srai a0, a0, 57
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: srai_i16:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: slli a0, a0, 48
; RV64ZBB-ZBP-ZBKB-NEXT: srai a0, a0, 57
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%1 = ashr i16 %a, 9
ret i16 %1
}
@ -643,17 +498,11 @@ define i1 @andn_seqz_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-NEXT: seqz a0, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: andn_seqz_i32:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: andn a0, a1, a0
; RV64ZBB-NEXT: seqz a0, a0
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: andn_seqz_i32:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: andn a0, a1, a0
; RV64ZBP-NEXT: seqz a0, a0
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: andn_seqz_i32:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: andn a0, a1, a0
; RV64ZBB-ZBP-ZBKB-NEXT: seqz a0, a0
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%and = and i32 %a, %b
%cmpeq = icmp eq i32 %and, %b
ret i1 %cmpeq
@ -667,17 +516,11 @@ define i1 @andn_seqz_i64(i64 %a, i64 %b) nounwind {
; RV64I-NEXT: seqz a0, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: andn_seqz_i64:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: andn a0, a1, a0
; RV64ZBB-NEXT: seqz a0, a0
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: andn_seqz_i64:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: andn a0, a1, a0
; RV64ZBP-NEXT: seqz a0, a0
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: andn_seqz_i64:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: andn a0, a1, a0
; RV64ZBB-ZBP-ZBKB-NEXT: seqz a0, a0
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%and = and i64 %a, %b
%cmpeq = icmp eq i64 %and, %b
ret i1 %cmpeq
@ -691,17 +534,11 @@ define i1 @andn_snez_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-NEXT: snez a0, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: andn_snez_i32:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: andn a0, a1, a0
; RV64ZBB-NEXT: snez a0, a0
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: andn_snez_i32:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: andn a0, a1, a0
; RV64ZBP-NEXT: snez a0, a0
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: andn_snez_i32:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: andn a0, a1, a0
; RV64ZBB-ZBP-ZBKB-NEXT: snez a0, a0
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%and = and i32 %a, %b
%cmpeq = icmp ne i32 %and, %b
ret i1 %cmpeq
@ -715,17 +552,11 @@ define i1 @andn_snez_i64(i64 %a, i64 %b) nounwind {
; RV64I-NEXT: snez a0, a0
; RV64I-NEXT: ret
;
; RV64ZBB-LABEL: andn_snez_i64:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: andn a0, a1, a0
; RV64ZBB-NEXT: snez a0, a0
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: andn_snez_i64:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: andn a0, a1, a0
; RV64ZBP-NEXT: snez a0, a0
; RV64ZBP-NEXT: ret
; RV64ZBB-ZBP-ZBKB-LABEL: andn_snez_i64:
; RV64ZBB-ZBP-ZBKB: # %bb.0:
; RV64ZBB-ZBP-ZBKB-NEXT: andn a0, a1, a0
; RV64ZBB-ZBP-ZBKB-NEXT: snez a0, a0
; RV64ZBB-ZBP-ZBKB-NEXT: ret
%and = and i64 %a, %b
%cmpeq = icmp ne i64 %and, %b
ret i1 %cmpeq

View File

@ -2,28 +2,6 @@
; RUN: llc -mtriple=riscv64 -mattr=+zbc -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZBC
declare i64 @llvm.riscv.clmul.i64(i64 %a, i64 %b)
define i64 @clmul64(i64 %a, i64 %b) nounwind {
; RV64ZBC-LABEL: clmul64:
; RV64ZBC: # %bb.0:
; RV64ZBC-NEXT: clmul a0, a0, a1
; RV64ZBC-NEXT: ret
%tmp = call i64 @llvm.riscv.clmul.i64(i64 %a, i64 %b)
ret i64 %tmp
}
declare i64 @llvm.riscv.clmulh.i64(i64 %a, i64 %b)
define i64 @clmul64h(i64 %a, i64 %b) nounwind {
; RV64ZBC-LABEL: clmul64h:
; RV64ZBC: # %bb.0:
; RV64ZBC-NEXT: clmulh a0, a0, a1
; RV64ZBC-NEXT: ret
%tmp = call i64 @llvm.riscv.clmulh.i64(i64 %a, i64 %b)
ret i64 %tmp
}
declare i64 @llvm.riscv.clmulr.i64(i64 %a, i64 %b)
define i64 @clmul64r(i64 %a, i64 %b) nounwind {

View File

@ -0,0 +1,28 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv64 -mattr=+zbc -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZBC-ZBKC
; RUN: llc -mtriple=riscv64 -mattr=+zbkc -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZBC-ZBKC
declare i64 @llvm.riscv.clmul.i64(i64 %a, i64 %b)
define i64 @clmul64(i64 %a, i64 %b) nounwind {
; RV64ZBC-ZBKC-LABEL: clmul64:
; RV64ZBC-ZBKC: # %bb.0:
; RV64ZBC-ZBKC-NEXT: clmul a0, a0, a1
; RV64ZBC-ZBKC-NEXT: ret
%tmp = call i64 @llvm.riscv.clmul.i64(i64 %a, i64 %b)
ret i64 %tmp
}
declare i64 @llvm.riscv.clmulh.i64(i64 %a, i64 %b)
define i64 @clmul64h(i64 %a, i64 %b) nounwind {
; RV64ZBC-ZBKC-LABEL: clmul64h:
; RV64ZBC-ZBKC: # %bb.0:
; RV64ZBC-ZBKC-NEXT: clmulh a0, a0, a1
; RV64ZBC-ZBKC-NEXT: ret
%tmp = call i64 @llvm.riscv.clmulh.i64(i64 %a, i64 %b)
ret i64 %tmp
}

View File

@ -0,0 +1,25 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv64 -mattr=+zbkb -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZBKB
declare i64 @llvm.riscv.brev8(i64)
define i64 @brev8(i64 %a) nounwind {
; RV64ZBKB-LABEL: brev8:
; RV64ZBKB: # %bb.0:
; RV64ZBKB-NEXT: brev8 a0, a0
; RV64ZBKB-NEXT: ret
%val = call i64 @llvm.riscv.brev8(i64 %a)
ret i64 %val
}
declare i64 @llvm.bswap.i64(i64)
define i64 @rev8_i64(i64 %a) {
; RV64ZBKB-LABEL: rev8_i64:
; RV64ZBKB: # %bb.0:
; RV64ZBKB-NEXT: rev8 a0, a0
; RV64ZBKB-NEXT: ret
%1 = call i64 @llvm.bswap.i64(i64 %a)
ret i64 %1
}

View File

@ -0,0 +1,24 @@
; RUN: llc -mtriple=riscv64 -mattr=+zbkx -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZBKX
declare i64 @llvm.riscv.xperm8.i64(i64 %a, i64 %b)
define i64 @xperm8(i64 %a, i64 %b) nounwind {
; RV64ZBKX-LABEL: xperm8:
; RV64ZBKX: # %bb.0:
; RV64ZBKX-NEXT: xperm8 a0, a0, a1
; RV64ZBKX-NEXT: ret
%tmp = call i64 @llvm.riscv.xperm8.i64(i64 %a, i64 %b)
ret i64 %tmp
}
declare i64 @llvm.riscv.xperm4.i64(i64 %a, i64 %b)
define i64 @xperm4(i64 %a, i64 %b) nounwind {
; RV64ZBKX-LABEL: xperm4:
; RV64ZBKX: # %bb.0:
; RV64ZBKX-NEXT: xperm4 a0, a0, a1
; RV64ZBKX-NEXT: ret
%tmp = call i64 @llvm.riscv.xperm4.i64(i64 %a, i64 %b)
ret i64 %tmp
}

View File

@ -0,0 +1,125 @@
; 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-zbp -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZBP-ZBKB
; RUN: llc -mtriple=riscv64 -mattr=+zbkb -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZBP-ZBKB
define signext i32 @pack_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: pack_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: slli a0, a0, 48
; RV64I-NEXT: srli a0, a0, 48
; RV64I-NEXT: slliw a1, a1, 16
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBP-ZBKB-LABEL: pack_i32:
; RV64ZBP-ZBKB: # %bb.0:
; RV64ZBP-ZBKB-NEXT: packw a0, a0, a1
; RV64ZBP-ZBKB-NEXT: ret
%shl = and i32 %a, 65535
%shl1 = shl i32 %b, 16
%or = or i32 %shl1, %shl
ret i32 %or
}
define i64 @pack_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: pack_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: slli a0, a0, 32
; RV64I-NEXT: srli a0, a0, 32
; RV64I-NEXT: slli a1, a1, 32
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBP-ZBKB-LABEL: pack_i64:
; RV64ZBP-ZBKB: # %bb.0:
; RV64ZBP-ZBKB-NEXT: pack a0, a0, a1
; RV64ZBP-ZBKB-NEXT: ret
%shl = and i64 %a, 4294967295
%shl1 = shl i64 %b, 32
%or = or i64 %shl1, %shl
ret i64 %or
}
define signext i32 @packh_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: packh_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: andi a0, a0, 255
; RV64I-NEXT: slli a1, a1, 56
; RV64I-NEXT: srli a1, a1, 48
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBP-ZBKB-LABEL: packh_i32:
; RV64ZBP-ZBKB: # %bb.0:
; RV64ZBP-ZBKB-NEXT: packh a0, a0, a1
; RV64ZBP-ZBKB-NEXT: ret
%and = and i32 %a, 255
%and1 = shl i32 %b, 8
%shl = and i32 %and1, 65280
%or = or i32 %shl, %and
ret i32 %or
}
define i32 @packh_i32_2(i32 %a, i32 %b) nounwind {
; RV64I-LABEL: packh_i32_2:
; RV64I: # %bb.0:
; RV64I-NEXT: andi a0, a0, 255
; RV64I-NEXT: andi a1, a1, 255
; RV64I-NEXT: slli a1, a1, 8
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBP-ZBKB-LABEL: packh_i32_2:
; RV64ZBP-ZBKB: # %bb.0:
; RV64ZBP-ZBKB-NEXT: packh a0, a0, a1
; RV64ZBP-ZBKB-NEXT: ret
%and = and i32 %a, 255
%and1 = and i32 %b, 255
%shl = shl i32 %and1, 8
%or = or i32 %shl, %and
ret i32 %or
}
define i64 @packh_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: packh_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: andi a0, a0, 255
; RV64I-NEXT: slli a1, a1, 56
; RV64I-NEXT: srli a1, a1, 48
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBP-ZBKB-LABEL: packh_i64:
; RV64ZBP-ZBKB: # %bb.0:
; RV64ZBP-ZBKB-NEXT: packh a0, a0, a1
; RV64ZBP-ZBKB-NEXT: ret
%and = and i64 %a, 255
%and1 = shl i64 %b, 8
%shl = and i64 %and1, 65280
%or = or i64 %shl, %and
ret i64 %or
}
define i64 @packh_i64_2(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: packh_i64_2:
; RV64I: # %bb.0:
; RV64I-NEXT: andi a0, a0, 255
; RV64I-NEXT: andi a1, a1, 255
; RV64I-NEXT: slli a1, a1, 8
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBP-ZBKB-LABEL: packh_i64_2:
; RV64ZBP-ZBKB: # %bb.0:
; RV64ZBP-ZBKB-NEXT: packh a0, a0, a1
; RV64ZBP-ZBKB-NEXT: ret
%and = and i64 %a, 255
%and1 = and i64 %b, 255
%shl = shl i64 %and1, 8
%or = or i64 %shl, %and
ret i64 %or
}

View File

@ -2713,44 +2713,6 @@ define i64 @shfl16(i64 %a, i64 %b) nounwind {
ret i64 %or3
}
define signext i32 @pack_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: pack_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: slli a0, a0, 48
; RV64I-NEXT: srli a0, a0, 48
; RV64I-NEXT: slliw a1, a1, 16
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBP-LABEL: pack_i32:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: packw a0, a0, a1
; RV64ZBP-NEXT: ret
%shl = and i32 %a, 65535
%shl1 = shl i32 %b, 16
%or = or i32 %shl1, %shl
ret i32 %or
}
define i64 @pack_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: pack_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: slli a0, a0, 32
; RV64I-NEXT: srli a0, a0, 32
; RV64I-NEXT: slli a1, a1, 32
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBP-LABEL: pack_i64:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: pack a0, a0, a1
; RV64ZBP-NEXT: ret
%shl = and i64 %a, 4294967295
%shl1 = shl i64 %b, 32
%or = or i64 %shl1, %shl
ret i64 %or
}
define signext i32 @packu_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: packu_i32:
; RV64I: # %bb.0:
@ -2790,86 +2752,6 @@ define i64 @packu_i64(i64 %a, i64 %b) nounwind {
ret i64 %or
}
define signext i32 @packh_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: packh_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: andi a0, a0, 255
; RV64I-NEXT: slli a1, a1, 56
; RV64I-NEXT: srli a1, a1, 48
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBP-LABEL: packh_i32:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: packh a0, a0, a1
; RV64ZBP-NEXT: ret
%and = and i32 %a, 255
%and1 = shl i32 %b, 8
%shl = and i32 %and1, 65280
%or = or i32 %shl, %and
ret i32 %or
}
define i32 @packh_i32_2(i32 %a, i32 %b) nounwind {
; RV64I-LABEL: packh_i32_2:
; RV64I: # %bb.0:
; RV64I-NEXT: andi a0, a0, 255
; RV64I-NEXT: andi a1, a1, 255
; RV64I-NEXT: slli a1, a1, 8
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBP-LABEL: packh_i32_2:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: packh a0, a0, a1
; RV64ZBP-NEXT: ret
%and = and i32 %a, 255
%and1 = and i32 %b, 255
%shl = shl i32 %and1, 8
%or = or i32 %shl, %and
ret i32 %or
}
define i64 @packh_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: packh_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: andi a0, a0, 255
; RV64I-NEXT: slli a1, a1, 56
; RV64I-NEXT: srli a1, a1, 48
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBP-LABEL: packh_i64:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: packh a0, a0, a1
; RV64ZBP-NEXT: ret
%and = and i64 %a, 255
%and1 = shl i64 %b, 8
%shl = and i64 %and1, 65280
%or = or i64 %shl, %and
ret i64 %or
}
define i64 @packh_i64_2(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: packh_i64_2:
; RV64I: # %bb.0:
; RV64I-NEXT: andi a0, a0, 255
; RV64I-NEXT: andi a1, a1, 255
; RV64I-NEXT: slli a1, a1, 8
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64ZBP-LABEL: packh_i64_2:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: packh a0, a0, a1
; RV64ZBP-NEXT: ret
%and = and i64 %a, 255
%and1 = and i64 %b, 255
%shl = shl i64 %and1, 8
%or = or i64 %shl, %and
ret i64 %or
}
define i32 @zexth_i32(i32 %a) nounwind {
; RV64I-LABEL: zexth_i32:
; RV64I: # %bb.0:

View File

@ -0,0 +1,36 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv64 -mattr=+zknd -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZKND
declare i64 @llvm.riscv.aes64ds(i64, i64);
define i64 @aes64ds(i64 %a, i64 %b) nounwind {
; RV64ZKND-LABEL: aes64ds
; RV64ZKND: # %bb.0:
; RV64ZKND-NEXT: aes64ds a0, a0, a1
; RV64ZKND-NEXT: ret
%val = call i64 @llvm.riscv.aes64ds(i64 %a, i64 %b)
ret i64 %val
}
declare i64 @llvm.riscv.aes64dsm(i64, i64);
define i64 @aes64dsm(i64 %a, i64 %b) nounwind {
; RV64ZKND-LABEL: aes64dsm
; RV64ZKND: # %bb.0:
; RV64ZKND-NEXT: aes64dsm a0, a0, a1
; RV64ZKND-NEXT: ret
%val = call i64 @llvm.riscv.aes64dsm(i64 %a, i64 %b)
ret i64 %val
}
declare i64 @llvm.riscv.aes64im(i64);
define i64 @aes64im(i64 %a) nounwind {
; RV64ZKND-LABEL: aes64im
; RV64ZKND: # %bb.0:
; RV64ZKND-NEXT: aes64im a0, a0
; RV64ZKND-NEXT: ret
%val = call i64 @llvm.riscv.aes64im(i64 %a)
ret i64 %val
}

View File

@ -0,0 +1,28 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv64 -mattr=+zknd -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZKND-ZKNE
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv64 -mattr=+zkne -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZKND-ZKNE
declare i64 @llvm.riscv.aes64ks2(i64, i64);
define i64 @aes64ks2(i64 %a, i64 %b) nounwind {
; RV64ZKND-ZKNE-LABEL: aes64ks2
; RV64ZKND-ZKNE: # %bb.0:
; RV64ZKND-ZKNE-NEXT: aes64ks2 a0, a0, a1
; RV64ZKND-ZKNE-NEXT: ret
%val = call i64 @llvm.riscv.aes64ks2(i64 %a, i64 %b)
ret i64 %val
}
declare i64 @llvm.riscv.aes64ks1i(i64, i32);
define i64 @aes64ks1i(i64 %a) nounwind {
; RV64ZKND-ZKNE-LABEL: aes64ks1i
; RV64ZKND-ZKNE: # %bb.0:
; RV64ZKND-ZKNE-NEXT: aes64ks1i a0, a0, 10
; RV64ZKND-ZKNE-NEXT: ret
%val = call i64 @llvm.riscv.aes64ks1i(i64 %a, i32 10)
ret i64 %val
}

View File

@ -0,0 +1,25 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv64 -mattr=+zkne -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZKNE
declare i64 @llvm.riscv.aes64es(i64, i64);
define i64 @aes64es(i64 %a, i64 %b) nounwind {
; RV64ZKNE-LABEL: aes64es
; RV64ZKNE: # %bb.0:
; RV64ZKNE-NEXT: aes64es a0, a0, a1
; RV64ZKNE-NEXT: ret
%val = call i64 @llvm.riscv.aes64es(i64 %a, i64 %b)
ret i64 %val
}
declare i64 @llvm.riscv.aes64esm(i64, i64);
define i64 @aes64esm(i64 %a, i64 %b) nounwind {
; RV64ZKNE-LABEL: aes64esm
; RV64ZKNE: # %bb.0:
; RV64ZKNE-NEXT: aes64esm a0, a0, a1
; RV64ZKNE-NEXT: ret
%val = call i64 @llvm.riscv.aes64esm(i64 %a, i64 %b)
ret i64 %val
}

View File

@ -0,0 +1,92 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv64 -mattr=+zknh -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZKNH
declare i64 @llvm.riscv.sha256sig0.i64(i64);
define i64 @sha256sig0_i64(i64 %a) nounwind {
; RV64ZKNH-LABEL: sha256sig0_i64
; RV64ZKNH: # %bb.0:
; RV64ZKNH-NEXT: sha256sig0 a0, a0
; RV64ZKNH-NEXT: ret
%val = call i64 @llvm.riscv.sha256sig0.i64(i64 %a)
ret i64 %val
}
declare i64 @llvm.riscv.sha256sig1.i64(i64);
define i64 @sha256sig1_i64(i64 %a) nounwind {
; RV64ZKNH-LABEL: sha256sig1_i64
; RV64ZKNH: # %bb.0:
; RV64ZKNH-NEXT: sha256sig1 a0, a0
; RV64ZKNH-NEXT: ret
%val = call i64 @llvm.riscv.sha256sig1.i64(i64 %a)
ret i64 %val
}
declare i64 @llvm.riscv.sha256sum0.i64(i64);
define i64 @sha256sum0_i64(i64 %a) nounwind {
; RV64ZKNH-LABEL: sha256sum0_i64
; RV64ZKNH: # %bb.0:
; RV64ZKNH-NEXT: sha256sum0 a0, a0
; RV64ZKNH-NEXT: ret
%val = call i64 @llvm.riscv.sha256sum0.i64(i64 %a)
ret i64 %val
}
declare i64 @llvm.riscv.sha256sum1.i64(i64);
define i64 @sha256sum1_i64(i64 %a) nounwind {
; RV64ZKNH-LABEL: sha256sum1_i64
; RV64ZKNH: # %bb.0:
; RV64ZKNH-NEXT: sha256sum1 a0, a0
; RV64ZKNH-NEXT: ret
%val = call i64 @llvm.riscv.sha256sum1.i64(i64 %a)
ret i64 %val
}
declare i64 @llvm.riscv.sha512sig0(i64);
define i64 @sha512sig0(i64 %a) nounwind {
; RV64ZKNH-LABEL: sha512sig0
; RV64ZKNH: # %bb.0:
; RV64ZKNH-NEXT: sha512sig0 a0, a0
; RV64ZKNH-NEXT: ret
%val = call i64 @llvm.riscv.sha512sig0(i64 %a)
ret i64 %val
}
declare i64 @llvm.riscv.sha512sig1(i64);
define i64 @sha512sig1(i64 %a) nounwind {
; RV64ZKNH-LABEL: sha512sig1
; RV64ZKNH: # %bb.0:
; RV64ZKNH-NEXT: sha512sig1 a0, a0
; RV64ZKNH-NEXT: ret
%val = call i64 @llvm.riscv.sha512sig1(i64 %a)
ret i64 %val
}
declare i64 @llvm.riscv.sha512sum0(i64);
define i64 @sha512sum0(i64 %a) nounwind {
; RV64ZKNH-LABEL: sha512sum0
; RV64ZKNH: # %bb.0:
; RV64ZKNH-NEXT: sha512sum0 a0, a0
; RV64ZKNH-NEXT: ret
%val = call i64 @llvm.riscv.sha512sum0(i64 %a)
ret i64 %val
}
declare i64 @llvm.riscv.sha512sum1(i64);
define i64 @sha512sum1(i64 %a) nounwind {
; RV64ZKNH-LABEL: sha512sum1
; RV64ZKNH: # %bb.0:
; RV64ZKNH-NEXT: sha512sum1 a0, a0
; RV64ZKNH-NEXT: ret
%val = call i64 @llvm.riscv.sha512sum1(i64 %a)
ret i64 %val
}

View File

@ -0,0 +1,25 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv64 -mattr=+zksed -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZKSED
declare i64 @llvm.riscv.sm4ks.i64(i64, i64, i8);
define i64 @sm4ks_i64(i64 %a, i64 %b) nounwind {
; RV64ZKSED-LABEL: sm4ks_i64:
; RV64ZKSED: # %bb.0:
; RV64ZKSED-NEXT: sm4ks a0, a0, a1, 0
; RV64ZKSED-NEXT: ret
%val = call i64 @llvm.riscv.sm4ks.i64(i64 %a, i64 %b, i8 0)
ret i64 %val
}
declare i64 @llvm.riscv.sm4ed.i64(i64, i64, i8);
define i64 @sm4ed_i64(i64 %a, i64 %b) nounwind {
; RV64ZKSED-LABEL: sm4ed_i64:
; RV64ZKSED: # %bb.0:
; RV64ZKSED-NEXT: sm4ed a0, a0, a1, 1
; RV64ZKSED-NEXT: ret
%val = call i64 @llvm.riscv.sm4ed.i64(i64 %a, i64 %b, i8 1)
ret i64 %val
}

View File

@ -0,0 +1,25 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv64 -mattr=+zksh -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZKSH
declare i64 @llvm.riscv.sm3p0.i64(i64);
define i64 @sm3p0_i64(i64 %a) nounwind {
; RV64ZKSH-LABEL: sm3p0_i64:
; RV64ZKSH: # %bb.0:
; RV64ZKSH-NEXT: sm3p0 a0, a0
; RV64ZKSH-NEXT: ret
%val = call i64 @llvm.riscv.sm3p0.i64(i64 %a)
ret i64 %val
}
declare i64 @llvm.riscv.sm3p1.i64(i64);
define i64 @sm3p1_i64(i64 %a) nounwind {
; RV64ZKSH-LABEL: sm3p1_i64:
; RV64ZKSH: # %bb.0:
; RV64ZKSH-NEXT: sm3p1 a0, a0
; RV64ZKSH-NEXT: ret
%val = call i64 @llvm.riscv.sm3p1.i64(i64 %a)
ret i64 %val
}