[clang] [llvm] [RISCV] Xqccmp Code Generation (PR #128815)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 25 20:23:19 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
@llvm/pr-subscribers-clang
Author: Sam Elliott (lenary)
<details>
<summary>Changes</summary>
This adds support for Xqccmp to the following passes:
- Prolog Epilog Insertion - reusing much of the existing push/pop logic, but extending it to cope with frame pointers and reorder the CFI information correctly.
- Move Merger - extending it to support the `qc.` variants of the double-move instructions.
- Push/Pop Optimizer - extending it to support the `qc.` variants of the pop instructions.
The testing is based on existing Zcmp tests, but I have put them in separate files as some of the Zcmp tests were getting quite long.
---
This is stacked on #<!-- -->128731.
---
Patch is 293.87 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/128815.diff
26 Files Affected:
- (modified) clang/test/Driver/print-supported-extensions-riscv.c (+1)
- (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+12-1)
- (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+3)
- (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+8)
- (modified) llvm/lib/Target/RISCV/RISCVFrameLowering.cpp (+59-8)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.td (+1)
- (added) llvm/lib/Target/RISCV/RISCVInstrInfoXqccmp.td (+95)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZc.td (-2)
- (modified) llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h (+32-3)
- (modified) llvm/lib/Target/RISCV/RISCVMoveMerger.cpp (+54-12)
- (modified) llvm/lib/Target/RISCV/RISCVPushPopOptimizer.cpp (+27-8)
- (modified) llvm/lib/TargetParser/RISCVISAInfo.cpp (+5)
- (modified) llvm/test/CodeGen/RISCV/attributes.ll (+5)
- (added) llvm/test/CodeGen/RISCV/xqccmp-additional-stack.ll (+54)
- (added) llvm/test/CodeGen/RISCV/xqccmp-callee-saved-gprs.ll (+1171)
- (added) llvm/test/CodeGen/RISCV/xqccmp-cm-popretz.mir (+66)
- (added) llvm/test/CodeGen/RISCV/xqccmp-cm-push-pop.mir (+92)
- (added) llvm/test/CodeGen/RISCV/xqccmp-push-pop-popret.ll (+3889)
- (added) llvm/test/CodeGen/RISCV/xqccmp-with-float.ll (+90)
- (added) llvm/test/CodeGen/RISCV/xqccmp_mvas_mvsa.mir (+28)
- (added) llvm/test/MC/RISCV/rv32xqccmp-invalid.s (+35)
- (added) llvm/test/MC/RISCV/rv32xqccmp-valid.s (+353)
- (added) llvm/test/MC/RISCV/rv64e-xqccmp-valid.s (+85)
- (added) llvm/test/MC/RISCV/rv64xqccmp-invalid.s (+35)
- (added) llvm/test/MC/RISCV/rv64xqccmp-valid.s (+181)
- (modified) llvm/unittests/TargetParser/RISCVISAInfoTest.cpp (+6)
``````````diff
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index fcd820464e2d1..1c29ae98c96f0 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -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)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 650ad48e50de0..fb0ff9a73159d 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -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,
+ "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)) {
@@ -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) {
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 8c07d87680d65..7beed1d157024 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -745,6 +745,9 @@ DecodeStatus RISCVDisassembler::getInstruction16(MCInst &MI, uint64_t &Size,
"Qualcomm uC Conditional Move 16bit");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXqciint, DecoderTableXqciint16,
"Qualcomm uC Interrupts 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,
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 1a93371a4d92f..2b5b7173f2a68 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -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
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 32834a6b84f10..6526390f38abd 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -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::PushKind Kind,
+ bool hasFP) {
+ switch (Kind) {
+ case RISCVMachineFunctionInfo::PushKind::StdExtZcmp:
+ return RISCV::CM_PUSH;
+ case RISCVMachineFunctionInfo::PushKind::VendorXqccmp:
+ return hasFP ? RISCV::QC_CM_PUSHFP : RISCV::QC_CM_PUSH;
+ default:
+ llvm_unreachable("Unhandled PushKind");
+ }
+}
+
+static unsigned getPopOpcode(RISCVMachineFunctionInfo::PushKind Kind) {
+ // There are other pops but they are introduced later by the Push/Pop
+ // Optimizer.
+ switch (Kind) {
+ case RISCVMachineFunctionInfo::PushKind::StdExtZcmp:
+ return RISCV::CM_POP;
+ case llvm::RISCVMachineFunctionInfo::PushKind::VendorXqccmp:
+ return RISCV::CM_POP;
+ default:
+ llvm_unreachable("Unhandled Push Kind");
+ }
+}
+
void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
MachineFrameInfo &MFI = MF.getFrameInfo();
@@ -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.
@@ -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->getPushKind(MF) !=
+ RISCVMachineFunctionInfo::PushKind::VendorXqccmp) {
if (STI.isRegisterReservedByUser(FPReg))
MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{
MF.getFunction(), "Frame pointer required, but has been reserved."});
@@ -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.
@@ -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->getPushKind(MF) ==
+ RISCVMachineFunctionInfo::PushKind::StdExtZcmp)
Offset = -((FII->second + RVFI->getRVPushRegs() + 1) * (int64_t)Size);
else
Offset = FII->second * (int64_t)Size;
@@ -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->getPushKind(*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);
@@ -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->getPushKind(*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);
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index a962e64581797..c84caa76b1b4d 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -2147,6 +2147,7 @@ include "RISCVInstrInfoSFB.td"
include "RISCVInstrInfoXCV.td"
include "RISCVInstrInfoXwch.td"
include "RISCVInstrInfoXqci.td"
+include "RISCVInstrInfoXqccmp.td"
include "RISCVInstrInfoXMips.td"
include "RISCVInstrInfoXRivos.td"
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqccmp.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqccmp.td
new file mode 100644
index 0000000000000..5bb9c1e4b228b
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqccmp.td
@@ -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
+//===----------------------------------------------------------------------===//
+
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td
index 9dfbcf678d6eb..4944e85cbbcbb 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td
@@ -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";
}
diff --git a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
index 27a13bb7cace1..e8744a0dcb5cb 100644
--- a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
@@ -141,9 +141,38 @@ class RISCVMachineFunctionInfo : public MachineFunctionInfo {
// 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;
+ if (VarArgsSaveSize != 0)
+ return false;
+
+ // Zcmp is not compatible with the frame pointer convention.
+ if (MF.getSubtarget<RISCVSubtarget>().hasStdExtZcmp())
+ return !MF.getTarget().Options.DisableFramePointerElim(MF);
+
+ // Xqccmp is Zcmp but has a push order compatible with the frame-pointer
+ // convention.
+ if (MF.getSubtarget<RISCVSubtarget>().hasVendorXqccmp())
+ return true;
+
+ return false;
+ }
+
+ enum class PushKind { None = 0, StdExtZcmp, VendorXqccmp };
+
+ PushKind getPushKind(const MachineFunction &MF) const {
+ if (VarArgsSaveSize != 0)
+ return PushKind::None;
+
+ // Zcmp is not compatible with the frame pointer convention.
+ if (MF.getSubtarget<RISCVSubtarget>().hasStdExtZcmp() &&
+ !MF.getTarget().Options.DisableFramePointerElim(MF))
+ return PushKind::StdExtZcmp;
+
+ // Xqccmp is Zcmp but has a push order compatible with the frame-pointer
+ // convention.
+ if (MF.getSubtarget<RISCVSubtarget>().hasVendorXqccmp())
+ return PushKind::VendorXqccmp;
+
+ return PushKind::None;
}
int getRVPushRlist() const { return RVPushRlist; }
diff --git a/llvm/lib/Target/RISCV/RISCVMoveMerger.cpp b/llvm/lib/Target/RISCV/RISCVMoveMerger.cpp
index 3c5462057b280..7a2541a652b58 100644
--- a/llvm/lib/Target/RISCV/RISCVMoveMerger.cpp
+++ b/llvm/lib/Target/RISCV/RISCVMoveMerger.cpp
@@ -9,10 +9,12 @@
// This file contains a pass that performs move related peephole optimizations
// as Zcmp has specified. This pass should be run after register allocation.
//
+// This pass also supports Xqccmp, which has identical instructions.
+//
//===----------------------------------------------------------------------===//
#include "RISCVInstrInfo.h"
-#include "RISCVMachineFunctionInfo.h"
+#include "RISCVSubtarget.h"
using namespace llvm;
@@ -43,7 +45,7 @@ struct RISCVMoveMerge : public MachineFunctionPass {
MachineBasicBlock::iterator
findMatchingInst(MachineBasicBlock::iterator &MBBI, unsigned InstOpcode,
const DestSourcePair &RegPair);
- bool mergeMoveSARegPair(MachineBasicBlock &MBB);
+ bool mergeMoveSARegPair(const RISCVSubtarget &STI, MachineBasicBlock &MBB);
bool runOnMachineFunction(MachineFunction &Fn) override;
StringRef getPassName() const override { return RISCV_MOVE_MERGE_NAME; }
@@ -56,6 +58,46 @@ char RISCVMoveMerge::ID = 0;
INITIALIZE_PASS(RISCVMoveMerge, "riscv-move-merge", RISCV_MOVE_MERGE_NAME,
false, false)
+static bool isMoveFromAToS(unsigned Opcode) {
+ switch (Opcode) {
+ case RISCV::CM_MVA01S:
+ case RISCV::QC_CM_MVA01S:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static unsigned getMoveFromAToSOpcode(const RISCVSubtarget &STI) {
+ if (STI.hasStdExtZcmp())
+ return RISCV::CM_MVA01S;
+
+ if (STI.hasVendorXqccmp())
+ return RISCV::QC_CM_MVA01S;
+
+ llvm_unreachable("Unhandled subtarget with paired A to S move.");
+}
+
+static bool isMoveFromSToA(unsigned Opcode) {
+ switch (Opcode) {
+ case RISCV::CM_MVSA01:
+ case RISCV::QC_CM_MVSA01:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static unsigned getMoveFromSToAOpcode(const RISCVSubtarget &STI) {
+ if (STI.hasStdExtZcmp())
+ return RISCV::CM_MVSA01;
+
+ if (STI.hasVendorXqccmp())
+ return RISCV::QC_CM_MVSA01;
+
+ llvm_unreachable("Unhandled subtarget with paired S to A move");
+}
+
// Check if registers meet CM.MVA01S constraints.
bool RISCVMoveMerge::isCandidateToMergeMVA01S(const DestSourcePair &RegPair) {
Register Destination = RegPair.Destination->getReg();
@@ -87,7 +129,7 @@ RISCVMoveMerge::mergePairedInsns(MachineBasicBlock::iterator I,
MachineBasicBlock::iterator NextI = next_nodbg(I, E);
DestSourcePair FirstPair = TII->isCopyInstrImpl(*I).value();
DestSourcePair PairedRegs = TII->isCopyInstrImpl(*Paired).value();
- Register ARegInFirstPair = Opcode == RISCV::CM_MVA01S
+ Register ARegInFirstPair = isMoveFromAToS(Opcode)
? FirstPair.Destination->getReg()
: FirstPair.Source->getReg();
@@ -104,7 +146,7 @@ RISCVMoveMerge::mergePairedInsns(MachineBasicBlock::iterator I,
// mv a0, s2
// mv a1, s1 => cm.mva01s s2,s1
bool StartWithX10 = ARegInFirstPa...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/128815
More information about the llvm-commits
mailing list