[llvm] [PowerPC] Add mnemonics to paddis (PR #179979)
Lei Huang via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 22 09:30:05 PDT 2026
https://github.com/lei137 updated https://github.com/llvm/llvm-project/pull/179979
>From a876aa10e81ab89f53236f0f41f6bad1551bd8dc Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Thu, 19 Feb 2026 16:05:02 -0500
Subject: [PATCH 1/5] [PowerPC] Add mnemonics to paddis
Add extended mnemonics to paddis:
paddis RT,RA,SI -> paddis RT,RA,SI,0
plis RT,SI -> paddis RT,0,SI,0
psubis RT,RA,si -> paddis RT,RA,-si,0
---
.../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 125 ++++++++++++------
.../PowerPC/MCTargetDesc/PPCInstPrinter.cpp | 11 ++
.../PowerPC/MCTargetDesc/PPCInstPrinter.h | 2 +
llvm/lib/Target/PowerPC/PPCInstrFuture.td | 13 ++
llvm/lib/Target/PowerPC/PPCOperands.td | 18 +++
.../PowerPC/ppc-encoding-ISAFuture.txt | 2 +-
.../PowerPC/ppc64le-encoding-ISAFuture.txt | 2 +-
llvm/test/MC/PowerPC/ppc-encoding-ISAFuture.s | 31 ++++-
8 files changed, 158 insertions(+), 46 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 7b07c0881d453..5c66f889488ca 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -161,6 +161,47 @@ class PPCAsmParser : public MCTargetAsmParser {
MCContext &Ctx) override;
};
+// Helper function to negate an operand - used by both PPCOperand and PPCAsmParser
+// Adds the negation of \p Op as an operand to \p Inst.
+//
+// This helper is used to lower pseudo-subtraction mnemonics (e.g. SUBI,
+// SUBIS, SUBIC, SUBIC_rec, PSUBI) into their real ADD-family equivalents by
+// negating the immediate or expression operand before appending it.
+//
+// The negation is performed as follows:
+// - If \p Op is an immediate, the negated integer value is added directly.
+// - If \p Op is a unary-minus expression (i.e. \c -E), the inner
+// sub-expression \c E is added, effectively cancelling the double negation.
+// - If \p Op is a binary-subtraction expression (i.e. \c LHS-RHS), the
+// operands are swapped to produce \c RHS-LHS.
+// - Otherwise, a new unary-minus expression wrapping \p Op's expression is
+// created and added.
+//
+// \param Inst The instruction being built; the negated operand is appended.
+// \param Op The source operand whose value is to be negated.
+// \param Ctx The MC context used to allocate new expression nodes.
+static void addNegOperand(MCInst &Inst, MCOperand &Op, MCContext &Ctx) {
+ if (Op.isImm()) {
+ Inst.addOperand(MCOperand::createImm(-Op.getImm()));
+ return;
+ }
+ const MCExpr *Expr = Op.getExpr();
+ if (const MCUnaryExpr *UnExpr = dyn_cast<MCUnaryExpr>(Expr)) {
+ if (UnExpr->getOpcode() == MCUnaryExpr::Minus) {
+ Inst.addOperand(MCOperand::createExpr(UnExpr->getSubExpr()));
+ return;
+ }
+ } else if (const MCBinaryExpr *BinExpr = dyn_cast<MCBinaryExpr>(Expr)) {
+ if (BinExpr->getOpcode() == MCBinaryExpr::Sub) {
+ const MCExpr *NE = MCBinaryExpr::createSub(BinExpr->getRHS(),
+ BinExpr->getLHS(), Ctx);
+ Inst.addOperand(MCOperand::createExpr(NE));
+ return;
+ }
+ }
+ Inst.addOperand(MCOperand::createExpr(MCUnaryExpr::createMinus(Expr, Ctx)));
+}
+
/// PPCOperand - Instances of this class represent a parsed PowerPC machine
/// instruction.
struct PPCOperand : public MCParsedAsmOperand {
@@ -174,6 +215,7 @@ struct PPCOperand : public MCParsedAsmOperand {
SMLoc StartLoc, EndLoc;
bool IsPPC64;
+ MCContext *Ctx;
struct TokOp {
const char *Data;
@@ -640,6 +682,20 @@ struct PPCOperand : public MCParsedAsmOperand {
}
}
+ void addNegImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+
+ if (Kind == Immediate) {
+ Inst.addOperand(MCOperand::createImm(-getImm()));
+ return;
+ }
+
+ // Create an MCOperand and use the static helper
+ assert(Ctx && "MCContext is required for addNegImmOperands");
+ MCOperand Op = MCOperand::createExpr(getExpr());
+ addNegOperand(Inst, Op, *Ctx);
+ }
+
void addBranchTargetOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
if (Kind == Immediate)
@@ -661,18 +717,19 @@ struct PPCOperand : public MCParsedAsmOperand {
void print(raw_ostream &OS, const MCAsmInfo &MAI) const override;
static std::unique_ptr<PPCOperand> CreateToken(StringRef Str, SMLoc S,
- bool IsPPC64) {
+ bool IsPPC64, MCContext *Ctx = nullptr) {
auto Op = std::make_unique<PPCOperand>(Token);
Op->Tok.Data = Str.data();
Op->Tok.Length = Str.size();
Op->StartLoc = S;
Op->EndLoc = S;
Op->IsPPC64 = IsPPC64;
+ Op->Ctx = Ctx;
return Op;
}
static std::unique_ptr<PPCOperand>
- CreateTokenWithStringCopy(StringRef Str, SMLoc S, bool IsPPC64) {
+ CreateTokenWithStringCopy(StringRef Str, SMLoc S, bool IsPPC64, MCContext *Ctx = nullptr) {
// Allocate extra memory for the string and copy it.
// FIXME: This is incorrect, Operands are owned by unique_ptr with a default
// deleter which will destroy them by simply using "delete", not correctly
@@ -686,11 +743,12 @@ struct PPCOperand : public MCParsedAsmOperand {
Op->StartLoc = S;
Op->EndLoc = S;
Op->IsPPC64 = IsPPC64;
+ Op->Ctx = Ctx;
return Op;
}
static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
- bool IsPPC64,
+ bool IsPPC64, MCContext *Ctx = nullptr,
bool IsMemOpBase = false) {
auto Op = std::make_unique<PPCOperand>(Immediate);
Op->Imm.Val = Val;
@@ -698,57 +756,61 @@ struct PPCOperand : public MCParsedAsmOperand {
Op->StartLoc = S;
Op->EndLoc = E;
Op->IsPPC64 = IsPPC64;
+ Op->Ctx = Ctx;
return Op;
}
static std::unique_ptr<PPCOperand> CreateExpr(const MCExpr *Val, SMLoc S,
- SMLoc E, bool IsPPC64) {
+ SMLoc E, bool IsPPC64, MCContext *Ctx = nullptr) {
auto Op = std::make_unique<PPCOperand>(Expression);
Op->Expr.Val = Val;
Op->Expr.CRVal = EvaluateCRExpr(Val);
Op->StartLoc = S;
Op->EndLoc = E;
Op->IsPPC64 = IsPPC64;
+ Op->Ctx = Ctx;
return Op;
}
static std::unique_ptr<PPCOperand>
- CreateTLSReg(const MCSymbolRefExpr *Sym, SMLoc S, SMLoc E, bool IsPPC64) {
+ CreateTLSReg(const MCSymbolRefExpr *Sym, SMLoc S, SMLoc E, bool IsPPC64, MCContext *Ctx = nullptr) {
auto Op = std::make_unique<PPCOperand>(TLSRegister);
Op->TLSReg.Sym = Sym;
Op->StartLoc = S;
Op->EndLoc = E;
Op->IsPPC64 = IsPPC64;
+ Op->Ctx = Ctx;
return Op;
}
static std::unique_ptr<PPCOperand>
- CreateContextImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64) {
+ CreateContextImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64, MCContext *Ctx = nullptr) {
auto Op = std::make_unique<PPCOperand>(ContextImmediate);
Op->Imm.Val = Val;
Op->StartLoc = S;
Op->EndLoc = E;
Op->IsPPC64 = IsPPC64;
+ Op->Ctx = Ctx;
return Op;
}
static std::unique_ptr<PPCOperand>
- CreateFromMCExpr(const MCExpr *Val, SMLoc S, SMLoc E, bool IsPPC64) {
+ CreateFromMCExpr(const MCExpr *Val, SMLoc S, SMLoc E, bool IsPPC64, MCContext *Ctx = nullptr) {
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val))
- return CreateImm(CE->getValue(), S, E, IsPPC64);
+ return CreateImm(CE->getValue(), S, E, IsPPC64, Ctx);
if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Val))
if (getSpecifier(SRE) == PPC::S_TLS ||
getSpecifier(SRE) == PPC::S_TLS_PCREL)
- return CreateTLSReg(SRE, S, E, IsPPC64);
+ return CreateTLSReg(SRE, S, E, IsPPC64, Ctx);
if (const auto *SE = dyn_cast<MCSpecifierExpr>(Val)) {
int64_t Res;
if (PPC::evaluateAsConstant(*SE, Res))
- return CreateContextImm(Res, S, E, IsPPC64);
+ return CreateContextImm(Res, S, E, IsPPC64, Ctx);
}
- return CreateExpr(Val, S, E, IsPPC64);
+ return CreateExpr(Val, S, E, IsPPC64, Ctx);
}
private:
@@ -791,29 +853,6 @@ void PPCOperand::print(raw_ostream &OS, const MCAsmInfo &MAI) const {
}
}
-static void
-addNegOperand(MCInst &Inst, MCOperand &Op, MCContext &Ctx) {
- if (Op.isImm()) {
- Inst.addOperand(MCOperand::createImm(-Op.getImm()));
- return;
- }
- const MCExpr *Expr = Op.getExpr();
- if (const MCUnaryExpr *UnExpr = dyn_cast<MCUnaryExpr>(Expr)) {
- if (UnExpr->getOpcode() == MCUnaryExpr::Minus) {
- Inst.addOperand(MCOperand::createExpr(UnExpr->getSubExpr()));
- return;
- }
- } else if (const MCBinaryExpr *BinExpr = dyn_cast<MCBinaryExpr>(Expr)) {
- if (BinExpr->getOpcode() == MCBinaryExpr::Sub) {
- const MCExpr *NE = MCBinaryExpr::createSub(BinExpr->getRHS(),
- BinExpr->getLHS(), Ctx);
- Inst.addOperand(MCOperand::createExpr(NE));
- return;
- }
- }
- Inst.addOperand(MCOperand::createExpr(MCUnaryExpr::createMinus(Expr, Ctx)));
-}
-
void PPCAsmParser::processInstruction(MCInst &Inst,
const OperandVector &Operands) {
int Opcode = Inst.getOpcode();
@@ -1454,7 +1493,7 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
if (!matchRegisterName(IntVal))
return Error(S, "invalid register name");
- Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64()));
+ Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64(), &getContext()));
return false;
}
case AsmToken::Identifier:
@@ -1475,7 +1514,7 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
}
// Push the parsed operand into the list of operands
- Operands.push_back(PPCOperand::CreateFromMCExpr(EVal, S, E, isPPC64()));
+ Operands.push_back(PPCOperand::CreateFromMCExpr(EVal, S, E, isPPC64(), &getContext()));
// Check whether this is a TLS call expression
const char TlsGetAddr[] = "__tls_get_addr";
@@ -1522,10 +1561,10 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
EVal = MCBinaryExpr::createAdd(EVal, TlsCallAddend, getContext());
// Add a __tls_get_addr operand with addend a, b, or a+b.
Operands.back() = PPCOperand::CreateFromMCExpr(
- EVal, S, Parser.getTok().getLoc(), false);
+ EVal, S, Parser.getTok().getLoc(), false, &getContext());
}
- Operands.push_back(PPCOperand::CreateFromMCExpr(TLSSym, S, E, isPPC64()));
+ Operands.push_back(PPCOperand::CreateFromMCExpr(TLSSym, S, E, isPPC64(), &getContext()));
}
// Otherwise, check for D-form memory operands
@@ -1553,7 +1592,7 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
if (parseToken(AsmToken::RParen, "missing ')'"))
return true;
Operands.push_back(
- PPCOperand::CreateImm(IntVal, S, E, isPPC64(), /*IsMemOpBase=*/true));
+ PPCOperand::CreateImm(IntVal, S, E, isPPC64(), &getContext(), /*IsMemOpBase=*/true));
}
return false;
@@ -1582,17 +1621,17 @@ bool PPCAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
StringRef Mnemonic = Name.slice(0, Dot);
if (!NewOpcode.empty()) // Underlying memory for Name is volatile.
Operands.push_back(
- PPCOperand::CreateTokenWithStringCopy(Mnemonic, NameLoc, isPPC64()));
+ PPCOperand::CreateTokenWithStringCopy(Mnemonic, NameLoc, isPPC64(), &getContext()));
else
- Operands.push_back(PPCOperand::CreateToken(Mnemonic, NameLoc, isPPC64()));
+ Operands.push_back(PPCOperand::CreateToken(Mnemonic, NameLoc, isPPC64(), &getContext()));
if (Dot != StringRef::npos) {
SMLoc DotLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Dot);
StringRef DotStr = Name.substr(Dot);
if (!NewOpcode.empty()) // Underlying memory for Name is volatile.
Operands.push_back(
- PPCOperand::CreateTokenWithStringCopy(DotStr, DotLoc, isPPC64()));
+ PPCOperand::CreateTokenWithStringCopy(DotStr, DotLoc, isPPC64(), &getContext()));
else
- Operands.push_back(PPCOperand::CreateToken(DotStr, DotLoc, isPPC64()));
+ Operands.push_back(PPCOperand::CreateToken(DotStr, DotLoc, isPPC64(), &getContext()));
}
// If there are no more operands then finish
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
index 0cf8dba4408e8..642cb612baf30 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
@@ -383,6 +383,17 @@ void PPCInstPrinter::printS32ImmOperand(const MCInst *MI, unsigned OpNo,
printOperand(MI, OpNo, STI, O);
}
+void PPCInstPrinter::printNegS32ImmOperand(const MCInst *MI, unsigned OpNo,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ if (MI->getOperand(OpNo).isImm()) {
+ long long Value = MI->getOperand(OpNo).getImm();
+ assert(isInt<32>(Value) && "Invalid s32imm argument!");
+ O << (long long)Value;
+ } else
+ printOperand(MI, OpNo, STI, O);
+}
+
void PPCInstPrinter::printS34ImmOperand(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI,
raw_ostream &O) {
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h
index f6781b66756cf..56804a1c43948 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h
@@ -72,6 +72,8 @@ class PPCInstPrinter : public MCInstPrinter {
const MCSubtargetInfo &STI, raw_ostream &O);
void printS32ImmOperand(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O);
+ void printNegS32ImmOperand(const MCInst *MI, unsigned OpNo,
+ const MCSubtargetInfo &STI, raw_ostream &O);
void printS34ImmOperand(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O);
void printU16ImmOperand(const MCInst *MI, unsigned OpNo,
diff --git a/llvm/lib/Target/PowerPC/PPCInstrFuture.td b/llvm/lib/Target/PowerPC/PPCInstrFuture.td
index 1561624b5e4ce..f910c9ab8ad4f 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrFuture.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrFuture.td
@@ -618,6 +618,19 @@ let Predicates = [HasFutureVector] in {
// Predicate combinations available:
// [HasVSX, IsISAFuture]
+def : InstAlias<"paddis $RT, $RA, $SI", (PADDIS gprc:$RT, gprc_nor0:$RA,
+ s32imm:$SI)>;
+def : InstAlias<"paddis $RT, $RA, $SI", (PADDIS8 g8rc:$RT, g8rc_nox0:$RA,
+ s32imm64:$SI)>;
+def : InstAlias<"plis $RT, $SI", (PADDIS gprc:$RT, ZERO, s32imm:$SI)>;
+def : InstAlias<"plis $RT, $SI", (PADDIS8 g8rc:$RT, ZERO8, s32imm64:$SI)>;
+// psubis: subtract immediate from register
+// For assembly: psubis $RT, $RA, $SI -> paddis $RT, $RA, -$SI, 0
+def : InstAlias<"psubis $RT, $RA, $SI", (PADDIS gprc:$RT, gprc_nor0:$RA,
+ neg_s32imm:$SI)>;
+def : InstAlias<"psubis $RT, $RA, $SI", (PADDIS8 g8rc:$RT, g8rc_nox0:$RA,
+ neg_s32imm64:$SI)>;
+
let Predicates = [HasFutureVector] in {
def : InstAlias<"xxaes128encp $XTp, $XAp, $XBp",
(XXAESENCP vsrprc:$XTp, vsrprc:$XAp, vsrprc:$XBp, 0)>;
diff --git a/llvm/lib/Target/PowerPC/PPCOperands.td b/llvm/lib/Target/PowerPC/PPCOperands.td
index f9ba7b06a41b8..3f9a91e8c263e 100644
--- a/llvm/lib/Target/PowerPC/PPCOperands.td
+++ b/llvm/lib/Target/PowerPC/PPCOperands.td
@@ -103,6 +103,16 @@ multiclass SignedImmediateWithPCRel<ValueType vt, code pred, SDNodeXForm xform,
defm _pcrel : SignedImmediateReloc<vt, pred, xform, asmop, width, fixup_pcrel>;
}
+//===----------------------------------------------------------------------===//
+// Immediate transformation functions
+//===----------------------------------------------------------------------===//
+
+// NEG_S32 - Negate a signed 32-bit immediate value
+def NEG_S32 : SDNodeXForm<imm, [{
+ // Transformation function: -imm
+ return getI32Imm(-N->getSExtValue(), SDLoc(N));
+}]>;
+
//===----------------------------------------------------------------------===//
// Immediate AsmOperand definitions
//===----------------------------------------------------------------------===//
@@ -126,6 +136,7 @@ def S16Imm : ImmediateAsmOperand<"isS16Imm","addS16ImmOperands">;
def S17Imm : ImmediateAsmOperand<"isS17Imm","addS16ImmOperands">;
def S32Imm : ImmediateAsmOperand<"isS32Imm">;
def S34Imm : ImmediateAsmOperand<"isS34Imm">;
+def NegS32Imm : ImmediateAsmOperand<"isS32Imm","addNegImmOperands">;
//===----------------------------------------------------------------------===//
// i32 immediate operands
@@ -179,6 +190,9 @@ defm s32imm : SignedImmediateWithPCRel<i32,
defm s34imm : SignedImmediateReloc<i32,
[{ return isInt<34>(Imm); }], NOOP_SDNodeXForm,
"S34Imm", 34, "PPC::fixup_ppc_imm34">;
+defm neg_s32imm : SignedImmediate<i32,
+ [{ return isInt<32>(Imm); }], NEG_S32,
+ "NegS32Imm", 32, "PPC::fixup_ppc_imm32">;
//===----------------------------------------------------------------------===//
// i64 immediate operands
@@ -190,6 +204,10 @@ defm s32imm64 : SignedImmediateWithPCRel<i64,
defm s34imm64 : SignedImmediateWithPCRel<i64,
[{ return isInt<34>(Imm); }], NOOP_SDNodeXForm,
"S34Imm", 34, "PPC::fixup_ppc_imm34", "PPC::fixup_ppc_pcrel34">;
+defm neg_s32imm64 : SignedImmediate<i64,
+ [{ return isInt<32>(Imm); }], NEG_S32,
+ "NegS32Imm", 32, "PPC::fixup_ppc_imm32">;
+
//===----------------------------------------------------------------------===//
// Special case immediate operands
diff --git a/llvm/test/MC/Disassembler/PowerPC/ppc-encoding-ISAFuture.txt b/llvm/test/MC/Disassembler/PowerPC/ppc-encoding-ISAFuture.txt
index 1024c6b546c4a..a93b920c80cd7 100644
--- a/llvm/test/MC/Disassembler/PowerPC/ppc-encoding-ISAFuture.txt
+++ b/llvm/test/MC/Disassembler/PowerPC/ppc-encoding-ISAFuture.txt
@@ -298,7 +298,7 @@
#CHECK: mtlpl 3, 4
0x7c,0x80,0x1a,0x26
-#CHECK: paddis 10, 12, 1000000000, 0
+#CHECK: paddis 10, 12, 1000000000
0x06,0x00,0x3b,0x9a,0x3d,0x4c,0xca,0x00
#CHECK: paddis 10, 0, 1000000000, 1
diff --git a/llvm/test/MC/Disassembler/PowerPC/ppc64le-encoding-ISAFuture.txt b/llvm/test/MC/Disassembler/PowerPC/ppc64le-encoding-ISAFuture.txt
index bda8d1e69442f..2a1077c159845 100644
--- a/llvm/test/MC/Disassembler/PowerPC/ppc64le-encoding-ISAFuture.txt
+++ b/llvm/test/MC/Disassembler/PowerPC/ppc64le-encoding-ISAFuture.txt
@@ -292,7 +292,7 @@
#CHECK: mtlpl 3, 4
0x26,0x1a,0x80,0x7c
-#CHECK: paddis 10, 12, 1000000000, 0
+#CHECK: paddis 10, 12, 1000000000
0x9a,0x3b,0x00,0x06,0x00,0xca,0x4c,0x3d
#CHECK: paddis 10, 0, 1000000000, 1
diff --git a/llvm/test/MC/PowerPC/ppc-encoding-ISAFuture.s b/llvm/test/MC/PowerPC/ppc-encoding-ISAFuture.s
index eb616a15500f1..04a26848582b7 100644
--- a/llvm/test/MC/PowerPC/ppc-encoding-ISAFuture.s
+++ b/llvm/test/MC/PowerPC/ppc-encoding-ISAFuture.s
@@ -40,7 +40,6 @@
# CHECK-BE: dmxxinstdmr512 1, 2, 34, 0 # encoding: [0xf0,0x82,0x17,0x52]
# CHECK-LE: dmxxinstdmr512 1, 2, 34, 0 # encoding: [0x52,0x17,0x82,0xf0]
dmxxinstdmr512 1, 2, 34, 0
-
# CHECK-BE: dmxxinstdmr512 1, 2, 34, 1 # encoding: [0xf0,0x83,0x17,0x52]
# CHECK-LE: dmxxinstdmr512 1, 2, 34, 1 # encoding: [0x52,0x17,0x83,0xf0]
dmxxinstdmr512 1, 2, 34, 1
@@ -419,18 +418,48 @@
#CHECK-BE: mtlpl 3, 4 # encoding: [0x7c,0x80,0x1a,0x26]
#CHECK-LE: mtlpl 3, 4 # encoding: [0x26,0x1a,0x80,0x7c]
+ paddis 10, 12, 1000000000
+#CHECK-BE: paddis 10, 12, 1000000000, 0 # encoding: [0x06,0x00,0x3b,0x9a,
+#CHECK-BE-SAME: 0x3d,0x4c,0xca,0x00]
+#CHECK-LE: paddis 10, 12, 1000000000, 0 # encoding: [0x9a,0x3b,0x00,0x06,
+#CHECK-LE-SAME: 0x00,0xca,0x4c,0x3d]
+
paddis 10, 12, 1000000000, 0
#CHECK-BE: paddis 10, 12, 1000000000, 0 # encoding: [0x06,0x00,0x3b,0x9a,
#CHECK-BE-SAME: 0x3d,0x4c,0xca,0x00]
#CHECK-LE: paddis 10, 12, 1000000000, 0 # encoding: [0x9a,0x3b,0x00,0x06,
#CHECK-LE-SAME: 0x00,0xca,0x4c,0x3d]
+ psubis 10, 12, -1000000000
+#CHECK-BE: paddis 10, 12, 1000000000, 0 # encoding: [0x06,0x00,0x3b,0x9a,
+#CHECK-BE-SAME: 0x3d,0x4c,0xca,0x00]
+#CHECK-LE: paddis 10, 12, 1000000000, 0 # encoding: [0x9a,0x3b,0x00,0x06,
+#CHECK-LE-SAME: 0x00,0xca,0x4c,0x3d]
+
+ paddis 10, 12, -1000000000
+#CHECK-BE: paddis 10, 12, -1000000000, 0 # encoding: [0x06,0x00,0xc4,0x65,
+#CHECK-BE-SAME: 0x3d,0x4c,0x36,0x00]
+#CHECK-LE: paddis 10, 12, -1000000000, 0 # encoding: [0x65,0xc4,0x00,0x06,
+#CHECK-LE-SAME: 0x00,0x36,0x4c,0x3d]
+
+ psubis 10, 12, 1000000000
+#CHECK-BE: paddis 10, 12, -1000000000, 0 # encoding: [0x06,0x00,0xc4,0x65,
+#CHECK-BE-SAME: 0x3d,0x4c,0x36,0x00]
+#CHECK-LE: paddis 10, 12, -1000000000, 0 # encoding: [0x65,0xc4,0x00,0x06,
+#CHECK-LE-SAME: 0x00,0x36,0x4c,0x3d]
+
paddis 10, 0, 1000000000, 1
#CHECK-BE: paddis 10, 0, 1000000000, 1 # encoding: [0x06,0x10,0x3b,0x9a,
#CHECK-BE-SAME: 0x3d,0x40,0xca,0x00]
#CHECK-LE: paddis 10, 0, 1000000000, 1 # encoding: [0x9a,0x3b,0x10,0x06,
#CHECK-LE-SAME: 0x00,0xca,0x40,0x3d]
+ plis 10, 1000000000
+#CHECK-BE: plis 10, 1000000000 # encoding: [0x06,0x00,0x3b,0x9a,
+#CHECK-BE-SAME: 0x3d,0x40,0xca,0x00]
+#CHECK-LE: plis 10, 1000000000 # encoding: [0x9a,0x3b,0x00,0x06,
+#CHECK-LE-SAME: 0x00,0xca,0x40,0x3d]
+
xxmulmul 8, 3, 4, 2
#CHECK-BE: xxmulmul 8, 3, 4, 2 # encoding: [0xed,0x03,0x22,0x08]
#CHECK-LE: xxmulmul 8, 3, 4, 2 # encoding: [0x08,0x22,0x03,0xed]
>From 034181f7ba905bb0edba74e99bbf3c3f6d4d20b8 Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Mon, 2 Mar 2026 09:58:16 -0500
Subject: [PATCH 2/5] add MC test for psubis
---
.../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 71 +++++++-----
llvm/test/MC/PowerPC/ppc64-psubis.s | 108 ++++++++++++++++++
2 files changed, 150 insertions(+), 29 deletions(-)
create mode 100644 llvm/test/MC/PowerPC/ppc64-psubis.s
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 5c66f889488ca..5325b416743b4 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -161,12 +161,13 @@ class PPCAsmParser : public MCTargetAsmParser {
MCContext &Ctx) override;
};
-// Helper function to negate an operand - used by both PPCOperand and PPCAsmParser
-// Adds the negation of \p Op as an operand to \p Inst.
+// Helper function to negate an operand - used by both PPCOperand and
+// PPCAsmParser to add the negation of \p Op as an operand to \p Inst.
//
-// This helper is used to lower pseudo-subtraction mnemonics (e.g. SUBI,
-// SUBIS, SUBIC, SUBIC_rec, PSUBI) into their real ADD-family equivalents by
-// negating the immediate or expression operand before appending it.
+// Originally this helper is only used to lower pseudo-subtraction mnemonics
+// (e.g. SUBI, SUBIS, SUBIC, SUBIC_rec, PSUBI) into their real ADD-family
+// equivalents by negating the immediate or expression operand before
+// appending it. Now it's also used by PPCOperand for PSUBIS.
//
// The negation is performed as follows:
// - If \p Op is an immediate, the negated integer value is added directly.
@@ -193,8 +194,8 @@ static void addNegOperand(MCInst &Inst, MCOperand &Op, MCContext &Ctx) {
}
} else if (const MCBinaryExpr *BinExpr = dyn_cast<MCBinaryExpr>(Expr)) {
if (BinExpr->getOpcode() == MCBinaryExpr::Sub) {
- const MCExpr *NE = MCBinaryExpr::createSub(BinExpr->getRHS(),
- BinExpr->getLHS(), Ctx);
+ const MCExpr *NE =
+ MCBinaryExpr::createSub(BinExpr->getRHS(), BinExpr->getLHS(), Ctx);
Inst.addOperand(MCOperand::createExpr(NE));
return;
}
@@ -690,8 +691,8 @@ struct PPCOperand : public MCParsedAsmOperand {
return;
}
- // Create an MCOperand and use the static helper
- assert(Ctx && "MCContext is required for addNegImmOperands");
+ // Create an MCOperand using the static helper function.
+ assert(Ctx && "MCContext is required for for non immediates");
MCOperand Op = MCOperand::createExpr(getExpr());
addNegOperand(Inst, Op, *Ctx);
}
@@ -716,8 +717,8 @@ struct PPCOperand : public MCParsedAsmOperand {
void print(raw_ostream &OS, const MCAsmInfo &MAI) const override;
- static std::unique_ptr<PPCOperand> CreateToken(StringRef Str, SMLoc S,
- bool IsPPC64, MCContext *Ctx = nullptr) {
+ static std::unique_ptr<PPCOperand>
+ CreateToken(StringRef Str, SMLoc S, bool IsPPC64, MCContext *Ctx = nullptr) {
auto Op = std::make_unique<PPCOperand>(Token);
Op->Tok.Data = Str.data();
Op->Tok.Length = Str.size();
@@ -729,7 +730,8 @@ struct PPCOperand : public MCParsedAsmOperand {
}
static std::unique_ptr<PPCOperand>
- CreateTokenWithStringCopy(StringRef Str, SMLoc S, bool IsPPC64, MCContext *Ctx = nullptr) {
+ CreateTokenWithStringCopy(StringRef Str, SMLoc S, bool IsPPC64,
+ MCContext *Ctx = nullptr) {
// Allocate extra memory for the string and copy it.
// FIXME: This is incorrect, Operands are owned by unique_ptr with a default
// deleter which will destroy them by simply using "delete", not correctly
@@ -748,7 +750,8 @@ struct PPCOperand : public MCParsedAsmOperand {
}
static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
- bool IsPPC64, MCContext *Ctx = nullptr,
+ bool IsPPC64,
+ MCContext *Ctx = nullptr,
bool IsMemOpBase = false) {
auto Op = std::make_unique<PPCOperand>(Immediate);
Op->Imm.Val = Val;
@@ -761,7 +764,8 @@ struct PPCOperand : public MCParsedAsmOperand {
}
static std::unique_ptr<PPCOperand> CreateExpr(const MCExpr *Val, SMLoc S,
- SMLoc E, bool IsPPC64, MCContext *Ctx = nullptr) {
+ SMLoc E, bool IsPPC64,
+ MCContext *Ctx = nullptr) {
auto Op = std::make_unique<PPCOperand>(Expression);
Op->Expr.Val = Val;
Op->Expr.CRVal = EvaluateCRExpr(Val);
@@ -772,8 +776,10 @@ struct PPCOperand : public MCParsedAsmOperand {
return Op;
}
- static std::unique_ptr<PPCOperand>
- CreateTLSReg(const MCSymbolRefExpr *Sym, SMLoc S, SMLoc E, bool IsPPC64, MCContext *Ctx = nullptr) {
+ static std::unique_ptr<PPCOperand> CreateTLSReg(const MCSymbolRefExpr *Sym,
+ SMLoc S, SMLoc E,
+ bool IsPPC64,
+ MCContext *Ctx = nullptr) {
auto Op = std::make_unique<PPCOperand>(TLSRegister);
Op->TLSReg.Sym = Sym;
Op->StartLoc = S;
@@ -784,7 +790,8 @@ struct PPCOperand : public MCParsedAsmOperand {
}
static std::unique_ptr<PPCOperand>
- CreateContextImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64, MCContext *Ctx = nullptr) {
+ CreateContextImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64,
+ MCContext *Ctx = nullptr) {
auto Op = std::make_unique<PPCOperand>(ContextImmediate);
Op->Imm.Val = Val;
Op->StartLoc = S;
@@ -795,7 +802,8 @@ struct PPCOperand : public MCParsedAsmOperand {
}
static std::unique_ptr<PPCOperand>
- CreateFromMCExpr(const MCExpr *Val, SMLoc S, SMLoc E, bool IsPPC64, MCContext *Ctx = nullptr) {
+ CreateFromMCExpr(const MCExpr *Val, SMLoc S, SMLoc E, bool IsPPC64,
+ MCContext *Ctx = nullptr) {
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val))
return CreateImm(CE->getValue(), S, E, IsPPC64, Ctx);
@@ -1493,7 +1501,8 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
if (!matchRegisterName(IntVal))
return Error(S, "invalid register name");
- Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64(), &getContext()));
+ Operands.push_back(
+ PPCOperand::CreateImm(IntVal, S, E, isPPC64(), &getContext()));
return false;
}
case AsmToken::Identifier:
@@ -1514,7 +1523,8 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
}
// Push the parsed operand into the list of operands
- Operands.push_back(PPCOperand::CreateFromMCExpr(EVal, S, E, isPPC64(), &getContext()));
+ Operands.push_back(
+ PPCOperand::CreateFromMCExpr(EVal, S, E, isPPC64(), &getContext()));
// Check whether this is a TLS call expression
const char TlsGetAddr[] = "__tls_get_addr";
@@ -1564,7 +1574,8 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
EVal, S, Parser.getTok().getLoc(), false, &getContext());
}
- Operands.push_back(PPCOperand::CreateFromMCExpr(TLSSym, S, E, isPPC64(), &getContext()));
+ Operands.push_back(
+ PPCOperand::CreateFromMCExpr(TLSSym, S, E, isPPC64(), &getContext()));
}
// Otherwise, check for D-form memory operands
@@ -1591,8 +1602,8 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
E = Parser.getTok().getLoc();
if (parseToken(AsmToken::RParen, "missing ')'"))
return true;
- Operands.push_back(
- PPCOperand::CreateImm(IntVal, S, E, isPPC64(), &getContext(), /*IsMemOpBase=*/true));
+ Operands.push_back(PPCOperand::CreateImm(
+ IntVal, S, E, isPPC64(), &getContext(), /*IsMemOpBase=*/true));
}
return false;
@@ -1620,18 +1631,20 @@ bool PPCAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
size_t Dot = Name.find('.');
StringRef Mnemonic = Name.slice(0, Dot);
if (!NewOpcode.empty()) // Underlying memory for Name is volatile.
- Operands.push_back(
- PPCOperand::CreateTokenWithStringCopy(Mnemonic, NameLoc, isPPC64(), &getContext()));
+ Operands.push_back(PPCOperand::CreateTokenWithStringCopy(
+ Mnemonic, NameLoc, isPPC64(), &getContext()));
else
- Operands.push_back(PPCOperand::CreateToken(Mnemonic, NameLoc, isPPC64(), &getContext()));
+ Operands.push_back(
+ PPCOperand::CreateToken(Mnemonic, NameLoc, isPPC64(), &getContext()));
if (Dot != StringRef::npos) {
SMLoc DotLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Dot);
StringRef DotStr = Name.substr(Dot);
if (!NewOpcode.empty()) // Underlying memory for Name is volatile.
- Operands.push_back(
- PPCOperand::CreateTokenWithStringCopy(DotStr, DotLoc, isPPC64(), &getContext()));
+ Operands.push_back(PPCOperand::CreateTokenWithStringCopy(
+ DotStr, DotLoc, isPPC64(), &getContext()));
else
- Operands.push_back(PPCOperand::CreateToken(DotStr, DotLoc, isPPC64(), &getContext()));
+ Operands.push_back(
+ PPCOperand::CreateToken(DotStr, DotLoc, isPPC64(), &getContext()));
}
// If there are no more operands then finish
diff --git a/llvm/test/MC/PowerPC/ppc64-psubis.s b/llvm/test/MC/PowerPC/ppc64-psubis.s
new file mode 100644
index 0000000000000..e0f4d8527800d
--- /dev/null
+++ b/llvm/test/MC/PowerPC/ppc64-psubis.s
@@ -0,0 +1,108 @@
+// NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 6
+# RUN: llvm-mc -triple powerpc64-unknown-unknown --show-encoding \
+# RUN: -mattr=+isa-future-instructions,+prefix-instrs %s | \
+# RUN: FileCheck -check-prefix=CHECK-BE %s
+# RUN: llvm-mc -triple powerpc64le-unknown-unknown --show-encoding \
+# RUN: -mattr=+isa-future-instructions,+prefix-instrs %s | \
+# RUN: FileCheck -check-prefix=CHECK-LE %s
+
+# Tests for psubis encoding with various immediate inputs.
+# Created via AI.
+
+# psubis RT, RA, SI is an alias for paddis RT, RA, -SI, 0.
+# The neg_s32imm operand negates SI before encoding.
+
+# The 32-bit negated immediate is split:
+# (-SI)[31:16] in the lower 16 bits of the prefix word,
+# (-SI)[15:0] in the lower 16 bits of the instruction word.
+# Prefix word (BE): 0x06 0x00 <(-SI)[31:16] high byte> <(-SI)[31:16] low byte>
+# Instr word (BE): 0x3C <(RT<<3)|(RA>>2)> <(RA<<6)|(-SI)[15:8]> <(-SI)[7:0]>
+
+# psubis 3, 3, 1 -> paddis 3, 3, -1, 0
+
+# -1 = 0xFFFFFFFF: prefix SI[31:16]=0xFFFF, instr SI[15:0]=0xFFFF
+# Prefix (BE): 06 00 FF FF
+# Instr (BE): 3C 63 FF FF
+ psubis 3, 3, 1
+// CHECK-BE: paddis 3, 3, -1, 0 # encoding: [0x06,0x00,0xff,0xff,0x3c,0x63,0xff,0xff]
+// CHECK-LE: paddis 3, 3, -1, 0 # encoding: [0xff,0xff,0x00,0x06,0xff,0xff,0x63,0x3c]
+
+# psubis 3, 3, -1 -> paddis 3, 3, 1, 0
+
+# 1 = 0x00000001: prefix SI[31:16]=0x0000, instr SI[15:0]=0x0001
+# Prefix (BE): 06 00 00 00
+# Instr (BE): 3C 63 00 01
+ psubis 3, 3, -1
+// CHECK-BE: paddis 3, 3, 1, 0 # encoding: [0x06,0x00,0x00,0x00,0x3c,0x63,0x00,0x01]
+// CHECK-LE: paddis 3, 3, 1, 0 # encoding: [0x00,0x00,0x00,0x06,0x01,0x00,0x63,0x3c]
+
+# psubis 3, 3, 0x1234 -> paddis 3, 3, -0x1234, 0
+
+# -0x1234 = 0xFFFFEDCC: prefix SI[31:16]=0xFFFF, instr SI[15:0]=0xEDCC
+# Prefix (BE): 06 00 FF FF
+# Instr (BE): 3C 63 ED CC
+ psubis 3, 3, 0x1234
+// CHECK-BE: paddis 3, 3, -4660, 0 # encoding: [0x06,0x00,0xff,0xff,0x3c,0x63,0xed,0xcc]
+// CHECK-LE: paddis 3, 3, -4660, 0 # encoding: [0xff,0xff,0x00,0x06,0xcc,0xed,0x63,0x3c]
+
+# psubis 3, 3, 0x12345678 -> paddis 3, 3, -0x12345678, 0
+
+# -0x12345678 = 0xEDCBA988: prefix SI[31:16]=0xEDCB, instr SI[15:0]=0xA988
+# Prefix (BE): 06 00 ED CB
+# Instr (BE): 3C 63 A9 88
+ psubis 3, 3, 0x12345678
+// CHECK-BE: paddis 3, 3, -305419896, 0 # encoding: [0x06,0x00,0xed,0xcb,0x3c,0x63,0xa9,0x88]
+// CHECK-LE: paddis 3, 3, -305419896, 0 # encoding: [0xcb,0xed,0x00,0x06,0x88,0xa9,0x63,0x3c]
+
+# psubis 1, 2, 1 -> paddis 1, 2, -1, 0 (different RT and RA)
+
+# -1 = 0xFFFFFFFF: prefix SI[31:16]=0xFFFF, instr SI[15:0]=0xFFFF
+# Prefix (BE): 06 00 FF FF
+# Instr (BE): 3C 22 FF FF
+ psubis 1, 2, 1
+// CHECK-BE: paddis 1, 2, -1, 0 # encoding: [0x06,0x00,0xff,0xff,0x3c,0x22,0xff,0xff]
+// CHECK-LE: paddis 1, 2, -1, 0 # encoding: [0xff,0xff,0x00,0x06,0xff,0xff,0x22,0x3c]
+
+# psubis 1, 2, 0x12345678 -> paddis 1, 2, -0x12345678, 0
+
+# -0x12345678 = 0xEDCBA988: prefix SI[31:16]=0xEDCB, instr SI[15:0]=0xA988
+# Prefix (BE): 06 00 ED CB
+# Instr (BE): 3C 22 A9 88
+ psubis 1, 2, 0x12345678
+// CHECK-BE: paddis 1, 2, -305419896, 0 # encoding: [0x06,0x00,0xed,0xcb,0x3c,0x22,0xa9,0x88]
+// CHECK-LE: paddis 1, 2, -305419896, 0 # encoding: [0xcb,0xed,0x00,0x06,0x88,0xa9,0x22,0x3c]
+
+# psubis 3, 0, 1 -> paddis 3, 0, -1, 0 (RA=0)
+
+# -1 = 0xFFFFFFFF: prefix SI[31:16]=0xFFFF, instr SI[15:0]=0xFFFF
+# Prefix (BE): 06 00 FF FF
+# Instr (BE): 3C 60 FF FF
+ psubis 3, 0, 1
+// CHECK-BE: plis 3, -1 # encoding: [0x06,0x00,0xff,0xff,0x3c,0x60,0xff,0xff]
+// CHECK-LE: plis 3, -1 # encoding: [0xff,0xff,0x00,0x06,0xff,0xff,0x60,0x3c]
+
+# psubis 3, 0, 0x7FFFFFFF -> paddis 3, 0, -0x7FFFFFFF, 0
+
+# -0x7FFFFFFF = 0x80000001: prefix SI[31:16]=0x8000, instr SI[15:0]=0x0001
+# Prefix (BE): 06 00 80 00
+# Instr (BE): 3C 60 00 01
+ psubis 3, 0, 0x7FFFFFFF
+// CHECK-BE: plis 3, -2147483647 # encoding: [0x06,0x00,0x80,0x00,0x3c,0x60,0x00,0x01]
+// CHECK-LE: plis 3, -2147483647 # encoding: [0x00,0x80,0x00,0x06,0x01,0x00,0x60,0x3c]
+
+# psubis with a symbol reference: psubis 3, 3, target
+# -> paddis 3, 3, -target, 0
+
+# The fixup negates the symbol value; fixup kind is fixup_ppc_imm32.
+
+# At encode time SI=0, so:
+# Prefix (BE): 0x06'A' A A A
+# Instr (BE): 3C 63 00 00
+target:
+// CHECK-BE: target:
+// CHECK-LE: target:
+ psubis 3, 3, target
+// CHECK-BE: paddis 3, 3, -target, 0 # encoding: [0x06'A',A,A,A,0x3c,0x63,0x00,0x00]
+// CHECK-BE-NEXT: # fixup A - offset: 0, value: -target, kind: fixup_ppc_imm32
+// CHECK-LE: paddis 3, 3, -target, 0 # encoding: [A,A,A,0x06'A',0x00,0x00,0x63,0x3c]
+// CHECK-LE-NEXT: # fixup A - offset: 0, value: -target, kind: fixup_ppc_imm32
>From 494a5a7c95c5c457c3f7d450a97498ebaaa8b9e1 Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Fri, 20 Mar 2026 14:21:41 -0400
Subject: [PATCH 3/5] address review comments
---
.../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 71 ++++++++-----------
llvm/lib/Target/PowerPC/PPCOperands.td | 4 +-
llvm/test/MC/PowerPC/ppc-encoding-ISAFuture.s | 1 +
llvm/test/MC/PowerPC/ppc64-psubis.s | 56 ++++++---------
4 files changed, 55 insertions(+), 77 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 5325b416743b4..49c9934655538 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -94,6 +94,8 @@ EvaluateCRExpr(const MCExpr *E) {
llvm_unreachable("Invalid expression kind!");
}
+static void addNegOperand(MCInst &Inst, MCOperand &Op, MCContext &Ctx);
+
namespace {
struct PPCOperand;
@@ -161,48 +163,6 @@ class PPCAsmParser : public MCTargetAsmParser {
MCContext &Ctx) override;
};
-// Helper function to negate an operand - used by both PPCOperand and
-// PPCAsmParser to add the negation of \p Op as an operand to \p Inst.
-//
-// Originally this helper is only used to lower pseudo-subtraction mnemonics
-// (e.g. SUBI, SUBIS, SUBIC, SUBIC_rec, PSUBI) into their real ADD-family
-// equivalents by negating the immediate or expression operand before
-// appending it. Now it's also used by PPCOperand for PSUBIS.
-//
-// The negation is performed as follows:
-// - If \p Op is an immediate, the negated integer value is added directly.
-// - If \p Op is a unary-minus expression (i.e. \c -E), the inner
-// sub-expression \c E is added, effectively cancelling the double negation.
-// - If \p Op is a binary-subtraction expression (i.e. \c LHS-RHS), the
-// operands are swapped to produce \c RHS-LHS.
-// - Otherwise, a new unary-minus expression wrapping \p Op's expression is
-// created and added.
-//
-// \param Inst The instruction being built; the negated operand is appended.
-// \param Op The source operand whose value is to be negated.
-// \param Ctx The MC context used to allocate new expression nodes.
-static void addNegOperand(MCInst &Inst, MCOperand &Op, MCContext &Ctx) {
- if (Op.isImm()) {
- Inst.addOperand(MCOperand::createImm(-Op.getImm()));
- return;
- }
- const MCExpr *Expr = Op.getExpr();
- if (const MCUnaryExpr *UnExpr = dyn_cast<MCUnaryExpr>(Expr)) {
- if (UnExpr->getOpcode() == MCUnaryExpr::Minus) {
- Inst.addOperand(MCOperand::createExpr(UnExpr->getSubExpr()));
- return;
- }
- } else if (const MCBinaryExpr *BinExpr = dyn_cast<MCBinaryExpr>(Expr)) {
- if (BinExpr->getOpcode() == MCBinaryExpr::Sub) {
- const MCExpr *NE =
- MCBinaryExpr::createSub(BinExpr->getRHS(), BinExpr->getLHS(), Ctx);
- Inst.addOperand(MCOperand::createExpr(NE));
- return;
- }
- }
- Inst.addOperand(MCOperand::createExpr(MCUnaryExpr::createMinus(Expr, Ctx)));
-}
-
/// PPCOperand - Instances of this class represent a parsed PowerPC machine
/// instruction.
struct PPCOperand : public MCParsedAsmOperand {
@@ -861,6 +821,33 @@ void PPCOperand::print(raw_ostream &OS, const MCAsmInfo &MAI) const {
}
}
+static void
+addNegOperand(MCInst &Inst, MCOperand &Op, MCContext &Ctx) {
+ if (Op.isImm()) {
+ Inst.addOperand(MCOperand::createImm(-Op.getImm()));
+ return;
+ }
+ const MCExpr *Expr = Op.getExpr();
+ if (const MCUnaryExpr *UnExpr = dyn_cast<MCUnaryExpr>(Expr)) {
+ // For unary-minus expression (i.e. -E), the inner sub-expression E
+ // is added, effectively cancelling the double negation.
+ if (UnExpr->getOpcode() == MCUnaryExpr::Minus) {
+ Inst.addOperand(MCOperand::createExpr(UnExpr->getSubExpr()));
+ return;
+ }
+ } else if (const MCBinaryExpr *BinExpr = dyn_cast<MCBinaryExpr>(Expr)) {
+ // For binary-subtraction expression (i.e. LHS-RHS), the operands
+ // are swapped to produce RHS-LHS.
+ if (BinExpr->getOpcode() == MCBinaryExpr::Sub) {
+ const MCExpr *NE = MCBinaryExpr::createSub(BinExpr->getRHS(),
+ BinExpr->getLHS(), Ctx);
+ Inst.addOperand(MCOperand::createExpr(NE));
+ return;
+ }
+ }
+ Inst.addOperand(MCOperand::createExpr(MCUnaryExpr::createMinus(Expr, Ctx)));
+}
+
void PPCAsmParser::processInstruction(MCInst &Inst,
const OperandVector &Operands) {
int Opcode = Inst.getOpcode();
diff --git a/llvm/lib/Target/PowerPC/PPCOperands.td b/llvm/lib/Target/PowerPC/PPCOperands.td
index 3f9a91e8c263e..6411ac51d589f 100644
--- a/llvm/lib/Target/PowerPC/PPCOperands.td
+++ b/llvm/lib/Target/PowerPC/PPCOperands.td
@@ -190,7 +190,7 @@ defm s32imm : SignedImmediateWithPCRel<i32,
defm s34imm : SignedImmediateReloc<i32,
[{ return isInt<34>(Imm); }], NOOP_SDNodeXForm,
"S34Imm", 34, "PPC::fixup_ppc_imm34">;
-defm neg_s32imm : SignedImmediate<i32,
+defm neg_s32imm : SignedImmediateReloc<i32,
[{ return isInt<32>(Imm); }], NEG_S32,
"NegS32Imm", 32, "PPC::fixup_ppc_imm32">;
@@ -204,7 +204,7 @@ defm s32imm64 : SignedImmediateWithPCRel<i64,
defm s34imm64 : SignedImmediateWithPCRel<i64,
[{ return isInt<34>(Imm); }], NOOP_SDNodeXForm,
"S34Imm", 34, "PPC::fixup_ppc_imm34", "PPC::fixup_ppc_pcrel34">;
-defm neg_s32imm64 : SignedImmediate<i64,
+defm neg_s32imm64 : SignedImmediateReloc<i64,
[{ return isInt<32>(Imm); }], NEG_S32,
"NegS32Imm", 32, "PPC::fixup_ppc_imm32">;
diff --git a/llvm/test/MC/PowerPC/ppc-encoding-ISAFuture.s b/llvm/test/MC/PowerPC/ppc-encoding-ISAFuture.s
index 04a26848582b7..1b816a97e1b28 100644
--- a/llvm/test/MC/PowerPC/ppc-encoding-ISAFuture.s
+++ b/llvm/test/MC/PowerPC/ppc-encoding-ISAFuture.s
@@ -40,6 +40,7 @@
# CHECK-BE: dmxxinstdmr512 1, 2, 34, 0 # encoding: [0xf0,0x82,0x17,0x52]
# CHECK-LE: dmxxinstdmr512 1, 2, 34, 0 # encoding: [0x52,0x17,0x82,0xf0]
dmxxinstdmr512 1, 2, 34, 0
+
# CHECK-BE: dmxxinstdmr512 1, 2, 34, 1 # encoding: [0xf0,0x83,0x17,0x52]
# CHECK-LE: dmxxinstdmr512 1, 2, 34, 1 # encoding: [0x52,0x17,0x83,0xf0]
dmxxinstdmr512 1, 2, 34, 1
diff --git a/llvm/test/MC/PowerPC/ppc64-psubis.s b/llvm/test/MC/PowerPC/ppc64-psubis.s
index e0f4d8527800d..6a60b0349fc73 100644
--- a/llvm/test/MC/PowerPC/ppc64-psubis.s
+++ b/llvm/test/MC/PowerPC/ppc64-psubis.s
@@ -1,4 +1,4 @@
-// NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 6
+# NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 6
# RUN: llvm-mc -triple powerpc64-unknown-unknown --show-encoding \
# RUN: -mattr=+isa-future-instructions,+prefix-instrs %s | \
# RUN: FileCheck -check-prefix=CHECK-BE %s
@@ -6,17 +6,7 @@
# RUN: -mattr=+isa-future-instructions,+prefix-instrs %s | \
# RUN: FileCheck -check-prefix=CHECK-LE %s
-# Tests for psubis encoding with various immediate inputs.
-# Created via AI.
-
# psubis RT, RA, SI is an alias for paddis RT, RA, -SI, 0.
-# The neg_s32imm operand negates SI before encoding.
-
-# The 32-bit negated immediate is split:
-# (-SI)[31:16] in the lower 16 bits of the prefix word,
-# (-SI)[15:0] in the lower 16 bits of the instruction word.
-# Prefix word (BE): 0x06 0x00 <(-SI)[31:16] high byte> <(-SI)[31:16] low byte>
-# Instr word (BE): 0x3C <(RT<<3)|(RA>>2)> <(RA<<6)|(-SI)[15:8]> <(-SI)[7:0]>
# psubis 3, 3, 1 -> paddis 3, 3, -1, 0
@@ -24,8 +14,8 @@
# Prefix (BE): 06 00 FF FF
# Instr (BE): 3C 63 FF FF
psubis 3, 3, 1
-// CHECK-BE: paddis 3, 3, -1, 0 # encoding: [0x06,0x00,0xff,0xff,0x3c,0x63,0xff,0xff]
-// CHECK-LE: paddis 3, 3, -1, 0 # encoding: [0xff,0xff,0x00,0x06,0xff,0xff,0x63,0x3c]
+# CHECK-BE: paddis 3, 3, -1, 0 # encoding: [0x06,0x00,0xff,0xff,0x3c,0x63,0xff,0xff]
+# CHECK-LE: paddis 3, 3, -1, 0 # encoding: [0xff,0xff,0x00,0x06,0xff,0xff,0x63,0x3c]
# psubis 3, 3, -1 -> paddis 3, 3, 1, 0
@@ -33,8 +23,8 @@
# Prefix (BE): 06 00 00 00
# Instr (BE): 3C 63 00 01
psubis 3, 3, -1
-// CHECK-BE: paddis 3, 3, 1, 0 # encoding: [0x06,0x00,0x00,0x00,0x3c,0x63,0x00,0x01]
-// CHECK-LE: paddis 3, 3, 1, 0 # encoding: [0x00,0x00,0x00,0x06,0x01,0x00,0x63,0x3c]
+# CHECK-BE: paddis 3, 3, 1, 0 # encoding: [0x06,0x00,0x00,0x00,0x3c,0x63,0x00,0x01]
+# CHECK-LE: paddis 3, 3, 1, 0 # encoding: [0x00,0x00,0x00,0x06,0x01,0x00,0x63,0x3c]
# psubis 3, 3, 0x1234 -> paddis 3, 3, -0x1234, 0
@@ -42,8 +32,8 @@
# Prefix (BE): 06 00 FF FF
# Instr (BE): 3C 63 ED CC
psubis 3, 3, 0x1234
-// CHECK-BE: paddis 3, 3, -4660, 0 # encoding: [0x06,0x00,0xff,0xff,0x3c,0x63,0xed,0xcc]
-// CHECK-LE: paddis 3, 3, -4660, 0 # encoding: [0xff,0xff,0x00,0x06,0xcc,0xed,0x63,0x3c]
+# CHECK-BE: paddis 3, 3, -4660, 0 # encoding: [0x06,0x00,0xff,0xff,0x3c,0x63,0xed,0xcc]
+# CHECK-LE: paddis 3, 3, -4660, 0 # encoding: [0xff,0xff,0x00,0x06,0xcc,0xed,0x63,0x3c]
# psubis 3, 3, 0x12345678 -> paddis 3, 3, -0x12345678, 0
@@ -51,8 +41,8 @@
# Prefix (BE): 06 00 ED CB
# Instr (BE): 3C 63 A9 88
psubis 3, 3, 0x12345678
-// CHECK-BE: paddis 3, 3, -305419896, 0 # encoding: [0x06,0x00,0xed,0xcb,0x3c,0x63,0xa9,0x88]
-// CHECK-LE: paddis 3, 3, -305419896, 0 # encoding: [0xcb,0xed,0x00,0x06,0x88,0xa9,0x63,0x3c]
+# CHECK-BE: paddis 3, 3, -305419896, 0 # encoding: [0x06,0x00,0xed,0xcb,0x3c,0x63,0xa9,0x88]
+# CHECK-LE: paddis 3, 3, -305419896, 0 # encoding: [0xcb,0xed,0x00,0x06,0x88,0xa9,0x63,0x3c]
# psubis 1, 2, 1 -> paddis 1, 2, -1, 0 (different RT and RA)
@@ -60,8 +50,8 @@
# Prefix (BE): 06 00 FF FF
# Instr (BE): 3C 22 FF FF
psubis 1, 2, 1
-// CHECK-BE: paddis 1, 2, -1, 0 # encoding: [0x06,0x00,0xff,0xff,0x3c,0x22,0xff,0xff]
-// CHECK-LE: paddis 1, 2, -1, 0 # encoding: [0xff,0xff,0x00,0x06,0xff,0xff,0x22,0x3c]
+# CHECK-BE: paddis 1, 2, -1, 0 # encoding: [0x06,0x00,0xff,0xff,0x3c,0x22,0xff,0xff]
+# CHECK-LE: paddis 1, 2, -1, 0 # encoding: [0xff,0xff,0x00,0x06,0xff,0xff,0x22,0x3c]
# psubis 1, 2, 0x12345678 -> paddis 1, 2, -0x12345678, 0
@@ -69,8 +59,8 @@
# Prefix (BE): 06 00 ED CB
# Instr (BE): 3C 22 A9 88
psubis 1, 2, 0x12345678
-// CHECK-BE: paddis 1, 2, -305419896, 0 # encoding: [0x06,0x00,0xed,0xcb,0x3c,0x22,0xa9,0x88]
-// CHECK-LE: paddis 1, 2, -305419896, 0 # encoding: [0xcb,0xed,0x00,0x06,0x88,0xa9,0x22,0x3c]
+# CHECK-BE: paddis 1, 2, -305419896, 0 # encoding: [0x06,0x00,0xed,0xcb,0x3c,0x22,0xa9,0x88]
+# CHECK-LE: paddis 1, 2, -305419896, 0 # encoding: [0xcb,0xed,0x00,0x06,0x88,0xa9,0x22,0x3c]
# psubis 3, 0, 1 -> paddis 3, 0, -1, 0 (RA=0)
@@ -78,8 +68,8 @@
# Prefix (BE): 06 00 FF FF
# Instr (BE): 3C 60 FF FF
psubis 3, 0, 1
-// CHECK-BE: plis 3, -1 # encoding: [0x06,0x00,0xff,0xff,0x3c,0x60,0xff,0xff]
-// CHECK-LE: plis 3, -1 # encoding: [0xff,0xff,0x00,0x06,0xff,0xff,0x60,0x3c]
+# CHECK-BE: plis 3, -1 # encoding: [0x06,0x00,0xff,0xff,0x3c,0x60,0xff,0xff]
+# CHECK-LE: plis 3, -1 # encoding: [0xff,0xff,0x00,0x06,0xff,0xff,0x60,0x3c]
# psubis 3, 0, 0x7FFFFFFF -> paddis 3, 0, -0x7FFFFFFF, 0
@@ -87,8 +77,8 @@
# Prefix (BE): 06 00 80 00
# Instr (BE): 3C 60 00 01
psubis 3, 0, 0x7FFFFFFF
-// CHECK-BE: plis 3, -2147483647 # encoding: [0x06,0x00,0x80,0x00,0x3c,0x60,0x00,0x01]
-// CHECK-LE: plis 3, -2147483647 # encoding: [0x00,0x80,0x00,0x06,0x01,0x00,0x60,0x3c]
+# CHECK-BE: plis 3, -2147483647 # encoding: [0x06,0x00,0x80,0x00,0x3c,0x60,0x00,0x01]
+# CHECK-LE: plis 3, -2147483647 # encoding: [0x00,0x80,0x00,0x06,0x01,0x00,0x60,0x3c]
# psubis with a symbol reference: psubis 3, 3, target
# -> paddis 3, 3, -target, 0
@@ -99,10 +89,10 @@
# Prefix (BE): 0x06'A' A A A
# Instr (BE): 3C 63 00 00
target:
-// CHECK-BE: target:
-// CHECK-LE: target:
+# CHECK-BE: target:
+# CHECK-LE: target:
psubis 3, 3, target
-// CHECK-BE: paddis 3, 3, -target, 0 # encoding: [0x06'A',A,A,A,0x3c,0x63,0x00,0x00]
-// CHECK-BE-NEXT: # fixup A - offset: 0, value: -target, kind: fixup_ppc_imm32
-// CHECK-LE: paddis 3, 3, -target, 0 # encoding: [A,A,A,0x06'A',0x00,0x00,0x63,0x3c]
-// CHECK-LE-NEXT: # fixup A - offset: 0, value: -target, kind: fixup_ppc_imm32
+# CHECK-BE: paddis 3, 3, -target, 0 # encoding: [0x06'A',A,A,A,0x3c,0x63,0x00,0x00]
+# CHECK-BE-NEXT: # fixup A - offset: 0, value: -target, kind: fixup_ppc_imm32
+# CHECK-LE: paddis 3, 3, -target, 0 # encoding: [A,A,A,0x06'A',0x00,0x00,0x63,0x3c]
+# CHECK-LE-NEXT: # fixup A - offset: 0, value: -target, kind: fixup_ppc_imm32
>From 98a4f34db177f96c5eaef68b99f31507120d7cbf Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Wed, 22 Apr 2026 12:11:42 -0400
Subject: [PATCH 4/5] Update MCContext a reference
---
.../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 60 +++++++++----------
1 file changed, 28 insertions(+), 32 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 49c9934655538..875596973f6c7 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -176,7 +176,10 @@ struct PPCOperand : public MCParsedAsmOperand {
SMLoc StartLoc, EndLoc;
bool IsPPC64;
- MCContext *Ctx;
+
+ // Keep the MCContext around as the MCExprs may need manipulated during
+ // the add<>Operands() calls.
+ MCContext &Ctx;
struct TokOp {
const char *Data;
@@ -204,10 +207,10 @@ struct PPCOperand : public MCParsedAsmOperand {
struct TLSRegOp TLSReg;
};
- PPCOperand(KindTy K) : Kind(K) {}
+ PPCOperand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
public:
- PPCOperand(const PPCOperand &o) : MCParsedAsmOperand() {
+ PPCOperand(const PPCOperand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
Kind = o.Kind;
StartLoc = o.StartLoc;
EndLoc = o.EndLoc;
@@ -678,92 +681,85 @@ struct PPCOperand : public MCParsedAsmOperand {
void print(raw_ostream &OS, const MCAsmInfo &MAI) const override;
static std::unique_ptr<PPCOperand>
- CreateToken(StringRef Str, SMLoc S, bool IsPPC64, MCContext *Ctx = nullptr) {
- auto Op = std::make_unique<PPCOperand>(Token);
+ CreateToken(StringRef Str, SMLoc S, bool IsPPC64, MCContext &Ctx) {
+ auto Op = std::make_unique<PPCOperand>(Token, Ctx);
Op->Tok.Data = Str.data();
Op->Tok.Length = Str.size();
Op->StartLoc = S;
Op->EndLoc = S;
Op->IsPPC64 = IsPPC64;
- Op->Ctx = Ctx;
return Op;
}
static std::unique_ptr<PPCOperand>
CreateTokenWithStringCopy(StringRef Str, SMLoc S, bool IsPPC64,
- MCContext *Ctx = nullptr) {
+ MCContext &Ctx) {
// Allocate extra memory for the string and copy it.
// FIXME: This is incorrect, Operands are owned by unique_ptr with a default
// deleter which will destroy them by simply using "delete", not correctly
// calling operator delete on this extra memory after calling the dtor
// explicitly.
void *Mem = ::operator new(sizeof(PPCOperand) + Str.size());
- std::unique_ptr<PPCOperand> Op(new (Mem) PPCOperand(Token));
+ std::unique_ptr<PPCOperand> Op(new (Mem) PPCOperand(Token, Ctx));
Op->Tok.Data = reinterpret_cast<const char *>(Op.get() + 1);
Op->Tok.Length = Str.size();
std::memcpy(const_cast<char *>(Op->Tok.Data), Str.data(), Str.size());
Op->StartLoc = S;
Op->EndLoc = S;
Op->IsPPC64 = IsPPC64;
- Op->Ctx = Ctx;
return Op;
}
static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
- bool IsPPC64,
- MCContext *Ctx = nullptr,
+ bool IsPPC64, MCContext &Ctx,
bool IsMemOpBase = false) {
- auto Op = std::make_unique<PPCOperand>(Immediate);
+ auto Op = std::make_unique<PPCOperand>(Immediate, Ctx);
Op->Imm.Val = Val;
Op->Imm.IsMemOpBase = IsMemOpBase;
Op->StartLoc = S;
Op->EndLoc = E;
Op->IsPPC64 = IsPPC64;
- Op->Ctx = Ctx;
return Op;
}
static std::unique_ptr<PPCOperand> CreateExpr(const MCExpr *Val, SMLoc S,
SMLoc E, bool IsPPC64,
- MCContext *Ctx = nullptr) {
- auto Op = std::make_unique<PPCOperand>(Expression);
+ MCContext &Ctx) {
+ auto Op = std::make_unique<PPCOperand>(Expression, Ctx);
Op->Expr.Val = Val;
Op->Expr.CRVal = EvaluateCRExpr(Val);
Op->StartLoc = S;
Op->EndLoc = E;
Op->IsPPC64 = IsPPC64;
- Op->Ctx = Ctx;
return Op;
}
static std::unique_ptr<PPCOperand> CreateTLSReg(const MCSymbolRefExpr *Sym,
SMLoc S, SMLoc E,
bool IsPPC64,
- MCContext *Ctx = nullptr) {
- auto Op = std::make_unique<PPCOperand>(TLSRegister);
+ MCContext &Ctx) {
+ auto Op = std::make_unique<PPCOperand>(TLSRegister, Ctx);
Op->TLSReg.Sym = Sym;
Op->StartLoc = S;
Op->EndLoc = E;
Op->IsPPC64 = IsPPC64;
- Op->Ctx = Ctx;
return Op;
}
static std::unique_ptr<PPCOperand>
CreateContextImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64,
- MCContext *Ctx = nullptr) {
- auto Op = std::make_unique<PPCOperand>(ContextImmediate);
+ MCContext &Ctx) {
+ auto Op = std::make_unique<PPCOperand>(ContextImmediate, Ctx);
Op->Imm.Val = Val;
Op->StartLoc = S;
Op->EndLoc = E;
Op->IsPPC64 = IsPPC64;
- Op->Ctx = Ctx;
return Op;
}
static std::unique_ptr<PPCOperand>
CreateFromMCExpr(const MCExpr *Val, SMLoc S, SMLoc E, bool IsPPC64,
- MCContext *Ctx = nullptr) {
+ MCContext &Ctx) {
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val))
return CreateImm(CE->getValue(), S, E, IsPPC64, Ctx);
@@ -1489,7 +1485,7 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
return Error(S, "invalid register name");
Operands.push_back(
- PPCOperand::CreateImm(IntVal, S, E, isPPC64(), &getContext()));
+ PPCOperand::CreateImm(IntVal, S, E, isPPC64(), getContext()));
return false;
}
case AsmToken::Identifier:
@@ -1511,7 +1507,7 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
// Push the parsed operand into the list of operands
Operands.push_back(
- PPCOperand::CreateFromMCExpr(EVal, S, E, isPPC64(), &getContext()));
+ PPCOperand::CreateFromMCExpr(EVal, S, E, isPPC64(), getContext()));
// Check whether this is a TLS call expression
const char TlsGetAddr[] = "__tls_get_addr";
@@ -1558,11 +1554,11 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
EVal = MCBinaryExpr::createAdd(EVal, TlsCallAddend, getContext());
// Add a __tls_get_addr operand with addend a, b, or a+b.
Operands.back() = PPCOperand::CreateFromMCExpr(
- EVal, S, Parser.getTok().getLoc(), false, &getContext());
+ EVal, S, Parser.getTok().getLoc(), false, getContext());
}
Operands.push_back(
- PPCOperand::CreateFromMCExpr(TLSSym, S, E, isPPC64(), &getContext()));
+ PPCOperand::CreateFromMCExpr(TLSSym, S, E, isPPC64(), getContext()));
}
// Otherwise, check for D-form memory operands
@@ -1590,7 +1586,7 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
if (parseToken(AsmToken::RParen, "missing ')'"))
return true;
Operands.push_back(PPCOperand::CreateImm(
- IntVal, S, E, isPPC64(), &getContext(), /*IsMemOpBase=*/true));
+ IntVal, S, E, isPPC64(), getContext(), /*IsMemOpBase=*/true));
}
return false;
@@ -1619,19 +1615,19 @@ bool PPCAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
StringRef Mnemonic = Name.slice(0, Dot);
if (!NewOpcode.empty()) // Underlying memory for Name is volatile.
Operands.push_back(PPCOperand::CreateTokenWithStringCopy(
- Mnemonic, NameLoc, isPPC64(), &getContext()));
+ Mnemonic, NameLoc, isPPC64(), getContext()));
else
Operands.push_back(
- PPCOperand::CreateToken(Mnemonic, NameLoc, isPPC64(), &getContext()));
+ PPCOperand::CreateToken(Mnemonic, NameLoc, isPPC64(), getContext()));
if (Dot != StringRef::npos) {
SMLoc DotLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Dot);
StringRef DotStr = Name.substr(Dot);
if (!NewOpcode.empty()) // Underlying memory for Name is volatile.
Operands.push_back(PPCOperand::CreateTokenWithStringCopy(
- DotStr, DotLoc, isPPC64(), &getContext()));
+ DotStr, DotLoc, isPPC64(), getContext()));
else
Operands.push_back(
- PPCOperand::CreateToken(DotStr, DotLoc, isPPC64(), &getContext()));
+ PPCOperand::CreateToken(DotStr, DotLoc, isPPC64(), getContext()));
}
// If there are no more operands then finish
>From 540c54d35b27e94747399637c5c97af42737a351 Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Wed, 22 Apr 2026 12:29:49 -0400
Subject: [PATCH 5/5] remove assert since this is now a reference
---
llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 875596973f6c7..3c2fb0bf73ecd 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -655,9 +655,8 @@ struct PPCOperand : public MCParsedAsmOperand {
}
// Create an MCOperand using the static helper function.
- assert(Ctx && "MCContext is required for for non immediates");
MCOperand Op = MCOperand::createExpr(getExpr());
- addNegOperand(Inst, Op, *Ctx);
+ addNegOperand(Inst, Op, Ctx);
}
void addBranchTargetOperands(MCInst &Inst, unsigned N) const {
More information about the llvm-commits
mailing list