Skip to content

Commit

Permalink
[RISCV] Implement intrinsics for XCVbitmanip extension in CV32E40P (#…
Browse files Browse the repository at this point in the history
…74993)

Implement XCVbitmanip intrinsics for CV32E40P according to the
specification.

This commit is part of a patch-set to upstream the vendor specific
extensions of CV32E40P that need LLVM intrinsics to implement Clang
builtins.

Contributors: @CharKeaney, @ChunyuLiao, @jeremybennett, @lewis-revill,
@NandniJamnadas, @PaoloS02, @simonpcook, @xingmingjie.

Spec:
https://github.com/openhwgroup/core-v-sw/blob/05481cf0ef7aa7b09067b14ff3f71faead7ba310/specifications/corev-builtin-spec.md#listing-of-pulp-bit-manipulation-builtins-xcvbitmanip.

Previously reviewed on Phabricator: https://reviews.llvm.org/D157510.
Parallel GCC patch:
https://gcc.gnu.org/pipermail/gcc-patches/2023-November/635795.html.

Co-authored-by: melonedo <funanzeng@gmail.com>
  • Loading branch information
melonedo and melonedo authored Dec 17, 2023
1 parent 3a1ae2f commit 3eaed9e
Show file tree
Hide file tree
Showing 6 changed files with 335 additions and 9 deletions.
1 change: 1 addition & 0 deletions llvm/include/llvm/IR/IntrinsicsRISCV.td
Original file line number Diff line number Diff line change
Expand Up @@ -1879,3 +1879,4 @@ let TargetPrefix = "riscv" in {
//===----------------------------------------------------------------------===//
include "llvm/IR/IntrinsicsRISCVXTHead.td"
include "llvm/IR/IntrinsicsRISCVXsf.td"
include "llvm/IR/IntrinsicsRISCVXCV.td"
37 changes: 37 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsRISCVXCV.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//===- IntrinsicsRISCVXCV.td - CORE-V intrinsics -----------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines all of the CORE-V vendor intrinsics for RISC-V.
//
//===----------------------------------------------------------------------===//

class ScalarCoreVBitManipGprGprIntrinsic
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, IntrSpeculatable]>;

class ScalarCoreVBitManipGprIntrinsic
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty],
[IntrNoMem, IntrSpeculatable]>;

let TargetPrefix = "riscv" in {
def int_riscv_cv_bitmanip_extract : ScalarCoreVBitManipGprGprIntrinsic;
def int_riscv_cv_bitmanip_extractu : ScalarCoreVBitManipGprGprIntrinsic;
def int_riscv_cv_bitmanip_bclr : ScalarCoreVBitManipGprGprIntrinsic;
def int_riscv_cv_bitmanip_bset : ScalarCoreVBitManipGprGprIntrinsic;

def int_riscv_cv_bitmanip_insert
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, IntrSpeculatable]>;

def int_riscv_cv_bitmanip_clb : ScalarCoreVBitManipGprIntrinsic;

def int_riscv_cv_bitmanip_bitrev
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, IntrWillReturn, IntrSpeculatable,
ImmArg<ArgIndex<1>>, ImmArg<ArgIndex<2>>]>;
} // TargetPrefix = "riscv"
23 changes: 16 additions & 7 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
if (Subtarget.is64Bit())
setOperationAction({ISD::ROTL, ISD::ROTR}, MVT::i32, Custom);
setOperationAction({ISD::ROTL, ISD::ROTR}, XLenVT, Custom);
} else if (Subtarget.hasVendorXCVbitmanip()) {
setOperationAction({ISD::ROTL}, XLenVT, Expand);
} else {
setOperationAction({ISD::ROTL, ISD::ROTR}, XLenVT, Expand);
if (RV64LegalI32 && Subtarget.is64Bit())
Expand All @@ -355,9 +357,14 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
? Promote
: Expand);

// Zbkb can use rev8+brev8 to implement bitreverse.
setOperationAction(ISD::BITREVERSE, XLenVT,
Subtarget.hasStdExtZbkb() ? Custom : Expand);

if (Subtarget.hasVendorXCVbitmanip()) {
setOperationAction(ISD::BITREVERSE, XLenVT, Legal);
} else {
// Zbkb can use rev8+brev8 to implement bitreverse.
setOperationAction(ISD::BITREVERSE, XLenVT,
Subtarget.hasStdExtZbkb() ? Custom : Expand);
}

if (Subtarget.hasStdExtZbb()) {
setOperationAction({ISD::SMIN, ISD::SMAX, ISD::UMIN, ISD::UMAX}, XLenVT,
Expand All @@ -372,13 +379,14 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
else
setOperationAction({ISD::CTTZ, ISD::CTTZ_ZERO_UNDEF}, MVT::i32, Custom);
}
} else {
} else if (!Subtarget.hasVendorXCVbitmanip()) {
setOperationAction({ISD::CTTZ, ISD::CTPOP}, XLenVT, Expand);
if (RV64LegalI32 && Subtarget.is64Bit())
setOperationAction({ISD::CTTZ, ISD::CTPOP}, MVT::i32, Expand);
}

