Skip to content

Revert "Revert "[RISCV] Add Qualcomm uC Xqcisync (Sync Delay) extensi… #132520

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/test/Driver/print-supported-extensions-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@
// CHECK-NEXT: xqcilsm 0.2 'Xqcilsm' (Qualcomm uC Load Store Multiple Extension)
// CHECK-NEXT: xqcisim 0.2 'Xqcisim' (Qualcomm uC Simulation Hint Extension)
// CHECK-NEXT: xqcisls 0.2 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
// CHECK-NEXT: xqcisync 0.2 'Xqcisync' (Qualcomm uC Sync Delay Extension)
// CHECK-NEXT: xrivosvisni 0.1 'XRivosVisni' (Rivos Vector Integer Small New)
// CHECK-NEXT: xrivosvizip 0.1 'XRivosVizip' (Rivos Vector Register Zips)
// CHECK-EMPTY:
Expand Down
3 changes: 3 additions & 0 deletions llvm/docs/RISCVUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,9 @@ The current vendor extensions supported are:
``experimental-Xqcisls``
LLVM implements `version 0.2 of the Qualcomm uC Scaled Load Store extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm. All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.

``experimental-Xqcisync``
LLVM implements `version 0.2 of the Qualcomm uC Sync Delay extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm. All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.

``Xmipscmove``
LLVM implements conditional move for the `p8700 processor <https://mips.com/products/hardware/p8700/>` by MIPS.

Expand Down
2 changes: 2 additions & 0 deletions llvm/docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ Changes to the RISC-V Backend
* Added non-quadratic ``log-vrgather`` cost model for ``vrgather.vv`` instruction
* Adds experimental assembler support for the Qualcomm uC 'Xqcisim` (Simulation Hint)
extension.
* Adds experimental assembler support for the Qualcomm uC 'Xqcisync` (Sync Delay)
extension.
* Adds assembler support for the 'Zilsd` (Load/Store Pair Instructions)
extension.
* Adds assembler support for the 'Zclsd` (Compressed Load/Store Pair Instructions)
Expand Down
17 changes: 17 additions & 0 deletions llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,18 @@ struct RISCVOperand final : public MCParsedAsmOperand {
VK == RISCVMCExpr::VK_None;
}

bool isUImm5Slist() const {
if (!isImm())
return false;
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
int64_t Imm;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
return IsConstantImm &&
((Imm == 0) || (Imm == 1) || (Imm == 2) || (Imm == 4) ||
(Imm == 8) || (Imm == 16) || (Imm == 15) || (Imm == 31)) &&
VK == RISCVMCExpr::VK_None;
}

bool isUImm8GE32() const {
int64_t Imm;
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
Expand Down Expand Up @@ -1655,6 +1667,11 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5));
case Match_InvalidUImm5GE6Plus1:
return generateImmOutOfRangeError(Operands, ErrorInfo, 6, (1 << 5));
case Match_InvalidUImm5Slist: {
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
return Error(ErrorLoc,
"immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31");
}
case Match_InvalidUImm6:
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
case Match_InvalidUImm7:
Expand Down
26 changes: 18 additions & 8 deletions llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,15 @@ static DecodeStatus decodeUImmPlus1OperandGE(MCInst &Inst, uint32_t Imm,
return MCDisassembler::Success;
}

static DecodeStatus decodeUImmSlistOperand(MCInst &Inst, uint32_t Imm,
int64_t Address,
const MCDisassembler *Decoder) {
assert(isUInt<3>(Imm) && "Invalid Slist immediate");
const uint8_t Slist[] = {0, 1, 2, 4, 8, 16, 15, 31};
Inst.addOperand(MCOperand::createImm(Slist[Imm]));
return MCDisassembler::Success;
}

