Skip to content

Commit

Permalink
[RISCV] Add vendor-defined XTHeadBs (single-bit) extension
Browse files Browse the repository at this point in the history
The vendor-defined XTHeadBs (predating the standard Zbs extension)
extension adds a bit-test instruction (th.tst) with similar semantics
as bexti from Zbs.  It is supported by the C9xx cores (e.g., found in
the wild in the Allwinner D1) by Alibaba T-Head.

The current (as of this commit) public documentation for XTHeadBs is
available from:
  https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.2.2/xthead-2023-01-30-2.2.2.pdf

Support for these instructions has already landed in GNU Binutils:
  https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=8254c3d2c94ae5458095ea6c25446ba89134b9da

Depends on D143394

Differential Revision: https://reviews.llvm.org/D143036
  • Loading branch information
ptomsich committed Feb 8, 2023
1 parent 3304d51 commit 656188d
Show file tree
Hide file tree
Showing 15 changed files with 439 additions and 8 deletions.
3 changes: 3 additions & 0 deletions llvm/docs/RISCVUsage.rst
Expand Up @@ -172,6 +172,9 @@ The current vendor extensions supported are:
``XTHeadBa``
LLVM implements `the THeadBa (address-generation) vendor-defined instructions specified in <https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.2.2/xthead-2023-01-30-2.2.2.pdf>`_ by T-HEAD of Alibaba. Instructions are prefixed with `th.` as described in the specification.

``XTHeadBs``
LLVM implements `the THeadBs (single-bit operations) vendor-defined instructions specified in <https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.2.2/xthead-2023-01-30-2.2.2.pdf>`_ by T-HEAD of Alibaba. Instructions are prefixed with `th.` as described in the specification.

``XTHeadVdot``
LLVM implements `version 1.0.0 of the THeadV-family custom instructions specification <https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.2.0/xthead-2022-12-04-2.2.0.pdf>`_ by T-HEAD of Alibaba. All instructions are prefixed with `th.` as described in the specification, and the riscv-toolchain-convention document linked above.

Expand Down
1 change: 1 addition & 0 deletions llvm/docs/ReleaseNotes.rst
Expand Up @@ -109,6 +109,7 @@ Changes to the RISC-V Backend
* vsetvli intrinsics no longer have side effects. They may now be combined,
moved, deleted, etc. by optimizations.
* Adds support for the vendor-defined XTHeadBa (address-generation) extension.
* Adds support for the vendor-defined XTHeadBs (single-bit) extension.