if (Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb()) {
if (Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() ||
Subtarget.hasVendorXCVbitmanip()) {
// We need the custom lowering to make sure that the resulting sequence
// for the 32bit case is efficient on 64bit targets.
if (Subtarget.is64Bit()) {
Expand Down Expand Up @@ -1796,11 +1804,12 @@ bool RISCVTargetLowering::signExtendConstant(const ConstantInt *CI) const {
}

bool RISCVTargetLowering::isCheapToSpeculateCttz(Type *Ty) const {
return Subtarget.hasStdExtZbb();
return Subtarget.hasStdExtZbb() || Subtarget.hasVendorXCVbitmanip();
}

bool RISCVTargetLowering::isCheapToSpeculateCtlz(Type *Ty) const {
return Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb();
return Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() ||
Subtarget.hasVendorXCVbitmanip();
}

bool RISCVTargetLowering::isMaskAndCmp0FoldingBeneficial(
Expand Down
48 changes: 47 additions & 1 deletion llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ let DecoderNamespace = "XCVbitmanip" in {

class CVBitManipR<bits<7> funct7, string opcodestr>
: RVInstR<funct7, 0b011, OPC_CUSTOM_1, (outs GPR:$rd),
(ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1"> {
(ins GPR:$rs1), opcodestr, "$rd, $rs1"> {
let rs2 = 0b00000;
}
}
Expand Down Expand Up @@ -658,3 +658,49 @@ let Predicates = [HasVendorXCVelw, IsRV32], hasSideEffects = 0,
// Event load
def CV_ELW : CVLoad_ri<0b011, "cv.elw">;
}

def cv_tuimm2 : TImmLeaf<XLenVT, [{return isUInt<2>(Imm);}]>;
def cv_tuimm5 : TImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]>;
def cv_uimm10 : ImmLeaf<XLenVT, [{return isUInt<10>(Imm);}]>;

def CV_LO5: SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(N->getZExtValue() & 0x1f, SDLoc(N),
N->getValueType(0));
}]>;

def CV_HI5: SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(N->getZExtValue() >> 5, SDLoc(N),
N->getValueType(0));
}]>;

multiclass PatCoreVBitManip<Intrinsic intr> {
def : PatGprGpr<intr, !cast<RVInst>("CV_" # NAME # "R")>;
def : Pat<(intr GPR:$rs1, cv_uimm10:$imm),
(!cast<RVInst>("CV_" # NAME)
GPR:$rs1, (CV_HI5 cv_uimm10:$imm), (CV_LO5 cv_uimm10:$imm))>;
}

let Predicates = [HasVendorXCVbitmanip, IsRV32] in {
defm EXTRACT : PatCoreVBitManip<int_riscv_cv_bitmanip_extract>;
defm EXTRACTU : PatCoreVBitManip<int_riscv_cv_bitmanip_extractu>;
defm BCLR : PatCoreVBitManip<int_riscv_cv_bitmanip_bclr>;
defm BSET : PatCoreVBitManip<int_riscv_cv_bitmanip_bset>;

def : Pat<(int_riscv_cv_bitmanip_insert GPR:$rs1, GPR:$rs2, GPR:$rd),
(CV_INSERTR GPR:$rd, GPR:$rs1, GPR:$rs2)>;
def : Pat<(int_riscv_cv_bitmanip_insert GPR:$rs1, cv_uimm10:$imm, GPR:$rd),
(CV_INSERT GPR:$rd, GPR:$rs1, (CV_HI5 cv_uimm10:$imm),
(CV_LO5 cv_uimm10:$imm))>;

def : PatGpr<cttz, CV_FF1>;
def : PatGpr<ctlz, CV_FL1>;
def : PatGpr<int_riscv_cv_bitmanip_clb, CV_CLB>;
def : PatGpr<ctpop, CV_CNT>;

def : PatGprGpr<rotr, CV_ROR>;

def : Pat<(int_riscv_cv_bitmanip_bitrev GPR:$rs1, cv_tuimm5:$pts,
cv_tuimm2:$radix),
(CV_BITREV GPR:$rs1, cv_tuimm2:$radix, cv_tuimm5:$pts)>;
def : Pat<(bitreverse (XLenVT GPR:$rs)), (CV_BITREV GPR:$rs, 0, 0)>;
}
4 changes: 3 additions & 1 deletion llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,9 @@ RISCVTTIImpl::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx,
TargetTransformInfo::PopcntSupportKind
RISCVTTIImpl::getPopcntSupport(unsigned TyWidth) {
assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2");
return ST->hasStdExtZbb() ? TTI::PSK_FastHardware : TTI::PSK_Software;
return ST->hasStdExtZbb() || ST->hasVendorXCVbitmanip()
? TTI::PSK_FastHardware
: TTI::PSK_Software;
}

bool RISCVTTIImpl::shouldExpandReduction(const IntrinsicInst *II) const {
Expand Down
Loading

0 comments on commit 3eaed9e

Please sign in to comment.