Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
6f8c6d1
[RISCV] Add Xqccmp Assembly Support
lenary Feb 25, 2025
1d71256
fixup! [RISCV] Add Xqccmp Assembly Support
lenary Feb 25, 2025
8162983
fixup! [RISCV] Add Xqccmp Assembly Support
lenary Feb 25, 2025
7e13372
fixup! [RISCV] Add Xqccmp Assembly Support
lenary Feb 25, 2025
b33add5
fixup! [RISCV] Add Xqccmp Assembly Support
lenary Feb 25, 2025
47e63a8
fixup! [RISCV] Add Xqccmp Assembly Support
lenary Feb 25, 2025
9e24cf9
[RISCV] Xqccmp Code Generation
lenary Feb 25, 2025
890cd31
Merge remote-tracking branch 'origin/main' into pr/xqccmp-assembly
lenary Feb 26, 2025
009a1cb
fixup! [RISCV] Add Xqccmp Assembly Support
lenary Feb 26, 2025
03a80db
Merge branch 'pr/xqccmp-assembly' into pr/riscv-xqccmp-codegen
lenary Feb 26, 2025
a80217e
fixup! [RISCV] Xqccmp Code Generation
lenary Feb 26, 2025
ee4b3c6
fixup! [RISCV] Xqccmp Code Generation
lenary Feb 26, 2025
607d6f4
fixup! [RISCV] Add Xqccmp Assembly Support
lenary Feb 26, 2025
cd9d4e3
Merge remote-tracking branch 'origin/main' into pr/xqccmp-assembly
lenary Feb 26, 2025
5d45bc7
Merge branch 'pr/xqccmp-assembly' into pr/riscv-xqccmp-codegen
lenary Feb 26, 2025
b5aa9bb
fixup! [RISCV] Xqccmp Code Generation
lenary Feb 26, 2025
35800f2
Merge remote-tracking branch 'origin/main' into pr/riscv-xqccmp-codegen
lenary Feb 28, 2025
ee917b4
Emit CFI to FP but don't move FP
lenary Feb 28, 2025
69eae06
fixup! Emit CFI to FP but don't move FP
lenary Feb 28, 2025
7eaab5f
fixup! Emit CFI to FP but don't move FP
lenary Feb 28, 2025
cbcf190
Merge remote-tracking branch 'origin/main' into pr/riscv-xqccmp-codegen
lenary Mar 4, 2025
c34be29
Fix Xqccmp test interrupt attributes
lenary Mar 4, 2025
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 @@ -193,6 +193,7 @@
// CHECK-NEXT: smctr 1.0 'Smctr' (Control Transfer Records Machine Level)
// CHECK-NEXT: ssctr 1.0 'Ssctr' (Control Transfer Records Supervisor Level)
// CHECK-NEXT: svukte 0.3 'Svukte' (Address-Independent Latency of User-Mode Faults to Supervisor Addresses)
// CHECK-NEXT: xqccmp 0.1 'Xqccmp' (Qualcomm 16-bit Push/Pop and Double Moves)
// CHECK-NEXT: xqcia 0.2 'Xqcia' (Qualcomm uC Arithmetic Extension)
// CHECK-NEXT: xqciac 0.3 'Xqciac' (Qualcomm uC Load-Store Address Calculation Extension)
// CHECK-NEXT: xqcicli 0.2 'Xqcicli' (Qualcomm uC Conditional Load Immediate Extension)
Expand Down
13 changes: 12 additions & 1 deletion llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1682,6 +1682,17 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidRnumArg: {
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);
}
case Match_InvalidStackAdj: {
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
StringRef SpecName = "Zc";
if (getSTI().hasFeature(RISCV::FeatureVendorXqccmp))
SpecName = "Xqccmp";

return Error(ErrorLoc,
Twine("stack adjustment is invalid for this instruction") +
" and register list; refer to " + SpecName +
" spec for a detailed range of stack adjustment");
}
}

if (const char *MatchDiag = getMatchKindDiag((RISCVMatchResultTy)Result)) {
Expand Down Expand Up @@ -3640,7 +3651,7 @@ bool RISCVAsmParser::validateInstruction(MCInst &Inst,
}
}

