[clang] [llvm] [RISCV] Add Andes XAndesperf (Andes Performance) extension. (PR #135110)
Jim Lin via cfe-commits
cfe-commits at lists.llvm.org
Sun Apr 13 22:21:31 PDT 2025
https://github.com/tclin914 updated https://github.com/llvm/llvm-project/pull/135110
>From 1615cb987f60d8c6123f7c95bc7bd7f22d897ea1 Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Wed, 9 Apr 2025 09:44:47 +0800
Subject: [PATCH 1/7] [RISCV] Add Andes XAndesperf (Andes Performance)
extension.
The spec can be found at:
https://github.com/andestech/andes-v5-isa/releases/tag/ast-v5_4_0-release.
This patch only supports assembler.
Relocation and fixup for the branch and gp-implied instructions will be
added in a later patch.
---
.../Driver/print-supported-extensions-riscv.c | 1 +
llvm/docs/RISCVUsage.rst | 3 +
llvm/docs/ReleaseNotes.md | 1 +
.../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 56 ++-
.../RISCV/Disassembler/RISCVDisassembler.cpp | 22 +-
.../RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp | 23 +-
llvm/lib/Target/RISCV/RISCVFeatures.td | 9 +
llvm/lib/Target/RISCV/RISCVInstrInfo.td | 1 +
llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td | 358 ++++++++++++++++++
llvm/test/CodeGen/RISCV/attributes.ll | 4 +
llvm/test/CodeGen/RISCV/features-info.ll | 1 +
llvm/test/MC/RISCV/xandesperf-invalid.s | 56 +++
llvm/test/MC/RISCV/xandesperf-rv64-invalid.s | 20 +
llvm/test/MC/RISCV/xandesperf-rv64-valid.s | 34 ++
llvm/test/MC/RISCV/xandesperf-valid.s | 105 +++++
.../TargetParser/RISCVISAInfoTest.cpp | 1 +
16 files changed, 673 insertions(+), 22 deletions(-)
create mode 100644 llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
create mode 100644 llvm/test/MC/RISCV/xandesperf-invalid.s
create mode 100644 llvm/test/MC/RISCV/xandesperf-rv64-invalid.s
create mode 100644 llvm/test/MC/RISCV/xandesperf-rv64-valid.s
create mode 100644 llvm/test/MC/RISCV/xandesperf-valid.s
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index d06cedac5b1eb..f65bfcc2e44d6 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -154,6 +154,7 @@
// CHECK-NEXT: svnapot 1.0 'Svnapot' (NAPOT Translation Contiguity)
// CHECK-NEXT: svpbmt 1.0 'Svpbmt' (Page-Based Memory Types)
// CHECK-NEXT: svvptc 1.0 'Svvptc' (Obviating Memory-Management Instructions after Marking PTEs Valid)
+// CHECK-NEXT: xandesperf 5.0 'XAndesPerf' (Andes Performance Extension)
// CHECK-NEXT: xcvalu 1.0 'XCValu' (CORE-V ALU Operations)
// CHECK-NEXT: xcvbi 1.0 'XCVbi' (CORE-V Immediate Branching)
// CHECK-NEXT: xcvbitmanip 1.0 'XCVbitmanip' (CORE-V Bit Manipulation)
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index cda7e5fec8488..118f45abc1c31 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -503,6 +503,9 @@ The current vendor extensions supported are:
``experimental-XRivosVizip``
LLVM implements `version 0.1 of the Rivos Vector Register Zips extension specification <https://github.com/rivosinc/rivos-custom-extensions>`__.
+``XAndesPerf``
+ LLVM implements `version 5.0.0 of the Andes Performance Extension specification <https://github.com/andestech/andes-v5-isa/releases/download/ast-v5_4_0-release/AndeStar_V5_ISA_Spec_UM165-v1.5.08-20250317.pdf>` by Andes Technology. All instructions are prefixed with `nds.` as described in the specification.
+
Experimental C Intrinsics
=========================
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 526d6b4002bba..6c219a5af8398 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -159,6 +159,7 @@ Changes to the RISC-V Backend
* Adds assembler support for ``.option exact``, which disables automatic compression,
and branch and linker relaxation. This can be disabled with ``.option noexact``,
which is also the default.
+* Adds assembler support for the Andes `XAndesperf` (Andes Performance extension).
Changes to the WebAssembly Backend
----------------------------------
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index c57c123ab01dc..3dafc21b84c21 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -536,19 +536,24 @@ struct RISCVOperand final : public MCParsedAsmOperand {
}
// True if operand is a symbol with no modifiers, or a constant with no
- // modifiers and isShiftedInt<N-1, 1>(Op).
- template <int N> bool isBareSimmNLsb0() const {
- int64_t Imm;
- RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
+ // modifiers and isShiftedInt<N-K, K>(Op).
+ template <unsigned N, unsigned K> bool isBareSimmNLsbK() const {
if (!isImm())
return false;
- bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
- bool IsValid;
- if (!IsConstantImm)
- IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
- else
- IsValid = isShiftedInt<N - 1, 1>(fixImmediateForRV32(Imm, isRV64Imm()));
- return IsValid && VK == RISCVMCExpr::VK_None;
+
+ int64_t Imm;
+ if (evaluateConstantImm(getImm(), Imm))
+ return isShiftedInt<N - K, K>(fixImmediateForRV32(Imm, isRV64Imm()));
+
+ RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
+ return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
+ VK == RISCVMCExpr::VK_None;
+ }
+
+ // True if operand is a symbol with no modifiers, or a constant with no
+ // modifiers and isShiftedInt<N-1, 1>(Op).
+ template <int N> bool isBareSimmNLsb0() const {
+ return isBareSimmNLsbK<N, 1>();
}
// True if operand is a symbol with no modifiers, or a constant with no
@@ -856,6 +861,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return SignExtend64<32>(Imm);
}
+ bool isSImm11Lsb0() const { return isBareSimmNLsb0<11>(); }
+
bool isSImm12() const {
if (!isImm())
return false;
@@ -940,6 +947,14 @@ struct RISCVOperand final : public MCParsedAsmOperand {
[](int64_t Imm) { return Imm != INT64_MIN && isInt<5>(Imm - 1); });
}
+ bool isSImm18() const { return isBareSimmNLsbK<18, 0>(); }
+
+ bool isSImm18Lsb0() const { return isBareSimmNLsb0<18>(); }
+
+ bool isSImm19Lsb00() const { return isBareSimmNLsbK<19, 2>(); }
+
+ bool isSImm20Lsb000() const { return isBareSimmNLsbK<20, 3>(); }
+
bool isSImm32Lsb0() const {
return isSImmPred([](int64_t Imm) { return isShiftedInt<31, 1>(Imm); });
}
@@ -1511,6 +1526,10 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidSImm11:
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 10),
(1 << 10) - 1);
+ case Match_InvalidSImm11Lsb0:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, -(1 << 10), (1 << 10) - 2,
+ "immediate must be a multiple of 2 bytes in the range");
case Match_InvalidUImm10:
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 10) - 1);
case Match_InvalidUImm11:
@@ -1583,6 +1602,21 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
(1 << 4),
"immediate must be in the range");
}
+ case Match_InvalidSImm18:
+ return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 17),
+ (1 << 17) - 1);
+ case Match_InvalidSImm18Lsb0:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, -(1 << 17), (1 << 17) - 2,
+ "immediate must be a multiple of 2 bytes in the range");
+ case Match_InvalidSImm19Lsb00:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, -(1 << 18), (1 << 18) - 4,
+ "immediate must be a multiple of 4 bytes in the range");
+ case Match_InvalidSImm20Lsb000:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, -(1 << 19), (1 << 19) - 8,
+ "immediate must be a multiple of 8 bytes in the range");
case Match_InvalidSImm26:
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 25),
(1 << 25) - 1);
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 366291b53bebb..c793bf2fa75f2 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -447,18 +447,25 @@ static DecodeStatus decodeSImmNonZeroOperand(MCInst &Inst, uint32_t Imm,
return decodeSImmOperand<N>(Inst, Imm, Address, Decoder);
}
-template <unsigned N>
-static DecodeStatus decodeSImmOperandAndLsl1(MCInst &Inst, uint32_t Imm,
+template <unsigned T, unsigned N>
+static DecodeStatus decodeSImmOperandAndLslN(MCInst &Inst, uint64_t Imm,
int64_t Address,
const MCDisassembler *Decoder) {
- assert(isUInt<N>(Imm) && "Invalid immediate");
- // Sign-extend the number in the bottom N bits of Imm after accounting for
- // the fact that the N bit immediate is stored in N-1 bits (the LSB is
+ assert(isUInt<T - N + 1>(Imm) && "Invalid immediate");
+ // Sign-extend the number in the bottom T bits of Imm after accounting for
+ // the fact that the T bit immediate is stored in T-N bits (the LSB is
// always zero)
- Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm << 1)));
+ Inst.addOperand(MCOperand::createImm(SignExtend64<T>(Imm << N)));
return MCDisassembler::Success;
}
+template <unsigned T>
+static DecodeStatus decodeSImmOperandAndLsl1(MCInst &Inst, uint32_t Imm,
+ int64_t Address,
+ const MCDisassembler *Decoder) {
+ return decodeSImmOperandAndLslN<T, 1>(Inst, Imm, Address, Decoder);
+}
+
static DecodeStatus decodeCLUIImmOperand(MCInst &Inst, uint32_t Imm,
int64_t Address,
const MCDisassembler *Decoder) {
@@ -727,6 +734,8 @@ static constexpr FeatureBitset XTHeadGroup = {
RISCV::FeatureVendorXTHeadMemPair, RISCV::FeatureVendorXTHeadSync,
RISCV::FeatureVendorXTHeadVdot};
+static constexpr FeatureBitset XAndesGroup = {RISCV::FeatureVendorXAndesPerf};
+
static constexpr DecoderListEntry DecoderList32[]{
// Vendor Extensions
{DecoderTableXVentana32,
@@ -740,6 +749,7 @@ static constexpr DecoderListEntry DecoderList32[]{
{DecoderTableXmipscmove32,
{RISCV::FeatureVendorXMIPSCMove},
"MIPS mips.ccmov"},
+ {DecoderTableXAndes32, XAndesGroup, "Andes extensions"},
// Standard Extensions
{DecoderTableXCV32, XCVFeatureGroup, "CORE-V extensions"},
{DecoderTableXqci32, XqciFeatureGroup, "Qualcomm uC Extensions"},
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index 95858da45f202..ed56a92d08af8 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -96,6 +96,11 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ template <unsigned N>
+ unsigned getImmOpValueAsrN(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
uint64_t getImmOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
@@ -535,21 +540,29 @@ RISCVMCCodeEmitter::getImmOpValueSlist(const MCInst &MI, unsigned OpNo,
}
}
-uint64_t
-RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
+template <unsigned N>
+unsigned
+RISCVMCCodeEmitter::getImmOpValueAsrN(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand &MO = MI.getOperand(OpNo);
if (MO.isImm()) {
- uint64_t Res = MO.getImm();
- assert((Res & 1) == 0 && "LSB is non-zero");
- return Res >> 1;
+ unsigned Res = MO.getImm();
+ assert((Res & ((1 << N) - 1)) == 0 && "LSB is non-zero");
+ return Res >> N;
}
return getImmOpValue(MI, OpNo, Fixups, STI);
}
+uint64_t
+RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ return getImmOpValueAsrN<1>(MI, OpNo, Fixups, STI);
+}
+
uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 60d3c0f397371..19bf35359e49e 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1479,6 +1479,15 @@ def HasVendorXRivosVizip
AssemblerPredicate<(all_of FeatureVendorXRivosVizip),
"'XRivosVizip' (Rivos Vector Register Zips)">;
+// Andes Extension(s)
+
+def FeatureVendorXAndesPerf
+ : RISCVExtension<5, 0, "Andes Performance Extension">;
+def HasVendorXAndesPerf
+ : Predicate<"Subtarget->hasVendorXAndesPerf()">,
+ AssemblerPredicate<(all_of FeatureVendorXAndesPerf),
+ "'XAndesPerf' (Andes Performance Extension)">;
+
//===----------------------------------------------------------------------===//
// LLVM specific features and extensions
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index c87452171f090..f1d455987c713 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -2182,6 +2182,7 @@ include "RISCVInstrInfoXqci.td"
include "RISCVInstrInfoXqccmp.td"
include "RISCVInstrInfoXMips.td"
include "RISCVInstrInfoXRivos.td"
+include "RISCVInstrInfoXAndes.td"
//===----------------------------------------------------------------------===//
// Global ISel
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
new file mode 100644
index 0000000000000..afe6e784dbfb0
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
@@ -0,0 +1,358 @@
+//===-- RISCVInstrInfoXAndes.td ----------------------------*- 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 describes the vendor extensions defined by Andes Technology.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Operand and SDNode transformation definitions.
+//===----------------------------------------------------------------------===//
+
+// A 11-bit signed immediate where the least significant bit is zero.
+def simm11_lsb0 : Operand<OtherVT> {
+ let ParserMatchClass = SImmAsmOperand<11, "Lsb0">;
+ let PrintMethod = "printBranchOperand";
+ let EncoderMethod = "getImmOpValueAsr1";
+ let DecoderMethod = "decodeSImmOperandAndLsl1<11>";
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isShiftedInt<10, 1>(Imm);
+ return MCOp.isBareSymbolRef();
+ }];
+ let OperandType = "OPERAND_PCREL";
+}
+
+def simm18 : Operand<XLenVT> {
+ let ParserMatchClass = SImmAsmOperand<18>;
+ let EncoderMethod = "getImmOpValue";
+ let DecoderMethod = "decodeSImmOperand<18>";
+}
+
+def simm18_lsb0 : Operand<XLenVT> {
+ let ParserMatchClass = SImmAsmOperand<18, "Lsb0">;
+ let EncoderMethod = "getImmOpValueAsr1";
+ let DecoderMethod = "decodeSImmOperandAndLsl1<18>";
+}
+
+def simm19_lsb00 : Operand<XLenVT> {
+ let ParserMatchClass = SImmAsmOperand<19, "Lsb00">;
+ let EncoderMethod = "getImmOpValueAsrN<2>";
+ let DecoderMethod = "decodeSImmOperandAndLslN<19, 2>";
+}
+
+def simm20_lsb000 : Operand<XLenVT> {
+ let ParserMatchClass = SImmAsmOperand<20, "Lsb000">;
+ let EncoderMethod = "getImmOpValueAsrN<3>";
+ let DecoderMethod = "decodeSImmOperandAndLslN<20, 3>";
+}
+
+//===----------------------------------------------------------------------===//
+// Instruction Class Templates
+//===----------------------------------------------------------------------===//
+
+class NDSRVInstBB<bit cs, string opcodestr>
+ : RVInst<(outs), (ins GPR:$rs1, uimmlog2xlen:$cimm, simm11_lsb0:$imm10),
+ opcodestr, "$rs1, $cimm, $imm10", [], InstFormatOther>,
+ Sched<[WriteJmp, ReadIALU]> {
+ bits<10> imm10;
+ bits<5> rs1;
+ bits<6> cimm;
+
+ let Inst{31} = imm10{9};
+ let Inst{30} = cs;
+ let Inst{29-25} = imm10{8-4};
+ let Inst{24-20} = cimm{4-0};
+ let Inst{19-15} = rs1;
+ let Inst{14-12} = 0b111;
+ let Inst{11-8} = imm10{3-0};
+ let Inst{7} = cimm{5};
+ let Inst{6-0} = OPC_CUSTOM_2.Value;
+ let hasSideEffects = 0;
+ let mayLoad = 0;
+ let mayStore = 0;
+ let isBranch = 1;
+ let isTerminator = 1;
+}
+
+class NDSRVInstBC<bits<3> funct3, string opcodestr>
+ : RVInst<(outs), (ins GPR:$rs1, uimm7:$cimm, simm11_lsb0:$imm10),
+ opcodestr, "$rs1, $cimm, $imm10", [], InstFormatOther>,
+ Sched<[WriteJmp, ReadIALU]> {
+ bits<10> imm10;
+ bits<5> rs1;
+ bits<7> cimm;
+
+ let Inst{31} = imm10{9};
+ let Inst{30} = cimm{6};
+ let Inst{29-25} = imm10{8-4};
+ let Inst{24-20} = cimm{4-0};
+ let Inst{19-15} = rs1;
+ let Inst{14-12} = funct3;
+ let Inst{11-8} = imm10{3-0};
+ let Inst{7} = cimm{5};
+ let Inst{6-0} = OPC_CUSTOM_2.Value;
+ let hasSideEffects = 0;
+ let mayLoad = 0;
+ let mayStore = 0;
+ let isBranch = 1;
+ let isTerminator = 1;
+}
+
+class NDSRVInstBFO<bits<3> funct3, string opcodestr>
+ : RVInst<(outs GPR:$rd), (ins GPR:$rs1, uimmlog2xlen:$msb, uimmlog2xlen:$lsb),
+ opcodestr, "$rd, $rs1, $msb, $lsb", [], InstFormatOther>,
+ Sched<[WriteIALU, ReadIALU]> {
+ bits<5> rd;
+ bits<5> rs1;
+ bits<6> msb;
+ bits<6> lsb;
+
+ let Inst{31-26} = msb;
+ let Inst{25-20} = lsb;
+ let Inst{19-15} = rs1;
+ let Inst{14-12} = funct3;
+ let Inst{11-7} = rd;
+ let Inst{6-0} = OPC_CUSTOM_2.Value;
+ let hasSideEffects = 0;
+ let mayLoad = 0;
+ let mayStore = 0;
+}
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class NDSRVInstRR<bits<7> funct7, string opcodestr>
+ : RVInstR<funct7, 0b000, OPC_CUSTOM_2,
+ (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2),
+ opcodestr, "$rd, $rs1, $rs2">,
+ Sched<[WriteIALU, ReadIALU, ReadIALU]> {
+ let hasSideEffects = 0;
+ let mayLoad = 0;
+ let mayStore = 0;
+}
+
+// GP: ADDI, LB, LBU
+class NDSRVInstLBGP<bits<2> funct2, string opcodestr>
+ : RVInst<(outs GPR:$rd), (ins simm18:$imm18),
+ opcodestr, "$rd, ${imm18}", [], InstFormatOther> {
+ bits<18> imm18;
+ bits<5> rd;
+
+ let Inst{31} = imm18{17};
+ let Inst{30-21} = imm18{10-1};
+ let Inst{20} = imm18{11};
+ let Inst{19-17} = imm18{14-12};
+ let Inst{16-15} = imm18{16-15};
+ let Inst{14} = imm18{0};
+ let Inst{13-12} = funct2;
+ let Inst{11-7} = rd;
+ let Inst{6-0} = OPC_CUSTOM_0.Value;
+ let hasSideEffects = 0;
+ let mayLoad = 1;
+ let mayStore = 0;
+}
+
+// GP: LH, LHU
+class NDSRVInstLHGP<bits<3> funct3, string opcodestr>
+ : RVInst<(outs GPR:$rd), (ins simm18_lsb0:$imm17),
+ opcodestr, "$rd, ${imm17}", [], InstFormatOther> {
+ bits<17> imm17;
+ bits<5> rd;
+
+ let Inst{31} = imm17{16};
+ let Inst{30-21} = imm17{9-0};
+ let Inst{20} = imm17{10};
+ let Inst{19-17} = imm17{13-11};
+ let Inst{16-15} = imm17{15-14};
+ let Inst{14-12} = funct3;
+ let Inst{11-7} = rd;
+ let Inst{6-0} = OPC_CUSTOM_1.Value;
+ let hasSideEffects = 0;
+ let mayLoad = 1;
+ let mayStore = 0;
+}
+
+class NDSRVInstLWGP<bits<3> funct3, string opcodestr>
+ : RVInst<(outs GPR:$rd), (ins simm19_lsb00:$imm17),
+ opcodestr, "$rd, ${imm17}", [], InstFormatOther> {
+ bits<17> imm17;
+ bits<5> rd;
+
+ let Inst{31} = imm17{16};
+ let Inst{30-22} = imm17{8-0};
+ let Inst{21} = imm17{15};
+ let Inst{20} = imm17{9};
+ let Inst{19-17} = imm17{12-10};
+ let Inst{16-15} = imm17{14-13};
+ let Inst{14-12} = funct3;
+ let Inst{11-7} = rd;
+ let Inst{6-0} = OPC_CUSTOM_1.Value;
+ let hasSideEffects = 0;
+ let mayLoad = 1;
+ let mayStore = 0;
+}
+
+// GP: LD
+class NDSRVInstLDGP<bits<3> funct3, string opcodestr>
+ : RVInst<(outs GPR:$rd), (ins simm20_lsb000:$imm17),
+ opcodestr, "$rd, ${imm17}", [], InstFormatOther> {
+ bits<17> imm17;
+ bits<5> rd;
+
+ let Inst{31} = imm17{16};
+ let Inst{30-23} = imm17{7-0};
+ let Inst{22-21} = imm17{15-14};
+ let Inst{20} = imm17{8};
+ let Inst{19-17} = imm17{11-9};
+ let Inst{16-15} = imm17{13-12};
+ let Inst{14-12} = funct3;
+ let Inst{11-7} = rd;
+ let Inst{6-0} = OPC_CUSTOM_1.Value;
+ let hasSideEffects = 0;
+ let mayLoad = 1;
+ let mayStore = 0;
+}
+
+// GP: SB
+class NDSRVInstSBGP<bits<2> funct2, string opcodestr>
+ : RVInst<(outs), (ins GPR:$rs2, simm18:$imm18),
+ opcodestr, "$rs2, ${imm18}", [], InstFormatOther> {
+ bits<18> imm18;
+ bits<5> rs2;
+
+ let Inst{31} = imm18{17};
+ let Inst{30-25} = imm18{10-5};
+ let Inst{24-20} = rs2;
+ let Inst{19-17} = imm18{14-12};
+ let Inst{16-15} = imm18{16-15};
+ let Inst{14} = imm18{0};
+ let Inst{13-12} = funct2;
+ let Inst{11-8} = imm18{4-1};
+ let Inst{7} = imm18{11};
+ let Inst{6-0} = OPC_CUSTOM_0.Value;
+ let hasSideEffects = 0;
+ let mayLoad = 0;
+ let mayStore = 1;
+}
+
+// GP: SH
+class NDSRVInstSHGP<bits<3> funct3, string opcodestr>
+ : RVInst<(outs), (ins GPR:$rs2, simm18_lsb0:$imm17),
+ opcodestr, "$rs2, ${imm17}", [], InstFormatOther> {
+ bits<17> imm17;
+ bits<5> rs2;
+
+ let Inst{31} = imm17{16};
+ let Inst{30-25} = imm17{9-4};
+ let Inst{24-20} = rs2;
+ let Inst{19-17} = imm17{13-11};
+ let Inst{16-15} = imm17{15-14};
+ let Inst{14-12} = funct3;
+ let Inst{11-8} = imm17{3-0};
+ let Inst{7} = imm17{10};
+ let Inst{6-0} = OPC_CUSTOM_1.Value;
+ let hasSideEffects = 0;
+ let mayLoad = 0;
+ let mayStore = 1;
+}
+
+// GP: SW
+class NDSRVInstSWGP<bits<3> funct3, string opcodestr>
+ : RVInst<(outs), (ins GPR:$rs2, simm19_lsb00:$imm17),
+ opcodestr, "$rs2, ${imm17}", [], InstFormatOther> {
+ bits<17> imm17;
+ bits<5> rs2;
+
+ let Inst{31} = imm17{16};
+ let Inst{30-25} = imm17{8-3};
+ let Inst{24-20} = rs2;
+ let Inst{19-17} = imm17{12-10};
+ let Inst{16-15} = imm17{14-13};
+ let Inst{14-12} = funct3;
+ let Inst{11-9} = imm17{2-0};
+ let Inst{8} = imm17{15};
+ let Inst{7} = imm17{9};
+ let Inst{6-0} = OPC_CUSTOM_1.Value;
+ let hasSideEffects = 0;
+ let mayLoad = 0;
+ let mayStore = 1;
+}
+
+// GP: SD
+class NDSRVInstSDGP<bits<3> funct3, string opcodestr>
+ : RVInst<(outs), (ins GPR:$rs2, simm20_lsb000:$imm17),
+ opcodestr, "$rs2, ${imm17}", [], InstFormatOther> {
+ bits<17> imm17;
+ bits<5> rs2;
+
+ let Inst{31} = imm17{16};
+ let Inst{30-25} = imm17{7-2};
+ let Inst{24-20} = rs2;
+ let Inst{19-17} = imm17{11-9};
+ let Inst{16-15} = imm17{13-12};
+ let Inst{14-12} = funct3;
+ let Inst{11-10} = imm17{1-0};
+ let Inst{9-8} = imm17{15-14};
+ let Inst{7} = imm17{8};
+ let Inst{6-0} = OPC_CUSTOM_1.Value;
+ let hasSideEffects = 0;
+ let mayLoad = 0;
+ let mayStore = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// XAndesPerf
+//===----------------------------------------------------------------------===//
+
+let DecoderNamespace = "XAndes" in {
+
+let Predicates = [HasVendorXAndesPerf] in {
+def NDS_BBC : NDSRVInstBB<0, "nds.bbc">;
+def NDS_BBS : NDSRVInstBB<1, "nds.bbs">;
+
+def NDS_BEQC : NDSRVInstBC<0b101, "nds.beqc">;
+def NDS_BNEC : NDSRVInstBC<0b110, "nds.bnec">;
+
+def NDS_BFOS : NDSRVInstBFO<0b011, "nds.bfos">;
+def NDS_BFOZ : NDSRVInstBFO<0b010, "nds.bfoz">;
+
+def NDS_LEA_H : NDSRVInstRR<0b0000101, "nds.lea.h">;
+def NDS_LEA_W : NDSRVInstRR<0b0000110, "nds.lea.w">;
+def NDS_LEA_D : NDSRVInstRR<0b0000111, "nds.lea.d">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+def NDS_ADDIGP : NDSRVInstLBGP<0b01, "nds.addigp">;
+
+def NDS_LBGP : NDSRVInstLBGP<0b00, "nds.lbgp">;
+def NDS_LBUGP : NDSRVInstLBGP<0b10, "nds.lbugp">;
+def NDS_LHGP : NDSRVInstLHGP<0b001, "nds.lhgp">;
+def NDS_LHUGP : NDSRVInstLHGP<0b101, "nds.lhugp">;
+def NDS_LWGP : NDSRVInstLWGP<0b010, "nds.lwgp">;
+
+def NDS_SBGP : NDSRVInstSBGP<0b11, "nds.sbgp">;
+def NDS_SHGP : NDSRVInstSHGP<0b000, "nds.shgp">;
+def NDS_SWGP : NDSRVInstSWGP<0b100, "nds.swgp">;
+
+def NDS_FFB : NDSRVInstRR<0b0010000, "nds.ffb">;
+def NDS_FFZMISM : NDSRVInstRR<0b0010001, "nds.ffzmism">;
+def NDS_FFMISM : NDSRVInstRR<0b0010010, "nds.ffmism">;
+def NDS_FLMISM : NDSRVInstRR<0b0010011, "nds.flmism">;
+} // Predicates = [HasVendorXAndesPerf]
+
+let Predicates = [HasVendorXAndesPerf, IsRV64] in {
+def NDS_LEA_B_ZE : NDSRVInstRR<0b0001000, "nds.lea.b.ze">;
+def NDS_LEA_H_ZE : NDSRVInstRR<0b0001001, "nds.lea.h.ze">;
+def NDS_LEA_W_ZE : NDSRVInstRR<0b0001010, "nds.lea.w.ze">;
+def NDS_LEA_D_ZE : NDSRVInstRR<0b0001011, "nds.lea.d.ze">;
+
+def NDS_LWUGP : NDSRVInstLWGP<0b110, "nds.lwugp">;
+def NDS_LDGP : NDSRVInstLDGP<0b011, "nds.ldgp">;
+
+def NDS_SDGP : NDSRVInstSDGP<0b111, "nds.sdgp">;
+} // Predicates = [HasVendorXAndesPerf, IsRV64]
+} // DecoderNamespace = "XAndes"
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index 4bb3eb81f3dfb..5a181dc94e0f1 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -103,6 +103,7 @@
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisim %s -o - | FileCheck --check-prefix=RV32XQCISIM %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisync %s -o - | FileCheck --check-prefix=RV32XQCISYNC %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisls %s -o - | FileCheck --check-prefix=RV32XQCISLS %s
+; RUN: llc -mtriple=riscv32 -mattr=+xandesperf %s -o - | FileCheck --check-prefix=RV32XANDESPERF %s
; RUN: llc -mtriple=riscv32 -mattr=+zaamo %s -o - | FileCheck --check-prefix=RV32ZAAMO %s
; RUN: llc -mtriple=riscv32 -mattr=+zalrsc %s -o - | FileCheck --check-prefix=RV32ZALRSC %s
; RUN: llc -mtriple=riscv32 -mattr=+zca %s -o - | FileCheck --check-prefixes=CHECK,RV32ZCA %s
@@ -251,6 +252,7 @@
; RUN: llc -mtriple=riscv64 -mattr=+xtheadmempair %s -o - | FileCheck --check-prefix=RV64XTHEADMEMPAIR %s
; RUN: llc -mtriple=riscv64 -mattr=+xtheadsync %s -o - | FileCheck --check-prefix=RV64XTHEADSYNC %s
; RUN: llc -mtriple=riscv64 -mattr=+xtheadvdot %s -o - | FileCheck --check-prefixes=CHECK,RV64XTHEADVDOT %s
+; RUN: llc -mtriple=riscv64 -mattr=+xandesperf %s -o - | FileCheck --check-prefix=RV64XANDESPERF %s
; RUN: llc -mtriple=riscv64 -mattr=+za64rs %s -o - | FileCheck --check-prefixes=CHECK,RV64ZA64RS %s
; RUN: llc -mtriple=riscv64 -mattr=+za128rs %s -o - | FileCheck --check-prefixes=CHECK,RV64ZA128RS %s
; RUN: llc -mtriple=riscv64 -mattr=+zama16b %s -o - | FileCheck --check-prefixes=CHECK,RV64ZAMA16B %s
@@ -441,6 +443,7 @@
; RV32XQCISIM: attribute 5, "rv32i2p1_zca1p0_xqcisim0p2"
; RV32XQCISYNC: attribute 5, "rv32i2p1_zca1p0_xqcisync0p2"
; RV32XQCISLS: .attribute 5, "rv32i2p1_xqcisls0p2"
+; RV32XANDESPERF: .attribute 5, "rv32i2p1_xandesperf5p0"
; RV32ZAAMO: .attribute 5, "rv32i2p1_zaamo1p0"
; RV32ZALRSC: .attribute 5, "rv32i2p1_zalrsc1p0"
; RV32ZCA: .attribute 5, "rv32i2p1_zca1p0"
@@ -590,6 +593,7 @@
; RV64XTHEADMEMPAIR: .attribute 5, "rv64i2p1_xtheadmempair1p0"
; RV64XTHEADSYNC: .attribute 5, "rv64i2p1_xtheadsync1p0"
; RV64XTHEADVDOT: .attribute 5, "rv64i2p1_f2p2_d2p2_v1p0_zicsr2p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0_xtheadvdot1p0"
+; RV64XANDESPERF: .attribute 5, "rv64i2p1_xandesperf5p0"
; RV64ZTSO: .attribute 5, "rv64i2p1_ztso1p0"
; RV64ZAAMO: .attribute 5, "rv64i2p1_zaamo1p0"
; RV64ZALRSC: .attribute 5, "rv64i2p1_zalrsc1p0"
diff --git a/llvm/test/CodeGen/RISCV/features-info.ll b/llvm/test/CodeGen/RISCV/features-info.ll
index 5d2f0881048bd..a00d3b375ff29 100644
--- a/llvm/test/CodeGen/RISCV/features-info.ll
+++ b/llvm/test/CodeGen/RISCV/features-info.ll
@@ -167,6 +167,7 @@
; CHECK-NEXT: v - 'V' (Vector Extension for Application Processors).
; CHECK-NEXT: ventana-veyron - Ventana Veyron-Series processors.
; CHECK-NEXT: vxrm-pipeline-flush - VXRM writes causes pipeline flush.
+; CHECK-NEXT: xandesperf - 'XAndesPerf' (Andes Performance Extension).
; CHECK-NEXT: xcvalu - 'XCValu' (CORE-V ALU Operations).
; CHECK-NEXT: xcvbi - 'XCVbi' (CORE-V Immediate Branching).
; CHECK-NEXT: xcvbitmanip - 'XCVbitmanip' (CORE-V Bit Manipulation).
diff --git a/llvm/test/MC/RISCV/xandesperf-invalid.s b/llvm/test/MC/RISCV/xandesperf-invalid.s
new file mode 100644
index 0000000000000..4c5a8d5a20277
--- /dev/null
+++ b/llvm/test/MC/RISCV/xandesperf-invalid.s
@@ -0,0 +1,56 @@
+# XAndesPerf - Andes Performance Extension
+# RUN: not llvm-mc -triple riscv32 -mattr=+xandesperf < %s 2>&1 \
+# RUN: | FileCheck %s
+# RUN: not llvm-mc -triple riscv64 -mattr=+xandesperf < %s 2>&1 \
+# RUN: | FileCheck %s -check-prefix=CHECK-64
+
+# Out of range immediates
+## uimm5
+nds.bbc t0, 33, 256 # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [0, 31]
+nds.bbs t1, 33, 256 # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [0, 31]
+nds.bbc t0, 64, 256 # CHECK-64: :[[@LINE]]:13: error: immediate must be an integer in the range [0, 63]
+nds.bbs t1, 64, 256 # CHECK-64: :[[@LINE]]:13: error: immediate must be an integer in the range [0, 63]
+
+## uimm7
+nds.beqc t0, 1024, 13 # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 127]
+nds.bnec t1, -1, -13 # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 127]
+
+## simm11_lsb0
+nds.bbc t0, 7, 1024 # CHECK, CHECK-64: :[[@LINE]]:16: error: immediate must be a multiple of 2 bytes in the range [-1024, 1022]
+nds.bbs t1, 21, -1200 # CHECK, CHECK-64: :[[@LINE]]:17: error: immediate must be a multiple of 2 bytes in the range [-1024, 1022]
+nds.beqc t0, 7, 13 # CHECK, CHECK-64: :[[@LINE]]:17: error: immediate must be a multiple of 2 bytes in the range [-1024, 1022]
+nds.bnec t1, 21, -13 # CHECK, CHECK-64: :[[@LINE]]:18: error: immediate must be a multiple of 2 bytes in the range [-1024, 1022]
+
+## uimmlog2xlen
+nds.bfos a0, a1, 35, 3 # CHECK: :[[@LINE]]:18: error: immediate must be an integer in the range [0, 31]
+nds.bfoz t0, t1, 6, 40 # CHECK: :[[@LINE]]:21: error: immediate must be an integer in the range [0, 31]
+nds.bfos a0, a1, 64, 3 # CHECK-64: :[[@LINE]]:18: error: immediate must be an integer in the range [0, 63]
+nds.bfoz t0, t1, 6, 64 # CHECK-64: :[[@LINE]]:21: error: immediate must be an integer in the range [0, 63]
+
+## simm18
+nds.addigp t0, 0x20000 # CHECK, CHECK-64: :[[@LINE]]:16: error: immediate must be an integer in the range [-131072, 131071]
+nds.addigp t0, -0x20001 # CHECK, CHECK-64: :[[@LINE]]:16: error: immediate must be an integer in the range [-131072, 131071]
+nds.lbgp t0, 0x20000 # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be an integer in the range [-131072, 131071]
+nds.lbugp t0, -0x20001 # CHECK, CHECK-64: :[[@LINE]]:15: error: immediate must be an integer in the range [-131072, 131071]
+nds.sbgp t0, 0x20000 # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be an integer in the range [-131072, 131071]
+nds.sbgp t0, -0x20001 # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be an integer in the range [-131072, 131071]
+
+## simm18_lsb0
+nds.lhgp t0, 0x1ffff # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-131072, 131070]
+nds.lhgp t0, 0x3 # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-131072, 131070]
+nds.lhugp t0, -0x20001 # CHECK, CHECK-64: :[[@LINE]]:15: error: immediate must be a multiple of 2 bytes in the range [-131072, 131070]
+nds.lhugp t0, -0x3 # CHECK, CHECK-64: :[[@LINE]]:15: error: immediate must be a multiple of 2 bytes in the range [-131072, 131070]
+nds.shgp t0, 0x1ffff # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-131072, 131070]
+nds.shgp t0, 0x3 # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-131072, 131070]
+nds.shgp t0, -0x20001 # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-131072, 131070]
+nds.shgp t0, -0x3 # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-131072, 131070]
+
+## simm19_lsb00
+nds.lwgp t0, 0x3fffd # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be a multiple of 4 bytes in the range [-262144, 262140]
+nds.lwgp t0, 0x7 # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be a multiple of 4 bytes in the range [-262144, 262140]
+nds.lwgp t0, -0x40001 # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be a multiple of 4 bytes in the range [-262144, 262140]
+nds.lwgp t0, -0x7 # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be a multiple of 4 bytes in the range [-262144, 262140]
+nds.swgp t0, 0x3fffd # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be a multiple of 4 bytes in the range [-262144, 262140]
+nds.swgp t0, 0x7 # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be a multiple of 4 bytes in the range [-262144, 262140]
+nds.swgp t0, -0x40001 # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be a multiple of 4 bytes in the range [-262144, 262140]
+nds.swgp t0, -0x7 # CHECK, CHECK-64: :[[@LINE]]:14: error: immediate must be a multiple of 4 bytes in the range [-262144, 262140]
diff --git a/llvm/test/MC/RISCV/xandesperf-rv64-invalid.s b/llvm/test/MC/RISCV/xandesperf-rv64-invalid.s
new file mode 100644
index 0000000000000..04a91ab4734c0
--- /dev/null
+++ b/llvm/test/MC/RISCV/xandesperf-rv64-invalid.s
@@ -0,0 +1,20 @@
+# XAndesPerf - Andes Performance Extension
+# RUN: not llvm-mc -triple riscv64 -mattr=+xandesperf < %s 2>&1 \
+# RUN: | FileCheck %s
+
+# Out of range immediates
+## simm19_lsb00
+nds.lwugp t0, 0x3fffd # CHECK: :[[@LINE]]:15: error: immediate must be a multiple of 4 bytes in the range [-262144, 262140]
+nds.lwugp t0, 0x7 # CHECK: :[[@LINE]]:15: error: immediate must be a multiple of 4 bytes in the range [-262144, 262140]
+nds.lwugp t0, -0x40001 # CHECK: :[[@LINE]]:15: error: immediate must be a multiple of 4 bytes in the range [-262144, 262140]
+nds.lwugp t0, -0x7 # CHECK: :[[@LINE]]:15: error: immediate must be a multiple of 4 bytes in the range [-262144, 262140]
+
+## simm20_lsb000
+nds.ldgp t0, 0x7fff9 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 8 bytes in the range [-524288, 524280]
+nds.ldgp t0, 0x14 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 8 bytes in the range [-524288, 524280]
+nds.ldgp t0, -0x80001 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 8 bytes in the range [-524288, 524280]
+nds.ldgp t0, -0x14 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 8 bytes in the range [-524288, 524280]
+nds.sdgp t0, 0x7fff9 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 8 bytes in the range [-524288, 524280]
+nds.sdgp t0, 0x14 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 8 bytes in the range [-524288, 524280]
+nds.sdgp t0, -0x80001 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 8 bytes in the range [-524288, 524280]
+nds.sdgp t0, -0x14 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 8 bytes in the range [-524288, 524280]
diff --git a/llvm/test/MC/RISCV/xandesperf-rv64-valid.s b/llvm/test/MC/RISCV/xandesperf-rv64-valid.s
new file mode 100644
index 0000000000000..8da7cbcddb8d9
--- /dev/null
+++ b/llvm/test/MC/RISCV/xandesperf-rv64-valid.s
@@ -0,0 +1,34 @@
+# XAndesPerf - Andes Performance Extension
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+xandesperf -show-encoding \
+# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+xandesperf < %s \
+# RUN: | llvm-objdump --mattr=+xandesperf -M no-aliases --no-print-imm-hex -d -r - \
+# RUN: | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: lea.b.ze t0, t1, t3
+# CHECK-ASM: encoding: [0xdb,0x02,0xc3,0x11]
+nds.lea.b.ze t0, t1, t3
+
+# CHECK-ASM-AND-OBJ: lea.h.ze a0, a1, a3
+# CHECK-ASM: encoding: [0x5b,0x85,0xd5,0x12]
+nds.lea.h.ze a0, a1, a3
+
+# CHECK-ASM-AND-OBJ: lea.w.ze s0, s1, s3
+# CHECK-ASM: encoding: [0x5b,0x84,0x34,0x15]
+nds.lea.w.ze s0, s1, s3
+
+# CHECK-ASM-AND-OBJ: lea.d.ze a3, a4, a5
+# CHECK-ASM: encoding: [0xdb,0x06,0xf7,0x16]
+nds.lea.d.ze a3, a4, a5
+
+# CHECK-ASM-AND-OBJ: lwugp t0, 9568
+# CHECK-ASM: encoding: [0xab,0x62,0x04,0x56]
+nds.lwugp t0, 0x2560
+
+# CHECK-ASM-AND-OBJ: ldgp t0, -9568
+# CHECK-ASM: encoding: [0xab,0xb2,0x7b,0xaa]
+nds.ldgp t0, -0x2560
+
+# CHECK-ASM-AND-OBJ: sdgp t0, 9568
+# CHECK-ASM: encoding: [0x2b,0x70,0x54,0x56]
+nds.sdgp t0, 0x2560
diff --git a/llvm/test/MC/RISCV/xandesperf-valid.s b/llvm/test/MC/RISCV/xandesperf-valid.s
new file mode 100644
index 0000000000000..f7c6b861a5098
--- /dev/null
+++ b/llvm/test/MC/RISCV/xandesperf-valid.s
@@ -0,0 +1,105 @@
+# XAndesPerf - Andes Performance Extension
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+xandesperf -show-encoding \
+# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+xandesperf < %s \
+# RUN: | llvm-objdump --mattr=+xandesperf -M no-aliases --no-print-imm-hex -d -r - \
+# RUN: | FileCheck -check-prefixes=CHECK-OBJ,CHECK-OBJ32,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+xandesperf -show-encoding \
+# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+xandesperf < %s \
+# RUN: | llvm-objdump --mattr=+xandesperf -M no-aliases --no-print-imm-hex -d -r - \
+# RUN: | FileCheck -check-prefixes=CHECK-OBJ,CHECK-OBJ64,CHECK-ASM-AND-OBJ %s
+
+# CHECK-OBJ: nds.bbc a0, 16, 0x200
+# CHECK-ASM: nds.bbc a0, 16, 512
+# CHECK-ASM: encoding: [0x5b,0x70,0x05,0x21]
+nds.bbc a0, 16, 512
+
+# CHECK-OBJ32: nds.bbs a1, 21, 0xffffff04
+# CHECK-OBJ64: nds.bbs a1, 21, 0xffffffffffffff04
+# CHECK-ASM: nds.bbs a1, 21, -256
+# CHECK-ASM: encoding: [0x5b,0xf0,0x55,0xf1]
+nds.bbs a1, 21, -256
+
+# CHECK-OBJ: beqc t0, 23, 0x108
+# CHECK-ASM: beqc t0, 23, 256
+# CHECK-ASM: encoding: [0x5b,0xd0,0x72,0x11]
+nds.beqc t0, 23, 256
+
+# CHECK-OBJ32: bnec t1, 9, 0xffffff8c
+# CHECK-OBJ64: bnec t1, 9, 0xffffffffffffff8c
+# CHECK-ASM: bnec t1, 9, -128
+# CHECK-ASM: encoding: [0x5b,0x60,0x93,0xb8]
+nds.bnec t1, 9, -128
+
+# CHECK-ASM-AND-OBJ: bfoz a0, a1, 9, 13
+# CHECK-ASM: encoding: [0x5b,0xa5,0xd5,0x24]
+nds.bfoz a0, a1, 9, 13
+
+# CHECK-ASM-AND-OBJ: bfos t0, t1, 23, 3
+# CHECK-ASM: encoding: [0xdb,0x32,0x33,0x5c]
+nds.bfos t0, t1, 23, 3
+
+# CHECK-ASM-AND-OBJ: lea.h t0, t1, t3
+# CHECK-ASM: encoding: [0xdb,0x02,0xc3,0x0b]
+nds.lea.h t0, t1, t3
+
+# CHECK-ASM-AND-OBJ: lea.w a0, a1, a3
+# CHECK-ASM: encoding: [0x5b,0x85,0xd5,0x0c]
+nds.lea.w a0, a1, a3
+
+# CHECK-ASM-AND-OBJ: lea.d s0, s1, s3
+# CHECK-ASM: encoding: [0x5b,0x84,0x34,0x0f]
+nds.lea.d s0, s1, s3
+
+# CHECK-ASM-AND-OBJ: addigp t0, 9568
+# CHECK-ASM: encoding: [0x8b,0x12,0x04,0x56]
+nds.addigp t0, 0x2560
+
+# CHECK-ASM-AND-OBJ: lbgp t0, -9568
+# CHECK-ASM: encoding: [0x8b,0x82,0x1b,0xaa]
+nds.lbgp t0, -0x2560
+
+# CHECK-ASM-AND-OBJ: lbugp t0, 9568
+# CHECK-ASM: encoding: [0x8b,0x22,0x04,0x56]
+nds.lbugp t0, 0x2560
+
+# CHECK-ASM-AND-OBJ: lhgp t0, -9568
+# CHECK-ASM: encoding: [0xab,0x92,0x1b,0xaa]
+nds.lhgp t0, -0x2560
+
+# CHECK-ASM-AND-OBJ: lhugp t0, 9568
+# CHECK-ASM: encoding: [0xab,0x52,0x04,0x56]
+nds.lhugp t0, 0x2560
+
+# CHECK-ASM-AND-OBJ: lwgp t0, -9568
+# CHECK-ASM: encoding: [0xab,0xa2,0x3b,0xaa]
+nds.lwgp t0, -0x2560
+
+# CHECK-ASM-AND-OBJ: sbgp t0, 9568
+# CHECK-ASM: encoding: [0x0b,0x30,0x54,0x56]
+nds.sbgp t0, 0x2560
+
+# CHECK-ASM-AND-OBJ: shgp t0, -9568
+# CHECK-ASM: encoding: [0xab,0x80,0x5b,0xaa]
+nds.shgp t0, -0x2560
+
+# CHECK-ASM-AND-OBJ: swgp t0, 9568
+# CHECK-ASM: encoding: [0x2b,0x40,0x54,0x56]
+nds.swgp t0, 0x2560
+
+# CHECK-ASM-AND-OBJ: ffb t0, t1, t3
+# CHECK-ASM: encoding: [0xdb,0x02,0xc3,0x21]
+nds.ffb t0, t1, t3
+
+# CHECK-ASM-AND-OBJ: ffzmism a0, a1, a3
+# CHECK-ASM: encoding: [0x5b,0x85,0xd5,0x22]
+nds.ffzmism a0, a1, a3
+
+# CHECK-ASM-AND-OBJ: ffmism s0, s1, s3
+# CHECK-ASM: encoding: [0x5b,0x84,0x34,0x25]
+nds.ffmism s0, s1, s3
+
+# CHECK-ASM-AND-OBJ: flmism s0, s1, s3
+# CHECK-ASM: encoding: [0x5b,0x84,0x34,0x27]
+nds.flmism s0, s1, s3
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index 2ec27ba9d91b7..3966754496536 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -1107,6 +1107,7 @@ R"(All available -march extensions for RISC-V
svnapot 1.0
svpbmt 1.0
svvptc 1.0
+ xandesperf 5.0
xcvalu 1.0
xcvbi 1.0
xcvbitmanip 1.0
>From 2b379d71ae0ed229176ab72e90fb6dab64ff5dcf Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Fri, 11 Apr 2025 09:03:01 +0800
Subject: [PATCH 2/7] Typo: unsigned -> uint64_t
---
llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index ed56a92d08af8..97e33662b62b7 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -548,7 +548,7 @@ RISCVMCCodeEmitter::getImmOpValueAsrN(const MCInst &MI, unsigned OpNo,
const MCOperand &MO = MI.getOperand(OpNo);
if (MO.isImm()) {
- unsigned Res = MO.getImm();
+ uint64_t Res = MO.getImm();
assert((Res & ((1 << N) - 1)) == 0 && "LSB is non-zero");
return Res >> N;
}
>From 3f0e3bf1fc3576b1afa273e1704767e26971bccc Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Fri, 11 Apr 2025 09:22:23 +0800
Subject: [PATCH 3/7] Use isBareSimm.. as operand instead
---
.../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 26 +++---------
llvm/lib/Target/RISCV/RISCVInstrInfo.td | 17 +++++++-
llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td | 41 ++++++++++---------
llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td | 5 ---
4 files changed, 42 insertions(+), 47 deletions(-)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 3dafc21b84c21..03777a5b9053d 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -550,12 +550,6 @@ struct RISCVOperand final : public MCParsedAsmOperand {
VK == RISCVMCExpr::VK_None;
}
- // True if operand is a symbol with no modifiers, or a constant with no
- // modifiers and isShiftedInt<N-1, 1>(Op).
- template <int N> bool isBareSimmNLsb0() const {
- return isBareSimmNLsbK<N, 1>();
- }
-
// True if operand is a symbol with no modifiers, or a constant with no
// modifiers and isInt<N>(Op).
template <int N> bool isBareSimmN() const {
@@ -861,8 +855,6 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return SignExtend64<32>(Imm);
}
- bool isSImm11Lsb0() const { return isBareSimmNLsb0<11>(); }
-
bool isSImm12() const {
if (!isImm())
return false;
@@ -947,14 +939,6 @@ struct RISCVOperand final : public MCParsedAsmOperand {
[](int64_t Imm) { return Imm != INT64_MIN && isInt<5>(Imm - 1); });
}
- bool isSImm18() const { return isBareSimmNLsbK<18, 0>(); }
-
- bool isSImm18Lsb0() const { return isBareSimmNLsb0<18>(); }
-
- bool isSImm19Lsb00() const { return isBareSimmNLsbK<19, 2>(); }
-
- bool isSImm20Lsb000() const { return isBareSimmNLsbK<20, 3>(); }
-
bool isSImm32Lsb0() const {
return isSImmPred([](int64_t Imm) { return isShiftedInt<31, 1>(Imm); });
}
@@ -1526,7 +1510,7 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidSImm11:
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 10),
(1 << 10) - 1);
- case Match_InvalidSImm11Lsb0:
+ case Match_InvalidBareSImm11Lsb0:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 10), (1 << 10) - 2,
"immediate must be a multiple of 2 bytes in the range");
@@ -1602,18 +1586,18 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
(1 << 4),
"immediate must be in the range");
}
- case Match_InvalidSImm18:
+ case Match_InvalidBareSImm18:
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 17),
(1 << 17) - 1);
- case Match_InvalidSImm18Lsb0:
+ case Match_InvalidBareSImm18Lsb0:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 17), (1 << 17) - 2,
"immediate must be a multiple of 2 bytes in the range");
- case Match_InvalidSImm19Lsb00:
+ case Match_InvalidBareSImm19Lsb00:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 18), (1 << 18) - 4,
"immediate must be a multiple of 4 bytes in the range");
- case Match_InvalidSImm20Lsb000:
+ case Match_InvalidBareSImm20Lsb000:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 19), (1 << 19) - 8,
"immediate must be a multiple of 8 bytes in the range");
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index f1d455987c713..c933f74daf3cc 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -163,7 +163,22 @@ class UImmAsmOperand<int width, string suffix = "">
class BareSImmNLsb0AsmOperand<int width>
: ImmAsmOperand<"BareS", width, "Lsb0"> {
- let PredicateMethod = "isBareSimmNLsb0<" # width # ">";
+ let PredicateMethod = "isBareSimmNLsbK<" # width # ", 1>";
+}
+
+class BareSImmNLsb00AsmOperand<int width>
+ : ImmAsmOperand<"BareS", width, "Lsb00"> {
+ let PredicateMethod = "isBareSimmNLsbK<" # width # ", 2>";
+}
+
+class BareSImmNLsb000AsmOperand<int width>
+ : ImmAsmOperand<"BareS", width, "Lsb000"> {
+ let PredicateMethod = "isBareSimmNLsbK<" # width # ", 3>";
+}
+
+class BareSImmNAsmOperand<int width>
+ : ImmAsmOperand<"BareS", width, ""> {
+ let PredicateMethod = "isBareSimmN<" # width # ">";
}
class RISCVOp<ValueType vt = XLenVT> : Operand<vt> {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
index afe6e784dbfb0..570c06518e2cd 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
@@ -15,8 +15,8 @@
//===----------------------------------------------------------------------===//
// A 11-bit signed immediate where the least significant bit is zero.
-def simm11_lsb0 : Operand<OtherVT> {
- let ParserMatchClass = SImmAsmOperand<11, "Lsb0">;
+def bare_simm11_lsb0 : Operand<OtherVT> {
+ let ParserMatchClass = BareSImmNLsb0AsmOperand<11>;
let PrintMethod = "printBranchOperand";
let EncoderMethod = "getImmOpValueAsr1";
let DecoderMethod = "decodeSImmOperandAndLsl1<11>";
@@ -29,26 +29,26 @@ def simm11_lsb0 : Operand<OtherVT> {
let OperandType = "OPERAND_PCREL";
}
-def simm18 : Operand<XLenVT> {
- let ParserMatchClass = SImmAsmOperand<18>;
+def bare_simm18 : Operand<XLenVT> {
+ let ParserMatchClass = BareSImmNAsmOperand<18>;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeSImmOperand<18>";
}
-def simm18_lsb0 : Operand<XLenVT> {
- let ParserMatchClass = SImmAsmOperand<18, "Lsb0">;
+def bare_simm18_lsb0 : Operand<XLenVT> {
+ let ParserMatchClass = BareSImmNLsb0AsmOperand<18>;
let EncoderMethod = "getImmOpValueAsr1";
let DecoderMethod = "decodeSImmOperandAndLsl1<18>";
}
-def simm19_lsb00 : Operand<XLenVT> {
- let ParserMatchClass = SImmAsmOperand<19, "Lsb00">;
+def bare_simm19_lsb00 : Operand<XLenVT> {
+ let ParserMatchClass = BareSImmNLsb00AsmOperand<19>;
let EncoderMethod = "getImmOpValueAsrN<2>";
let DecoderMethod = "decodeSImmOperandAndLslN<19, 2>";
}
-def simm20_lsb000 : Operand<XLenVT> {
- let ParserMatchClass = SImmAsmOperand<20, "Lsb000">;
+def bare_simm20_lsb000 : Operand<XLenVT> {
+ let ParserMatchClass = BareSImmNLsb000AsmOperand<20>;
let EncoderMethod = "getImmOpValueAsrN<3>";
let DecoderMethod = "decodeSImmOperandAndLslN<20, 3>";
}
@@ -58,7 +58,7 @@ def simm20_lsb000 : Operand<XLenVT> {
//===----------------------------------------------------------------------===//
class NDSRVInstBB<bit cs, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs1, uimmlog2xlen:$cimm, simm11_lsb0:$imm10),
+ : RVInst<(outs), (ins GPR:$rs1, uimmlog2xlen:$cimm, bare_simm11_lsb0:$imm10),
opcodestr, "$rs1, $cimm, $imm10", [], InstFormatOther>,
Sched<[WriteJmp, ReadIALU]> {
bits<10> imm10;
@@ -82,7 +82,7 @@ class NDSRVInstBB<bit cs, string opcodestr>
}
class NDSRVInstBC<bits<3> funct3, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs1, uimm7:$cimm, simm11_lsb0:$imm10),
+ : RVInst<(outs), (ins GPR:$rs1, uimm7:$cimm, bare_simm11_lsb0:$imm10),
opcodestr, "$rs1, $cimm, $imm10", [], InstFormatOther>,
Sched<[WriteJmp, ReadIALU]> {
bits<10> imm10;
@@ -138,7 +138,7 @@ class NDSRVInstRR<bits<7> funct7, string opcodestr>
// GP: ADDI, LB, LBU
class NDSRVInstLBGP<bits<2> funct2, string opcodestr>
- : RVInst<(outs GPR:$rd), (ins simm18:$imm18),
+ : RVInst<(outs GPR:$rd), (ins bare_simm18:$imm18),
opcodestr, "$rd, ${imm18}", [], InstFormatOther> {
bits<18> imm18;
bits<5> rd;
@@ -159,7 +159,7 @@ class NDSRVInstLBGP<bits<2> funct2, string opcodestr>
// GP: LH, LHU
class NDSRVInstLHGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs GPR:$rd), (ins simm18_lsb0:$imm17),
+ : RVInst<(outs GPR:$rd), (ins bare_simm18_lsb0:$imm17),
opcodestr, "$rd, ${imm17}", [], InstFormatOther> {
bits<17> imm17;
bits<5> rd;
@@ -177,8 +177,9 @@ class NDSRVInstLHGP<bits<3> funct3, string opcodestr>
let mayStore = 0;
}
+// GP: LW
class NDSRVInstLWGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs GPR:$rd), (ins simm19_lsb00:$imm17),
+ : RVInst<(outs GPR:$rd), (ins bare_simm19_lsb00:$imm17),
opcodestr, "$rd, ${imm17}", [], InstFormatOther> {
bits<17> imm17;
bits<5> rd;
@@ -199,7 +200,7 @@ class NDSRVInstLWGP<bits<3> funct3, string opcodestr>
// GP: LD
class NDSRVInstLDGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs GPR:$rd), (ins simm20_lsb000:$imm17),
+ : RVInst<(outs GPR:$rd), (ins bare_simm20_lsb000:$imm17),
opcodestr, "$rd, ${imm17}", [], InstFormatOther> {
bits<17> imm17;
bits<5> rd;
@@ -220,7 +221,7 @@ class NDSRVInstLDGP<bits<3> funct3, string opcodestr>
// GP: SB
class NDSRVInstSBGP<bits<2> funct2, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs2, simm18:$imm18),
+ : RVInst<(outs), (ins GPR:$rs2, bare_simm18:$imm18),
opcodestr, "$rs2, ${imm18}", [], InstFormatOther> {
bits<18> imm18;
bits<5> rs2;
@@ -242,7 +243,7 @@ class NDSRVInstSBGP<bits<2> funct2, string opcodestr>
// GP: SH
class NDSRVInstSHGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs2, simm18_lsb0:$imm17),
+ : RVInst<(outs), (ins GPR:$rs2, bare_simm18_lsb0:$imm17),
opcodestr, "$rs2, ${imm17}", [], InstFormatOther> {
bits<17> imm17;
bits<5> rs2;
@@ -263,7 +264,7 @@ class NDSRVInstSHGP<bits<3> funct3, string opcodestr>
// GP: SW
class NDSRVInstSWGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs2, simm19_lsb00:$imm17),
+ : RVInst<(outs), (ins GPR:$rs2, bare_simm19_lsb00:$imm17),
opcodestr, "$rs2, ${imm17}", [], InstFormatOther> {
bits<17> imm17;
bits<5> rs2;
@@ -285,7 +286,7 @@ class NDSRVInstSWGP<bits<3> funct3, string opcodestr>
// GP: SD
class NDSRVInstSDGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs2, simm20_lsb000:$imm17),
+ : RVInst<(outs), (ins GPR:$rs2, bare_simm20_lsb000:$imm17),
opcodestr, "$rs2, ${imm17}", [], InstFormatOther> {
bits<17> imm17;
bits<5> rs2;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 78bf6337b4a00..042245b978cd7 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -118,11 +118,6 @@ def simm20_li : RISCVOp<XLenVT> {
def simm26 : RISCVSImmLeafOp<26>;
-class BareSImmNAsmOperand<int width>
- : ImmAsmOperand<"BareS", width, ""> {
- let PredicateMethod = "isBareSimmN<" # width # ">";
-}
-
// 32-bit Immediate, used by RV32 Instructions in 32-bit operations, so no
// sign-/zero-extension. This is represented internally as a signed 32-bit value.
def bare_simm32 : RISCVOp<XLenVT> {
>From 9a6c24d6042a0d3b1ba726425dd522253d021a45 Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Fri, 11 Apr 2025 09:23:33 +0800
Subject: [PATCH 4/7] Remove duplicated `let hasSideEffects = 0, mayLoad = 0,
mayStore = 0 in`
---
llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
index 570c06518e2cd..926bcd4f75c7d 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
@@ -125,7 +125,6 @@ class NDSRVInstBFO<bits<3> funct3, string opcodestr>
let mayStore = 0;
}
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class NDSRVInstRR<bits<7> funct7, string opcodestr>
: RVInstR<funct7, 0b000, OPC_CUSTOM_2,
(outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2),
>From f22e87b9f3c266a103c293ce529485a4acabbe84 Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Fri, 11 Apr 2025 13:31:05 +0800
Subject: [PATCH 5/7] Revert "Use isBareSimm.. as operand instead"
This reverts commit 3f0e3bf1fc3576b1afa273e1704767e26971bccc.
---
.../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 26 +++++++++---
llvm/lib/Target/RISCV/RISCVInstrInfo.td | 17 +-------
llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td | 41 +++++++++----------
llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td | 5 +++
4 files changed, 47 insertions(+), 42 deletions(-)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 03777a5b9053d..3dafc21b84c21 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -550,6 +550,12 @@ struct RISCVOperand final : public MCParsedAsmOperand {
VK == RISCVMCExpr::VK_None;
}
+ // True if operand is a symbol with no modifiers, or a constant with no
+ // modifiers and isShiftedInt<N-1, 1>(Op).
+ template <int N> bool isBareSimmNLsb0() const {
+ return isBareSimmNLsbK<N, 1>();
+ }
+
// True if operand is a symbol with no modifiers, or a constant with no
// modifiers and isInt<N>(Op).
template <int N> bool isBareSimmN() const {
@@ -855,6 +861,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return SignExtend64<32>(Imm);
}
+ bool isSImm11Lsb0() const { return isBareSimmNLsb0<11>(); }
+
bool isSImm12() const {
if (!isImm())
return false;
@@ -939,6 +947,14 @@ struct RISCVOperand final : public MCParsedAsmOperand {
[](int64_t Imm) { return Imm != INT64_MIN && isInt<5>(Imm - 1); });
}
+ bool isSImm18() const { return isBareSimmNLsbK<18, 0>(); }
+
+ bool isSImm18Lsb0() const { return isBareSimmNLsb0<18>(); }
+
+ bool isSImm19Lsb00() const { return isBareSimmNLsbK<19, 2>(); }
+
+ bool isSImm20Lsb000() const { return isBareSimmNLsbK<20, 3>(); }
+
bool isSImm32Lsb0() const {
return isSImmPred([](int64_t Imm) { return isShiftedInt<31, 1>(Imm); });
}
@@ -1510,7 +1526,7 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidSImm11:
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 10),
(1 << 10) - 1);
- case Match_InvalidBareSImm11Lsb0:
+ case Match_InvalidSImm11Lsb0:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 10), (1 << 10) - 2,
"immediate must be a multiple of 2 bytes in the range");
@@ -1586,18 +1602,18 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
(1 << 4),
"immediate must be in the range");
}
- case Match_InvalidBareSImm18:
+ case Match_InvalidSImm18:
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 17),
(1 << 17) - 1);
- case Match_InvalidBareSImm18Lsb0:
+ case Match_InvalidSImm18Lsb0:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 17), (1 << 17) - 2,
"immediate must be a multiple of 2 bytes in the range");
- case Match_InvalidBareSImm19Lsb00:
+ case Match_InvalidSImm19Lsb00:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 18), (1 << 18) - 4,
"immediate must be a multiple of 4 bytes in the range");
- case Match_InvalidBareSImm20Lsb000:
+ case Match_InvalidSImm20Lsb000:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 19), (1 << 19) - 8,
"immediate must be a multiple of 8 bytes in the range");
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index c933f74daf3cc..f1d455987c713 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -163,22 +163,7 @@ class UImmAsmOperand<int width, string suffix = "">
class BareSImmNLsb0AsmOperand<int width>
: ImmAsmOperand<"BareS", width, "Lsb0"> {
- let PredicateMethod = "isBareSimmNLsbK<" # width # ", 1>";
-}
-
-class BareSImmNLsb00AsmOperand<int width>
- : ImmAsmOperand<"BareS", width, "Lsb00"> {
- let PredicateMethod = "isBareSimmNLsbK<" # width # ", 2>";
-}
-
-class BareSImmNLsb000AsmOperand<int width>
- : ImmAsmOperand<"BareS", width, "Lsb000"> {
- let PredicateMethod = "isBareSimmNLsbK<" # width # ", 3>";
-}
-
-class BareSImmNAsmOperand<int width>
- : ImmAsmOperand<"BareS", width, ""> {
- let PredicateMethod = "isBareSimmN<" # width # ">";
+ let PredicateMethod = "isBareSimmNLsb0<" # width # ">";
}
class RISCVOp<ValueType vt = XLenVT> : Operand<vt> {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
index 926bcd4f75c7d..bf45ade786056 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
@@ -15,8 +15,8 @@
//===----------------------------------------------------------------------===//
// A 11-bit signed immediate where the least significant bit is zero.
-def bare_simm11_lsb0 : Operand<OtherVT> {
- let ParserMatchClass = BareSImmNLsb0AsmOperand<11>;
+def simm11_lsb0 : Operand<OtherVT> {
+ let ParserMatchClass = SImmAsmOperand<11, "Lsb0">;
let PrintMethod = "printBranchOperand";
let EncoderMethod = "getImmOpValueAsr1";
let DecoderMethod = "decodeSImmOperandAndLsl1<11>";
@@ -29,26 +29,26 @@ def bare_simm11_lsb0 : Operand<OtherVT> {
let OperandType = "OPERAND_PCREL";
}
-def bare_simm18 : Operand<XLenVT> {
- let ParserMatchClass = BareSImmNAsmOperand<18>;
+def simm18 : Operand<XLenVT> {
+ let ParserMatchClass = SImmAsmOperand<18>;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeSImmOperand<18>";
}
-def bare_simm18_lsb0 : Operand<XLenVT> {
- let ParserMatchClass = BareSImmNLsb0AsmOperand<18>;
+def simm18_lsb0 : Operand<XLenVT> {
+ let ParserMatchClass = SImmAsmOperand<18, "Lsb0">;
let EncoderMethod = "getImmOpValueAsr1";
let DecoderMethod = "decodeSImmOperandAndLsl1<18>";
}
-def bare_simm19_lsb00 : Operand<XLenVT> {
- let ParserMatchClass = BareSImmNLsb00AsmOperand<19>;
+def simm19_lsb00 : Operand<XLenVT> {
+ let ParserMatchClass = SImmAsmOperand<19, "Lsb00">;
let EncoderMethod = "getImmOpValueAsrN<2>";
let DecoderMethod = "decodeSImmOperandAndLslN<19, 2>";
}
-def bare_simm20_lsb000 : Operand<XLenVT> {
- let ParserMatchClass = BareSImmNLsb000AsmOperand<20>;
+def simm20_lsb000 : Operand<XLenVT> {
+ let ParserMatchClass = SImmAsmOperand<20, "Lsb000">;
let EncoderMethod = "getImmOpValueAsrN<3>";
let DecoderMethod = "decodeSImmOperandAndLslN<20, 3>";
}
@@ -58,7 +58,7 @@ def bare_simm20_lsb000 : Operand<XLenVT> {
//===----------------------------------------------------------------------===//
class NDSRVInstBB<bit cs, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs1, uimmlog2xlen:$cimm, bare_simm11_lsb0:$imm10),
+ : RVInst<(outs), (ins GPR:$rs1, uimmlog2xlen:$cimm, simm11_lsb0:$imm10),
opcodestr, "$rs1, $cimm, $imm10", [], InstFormatOther>,
Sched<[WriteJmp, ReadIALU]> {
bits<10> imm10;
@@ -82,7 +82,7 @@ class NDSRVInstBB<bit cs, string opcodestr>
}
class NDSRVInstBC<bits<3> funct3, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs1, uimm7:$cimm, bare_simm11_lsb0:$imm10),
+ : RVInst<(outs), (ins GPR:$rs1, uimm7:$cimm, simm11_lsb0:$imm10),
opcodestr, "$rs1, $cimm, $imm10", [], InstFormatOther>,
Sched<[WriteJmp, ReadIALU]> {
bits<10> imm10;
@@ -137,7 +137,7 @@ class NDSRVInstRR<bits<7> funct7, string opcodestr>
// GP: ADDI, LB, LBU
class NDSRVInstLBGP<bits<2> funct2, string opcodestr>
- : RVInst<(outs GPR:$rd), (ins bare_simm18:$imm18),
+ : RVInst<(outs GPR:$rd), (ins simm18:$imm18),
opcodestr, "$rd, ${imm18}", [], InstFormatOther> {
bits<18> imm18;
bits<5> rd;
@@ -158,7 +158,7 @@ class NDSRVInstLBGP<bits<2> funct2, string opcodestr>
// GP: LH, LHU
class NDSRVInstLHGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs GPR:$rd), (ins bare_simm18_lsb0:$imm17),
+ : RVInst<(outs GPR:$rd), (ins simm18_lsb0:$imm17),
opcodestr, "$rd, ${imm17}", [], InstFormatOther> {
bits<17> imm17;
bits<5> rd;
@@ -176,9 +176,8 @@ class NDSRVInstLHGP<bits<3> funct3, string opcodestr>
let mayStore = 0;
}
-// GP: LW
class NDSRVInstLWGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs GPR:$rd), (ins bare_simm19_lsb00:$imm17),
+ : RVInst<(outs GPR:$rd), (ins simm19_lsb00:$imm17),
opcodestr, "$rd, ${imm17}", [], InstFormatOther> {
bits<17> imm17;
bits<5> rd;
@@ -199,7 +198,7 @@ class NDSRVInstLWGP<bits<3> funct3, string opcodestr>
// GP: LD
class NDSRVInstLDGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs GPR:$rd), (ins bare_simm20_lsb000:$imm17),
+ : RVInst<(outs GPR:$rd), (ins simm20_lsb000:$imm17),
opcodestr, "$rd, ${imm17}", [], InstFormatOther> {
bits<17> imm17;
bits<5> rd;
@@ -220,7 +219,7 @@ class NDSRVInstLDGP<bits<3> funct3, string opcodestr>
// GP: SB
class NDSRVInstSBGP<bits<2> funct2, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs2, bare_simm18:$imm18),
+ : RVInst<(outs), (ins GPR:$rs2, simm18:$imm18),
opcodestr, "$rs2, ${imm18}", [], InstFormatOther> {
bits<18> imm18;
bits<5> rs2;
@@ -242,7 +241,7 @@ class NDSRVInstSBGP<bits<2> funct2, string opcodestr>
// GP: SH
class NDSRVInstSHGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs2, bare_simm18_lsb0:$imm17),
+ : RVInst<(outs), (ins GPR:$rs2, simm18_lsb0:$imm17),
opcodestr, "$rs2, ${imm17}", [], InstFormatOther> {
bits<17> imm17;
bits<5> rs2;
@@ -263,7 +262,7 @@ class NDSRVInstSHGP<bits<3> funct3, string opcodestr>
// GP: SW
class NDSRVInstSWGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs2, bare_simm19_lsb00:$imm17),
+ : RVInst<(outs), (ins GPR:$rs2, simm19_lsb00:$imm17),
opcodestr, "$rs2, ${imm17}", [], InstFormatOther> {
bits<17> imm17;
bits<5> rs2;
@@ -285,7 +284,7 @@ class NDSRVInstSWGP<bits<3> funct3, string opcodestr>
// GP: SD
class NDSRVInstSDGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs2, bare_simm20_lsb000:$imm17),
+ : RVInst<(outs), (ins GPR:$rs2, simm20_lsb000:$imm17),
opcodestr, "$rs2, ${imm17}", [], InstFormatOther> {
bits<17> imm17;
bits<5> rs2;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 042245b978cd7..78bf6337b4a00 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -118,6 +118,11 @@ def simm20_li : RISCVOp<XLenVT> {
def simm26 : RISCVSImmLeafOp<26>;
+class BareSImmNAsmOperand<int width>
+ : ImmAsmOperand<"BareS", width, ""> {
+ let PredicateMethod = "isBareSimmN<" # width # ">";
+}
+
// 32-bit Immediate, used by RV32 Instructions in 32-bit operations, so no
// sign-/zero-extension. This is represented internally as a signed 32-bit value.
def bare_simm32 : RISCVOp<XLenVT> {
>From 7f3d5d6bf42f1de78a12ff19cc4af180a6b78f48 Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Fri, 11 Apr 2025 14:21:30 +0800
Subject: [PATCH 6/7] Only support immediate operand for the branch and
GP-relative instructions
Parsing bare symbel would be supported in a follow-up patch.
---
.../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 32 +++++++++++--------
llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td | 6 ++--
2 files changed, 21 insertions(+), 17 deletions(-)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 3dafc21b84c21..9b149d006fc30 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -536,26 +536,20 @@ struct RISCVOperand final : public MCParsedAsmOperand {
}
// True if operand is a symbol with no modifiers, or a constant with no
- // modifiers and isShiftedInt<N-K, K>(Op).
- template <unsigned N, unsigned K> bool isBareSimmNLsbK() const {
+ // modifiers and isShiftedInt<N-1, 1>(Op).
+ template <int N> bool isBareSimmNLsb0() const {
if (!isImm())
return false;
int64_t Imm;
if (evaluateConstantImm(getImm(), Imm))
- return isShiftedInt<N - K, K>(fixImmediateForRV32(Imm, isRV64Imm()));
+ return isShiftedInt<N - 1, 1>(fixImmediateForRV32(Imm, isRV64Imm()));
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
VK == RISCVMCExpr::VK_None;
}
- // True if operand is a symbol with no modifiers, or a constant with no
- // modifiers and isShiftedInt<N-1, 1>(Op).
- template <int N> bool isBareSimmNLsb0() const {
- return isBareSimmNLsbK<N, 1>();
- }
-
// True if operand is a symbol with no modifiers, or a constant with no
// modifiers and isInt<N>(Op).
template <int N> bool isBareSimmN() const {
@@ -861,7 +855,9 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return SignExtend64<32>(Imm);
}
- bool isSImm11Lsb0() const { return isBareSimmNLsb0<11>(); }
+ bool isSImm11Lsb0() const {
+ return isSImmPred([](int64_t Imm) { return isShiftedInt<10, 1>(Imm); });
+ }
bool isSImm12() const {
if (!isImm())
@@ -947,13 +943,21 @@ struct RISCVOperand final : public MCParsedAsmOperand {
[](int64_t Imm) { return Imm != INT64_MIN && isInt<5>(Imm - 1); });
}
- bool isSImm18() const { return isBareSimmNLsbK<18, 0>(); }
+ bool isSImm18() const {
+ return isSImmPred([](int64_t Imm) { return isInt<18>(Imm); });
+ }
- bool isSImm18Lsb0() const { return isBareSimmNLsb0<18>(); }
+ bool isSImm18Lsb0() const {
+ return isSImmPred([](int64_t Imm) { return isShiftedInt<17, 1>(Imm); });
+ }
- bool isSImm19Lsb00() const { return isBareSimmNLsbK<19, 2>(); }
+ bool isSImm19Lsb00() const {
+ return isSImmPred([](int64_t Imm) { return isShiftedInt<17, 2>(Imm); });
+ }
- bool isSImm20Lsb000() const { return isBareSimmNLsbK<20, 3>(); }
+ bool isSImm20Lsb000() const {
+ return isSImmPred([](int64_t Imm) { return isShiftedInt<17, 3>(Imm); });
+ }
bool isSImm32Lsb0() const {
return isSImmPred([](int64_t Imm) { return isShiftedInt<31, 1>(Imm); });
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
index bf45ade786056..8ecbe267d3b11 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
@@ -22,9 +22,9 @@ def simm11_lsb0 : Operand<OtherVT> {
let DecoderMethod = "decodeSImmOperandAndLsl1<11>";
let MCOperandPredicate = [{
int64_t Imm;
- if (MCOp.evaluateAsConstantImm(Imm))
- return isShiftedInt<10, 1>(Imm);
- return MCOp.isBareSymbolRef();
+ if (!MCOp.evaluateAsConstantImm(Imm))
+ return false;
+ return isShiftedInt<10, 1>(Imm);
}];
let OperandType = "OPERAND_PCREL";
}
>From 2d51b9898615db04c1e2e9235a037de9ba7bd5cb Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Mon, 14 Apr 2025 13:10:01 +0800
Subject: [PATCH 7/7] Add comment for NDSRVInstLWGP
---
llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
index 8ecbe267d3b11..261d1a37d3f90 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
@@ -176,6 +176,7 @@ class NDSRVInstLHGP<bits<3> funct3, string opcodestr>
let mayStore = 0;
}
+// GP: LW, LWU
class NDSRVInstLWGP<bits<3> funct3, string opcodestr>
: RVInst<(outs GPR:$rd), (ins simm19_lsb00:$imm17),
opcodestr, "$rd, ${imm17}", [], InstFormatOther> {
More information about the cfe-commits
mailing list