Skip to content

[RISCV][Xqccmp] Correctly Parse/Disassemble pushfp #133188

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 10 commits into from
Mar 28, 2025

Conversation

lenary
Copy link
Member

@lenary lenary commented Mar 27, 2025

In the qc.cm.pushfp instruction, it is like cm.pushfp except in one important way - qc.cm.pushfp {ra}, -N*16 is not a valid encoding, because this would update s0/fp/x8 without saving it.

This change now correctly rejects this variant of the instruction, both during parsing and during disassembly. I also implemented validation for immediates that represent register lists (both kinds), which may help to catch bugs in the future.

In the `qc.cm.pushfp` instruction, it is like `cm.pushfp` except in one
important way - `qc.cm.pushfp {ra}, -N*16` is not a valid encoding,
because this would update `s0`/`fp`/`x8` without saving it.

This change now correctly rejects this variant of the instruction, both
during parsing and during disassembly. I also implemented validation for
immediates that represent register lists (both kinds), which may help to
catch bugs in the future.
@lenary lenary requested review from svs-quic and hchandel March 27, 2025 01:04
@llvmbot llvmbot added backend:RISC-V mc Machine (object) code labels Mar 27, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 27, 2025

@llvm/pr-subscribers-backend-risc-v

@llvm/pr-subscribers-mc

Author: Sam Elliott (lenary)

Changes

In the qc.cm.pushfp instruction, it is like cm.pushfp except in one important way - qc.cm.pushfp {ra}, -N*16 is not a valid encoding, because this would update s0/fp/x8 without saving it.

This change now correctly rejects this variant of the instruction, both during parsing and during disassembly. I also implemented validation for immediates that represent register lists (both kinds), which may help to catch bugs in the future.


Full diff: https://github.com/llvm/llvm-project/pull/133188.diff