static DecodeStatus decodeUImmLog2XLenOperand(MCInst &Inst, uint32_t Imm,
int64_t Address,
const MCDisassembler *Decoder) {
Expand Down Expand Up @@ -663,14 +672,15 @@ static constexpr FeatureBitset XRivosFeatureGroup = {
};

static constexpr FeatureBitset XqciFeatureGroup = {
RISCV::FeatureVendorXqcia, RISCV::FeatureVendorXqciac,
RISCV::FeatureVendorXqcibi, RISCV::FeatureVendorXqcibm,
RISCV::FeatureVendorXqcicli, RISCV::FeatureVendorXqcicm,
RISCV::FeatureVendorXqcics, RISCV::FeatureVendorXqcicsr,
RISCV::FeatureVendorXqciint, RISCV::FeatureVendorXqcilb,
RISCV::FeatureVendorXqcili, RISCV::FeatureVendorXqcilia,
RISCV::FeatureVendorXqcilo, RISCV::FeatureVendorXqcilsm,
RISCV::FeatureVendorXqcisim, RISCV::FeatureVendorXqcisls,
RISCV::FeatureVendorXqcia, RISCV::FeatureVendorXqciac,
RISCV::FeatureVendorXqcibi, RISCV::FeatureVendorXqcibm,
RISCV::FeatureVendorXqcicli, RISCV::FeatureVendorXqcicm,
RISCV::FeatureVendorXqcics, RISCV::FeatureVendorXqcicsr,
RISCV::FeatureVendorXqciint, RISCV::FeatureVendorXqcilb,
RISCV::FeatureVendorXqcili, RISCV::FeatureVendorXqcilia,
RISCV::FeatureVendorXqcilo, RISCV::FeatureVendorXqcilsm,
RISCV::FeatureVendorXqcisim, RISCV::FeatureVendorXqcisls,
RISCV::FeatureVendorXqcisync,
};

static constexpr FeatureBitset XSfVectorGroup = {
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ enum OperandType : unsigned {
OPERAND_UIMM5_PLUS1,
OPERAND_UIMM5_GE6_PLUS1,
OPERAND_UIMM5_LSB0,
OPERAND_UIMM5_SLIST,
OPERAND_UIMM6,
OPERAND_UIMM6_LSB0,
OPERAND_UIMM7,
Expand Down
34 changes: 34 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;

uint64_t getImmOpValueSlist(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;

uint64_t getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
Expand Down Expand Up @@ -404,6 +408,36 @@ RISCVMCCodeEmitter::getImmOpValueMinus1(const MCInst &MI, unsigned OpNo,
return 0;
}

uint64_t
RISCVMCCodeEmitter::getImmOpValueSlist(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand &MO = MI.getOperand(OpNo);
assert(MO.isImm() && "Slist operand must be immediate");

uint64_t Res = MO.getImm();
switch (Res) {
case 0:
return 0;
case 1:
return 1;
case 2:
return 2;
case 4:
return 3;
case 8:
return 4;
case 16:
return 5;
case 15:
return 6;
case 31:
return 7;
default:
llvm_unreachable("Unhandled Slist value!");
}
}

uint64_t
RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/RISCV/RISCVFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -1448,6 +1448,14 @@ def HasVendorXqcisim
AssemblerPredicate<(all_of FeatureVendorXqcisim),
"'Xqcisim' (Qualcomm uC Simulation Hint Extension)">;

def FeatureVendorXqcisync
: RISCVExperimentalExtension<0, 2, "Qualcomm uC Sync Delay Extension",
[FeatureStdExtZca]>;
def HasVendorXqcisync
: Predicate<"Subtarget->hasVendorXqcisync()">,
AssemblerPredicate<(all_of FeatureVendorXqcisync),
"'Xqcisync' (Qualcomm uC Sync Delay Extension)">;

// Rivos Extension(s)

def FeatureVendorXRivosVisni
Expand Down
57 changes: 57 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,21 @@ def uimm5ge6_plus1 : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
let OperandType = "OPERAND_UIMM5_GE6_PLUS1";
}

def uimm5slist : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
[{return ((Imm == 0) ||
(Imm == 1) ||
(Imm == 2) ||
(Imm == 4) ||
(Imm == 8) ||
(Imm == 16) ||
(Imm == 15) ||
(Imm == 31));}]> {
let ParserMatchClass = UImmAsmOperand<5, "Slist">;
let EncoderMethod = "getImmOpValueSlist";
let DecoderMethod = "decodeUImmSlistOperand";
let OperandType = "OPERAND_UIMM5_SLIST";
}

def uimm10 : RISCVUImmLeafOp<10>;

def uimm11 : RISCVUImmLeafOp<11>;
Expand Down Expand Up @@ -364,6 +379,27 @@ class QCISim_RS1<bits<4> imm11_8, string opcodestr>
let imm12 = {imm11_8, 0b00000000};
}

let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
class QCISync_UIMM5<bits<4> imm11_8, string opcodestr>
: RVInstI<0b011, OPC_OP_IMM, (outs), (ins uimm5:$imm5), opcodestr, "$imm5">
{
bits<5> imm5;

let rs1 = 0;
let rd = 0;
let imm12 = {imm11_8, 0b000, imm5};
}

let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
class QCIRVInst16CBSYNC<bits<3> imm5_func2, string OpcodeStr>
: RVInst16CB<0b100, 0b01, (outs), (ins uimm5slist:$slist), OpcodeStr, "$slist"> {
bits<3> slist;

let Inst{6-2} = 0;
let Inst{9-7} = slist;
let Inst{12-10} = imm5_func2;
}

class QCIRVInstEIBase<bits<3> funct3, bits<2> funct2, dag outs,
dag ins, string opcodestr, string argstr>
: RVInst48<outs, ins, opcodestr, argstr, [], InstFormatOther> {
Expand Down Expand Up @@ -753,6 +789,27 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
} // Predicates = [HasVendorXqcilia, IsRV32]

let Predicates = [HasVendorXqcisync, IsRV32] in {
def QC_SYNC : QCISync_UIMM5<0b0001, "qc.sync">;
def QC_SYNCR : QCISync_UIMM5<0b0010, "qc.syncr">;
def QC_SYNCWF : QCISync_UIMM5<0b0100, "qc.syncwf">;
def QC_SYNCWL : QCISync_UIMM5<0b1000, "qc.syncwl">;

def QC_C_SYNC : QCIRVInst16CBSYNC<0b000, "qc.c.sync">;
def QC_C_SYNCR : QCIRVInst16CBSYNC<0b001, "qc.c.syncr">;
def QC_C_SYNCWF : QCIRVInst16CBSYNC<0b100, "qc.c.syncwf">;
def QC_C_SYNCWL : QCIRVInst16CBSYNC<0b101, "qc.c.syncwl">;

let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
def QC_C_DELAY : RVInst16CI<0b000, 0b10, (outs),
(ins uimm5nonzero:$imm),
"qc.c.delay", "$imm"> {
let Inst{12} = 0;
let Inst{11-7} = 0;
let Inst{6-2} = imm{4-0};
}
} // Predicates = [HasVendorXqcisync, IsRV32]

let Predicates = [HasVendorXqcisim, IsRV32] in {
let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in {
def QC_PSYSCALLI : RVInstI<0b010, OPC_OP_IMM, (outs), (ins uimm10:$imm10),
Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/TargetParser/RISCVISAInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -744,10 +744,10 @@ Error RISCVISAInfo::checkDependency() {
bool HasXqccmp = Exts.count("xqccmp") != 0;

static constexpr StringLiteral XqciExts[] = {
{"xqcia"}, {"xqciac"}, {"xqcibi"}, {"xqcibm"},
{"xqcicli"}, {"xqcicm"}, {"xqcics"}, {"xqcicsr"},
{"xqciint"}, {"xqcilb"}, {"xqcili"}, {"xqcilia"},
{"xqcilo"}, {"xqcilsm"}, {"xqcisim"}, {"xqcisls"}};
{"xqcia"}, {"xqciac"}, {"xqcibi"}, {"xqcibm"}, {"xqcicli"},
{"xqcicm"}, {"xqcics"}, {"xqcicsr"}, {"xqciint"}, {"xqcilb"},
{"xqcili"}, {"xqcilia"}, {"xqcilo"}, {"xqcilsm"}, {"xqcisim"},
{"xqcisls"}, {"xqcisync"}};
static constexpr StringLiteral ZcdOverlaps[] = {
{"zcmt"}, {"zcmp"}, {"xqccmp"}, {"xqciac"}, {"xqcicm"}};

Expand Down
2 changes: 2 additions & 0 deletions llvm/test/CodeGen/RISCV/attributes.ll
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilo %s -o - | FileCheck --check-prefix=RV32XQCILO %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilsm %s -o - | FileCheck --check-prefix=RV32XQCILSM %s
; 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=+zaamo %s -o - | FileCheck --check-prefix=RV32ZAAMO %s
; RUN: llc -mtriple=riscv32 -mattr=+zalrsc %s -o - | FileCheck --check-prefix=RV32ZALRSC %s
Expand Down Expand Up @@ -427,6 +428,7 @@
; RV32XQCILO: .attribute 5, "rv32i2p1_zca1p0_xqcilo0p2"
; RV32XQCILSM: .attribute 5, "rv32i2p1_xqcilsm0p2"
; RV32XQCISIM: attribute 5, "rv32i2p1_zca1p0_xqcisim0p2"
; RV32XQCISYNC: attribute 5, "rv32i2p1_zca1p0_xqcisync0p2"
; RV32XQCISLS: .attribute 5, "rv32i2p1_xqcisls0p2"
; RV32ZAAMO: .attribute 5, "rv32i2p1_zaamo1p0"
; RV32ZALRSC: .attribute 5, "rv32i2p1_zalrsc1p0"
Expand Down
121 changes: 121 additions & 0 deletions llvm/test/MC/RISCV/xqcisync-invalid.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Xqcisync - Qualcomm uC Sync Delay Extension
# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-xqcisync < %s 2>&1 \
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-PLUS %s
# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcisync < %s 2>&1 \
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-MINUS %s

# CHECK-PLUS: :[[@LINE+1]]:12: error: immediate must be an integer in the range [1, 31]
qc.c.delay 34

# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
qc.c.delay 11, 12

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.c.delay

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
qc.c.delay 10


# CHECK-PLUS: :[[@LINE+1]]:9: error: immediate must be an integer in the range [0, 31]
qc.sync 45

# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
qc.sync 22, x4

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.sync

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
qc.sync 8


# CHECK-PLUS: :[[@LINE+1]]:10: error: immediate must be an integer in the range [0, 31]
qc.syncr 56

# CHECK: :[[@LINE+1]]:14: error: invalid operand for instruction
qc.syncr 31, 45

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.syncr

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
qc.syncr 23


# CHECK-PLUS: :[[@LINE+1]]:11: error: immediate must be an integer in the range [0, 31]
qc.syncwf 88

# CHECK: :[[@LINE+1]]:14: error: invalid operand for instruction
qc.syncwf 5, 44

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.syncwf

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
qc.syncwf 31


# CHECK-PLUS: :[[@LINE+1]]:11: error: immediate must be an integer in the range [0, 31]
qc.syncwl 99

# CHECK: :[[@LINE+1]]:15: error: invalid operand for instruction
qc.syncwl 11, x10

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.syncwl

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
qc.syncwl 1


# CHECK-PLUS: :[[@LINE+1]]:11: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
qc.c.sync 45

# CHECK: :[[@LINE+1]]:15: error: invalid operand for instruction
qc.c.sync 31, x4

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.c.sync

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
qc.c.sync 8


# CHECK-PLUS: :[[@LINE+1]]:12: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
qc.c.syncr 56

# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
qc.c.syncr 31, 45

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.c.syncr

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
qc.c.syncr 8


# CHECK-PLUS: :[[@LINE+1]]:13: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
qc.c.syncwf 88

# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
qc.c.syncwf 8, 44

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.c.syncwf

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
qc.c.syncwf 31


# CHECK-PLUS: :[[@LINE+1]]:13: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
qc.c.syncwl 99

# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction
qc.c.syncwl 15, x10

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.c.syncwl

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
qc.c.syncwl 1
Loading