if (Opcode == RISCV::CM_MVSA01) {
if (Opcode == RISCV::CM_MVSA01 || Opcode == RISCV::QC_CM_MVSA01) {
MCRegister Rd1 = Inst.getOperand(0).getReg();
MCRegister Rd2 = Inst.getOperand(1).getReg();
if (Rd1 == Rd2) {
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,9 @@ DecodeStatus RISCVDisassembler::getInstruction16(MCInst &MI, uint64_t &Size,

TRY_TO_DECODE_FEATURE_ANY(XqciFeatureGroup, DecoderTableXqci16,
"Qualcomm uC 16bit");

TRY_TO_DECODE_FEATURE(
RISCV::FeatureVendorXqccmp, DecoderTableXqccmp16,
"Xqccmp (Qualcomm 16-bit Push/Pop & Double Move Instructions)");
TRY_TO_DECODE_AND_ADD_SP(STI.hasFeature(RISCV::FeatureVendorXwchc),
DecoderTableXwchc16, "WCH QingKe XW");
TRY_TO_DECODE_AND_ADD_SP(true, DecoderTable16,
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 @@ -1374,6 +1374,14 @@ def HasVendorXqcilo
AssemblerPredicate<(all_of FeatureVendorXqcilo),
"'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)">;

def FeatureVendorXqccmp
: RISCVExperimentalExtension<0, 1,
"Qualcomm 16-bit Push/Pop and Double Moves",
[FeatureStdExtZca]>;
def HasVendorXqccmp : Predicate<"Subtarget->hasVendorXqccmp()">,
AssemblerPredicate<(all_of FeatureVendorXqccmp),
"'Xqccmp' (Qualcomm 16-bit Push/Pop and Double Moves)">;

// Rivos Extension(s)

def FeatureVendorXRivosVizip
Expand Down
67 changes: 59 additions & 8 deletions llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,54 @@ void RISCVFrameLowering::allocateStack(MachineBasicBlock &MBB,
}
}

static bool isPush(unsigned Opcode) {
switch (Opcode) {
case RISCV::CM_PUSH:
case RISCV::QC_CM_PUSH:
case RISCV::QC_CM_PUSHFP:
return true;
default:
return false;
}
}

static bool isPop(unsigned Opcode) {
// There are other pops but these are the only ones introduced during this
// pass.
switch (Opcode) {
case RISCV::CM_POP:
case RISCV::QC_CM_POP:
return true;
default:
return false;
}
}

static unsigned getPushOpcode(RISCVMachineFunctionInfo::PushPopKind Kind,
bool HasFP) {
switch (Kind) {
case RISCVMachineFunctionInfo::PushPopKind::StdExtZcmp:
return RISCV::CM_PUSH;
case RISCVMachineFunctionInfo::PushPopKind::VendorXqccmp:
return HasFP ? RISCV::QC_CM_PUSHFP : RISCV::QC_CM_PUSH;
default:
llvm_unreachable("Unhandled PushPopKind");
}
}

static unsigned getPopOpcode(RISCVMachineFunctionInfo::PushPopKind Kind) {
// There are other pops but they are introduced later by the Push/Pop
// Optimizer.
switch (Kind) {
case RISCVMachineFunctionInfo::PushPopKind::StdExtZcmp:
return RISCV::CM_POP;
case RISCVMachineFunctionInfo::PushPopKind::VendorXqccmp:
return RISCV::QC_CM_POP;
default:
llvm_unreachable("Unhandled PushPopKind");
}
}

void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
MachineFrameInfo &MFI = MF.getFrameInfo();
Expand Down Expand Up @@ -882,7 +930,7 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
}

if (RVFI->isPushable(MF) && FirstFrameSetup != MBB.end() &&
FirstFrameSetup->getOpcode() == RISCV::CM_PUSH) {
isPush(FirstFrameSetup->getOpcode())) {
// Use available stack adjustment in push instruction to allocate additional
// stack space. Align the stack size down to a multiple of 16. This is
// needed for RVE.
Expand Down Expand Up @@ -926,7 +974,8 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
emitCFIForCSI<CFISaveRegisterEmitter>(MBB, MBBI, getUnmanagedCSI(MF, CSI));

// Generate new FP.
if (hasFP(MF)) {
if (hasFP(MF) && RVFI->getPushPopKind(MF) !=
RISCVMachineFunctionInfo::PushPopKind::VendorXqccmp) {
if (STI.isRegisterReservedByUser(FPReg))
MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{
MF.getFunction(), "Frame pointer required, but has been reserved."});
Expand Down Expand Up @@ -1193,9 +1242,7 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
// Recover callee-saved registers.
emitCFIForCSI<CFIRestoreRegisterEmitter>(MBB, MBBI, getUnmanagedCSI(MF, CSI));

bool ApplyPop = RVFI->isPushable(MF) && MBBI != MBB.end() &&
MBBI->getOpcode() == RISCV::CM_POP;
if (ApplyPop) {
if (RVFI->isPushable(MF) && MBBI != MBB.end() && isPop(MBBI->getOpcode())) {
// Use available stack adjustment in pop instruction to deallocate stack
// space. Align the stack size down to a multiple of 16. This is needed for
// RVE.
Expand Down Expand Up @@ -1816,7 +1863,8 @@ bool RISCVFrameLowering::assignCalleeSavedSpillSlots(
FixedCSRFIMap, [&](auto P) { return P.first == CS.getReg(); });
if (FII != std::end(FixedCSRFIMap)) {
int64_t Offset;
if (RVFI->isPushable(MF))
if (RVFI->getPushPopKind(MF) ==
RISCVMachineFunctionInfo::PushPopKind::StdExtZcmp)
Offset = -((FII->second + RVFI->getRVPushRegs() + 1) * (int64_t)Size);
else
Offset = FII->second * (int64_t)Size;
Expand Down Expand Up @@ -1881,8 +1929,10 @@ bool RISCVFrameLowering::spillCalleeSavedRegisters(
if (PushedRegNum > 0) {
// Use encoded number to represent registers to spill.
int RegEnc = RVFI->getRVPushRlist();

unsigned Opcode = getPushOpcode(RVFI->getPushPopKind(*MF), hasFP(*MF));
MachineInstrBuilder PushBuilder =
BuildMI(MBB, MI, DL, TII.get(RISCV::CM_PUSH))
BuildMI(MBB, MI, DL, TII.get(Opcode))
.setMIFlag(MachineInstr::FrameSetup);
PushBuilder.addImm((int64_t)RegEnc);
PushBuilder.addImm(0);
Expand Down Expand Up @@ -2035,8 +2085,9 @@ bool RISCVFrameLowering::restoreCalleeSavedRegisters(
if (RVFI->isPushable(*MF)) {
int RegEnc = RVFI->getRVPushRlist();
if (RegEnc != llvm::RISCVZC::RLISTENCODE::INVALID_RLIST) {
unsigned Opcode = getPopOpcode(RVFI->getPushPopKind(*MF));
MachineInstrBuilder PopBuilder =
BuildMI(MBB, MI, DL, TII.get(RISCV::CM_POP))
BuildMI(MBB, MI, DL, TII.get(Opcode))
.setMIFlag(MachineInstr::FrameDestroy);
// Use encoded number to represent registers to restore.
PopBuilder.addImm(RegEnc);
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -2153,6 +2153,7 @@ include "RISCVInstrInfoSFB.td"
include "RISCVInstrInfoXCV.td"
include "RISCVInstrInfoXwch.td"
include "RISCVInstrInfoXqci.td"
include "RISCVInstrInfoXqccmp.td"
include "RISCVInstrInfoXMips.td"
include "RISCVInstrInfoXRivos.td"

Expand Down
95 changes: 95 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXqccmp.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//===---------------- RISCVInstrInfoXqccmp.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 Qualcomm's Xqccmp extension.
//
// Xqccmp is broadly equivalent to (and incompatible with) Zcmp except the
// following changes:
//
// - The registers are pushed in the opposite order, so `ra` and `fp` are
// closest to the incoming stack pointer (to be compatible with the
// frame-pointer convention), and
//
// - There is a new `qc.cm.pushfp` instruction which is `qc.cm.push` but it sets
// `fp` to the incoming stack pointer value, as expected by the frame-pointer
// convention.
//
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// Operand and SDNode transformation definitions.
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// Instruction Formats
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// Instruction Class Templates
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//

let DecoderNamespace = "Xqccmp", Predicates = [HasVendorXqccmp] in {

let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
let Defs = [X10, X11] in
def QC_CM_MVA01S : RVInst16CA<0b101011, 0b11, 0b10, (outs),
(ins SR07:$rs1, SR07:$rs2), "qc.cm.mva01s", "$rs1, $rs2">,
Sched<[WriteIALU, WriteIALU, ReadIALU, ReadIALU]>;

let Uses = [X10, X11] in
def QC_CM_MVSA01 : RVInst16CA<0b101011, 0b01, 0b10, (outs SR07:$rs1, SR07:$rs2),
(ins), "qc.cm.mvsa01", "$rs1, $rs2">,
Sched<[WriteIALU, WriteIALU, ReadIALU, ReadIALU]>;
} // hasSideEffects = 0, mayLoad = 0, mayStore = 0

let hasSideEffects = 0, mayLoad = 0, mayStore = 1, Uses = [X2], Defs = [X2] in
def QC_CM_PUSH : RVInstZcCPPP<0b11000, "qc.cm.push", negstackadj>,
Sched<[WriteIALU, ReadIALU, ReadStoreData, ReadStoreData,
ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData,
ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData,
ReadStoreData, ReadStoreData, ReadStoreData]>;

let hasSideEffects = 0, mayLoad = 0, mayStore = 1, Uses = [X2], Defs = [X2, X8] in
def QC_CM_PUSHFP : RVInstZcCPPP<0b11001, "qc.cm.pushfp", negstackadj>,
Sched<[WriteIALU, WriteIALU, ReadIALU, ReadStoreData, ReadStoreData,
ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData,
ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData,
ReadStoreData, ReadStoreData, ReadStoreData]>;

let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isReturn = 1,
Uses = [X2], Defs = [X2] in
def QC_CM_POPRET : RVInstZcCPPP<0b11110, "qc.cm.popret">,
Sched<[WriteIALU, WriteLDW, WriteLDW, WriteLDW, WriteLDW,
WriteLDW, WriteLDW, WriteLDW, WriteLDW, WriteLDW,
WriteLDW, WriteLDW, WriteLDW, WriteLDW, ReadIALU]>;

let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isReturn = 1,
Uses = [X2], Defs = [X2, X10] in
def QC_CM_POPRETZ : RVInstZcCPPP<0b11100, "qc.cm.popretz">,
Sched<[WriteIALU, WriteIALU, WriteLDW, WriteLDW, WriteLDW,
WriteLDW, WriteLDW, WriteLDW, WriteLDW, WriteLDW,
WriteLDW, WriteLDW, WriteLDW, WriteLDW, WriteLDW,
ReadIALU]>;

let hasSideEffects = 0, mayLoad = 1, mayStore = 0,
Uses = [X2], Defs = [X2] in
def QC_CM_POP : RVInstZcCPPP<0b11010, "qc.cm.pop">,
Sched<[WriteIALU, WriteLDW, WriteLDW, WriteLDW, WriteLDW,
WriteLDW, WriteLDW, WriteLDW, WriteLDW, WriteLDW, WriteLDW,
WriteLDW, WriteLDW, WriteLDW, ReadIALU]>;

} // DecoderNamespace = "Xqccmp", Predicates = [HasVendorXqccmp]

//===----------------------------------------------------------------------===//
// Aliases
//===----------------------------------------------------------------------===//

2 changes: 0 additions & 2 deletions llvm/lib/Target/RISCV/RISCVInstrInfoZc.td
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ def StackAdjAsmOperand : AsmOperandClass {
let Name = "StackAdj";
let ParserMethod = "parseZcmpStackAdj";
let DiagnosticType = "InvalidStackAdj";
let DiagnosticString = "stack adjustment is invalid for this instruction and register list; "
"refer to Zc spec for a detailed range of stack adjustment";
let PredicateMethod = "isSpimm";
let RenderMethod = "addSpimmOperands";
}
Expand Down
21 changes: 21 additions & 0 deletions llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,27 @@ void yaml::RISCVMachineFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
MappingTraits<RISCVMachineFunctionInfo>::mapping(YamlIO, *this);
}

RISCVMachineFunctionInfo::PushPopKind
RISCVMachineFunctionInfo::getPushPopKind(const MachineFunction &MF) const {
// We cannot use fixed locations for the callee saved spill slots if the
// function uses a varargs save area.
// TODO: Use a separate placement for vararg registers to enable Zcmp.
if (VarArgsSaveSize != 0)
return PushPopKind::None;

// Zcmp is not compatible with the frame pointer convention.
if (MF.getSubtarget<RISCVSubtarget>().hasStdExtZcmp() &&
!MF.getTarget().Options.DisableFramePointerElim(MF))
return PushPopKind::StdExtZcmp;

// Xqccmp is Zcmp but has a push order compatible with the frame-pointer
// convention.
if (MF.getSubtarget<RISCVSubtarget>().hasVendorXqccmp())
return PushPopKind::VendorXqccmp;

return PushPopKind::None;
}

void RISCVMachineFunctionInfo::initializeBaseYamlFields(
const yaml::RISCVMachineFunctionInfo &YamlMFI) {
VarArgsFrameIndex = YamlMFI.VarArgsFrameIndex;
Expand Down
11 changes: 5 additions & 6 deletions llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,12 @@ class RISCVMachineFunctionInfo : public MachineFunctionInfo {
unsigned getCalleeSavedStackSize() const { return CalleeSavedStackSize; }
void setCalleeSavedStackSize(unsigned Size) { CalleeSavedStackSize = Size; }

enum class PushPopKind { None = 0, StdExtZcmp, VendorXqccmp };

PushPopKind getPushPopKind(const MachineFunction &MF) const;

bool isPushable(const MachineFunction &MF) const {
// We cannot use fixed locations for the callee saved spill slots if the
// function uses a varargs save area.
// TODO: Use a separate placement for vararg registers to enable Zcmp.
return MF.getSubtarget<RISCVSubtarget>().hasStdExtZcmp() &&
!MF.getTarget().Options.DisableFramePointerElim(MF) &&
VarArgsSaveSize == 0;
return getPushPopKind(MF) != PushPopKind::None;
}

int getRVPushRlist() const { return RVPushRlist; }
Expand Down
Loading