Changes to the WebAssembly Backend
----------------------------------
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Support/RISCVISAInfo.cpp
Expand Up @@ -110,6 +110,7 @@ static const RISCVSupportedExtension SupportedExtensions[] = {

// vendor-defined ('X') extensions
{"xtheadba", RISCVExtensionVersion{1, 0}},
{"xtheadbs", RISCVExtensionVersion{1, 0}},
{"xtheadvdot", RISCVExtensionVersion{1, 0}},
{"xventanacondops", RISCVExtensionVersion{1, 0}},
};
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
Expand Up @@ -478,6 +478,13 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
if (Result != MCDisassembler::Fail)
return Result;
}
if (STI.getFeatureBits()[RISCV::FeatureVendorXTHeadBs]) {
LLVM_DEBUG(dbgs() << "Trying XTHeadBs custom opcode table:\n");
Result = decodeInstruction(DecoderTableTHeadBs32, MI, Insn, Address, this,
STI);
if (Result != MCDisassembler::Fail)
return Result;
}
if (STI.getFeatureBits()[RISCV::FeatureVendorXTHeadVdot]) {
LLVM_DEBUG(dbgs() << "Trying XTHeadVdot custom opcode table:\n");
Result =
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/RISCV/RISCVFeatures.td
Expand Up @@ -470,6 +470,13 @@ def HasVendorXTHeadBa : Predicate<"Subtarget->hasVendorXTHeadBa()">,
AssemblerPredicate<(all_of FeatureVendorXTHeadBa),
"'xtheadba' (T-Head address calculation instructions)">;

def FeatureVendorXTHeadBs
: SubtargetFeature<"xtheadbs", "HasVendorXTHeadBs", "true",
"'xtheadbs' (T-Head single-bit instructions)">;
def HasVendorXTHeadBs : Predicate<"Subtarget->hasVendorXTHeadBs()">,
AssemblerPredicate<(all_of FeatureVendorXTHeadBs),
"'xtheadbs' (T-Head single-bit instructions)">;

def FeatureVendorXTHeadVdot
: SubtargetFeature<"xtheadvdot", "HasVendorXTHeadVdot", "true",
"'xtheadvdot' (T-Head Vector Extensions for Dot)",
Expand Down
16 changes: 10 additions & 6 deletions llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
Expand Up @@ -834,14 +834,17 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
if (!N0.hasOneUse())
break;

// If C2 is (1 << ShAmt) use bexti if possible.
if (Subtarget->hasStdExtZbs() && ShAmt + 1 == TrailingOnes) {
SDNode *BEXTI =
CurDAG->getMachineNode(RISCV::BEXTI, DL, VT, N0->getOperand(0),
CurDAG->getTargetConstant(ShAmt, DL, VT));
// If C2 is (1 << ShAmt) use bexti or th.tst if possible.
bool HasBitTest =
Subtarget->hasStdExtZbs() || Subtarget->hasVendorXTHeadBs();
if (HasBitTest && ShAmt + 1 == TrailingOnes) {
SDNode *BEXTI = CurDAG->getMachineNode(
Subtarget->hasStdExtZbs() ? RISCV::BEXTI : RISCV::TH_TST, DL, VT,
N0->getOperand(0), CurDAG->getTargetConstant(ShAmt, DL, VT));
ReplaceNode(Node, BEXTI);
return;
}

unsigned LShAmt = Subtarget->getXLen() - TrailingOnes;
SDNode *SLLI =
CurDAG->getMachineNode(RISCV::SLLI, DL, VT, N0->getOperand(0),
Expand Down Expand Up @@ -963,8 +966,9 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
bool Skip = Subtarget->hasStdExtZba() && Leading == 32 &&
X.getOpcode() == ISD::SIGN_EXTEND_INREG &&
cast<VTSDNode>(X.getOperand(1))->getVT() == MVT::i32;
// Also Skip if we can use bexti.
// Also Skip if we can use bexti or th.tst.
Skip |= Subtarget->hasStdExtZbs() && Leading == XLen - 1;
Skip |= Subtarget->hasVendorXTHeadBs() && Leading == XLen - 1;
if (OneUseOrZExtW && !Skip) {
SDNode *SLLI = CurDAG->getMachineNode(
RISCV::SLLI, DL, VT, X,
Expand Down
7 changes: 5 additions & 2 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Expand Up @@ -1223,7 +1223,7 @@ bool RISCVTargetLowering::isMaskAndCmp0FoldingBeneficial(
// on the basis that it's possible the sinking+duplication of the AND in
// CodeGenPrepare triggered by this hook wouldn't decrease the instruction
// count and would increase code size (e.g. ANDI+BNEZ => BEXTI+BNEZ).
if (!Subtarget.hasStdExtZbs())
if (!Subtarget.hasStdExtZbs() && !Subtarget.hasVendorXTHeadBs())
return false;
ConstantInt *Mask = dyn_cast<ConstantInt>(AndI.getOperand(1));
if (!Mask)
Expand All @@ -1246,8 +1246,11 @@ bool RISCVTargetLowering::hasBitTest(SDValue X, SDValue Y) const {
// Zbs provides BEXT[_I], which can be used with SEQZ/SNEZ as a bit test.
if (Subtarget.hasStdExtZbs())
return X.getValueType().isScalarInteger();
// We can use ANDI+SEQZ/SNEZ as a bit test. Y contains the bit position.
auto *C = dyn_cast<ConstantSDNode>(Y);
// XTheadBs provides th.tst (similar to bexti), if Y is a constant
if (Subtarget.hasVendorXTHeadBs())
return C != nullptr;
// We can use ANDI+SEQZ/SNEZ as a bit test. Y contains the bit position.
return C && C->getAPIntValue().ule(10);
}

Expand Down
14 changes: 14 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td
Expand Up @@ -75,6 +75,12 @@ def TH_ADDSL : THShiftALU_rri<0b001, "th.addsl">,
Sched<[WriteSHXADD, ReadSHXADD, ReadSHXADD]>;
} // Predicates = [HasVendorXTHeadBa]

let Predicates = [HasVendorXTHeadBs], DecoderNamespace = "THeadBs" in {
let IsSignExtendingOpW = 1 in
def TH_TST : RVBShift_ri<0b10001, 0b001, OPC_CUSTOM_0, "th.tst">,
Sched<[WriteSingleBitImm, ReadSingleBitImm]>;
} // Predicates = [HasVendorXTHeadBs]

let Predicates = [HasVendorXTHeadVdot],
Constraints = "@earlyclobber $vd",
RVVConstraint = WidenV in {
Expand Down Expand Up @@ -163,6 +169,14 @@ def : Pat<(add sh3add_op:$rs1, non_imm12:$rs2),
(TH_ADDSL GPR:$rs2, sh3add_op:$rs1, 3)>;
} // Predicates = [HasVendorXTHeadBa]

let Predicates = [HasVendorXTHeadBs] in {
def : Pat<(and (srl GPR:$rs1, uimmlog2xlen:$shamt), 1),
(TH_TST GPR:$rs1, uimmlog2xlen:$shamt)>;
def : Pat<(seteq (and GPR:$rs1, SingleBitSetMask:$mask), 0),
(TH_TST (XORI GPR:$rs1, -1), SingleBitSetMask:$mask)>;
} // Predicates = [HasVendorXTHeadBs]


defm PseudoTHVdotVMAQA : VPseudoVMAQA_VV_VX;
defm PseudoTHVdotVMAQAU : VPseudoVMAQA_VV_VX;
defm PseudoTHVdotVMAQASU : VPseudoVMAQA_VV_VX;
Expand Down
2 changes: 2 additions & 0 deletions llvm/test/CodeGen/RISCV/attributes.ll
Expand Up @@ -87,6 +87,7 @@
; RUN: llc -mtriple=riscv64 -mattr=+svinval %s -o - | FileCheck --check-prefix=RV64SVINVAL %s
; RUN: llc -mtriple=riscv64 -mattr=+xventanacondops %s -o - | FileCheck --check-prefix=RV64XVENTANACONDOPS %s
; RUN: llc -mtriple=riscv64 -mattr=+xtheadba %s -o - | FileCheck --check-prefix=RV64XTHEADBA %s
; RUN: llc -mtriple=riscv64 -mattr=+xtheadbs %s -o - | FileCheck --check-prefix=RV64XTHEADBS %s
; RUN: llc -mtriple=riscv64 -mattr=+xtheadvdot %s -o - | FileCheck --check-prefix=RV64XTHEADVDOT %s
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zawrs %s -o - | FileCheck --check-prefix=RV64ZAWRS %s
; RUN: llc -mtriple=riscv64 -mattr=+experimental-ztso %s -o - | FileCheck --check-prefix=RV64ZTSO %s
Expand Down Expand Up @@ -182,6 +183,7 @@
; RV64SVINVAL: .attribute 5, "rv64i2p0_svinval1p0"
; RV64XVENTANACONDOPS: .attribute 5, "rv64i2p0_xventanacondops1p0"
; RV64XTHEADBA: .attribute 5, "rv64i2p0_xtheadba1p0"
; RV64XTHEADBS: .attribute 5, "rv64i2p0_xtheadbs1p0"
; RV64XTHEADVDOT: .attribute 5, "rv64i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0_xtheadvdot1p0"
; RV64ZTSO: .attribute 5, "rv64i2p0_ztso0p1"
; RV64ZCA: .attribute 5, "rv64i2p0_zca1p0"
Expand Down

0 comments on commit 656188d

Please sign in to comment.