12 Files Affected:

  • (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+25-2)
  • (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+11)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h (+2)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp (+15)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.cpp (+6)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqccmp.td (+39-1)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZc.td (+3-1)
  • (added) llvm/test/MC/Disassembler/RISCV/xqccmp-invalid-rlist.txt (+11)
  • (modified) llvm/test/MC/RISCV/rv32xqccmp-invalid.s (+4)
  • (modified) llvm/test/MC/RISCV/rv32xqccmp-valid.s (-8)
  • (modified) llvm/test/MC/RISCV/rv64e-xqccmp-valid.s (-4)
  • (modified) llvm/test/MC/RISCV/rv64xqccmp-valid.s (-4)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 0d40fb5614009..19f28a6287060 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -215,7 +215,10 @@ class RISCVAsmParser : public MCTargetAsmParser {
   ParseStatus parseGPRPair(OperandVector &Operands, bool IsRV64Inst);
   ParseStatus parseFRMArg(OperandVector &Operands);
   ParseStatus parseFenceArg(OperandVector &Operands);
+
+  template <bool MustIncludeS0 = false>
   ParseStatus parseReglist(OperandVector &Operands);
+
   ParseStatus parseRegReg(OperandVector &Operands);
   ParseStatus parseRetval(OperandVector &Operands);
   ParseStatus parseZcmpStackAdj(OperandVector &Operands,
@@ -474,6 +477,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
   bool isRegReg() const { return Kind == KindTy::RegReg; }
   bool isRlist() const { return Kind == KindTy::Rlist; }
+  bool isRlistS0() const { return Kind == KindTy::Rlist && Rlist.Val != 4; }
   bool isSpimm() const { return Kind == KindTy::Spimm; }
 
   bool isGPR() const {
@@ -2794,9 +2798,15 @@ ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
   return ParseStatus::Success;
 }
 
+template <bool MustIncludeS0>
 ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
   // Rlist: {ra [, s0[-sN]]}
   // XRlist: {x1 [, x8[-x9][, x18[-xN]]]}
+
+  // When MustIncludeS0 = true (not the default) (used for `qc.cm.pushfp`) which
+  // must include `fp`/`s0` in the list:
+  // Rlist: {ra, s0[-sN]}
+  // XRlist: {x1, x8[-x9][, x18[-xN]]}
   SMLoc S = getLoc();
 
   if (parseToken(AsmToken::LCurly, "register list must start with '{'"))
@@ -2814,8 +2824,19 @@ ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
     return Error(getLoc(), "register list must start from 'ra' or 'x1'");
   getLexer().Lex();
 
-  // parse case like ,s0
-  if (parseOptionalToken(AsmToken::Comma)) {
+  bool SeenComma = false;
+
+  // If you must include S0, then you need the comma. Fail now if it isn't there
+  if constexpr (MustIncludeS0) {
+    if (parseToken(AsmToken::Comma, "register list must include 's0' or 'x8'"))
+      return ParseStatus::Failure;
+    SeenComma = true;
+  } else {
+    SeenComma = parseOptionalToken(AsmToken::Comma);
+  }
+
+  // parse case like ,s0 - we may have already seen the comma in which case skip
+  if (SeenComma) {
     if (getLexer().isNot(AsmToken::Identifier))
       return Error(getLoc(), "invalid register");
     StringRef RegName = getLexer().getTok().getIdentifier();
@@ -2884,6 +2905,8 @@ ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
 
   auto Encode = RISCVZC::encodeRlist(RegEnd, IsEABI);
   assert(Encode != RISCVZC::INVALID_RLIST);
+  if constexpr (MustIncludeS0)
+    assert(Encode != RISCVZC::RA);
   Operands.push_back(RISCVOperand::createRlist(Encode, S));
 
   return ParseStatus::Success;
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 93cbf662bfa32..d03351db5473b 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -507,6 +507,9 @@ static DecodeStatus decodeXTHeadMemPair(MCInst &Inst, uint32_t Insn,
 static DecodeStatus decodeZcmpRlist(MCInst &Inst, uint32_t Imm,
                                     uint64_t Address, const void *Decoder);
 
+static DecodeStatus decodeXqccmpRlistS0(MCInst &Inst, uint32_t Imm,
+                                        uint64_t Address, const void *Decoder);
+
 static DecodeStatus decodeRegReg(MCInst &Inst, uint32_t Insn, uint64_t Address,
                                  const MCDisassembler *Decoder);
 
@@ -621,6 +624,14 @@ static DecodeStatus decodeZcmpRlist(MCInst &Inst, uint32_t Imm,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus decodeXqccmpRlistS0(MCInst &Inst, uint32_t Imm,
+                                        uint64_t Address, const void *Decoder) {
+  if (Imm <= 4)
+    return MCDisassembler::Fail;
+  Inst.addOperand(MCOperand::createImm(Imm));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus decodeRegReg(MCInst &Inst, uint32_t Insn, uint64_t Address,
                                  const MCDisassembler *Decoder) {
   uint32_t Rs1 = fieldFromInstruction(Insn, 0, 5);
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index db305b0083415..0ede9ba7cf712 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -343,6 +343,8 @@ enum OperandType : unsigned {
   OPERAND_RVKRNUM_0_7,
   OPERAND_RVKRNUM_1_10,
   OPERAND_RVKRNUM_2_14,
+  OPERAND_RLIST,
+  OPERAND_RLIST_S0,
   OPERAND_SPIMM,
   // Operand is a 3-bit rounding mode, '111' indicates FRM register.
   // Represents 'frm' argument passing to floating-point operations.
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index e589e6171d010..6163175347ca0 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -104,6 +104,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
                            SmallVectorImpl<MCFixup> &Fixups,
                            const MCSubtargetInfo &STI) const;
 
+  unsigned getRlistS0OpValue(const MCInst &MI, unsigned OpNo,
+                             SmallVectorImpl<MCFixup> &Fixups,
+                             const MCSubtargetInfo &STI) const;
+
   unsigned getRegReg(const MCInst &MI, unsigned OpNo,
                      SmallVectorImpl<MCFixup> &Fixups,
                      const MCSubtargetInfo &STI) const;
@@ -621,6 +625,17 @@ unsigned RISCVMCCodeEmitter::getRlistOpValue(const MCInst &MI, unsigned OpNo,
   return Imm;
 }
 
+unsigned
+RISCVMCCodeEmitter::getRlistS0OpValue(const MCInst &MI, unsigned OpNo,
+                                      SmallVectorImpl<MCFixup> &Fixups,
+                                      const MCSubtargetInfo &STI) const {
+  const MCOperand &MO = MI.getOperand(OpNo);
+  assert(MO.isImm() && "Rlist operand must be immediate");
+  auto Imm = MO.getImm();
+  assert(Imm >= 5 && "EABI is currently not implemented");
+  return Imm;
+}
+
 unsigned RISCVMCCodeEmitter::getRegReg(const MCInst &MI, unsigned OpNo,
                                        SmallVectorImpl<MCFixup> &Fixups,
                                        const MCSubtargetInfo &STI) const {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 4fb11f278df97..7867fd7d516cc 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -2642,6 +2642,12 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
         case RISCVOp::OPERAND_RVKRNUM_2_14:
           Ok = Imm >= 2 && Imm <= 14;
           break;
+        case RISCVOp::OPERAND_RLIST:
+          Ok = Imm >= RISCVZC::RA && Imm <= RISCVZC::RA_S0_S11;
+          break;
+        case RISCVOp::OPERAND_RLIST_S0:
+          Ok = Imm >= RISCVZC::RA_S0 && Imm <= RISCVZC::RA_S0_S11;
+          break;
         case RISCVOp::OPERAND_SPIMM:
           Ok = (Imm & 0xf) == 0;
           break;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqccmp.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqccmp.td
index 5bb9c1e4b228b..8cb1cf151f1ad 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqccmp.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqccmp.td
@@ -25,6 +25,30 @@
 // Operand and SDNode transformation definitions.
 //===----------------------------------------------------------------------===//
 
+def RlistS0AsmOperand : AsmOperandClass {
+  let Name = "RlistS0";
+  let ParserMethod = "parseReglist<true>";
+  let RenderMethod = "addRlistOperands";
+  let DiagnosticType = "InvalidRlistS0";
+  let DiagnosticString = "operand must be {ra, s0[-sN]} or {x1, x8[-x9][, x18[-xN]]}";
+}
+
+def rlist_s0 : RISCVOp<OtherVT> {
+   let ParserMatchClass = RlistS0AsmOperand;
+   let PrintMethod = "printRlist";
+   let DecoderMethod = "decodeXqccmpRlistS0";
+   let EncoderMethod = "getRlistS0OpValue";
+   let MCOperandPredicate = [{
+    int64_t Imm;
+    if (!MCOp.evaluateAsConstantImm(Imm))
+      return false;
+    // 0~4 invalid for `qc.cm.pushfp`
+    return isUInt<4>(Imm) && Imm >= 5;
+  }];
+
+  string OperandType = "OPERAND_RLIST_S0";
+}
+
 //===----------------------------------------------------------------------===//
 // Instruction Formats
 //===----------------------------------------------------------------------===//
@@ -33,6 +57,20 @@
 // Instruction Class Templates
 //===----------------------------------------------------------------------===//
 
+class RVInstXqccmpCPPPFP<bits<5> funct5, string opcodestr,
+                         DAGOperand immtype = stackadj>
+    : RVInst16<(outs), (ins rlist_s0:$rlist, immtype:$stackadj),
+               opcodestr, "$rlist, $stackadj", [], InstFormatOther> {
+  bits<4> rlist;
+  bits<16> stackadj;
+
+  let Inst{1-0} = 0b10;
+  let Inst{3-2} = stackadj{5-4};
+  let Inst{7-4} = rlist;
+  let Inst{12-8} = funct5;
+  let Inst{15-13} = 0b101;
+}
+
 //===----------------------------------------------------------------------===//
 // Instructions
 //===----------------------------------------------------------------------===//
@@ -59,7 +97,7 @@ def QC_CM_PUSH : RVInstZcCPPP<0b11000, "qc.cm.push", negstackadj>,
                         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>,
+def QC_CM_PUSHFP : RVInstXqccmpCPPPFP<0b11001, "qc.cm.pushfp", negstackadj>,
                    Sched<[WriteIALU, WriteIALU, ReadIALU, ReadStoreData, ReadStoreData,
                           ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData,
                           ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td
index efed74ca8c870..04c10220f5bf1 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td
@@ -58,7 +58,7 @@ def NegStackAdjAsmOperand : AsmOperandClass {
   let RenderMethod = "addSpimmOperands";
 }
 
-def rlist : Operand<OtherVT> {
+def rlist : RISCVOp<OtherVT> {
    let ParserMatchClass = RlistAsmOperand;
    let PrintMethod = "printRlist";
    let DecoderMethod = "decodeZcmpRlist";
@@ -70,6 +70,8 @@ def rlist : Operand<OtherVT> {
     // 0~3 Reserved for EABI
     return isUInt<4>(Imm) && Imm >= 4;
   }];
+
+  let OperandType = "OPERAND_RLIST";
 }
 
 def stackadj : RISCVOp<OtherVT> {
diff --git a/llvm/test/MC/Disassembler/RISCV/xqccmp-invalid-rlist.txt b/llvm/test/MC/Disassembler/RISCV/xqccmp-invalid-rlist.txt
new file mode 100644
index 0000000000000..fe81c01a037af
--- /dev/null
+++ b/llvm/test/MC/Disassembler/RISCV/xqccmp-invalid-rlist.txt
@@ -0,0 +1,11 @@
+# RUN: not llvm-mc -disassemble -triple=riscv32 -mattr=+experimental-xqccmp %s \
+# RUN:   | FileCheck -check-prefixes=CHECK,CHECK-XQCCMP %s
+
+[0x00,0x00]
+# CHECK: unimp
+
+[0x42,0xb9]
+# CHECK-XQCCMP-NOT: qc.cm.pushfp {ra}, -{{[0-9]+}}
+
+[0x00,0x00]
+# CHECK: unimp
diff --git a/llvm/test/MC/RISCV/rv32xqccmp-invalid.s b/llvm/test/MC/RISCV/rv32xqccmp-invalid.s
index 74f96f076756c..059009de3d830 100644
--- a/llvm/test/MC/RISCV/rv32xqccmp-invalid.s
+++ b/llvm/test/MC/RISCV/rv32xqccmp-invalid.s
@@ -33,3 +33,7 @@ qc.cm.pushfp {ra, s0}, -12
 
 # CHECK-ERROR: error: stack adjustment for register list must be a multiple of 16 bytes in the range [16, 64]
 qc.cm.pop {ra, s0-s1}, -40
+
+# CHECK-ERROR: error: register list must include 's0' or 'x8'
+qc.cm.pushfp {ra}, -16
+
diff --git a/llvm/test/MC/RISCV/rv32xqccmp-valid.s b/llvm/test/MC/RISCV/rv32xqccmp-valid.s
index 5827777e524ca..b1f373ede247d 100644
--- a/llvm/test/MC/RISCV/rv32xqccmp-valid.s
+++ b/llvm/test/MC/RISCV/rv32xqccmp-valid.s
@@ -288,14 +288,6 @@ qc.cm.push {ra, s0-s11}, -112
 # CHECK-ASM: encoding: [0xfe,0xb8]
 qc.cm.push {x1, x8-x9, x18-x27}, -112
 
-# CHECK-ASM-AND-OBJ: qc.cm.pushfp {ra}, -16
-# CHECK-ASM: encoding: [0x42,0xb9]
-qc.cm.pushfp {ra}, -16
-
-# CHECK-ASM-AND-OBJ: qc.cm.pushfp {ra}, -16
-# CHECK-ASM: encoding: [0x42,0xb9]
-qc.cm.pushfp {x1}, -16
-
 # CHECK-ASM-AND-OBJ: qc.cm.pushfp {ra, s0}, -32
 # CHECK-ASM: encoding: [0x56,0xb9]
 qc.cm.pushfp {ra, s0}, -32
diff --git a/llvm/test/MC/RISCV/rv64e-xqccmp-valid.s b/llvm/test/MC/RISCV/rv64e-xqccmp-valid.s
index 8f9e3ce7ee533..003f9852b184a 100644
--- a/llvm/test/MC/RISCV/rv64e-xqccmp-valid.s
+++ b/llvm/test/MC/RISCV/rv64e-xqccmp-valid.s
@@ -72,10 +72,6 @@ qc.cm.push {ra, s0}, -32
 # CHECK-ASM: encoding: [0x62,0xb8]
 qc.cm.push {ra, s0-s1}, -32
 
-# CHECK-ASM-AND-OBJ: qc.cm.pushfp {ra}, -16
-# CHECK-ASM: encoding: [0x42,0xb9]
-qc.cm.pushfp {ra}, -16
-
 # CHECK-ASM-AND-OBJ: qc.cm.pushfp {ra, s0}, -32
 # CHECK-ASM: encoding: [0x56,0xb9]
 qc.cm.pushfp {ra, s0}, -32
diff --git a/llvm/test/MC/RISCV/rv64xqccmp-valid.s b/llvm/test/MC/RISCV/rv64xqccmp-valid.s
index 06ba33fe8a495..29cf6f0dfbdac 100644
--- a/llvm/test/MC/RISCV/rv64xqccmp-valid.s
+++ b/llvm/test/MC/RISCV/rv64xqccmp-valid.s
@@ -148,10 +148,6 @@ qc.cm.push {ra, s0-s11}, -112
 # CHECK-ASM: encoding: [0xf6,0xb8]
 qc.cm.push {ra, s0-s11}, -128
 
-# CHECK-ASM-AND-OBJ: qc.cm.pushfp {ra}, -16
-# CHECK-ASM: encoding: [0x42,0xb9]
-qc.cm.pushfp {ra}, -16
-
 # CHECK-ASM-AND-OBJ: qc.cm.pushfp {ra, s0}, -32
 # CHECK-ASM: encoding: [0x56,0xb9]
 qc.cm.pushfp {ra, s0}, -32

@lenary
Copy link
Member Author

lenary commented Mar 27, 2025

I templated parseReglist because the function seemed too long to copy/paste, but I avoided doing the same for most of the other methods - maybe I should have though? I'm not sure, feedback appreciated.

I may need a declaration somewhere that the parseRegList template instantiations actually (need to) exist.

@topperc
Copy link
Collaborator

topperc commented Mar 27, 2025

I templated parseReglist because the function seemed too long to copy/paste, but I avoided doing the same for most of the other methods - maybe I should have though? I'm not sure, feedback appreciated.

I may need a declaration somewhere that the parseRegList template instantiations actually (need to) exist.

Can we have an untemplated parseRegList that takes the flag as an argument and make the template function call the untemplate function with the template parameter passed as an argument? That will prevent the function from being duplicated in the binary.

const MCOperand &MO = MI.getOperand(OpNo);
assert(MO.isImm() && "Rlist operand must be immediate");
auto Imm = MO.getImm();
assert(Imm >= 5 && "EABI is currently not implemented");
Copy link
Collaborator

@topperc topperc Mar 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably should split this assert so the error makes sense. The Zcmp has some note that encodings 0-3 are reserved for future EABI version which is why this assert mentions EABI.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@lenary
Copy link
Member Author

lenary commented Mar 27, 2025

I templated parseReglist because the function seemed too long to copy/paste, but I avoided doing the same for most of the other methods - maybe I should have though? I'm not sure, feedback appreciated.
I may need a declaration somewhere that the parseRegList template instantiations actually (need to) exist.

Can we have an untemplated parseRegList that takes the flag as an argument and make the template function call the untemplate function with the template parameter passed as an argument? That will prevent the function from being duplicated in the binary.

Sure, I guess the size savings of this are better than any savings from if constexpr

Copy link

github-actions bot commented Mar 27, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

OS << "-s11";
else if (SlistEncode > 5 && SlistEncode <= 14)
else if (SlistEncode > RISCVZC::RA_S0 && SlistEncode <= RISCVZC::RA_S0_S11)
OS << "-s" << (SlistEncode - 5);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SlistEncode - RISCVZC::RA_S0

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@lenary lenary merged commit 75ca080 into llvm:main Mar 28, 2025
11 checks passed
@lenary lenary deleted the pr/xqccmp-pushfp-list branch March 28, 2025 00:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:RISC-V mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants