[llvm] [PowerPC] Add error for incorrect use of memory operands (PR #114277)

Jake Egan via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 7 10:28:10 PST 2024


https://github.com/jakeegan updated https://github.com/llvm/llvm-project/pull/114277

>From e7ee0206c194092e2bdf86ad3be75d3a2cfc4d0d Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Wed, 30 Oct 2024 13:14:01 -0400
Subject: [PATCH 1/6] [PowerPC] Add error for incorrect use of memory operands

---
 .../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 12 +++++++-
 .../PowerPC/MCTargetDesc/PPCMCTargetDesc.h    |  4 ++-
 llvm/lib/Target/PowerPC/PPCInstr64Bit.td      |  8 +++---
 llvm/lib/Target/PowerPC/PPCInstrFormats.td    | 14 +++++++---
 llvm/lib/Target/PowerPC/PPCInstrInfo.h        |  3 ++
 llvm/lib/Target/PowerPC/PPCInstrInfo.td       | 12 +++++---
 llvm/lib/Target/PowerPC/PPCInstrP10.td        | 28 +++++++++++--------
 llvm/lib/Target/PowerPC/PPCInstrSPE.td        |  2 +-
 .../PowerPC/2007-01-31-InlineAsmAddrMode.ll   |  2 +-
 .../PowerPC/2009-07-16-InlineAsm-M-Operand.ll |  2 +-
 llvm/test/MC/PowerPC/ppc64-errors.s           | 10 +++++++
 11 files changed, 68 insertions(+), 29 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index bf512481cf6460..5ed41844bfbf9b 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -9,6 +9,7 @@
 #include "MCTargetDesc/PPCMCExpr.h"
 #include "MCTargetDesc/PPCMCTargetDesc.h"
 #include "PPCTargetStreamer.h"
+#include "PPCInstrInfo.h"
 #include "TargetInfo/PowerPCTargetInfo.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Twine.h"
@@ -99,10 +100,14 @@ struct PPCOperand;
 class PPCAsmParser : public MCTargetAsmParser {
   bool IsPPC64;
 
+  bool UsesMemOp;
+
   void Warning(SMLoc L, const Twine &Msg) { getParser().Warning(L, Msg); }
 
   bool isPPC64() const { return IsPPC64; }
 
+  bool usesMemOp() const { return UsesMemOp; }
+
   MCRegister matchRegisterName(int64_t &IntVal);
 
   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
@@ -146,6 +151,7 @@ class PPCAsmParser : public MCTargetAsmParser {
     // Check for 64-bit vs. 32-bit pointer mode.
     const Triple &TheTriple = STI.getTargetTriple();
     IsPPC64 = TheTriple.isPPC64();
+    UsesMemOp = false;
     // Initialize the set of available features.
     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
   }
@@ -1257,9 +1263,11 @@ bool PPCAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
                                            MCStreamer &Out, uint64_t &ErrorInfo,
                                            bool MatchingInlineAsm) {
   MCInst Inst;
-
+  const PPCInstrInfo *TII = static_cast<const PPCInstrInfo*>(&MII);
   switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
   case Match_Success:
+    if (usesMemOp() != TII->isMemOp(Inst.getOpcode()))
+      return Error(IDLoc, "invalid operand for instruction");
     // Post-process instructions (typically extended mnemonics)
     processInstruction(Inst, Operands);
     Inst.setLoc(IDLoc);
@@ -1595,6 +1603,7 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
 
   // Otherwise, check for D-form memory operands
   if (!TlsCall && parseOptionalToken(AsmToken::LParen)) {
+    UsesMemOp = true;
     S = Parser.getTok().getLoc();
 
     int64_t IntVal;
@@ -1626,6 +1635,7 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
 /// Parse an instruction mnemonic followed by its operands.
 bool PPCAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
                                     SMLoc NameLoc, OperandVector &Operands) {
+  UsesMemOp = false;
   // The first operand is the token for the instruction name.
   // If the next character is a '+' or '-', we need to add it to the
   // instruction name, to match what TableGen is doing.
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
index 16777725990aa1..caa3ad0d22e3bd 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
@@ -171,7 +171,9 @@ enum {
   /// This instruction produced a sign extended result.
   SExt32To64 = 0x1 << (NewDef_Shift + 2),
   /// This instruction produced a zero extended result.
-  ZExt32To64 = 0x1 << (NewDef_Shift + 3)
+  ZExt32To64 = 0x1 << (NewDef_Shift + 3),
+  /// This instruction uses a memory operand.
+  MemOp = 0x1 << (NewDef_Shift + 4)
 };
 } // end namespace PPCII
 
diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index ae25f5c78a0e2d..99f945a92b5cf5 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -218,7 +218,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
                               (ins (memrix $D, $RA):$src),
                               "bctrl\n\tld 2, $src", IIC_BrB,
                               [(PPCbctrl_load_toc iaddrX4:$src)]>,
-    Requires<[In64BitMode]>;
+    Requires<[In64BitMode]>, MemOp;
 }
 
 let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
@@ -228,7 +228,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
                               (ins (memrix $D, $RA):$src),
                               "bctrl\n\tld 2, $src", IIC_BrB,
                               [(PPCbctrl_load_toc_rm iaddrX4:$src)]>,
-    Requires<[In64BitMode]>;
+    Requires<[In64BitMode]>, MemOp;
 }
 
 } // Interpretation64Bit
@@ -777,7 +777,7 @@ def ADDIS8 : DForm_2<15, (outs g8rc:$RST), (ins g8rc_nox0:$RA, s17imm64:$D),
 def LA8     : DForm_2<14, (outs g8rc:$RST), (ins g8rc_nox0:$RA, s16imm64:$D),
                      "la $RST, $D($RA)", IIC_IntGeneral,
                      [(set i64:$RST, (add i64:$RA,
-                                    (PPClo tglobaladdr:$D, 0)))]>;
+                                    (PPClo tglobaladdr:$D, 0)))]>, MemOp;
 
 let Defs = [CARRY] in {
 def SUBFIC8: DForm_2< 8, (outs g8rc:$RST), (ins g8rc:$RA, s16imm64:$D),
@@ -1457,7 +1457,7 @@ def LQ   : DQForm_RTp5_RA17_MEM<56, 0,
                                 "lq $RTp, $addr", IIC_LdStLQ,
                                 []>,
                                 RegConstraint<"@earlyclobber $RTp">,
-                                isPPC64;
+                                isPPC64, MemOp;
 // We don't really have LQX in the ISA, make a pseudo one so that we can
 // handle x-form during isel. Make it pre-ra may expose
 // oppotunities to some opts(CSE, LICM and etc.) for the result of adding
diff --git a/llvm/lib/Target/PowerPC/PPCInstrFormats.td b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
index 5389f42a325ce6..45fd0112b2bfdf 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrFormats.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
@@ -55,6 +55,10 @@ class I<bits<6> opcode, dag OOL, dag IOL, string asmstr, InstrItinClass itin>
   bits<1> ZExt32To64 = 0;
   let TSFlags{9} = ZExt32To64;
 
+  // Indicate that this instruction uses a memory operand.
+  bits<1> MemOp = 0;
+  let TSFlags{10} = MemOp;
+
   // Fields used for relation models.
   string BaseName = "";
 
@@ -82,6 +86,7 @@ class PPC970_Unit_BRU      { bits<3> PPC970_Unit = 7;   }
 class XFormMemOp { bits<1> XFormMemOp = 1; }
 class SExt32To64 { bits<1> SExt32To64 = 1; }
 class ZExt32To64 { bits<1> ZExt32To64 = 1; }
+class MemOp      { bits<1> MemOp = 1;      }
 
 // Two joined instructions; used to emit two adjacent instructions as one.
 // The itinerary from the first instruction is used for scheduling and
@@ -250,7 +255,7 @@ class DForm_base<bits<6> opcode, dag OOL, dag IOL, string asmstr,
 
 class DForm_1<bits<6> opcode, dag OOL, dag IOL, string asmstr,
               InstrItinClass itin, list<dag> pattern>
-  : DForm_base<opcode, OOL, IOL, asmstr, itin, pattern> {
+  : DForm_base<opcode, OOL, IOL, asmstr, itin, pattern>, MemOp {
 }
 
 class DForm_2<bits<6> opcode, dag OOL, dag IOL, string asmstr,
@@ -295,6 +300,7 @@ class DForm_4_zero<bits<6> opcode, dag OOL, dag IOL, string asmstr,
   let RST = 0;
   let RA = 0;
   let D = 0;
+  let MemOp = 0;
 }
 
 class DForm_4_fixedreg_zero<bits<6> opcode, bits<5> R, dag OOL, dag IOL,
@@ -372,7 +378,7 @@ class DForm_6_ext<bits<6> opcode, dag OOL, dag IOL, string asmstr,
 // 1.7.5 DS-Form
 class DSForm_1<bits<6> opcode, bits<2> xo, dag OOL, dag IOL, string asmstr,
                InstrItinClass itin, list<dag> pattern>
-         : I<opcode, OOL, IOL, asmstr, itin> {
+         : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
   bits<5>  RST;
   bits<5>  RA;
   bits<14> D;
@@ -404,7 +410,7 @@ class DXForm<bits<6> opcode, bits<5> xo, dag OOL, dag IOL, string asmstr,
 // DQ-Form: [PO T RA DQ TX XO] or [PO S RA DQ SX XO]
 class DQ_RD6_RS5_DQ12<bits<6> opcode, bits<3> xo, dag OOL, dag IOL,
                       string asmstr, InstrItinClass itin, list<dag> pattern>
-  : I<opcode, OOL, IOL, asmstr, itin> {
+  : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
   bits<6>  XT;
   bits<5> RA;
   bits<12> DQ;
@@ -1246,7 +1252,7 @@ class XX2_RD6_DCMX7_RS6<bits<6> opcode, bits<4> xo1, bits<3> xo2,
 
 class XForm_XD6_RA5_RB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
                         string asmstr, InstrItinClass itin, list<dag> pattern>
-  : I<opcode, OOL, IOL, asmstr, itin> {
+  : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
   bits<5> RA;
   bits<6> D;
   bits<5> RB;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.h b/llvm/lib/Target/PowerPC/PPCInstrInfo.h
index 40996f6fbb75e1..0c9b9207f5fe75 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.h
@@ -285,6 +285,9 @@ class PPCInstrInfo : public PPCGenInstrInfo {
   bool isZExt32To64(unsigned Opcode) const {
     return get(Opcode).TSFlags & PPCII::ZExt32To64;
   }
+  bool isMemOp(unsigned Opcode) const {
+    return get(Opcode).TSFlags & PPCII::MemOp;
+  }
 
   static bool isSameClassPhysRegCopy(unsigned Opcode) {
     unsigned CopyOpcodes[] = {PPC::OR,        PPC::OR8,   PPC::FMR,
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index b4a5e41c0107a3..b79c5f79efeb1c 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -1584,7 +1584,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
   def BCTRL_LWZinto_toc:
     XLForm_2_ext_and_DForm_1<19, 528, 20, 0, 1, 32, (outs),
      (ins (memri $D, $RA):$addr), "bctrl\n\tlwz 2, $addr", IIC_BrB,
-     [(PPCbctrl_load_toc iaddr:$addr)]>, Requires<[In32BitMode]>;
+     [(PPCbctrl_load_toc iaddr:$addr)]>, Requires<[In32BitMode]>, MemOp;
 
 }
 
@@ -1593,7 +1593,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
   def BCTRL_LWZinto_toc_RM:
     XLForm_2_ext_and_DForm_1<19, 528, 20, 0, 1, 32, (outs),
      (ins (memri $D, $RA):$addr), "bctrl\n\tlwz 2, $addr", IIC_BrB,
-     [(PPCbctrl_load_toc_rm iaddr:$addr)]>, Requires<[In32BitMode]>;
+     [(PPCbctrl_load_toc_rm iaddr:$addr)]>, Requires<[In32BitMode]>, MemOp;
 
 }
 
@@ -2303,7 +2303,7 @@ let isCodeGenOnly = 1 in
 def LA     : DForm_2<14, (outs gprc:$RST), (ins gprc_nor0:$RA, s16imm:$D),
                      "la $RST, $D($RA)", IIC_IntGeneral,
                      [(set i32:$RST, (add i32:$RA,
-                                          (PPClo tglobaladdr:$D, 0)))]>;
+                                          (PPClo tglobaladdr:$D, 0)))]>, MemOp;
 def MULLI  : DForm_2< 7, (outs gprc:$RST), (ins gprc:$RA, s16imm:$D),
                      "mulli $RST, $RA, $D", IIC_IntMulLI,
                      [(set i32:$RST, (mul i32:$RA, imm32SExt16:$D))]>;
@@ -3466,6 +3466,10 @@ class PPCAsmPseudo<string asm, dag iops>
   let isAsmParserOnly = 1;
   let isPseudo = 1;
   let hasNoSchedulingInfo = 1;
+
+  // Indicate that this instruction uses a memory operand.
+  bits<1> MemOp = 0;
+  let TSFlags{10} = MemOp;
 }
 
 // Prefixed instructions may require access to the above defs at a later
@@ -4714,7 +4718,7 @@ def : InstAlias<"tlbilxva $RA, $RB", (TLBILX 3, gprc:$RA, gprc:$RB)>,
                 Requires<[IsBookE]>;
 def : InstAlias<"tlbilxva $RB", (TLBILX 3, R0, gprc:$RB)>, Requires<[IsBookE]>;
 
-def LAx : PPCAsmPseudo<"la $rA, $addr", (ins gprc:$rA, memri:$addr)>;
+def LAx : PPCAsmPseudo<"la $rA, $addr", (ins gprc:$rA, memri:$addr)>, MemOp;
 
 def SUBI : PPCAsmPseudo<"subi $rA, $rB, $imm",
                         (ins gprc:$rA, gprc:$rB, s16imm:$imm)>;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrP10.td b/llvm/lib/Target/PowerPC/PPCInstrP10.td
index c4b8597b1df9ff..1dd9a44f9e0b32 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrP10.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrP10.td
@@ -138,6 +138,10 @@ class PI<bits<6> pref, bits<6> opcode, dag OOL, dag IOL, string asmstr,
   bits<1> Prefixed = 1;  // This is a prefixed instruction.
   let TSFlags{7}  = Prefixed;
 
+  // Indicate that this instruction uses a memory operand.
+  bits<1> MemOp = 0;
+  let TSFlags{10} = MemOp;
+
   // For cases where multiple instruction definitions really represent the
   // same underlying instruction but with one definition for 64-bit arguments
   // and one for 32-bit arguments, this bit breaks the degeneracy between
@@ -183,7 +187,7 @@ multiclass VXForm_VTB5_RCr<bits<10> xo, bits<5> R, dag OOL, dag IOL,
 
 class MLS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
                                 InstrItinClass itin, list<dag> pattern>
-  : PI<1, opcode, OOL, IOL, asmstr, itin> {
+  : PI<1, opcode, OOL, IOL, asmstr, itin>, MemOp {
   bits<5> RST;
   bits<5> RA;
   bits<34> D;
@@ -257,7 +261,7 @@ multiclass MLS_DForm_R_SI34_RTA5_p<bits<6> opcode, dag OOL, dag IOL,
 
 class 8LS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
                                 InstrItinClass itin, list<dag> pattern>
-  : PI<1, opcode, OOL, IOL, asmstr, itin> {
+  : PI<1, opcode, OOL, IOL, asmstr, itin>, MemOp {
   bits<5> RST;
   bits<5> RA;
   bits<34> D;
@@ -281,7 +285,7 @@ class 8LS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
 class 8LS_DForm_R_SI34_XT6_RA5_MEM<bits<5> opcode, dag OOL, dag IOL,
                                    string asmstr, InstrItinClass itin,
                                    list<dag> pattern>
-  : PI<1, { opcode, ? }, OOL, IOL, asmstr, itin> {
+  : PI<1, { opcode, ? }, OOL, IOL, asmstr, itin>, MemOp {
   bits<6> XST;
   bits<5> RA;
   bits<34> D;
@@ -585,7 +589,7 @@ multiclass MLS_DForm_R_SI34_RTA5_MEM_p<bits<6> opcode, dag OOL, dag IOL,
                                      isPCRel;
   let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
     def nopc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
-    let RA = 0 in
+    let RA = 0, MemOp = 0 in
       def onlypc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRelOnly_IOL,
                                              asmstr_pcext, itin, []>, isPCRel;
   }
@@ -602,7 +606,7 @@ multiclass 8LS_DForm_R_SI34_RTA5_MEM_p<bits<6> opcode, dag OOL, dag IOL,
                                      isPCRel;
   let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
     def nopc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
-    let RA = 0 in
+    let RA = 0, MemOp = 0 in
       def onlypc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRelOnly_IOL,
                                              asmstr_pcext, itin, []>, isPCRel;
   }
@@ -619,7 +623,7 @@ multiclass 8LS_DForm_R_SI34_XT6_RA5_MEM_p<bits<5> opcode, dag OOL, dag IOL,
                                         isPCRel;
   let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
     def nopc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
-    let RA = 0 in
+    let RA = 0, MemOp = 0 in
       def onlypc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, PCRelOnly_IOL,
                                                 asmstr_pcext, itin, []>, isPCRel;
   }
@@ -847,7 +851,7 @@ let Predicates = [PrefixInstrs, HasP10Vector] in {
 
 class DQForm_XTp5_RA17_MEM<bits<6> opcode, bits<4> xo, dag OOL, dag IOL,
                            string asmstr, InstrItinClass itin, list<dag> pattern>
-  : I<opcode, OOL, IOL, asmstr, itin> {
+  : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
   bits<5> XTp;
   bits<5> RA;
   bits<12> DQ;
@@ -879,7 +883,7 @@ class XForm_XTp5_XAB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
 
 class 8LS_DForm_R_XTp5_SI34_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
                                 InstrItinClass itin, list<dag> pattern>
-  : PI<1, opcode, OOL, IOL, asmstr, itin> {
+  : PI<1, opcode, OOL, IOL, asmstr, itin>, MemOp {
   bits<5> XTp;
   bits<5> RA;
   bits<34> D;
@@ -910,7 +914,7 @@ multiclass 8LS_DForm_R_XTp5_SI34_MEM_p<bits<6> opcode, dag OOL,
                                      isPCRel;
   let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
     def nopc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, IOL, asmstr, itin, []>;
-    let RA = 0 in
+    let RA = 0, MemOp = 0 in
       def onlypc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, PCRelOnly_IOL,
                                              asmstr_pcext, itin, []>, isPCRel;
   }
@@ -2506,7 +2510,7 @@ let Predicates = [IsISA3_1, PrefixInstrs], isAsmParserOnly = 1, hasNoSchedulingI
   let Interpretation64Bit = 1 in {
     def PLA8 : MLS_DForm_SI34_RT5<14, (outs g8rc:$RT),
                                   (ins g8rc_nox0:$RA, s34imm:$SI),
-                                  "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>;
+                                  "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemOp;
     def PLA8pc : MLS_DForm_SI34_RT5<14, (outs g8rc:$RT),
                                     (ins s34imm_pcrel:$SI),
                                     "pla $RT, $SI", IIC_IntSimple, []>, isPCRel;
@@ -2514,10 +2518,10 @@ let Predicates = [IsISA3_1, PrefixInstrs], isAsmParserOnly = 1, hasNoSchedulingI
 
   def PSUBI : PPCAsmPseudo<"psubi $RT, $RA, $SI",
                            (ins g8rc:$RT, g8rc_nox0:$RA, s34imm:$SI)>;
-
   def PLA : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
                                (ins gprc_nor0:$RA, s34imm:$SI),
-                               "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>;
+                               "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemOp;
+  
   def PLApc : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
                                  (ins s34imm_pcrel:$SI),
                                  "pla $RT, $SI", IIC_IntSimple, []>, isPCRel;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrSPE.td b/llvm/lib/Target/PowerPC/PPCInstrSPE.td
index 5adfbad6ca1186..b7e670413d4ff2 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrSPE.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrSPE.td
@@ -114,7 +114,7 @@ class EVXForm_4<bits<8> xo, dag OOL, dag IOL, string asmstr,
 
 class EVXForm_D<bits<11> xo, dag OOL, dag IOL, string asmstr,
                InstrItinClass itin, list<dag> pattern> :
-               I<4, OOL, IOL, asmstr, itin> {
+               I<4, OOL, IOL, asmstr, itin>, MemOp {
   bits<5> RT;
   bits<5> RA;
   bits<5> D;
diff --git a/llvm/test/CodeGen/PowerPC/2007-01-31-InlineAsmAddrMode.ll b/llvm/test/CodeGen/PowerPC/2007-01-31-InlineAsmAddrMode.ll
index 24db84c0fb86e6..8dff7c9ecd1e37 100644
--- a/llvm/test/CodeGen/PowerPC/2007-01-31-InlineAsmAddrMode.ll
+++ b/llvm/test/CodeGen/PowerPC/2007-01-31-InlineAsmAddrMode.ll
@@ -11,7 +11,7 @@ define void @test1() {
 entry:
 	%Out = alloca %struct.A, align 4		; <ptr> [#uses=1]
 	%tmp2 = getelementptr %struct.A, ptr %Out, i32 0, i32 1
-	%tmp5 = call i32 asm "lwbrx $0, $1", "=r,m"(ptr %tmp2 )
+	%tmp5 = call i32 asm "lbz $0, $1", "=r,m"(ptr %tmp2 )
 	ret void
 }
 
diff --git a/llvm/test/CodeGen/PowerPC/2009-07-16-InlineAsm-M-Operand.ll b/llvm/test/CodeGen/PowerPC/2009-07-16-InlineAsm-M-Operand.ll
index 76468f63ee741c..537a7ae78a5a2f 100644
--- a/llvm/test/CodeGen/PowerPC/2009-07-16-InlineAsm-M-Operand.ll
+++ b/llvm/test/CodeGen/PowerPC/2009-07-16-InlineAsm-M-Operand.ll
@@ -10,7 +10,7 @@ define void @memory_asm_operand(i32 %a) {
   ; "m" operand will be represented as:
   ; INLINEASM fake $0, 10, %R2, 20, -4, %R1
   ; It is difficult to find the flag operand (20) when starting from %R1
-  call i32 asm "lbzx $0, $1", "=r,m" (i32 %a)
+  call i32 asm "lbz $0, $1", "=r,m" (i32 %a)
   ret void
 }
 
diff --git a/llvm/test/MC/PowerPC/ppc64-errors.s b/llvm/test/MC/PowerPC/ppc64-errors.s
index 1c03dc084acdff..85b98d07540a47 100644
--- a/llvm/test/MC/PowerPC/ppc64-errors.s
+++ b/llvm/test/MC/PowerPC/ppc64-errors.s
@@ -143,3 +143,13 @@
 # CHECK: error: invalid operand for instruction
 # CHECK-NEXT: lwarx 1, 2, 3, a
               lwarx 1, 2, 3, a
+
+# Instruction requires memory operand
+# CHECK: error: invalid operand for instruction
+# CHECK-NEXT: la 3, 3, 10
+              la 3, 3, 10
+
+# Instruction doesn't support memory operands
+# CHECK: error: invalid operand for instruction
+# CHECK-NEXT: addi 3, 10(3)
+              addi 3, 10(3)

>From b8e3233b281775e2b3847f6d1a930161ef08a2df Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Fri, 1 Nov 2024 22:23:33 -0400
Subject: [PATCH 2/6] Address comments

---
 .../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 36 ++++++++++++-------
 llvm/lib/Target/PowerPC/PPCInstr64Bit.td      |  6 ++--
 llvm/lib/Target/PowerPC/PPCInstrFormats.td    | 10 ++++--
 llvm/lib/Target/PowerPC/PPCInstrInfo.td       |  4 +--
 llvm/lib/Target/PowerPC/PPCInstrP10.td        |  4 +--
 5 files changed, 38 insertions(+), 22 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 5ed41844bfbf9b..beae1935a046b4 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -8,8 +8,8 @@
 
 #include "MCTargetDesc/PPCMCExpr.h"
 #include "MCTargetDesc/PPCMCTargetDesc.h"
-#include "PPCTargetStreamer.h"
 #include "PPCInstrInfo.h"
+#include "PPCTargetStreamer.h"
 #include "TargetInfo/PowerPCTargetInfo.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Twine.h"
@@ -100,14 +100,10 @@ struct PPCOperand;
 class PPCAsmParser : public MCTargetAsmParser {
   bool IsPPC64;
 
-  bool UsesMemOp;
-
   void Warning(SMLoc L, const Twine &Msg) { getParser().Warning(L, Msg); }
 
   bool isPPC64() const { return IsPPC64; }
 
-  bool usesMemOp() const { return UsesMemOp; }
-
   MCRegister matchRegisterName(int64_t &IntVal);
 
   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
@@ -135,6 +131,8 @@ class PPCAsmParser : public MCTargetAsmParser {
 
   void processInstruction(MCInst &Inst, const OperandVector &Ops);
 
+  bool hasMemOp(const OperandVector &Ops);
+
   /// @name Auto-generated Match Functions
   /// {
 
@@ -151,7 +149,6 @@ class PPCAsmParser : public MCTargetAsmParser {
     // Check for 64-bit vs. 32-bit pointer mode.
     const Triple &TheTriple = STI.getTargetTriple();
     IsPPC64 = TheTriple.isPPC64();
-    UsesMemOp = false;
     // Initialize the set of available features.
     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
   }
@@ -190,6 +187,7 @@ struct PPCOperand : public MCParsedAsmOperand {
 
   struct ImmOp {
     int64_t Val;
+    bool IsMemOp;
   };
 
   struct ExprOp {
@@ -250,6 +248,11 @@ struct PPCOperand : public MCParsedAsmOperand {
   /// isPPC64 - True if this operand is for an instruction in 64-bit mode.
   bool isPPC64() const { return IsPPC64; }
 
+  /// isMemOp - True if this operand is a memory operand.
+  bool isMemOp() const { 
+    return Kind == Immediate && Imm.IsMemOp; 
+  }
+
   int64_t getImm() const {
     assert(Kind == Immediate && "Invalid access!");
     return Imm.Val;
@@ -702,9 +705,10 @@ struct PPCOperand : public MCParsedAsmOperand {
   }
 
   static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
-                                               bool IsPPC64) {
+                                               bool IsPPC64, bool IsMemOp = false) {
     auto Op = std::make_unique<PPCOperand>(Immediate);
     Op->Imm.Val = Val;
+    Op->Imm.IsMemOp = IsMemOp;
     Op->StartLoc = S;
     Op->EndLoc = E;
     Op->IsPPC64 = IsPPC64;
@@ -1263,10 +1267,11 @@ bool PPCAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
                                            MCStreamer &Out, uint64_t &ErrorInfo,
                                            bool MatchingInlineAsm) {
   MCInst Inst;
-  const PPCInstrInfo *TII = static_cast<const PPCInstrInfo*>(&MII);
+  const PPCInstrInfo *TII = static_cast<const PPCInstrInfo *>(&MII);
+
   switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
   case Match_Success:
-    if (usesMemOp() != TII->isMemOp(Inst.getOpcode()))
+    if (hasMemOp(Operands) != TII->isMemOp(Inst.getOpcode()))
       return Error(IDLoc, "invalid operand for instruction");
     // Post-process instructions (typically extended mnemonics)
     processInstruction(Inst, Operands);
@@ -1603,7 +1608,6 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
 
   // Otherwise, check for D-form memory operands
   if (!TlsCall && parseOptionalToken(AsmToken::LParen)) {
-    UsesMemOp = true;
     S = Parser.getTok().getLoc();
 
     int64_t IntVal;
@@ -1626,7 +1630,7 @@ 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()));
+    Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64(), /*IsMemOp=*/true));
   }
 
   return false;
@@ -1635,7 +1639,6 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
 /// Parse an instruction mnemonic followed by its operands.
 bool PPCAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
                                     SMLoc NameLoc, OperandVector &Operands) {
-  UsesMemOp = false;
   // The first operand is the token for the instruction name.
   // If the next character is a '+' or '-', we need to add it to the
   // instruction name, to match what TableGen is doing.
@@ -1915,3 +1918,12 @@ PPCAsmParser::applyModifierToExpr(const MCExpr *E,
     return nullptr;
   }
 }
+
+bool PPCAsmParser::hasMemOp(const OperandVector &Operands) {
+  for (const auto &Operand : Operands) {
+    const PPCOperand &Op = static_cast<const PPCOperand &>(*Operand);
+    if (Op.isMemOp())
+      return true;
+  }
+  return false;
+}
diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index 99f945a92b5cf5..9bee26307fc420 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -218,7 +218,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
                               (ins (memrix $D, $RA):$src),
                               "bctrl\n\tld 2, $src", IIC_BrB,
                               [(PPCbctrl_load_toc iaddrX4:$src)]>,
-    Requires<[In64BitMode]>, MemOp;
+    Requires<[In64BitMode]>;
 }
 
 let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
@@ -228,7 +228,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
                               (ins (memrix $D, $RA):$src),
                               "bctrl\n\tld 2, $src", IIC_BrB,
                               [(PPCbctrl_load_toc_rm iaddrX4:$src)]>,
-    Requires<[In64BitMode]>, MemOp;
+    Requires<[In64BitMode]>;
 }
 
 } // Interpretation64Bit
@@ -1457,7 +1457,7 @@ def LQ   : DQForm_RTp5_RA17_MEM<56, 0,
                                 "lq $RTp, $addr", IIC_LdStLQ,
                                 []>,
                                 RegConstraint<"@earlyclobber $RTp">,
-                                isPPC64, MemOp;
+                                isPPC64;
 // We don't really have LQX in the ISA, make a pseudo one so that we can
 // handle x-form during isel. Make it pre-ra may expose
 // oppotunities to some opts(CSE, LICM and etc.) for the result of adding
diff --git a/llvm/lib/Target/PowerPC/PPCInstrFormats.td b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
index 45fd0112b2bfdf..99ef4fbfdd1ffb 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrFormats.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
@@ -120,6 +120,10 @@ class I2<bits<6> opcode1, bits<6> opcode2, dag OOL, dag IOL, string asmstr,
   let TSFlags{2}   = PPC970_Cracked;
   let TSFlags{5-3} = PPC970_Unit;
 
+  // Indicate that this instruction uses a memory operand.
+  bits<1> MemOp = 0;
+  let TSFlags{10} = MemOp;
+
   // Fields used for relation models.
   string BaseName = "";
   bit Interpretation64Bit = 0;
@@ -427,7 +431,7 @@ class DQ_RD6_RS5_DQ12<bits<6> opcode, bits<3> xo, dag OOL, dag IOL,
 class DQForm_RTp5_RA17_MEM<bits<6> opcode, bits<4> xo, dag OOL, dag IOL,
                            string asmstr, InstrItinClass itin,
                            list<dag> pattern>
-  : I<opcode, OOL, IOL, asmstr, itin> {
+  : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
   bits<5> RTp;
   bits<5> RA;
   bits<12> DQ;
@@ -1661,7 +1665,7 @@ class XLForm_2_ext_and_DSForm_1<bits<6> opcode1, bits<10> xo1,
                                 dag OOL, dag IOL, string asmstr,
                                 InstrItinClass itin, list<dag> pattern>
   : XLForm_2_and_DSForm_1<opcode1, xo1, lk, opcode2, xo2,
-                          OOL, IOL, asmstr, itin, pattern> {
+                          OOL, IOL, asmstr, itin, pattern>, MemOp {
   let BO = bo;
   let BI = bi;
   let BH = 0;
@@ -1671,7 +1675,7 @@ class XLForm_2_ext_and_DForm_1<bits<6> opcode1, bits<10> xo1, bits<5> bo,
                                bits<5> bi, bit lk, bits<6> opcode2, dag OOL,
                                dag IOL, string asmstr, InstrItinClass itin,
                                list<dag> pattern>
-  : I2<opcode1, opcode2, OOL, IOL, asmstr, itin> {
+  : I2<opcode1, opcode2, OOL, IOL, asmstr, itin>, MemOp {
 
   bits<5>  RST;
   bits<5>  RA;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index b79c5f79efeb1c..f896ca5a551e2a 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -1584,7 +1584,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
   def BCTRL_LWZinto_toc:
     XLForm_2_ext_and_DForm_1<19, 528, 20, 0, 1, 32, (outs),
      (ins (memri $D, $RA):$addr), "bctrl\n\tlwz 2, $addr", IIC_BrB,
-     [(PPCbctrl_load_toc iaddr:$addr)]>, Requires<[In32BitMode]>, MemOp;
+     [(PPCbctrl_load_toc iaddr:$addr)]>, Requires<[In32BitMode]>;
 
 }
 
@@ -1593,7 +1593,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
   def BCTRL_LWZinto_toc_RM:
     XLForm_2_ext_and_DForm_1<19, 528, 20, 0, 1, 32, (outs),
      (ins (memri $D, $RA):$addr), "bctrl\n\tlwz 2, $addr", IIC_BrB,
-     [(PPCbctrl_load_toc_rm iaddr:$addr)]>, Requires<[In32BitMode]>, MemOp;
+     [(PPCbctrl_load_toc_rm iaddr:$addr)]>, Requires<[In32BitMode]>;
 
 }
 
diff --git a/llvm/lib/Target/PowerPC/PPCInstrP10.td b/llvm/lib/Target/PowerPC/PPCInstrP10.td
index 1dd9a44f9e0b32..cb3532f892cb15 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrP10.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrP10.td
@@ -2518,10 +2518,10 @@ let Predicates = [IsISA3_1, PrefixInstrs], isAsmParserOnly = 1, hasNoSchedulingI
 
   def PSUBI : PPCAsmPseudo<"psubi $RT, $RA, $SI",
                            (ins g8rc:$RT, g8rc_nox0:$RA, s34imm:$SI)>;
+
   def PLA : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
                                (ins gprc_nor0:$RA, s34imm:$SI),
-                               "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemOp;
-  
+                               "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemOp; 
   def PLApc : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
                                  (ins s34imm_pcrel:$SI),
                                  "pla $RT, $SI", IIC_IntSimple, []>, isPCRel;

>From 6aa4468e3abbc4f60a454aa4504ba066b97ef5ef Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Tue, 5 Nov 2024 11:51:09 -0500
Subject: [PATCH 3/6] Address comments

---
 .../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 38 +++++++++----------
 1 file changed, 17 insertions(+), 21 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index beae1935a046b4..ca1b97506a2032 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -131,8 +131,6 @@ class PPCAsmParser : public MCTargetAsmParser {
 
   void processInstruction(MCInst &Inst, const OperandVector &Ops);
 
-  bool hasMemOp(const OperandVector &Ops);
-
   /// @name Auto-generated Match Functions
   /// {
 
@@ -187,7 +185,7 @@ struct PPCOperand : public MCParsedAsmOperand {
 
   struct ImmOp {
     int64_t Val;
-    bool IsMemOp;
+    bool IsMemOpBase;
   };
 
   struct ExprOp {
@@ -248,10 +246,8 @@ struct PPCOperand : public MCParsedAsmOperand {
   /// isPPC64 - True if this operand is for an instruction in 64-bit mode.
   bool isPPC64() const { return IsPPC64; }
 
-  /// isMemOp - True if this operand is a memory operand.
-  bool isMemOp() const { 
-    return Kind == Immediate && Imm.IsMemOp; 
-  }
+  /// isMemOpBase - True if this operand is the base of a memory operand.
+  bool isMemOpBase() const { return Kind == Immediate && Imm.IsMemOpBase; }
 
   int64_t getImm() const {
     assert(Kind == Immediate && "Invalid access!");
@@ -703,12 +699,11 @@ struct PPCOperand : public MCParsedAsmOperand {
     Op->IsPPC64 = IsPPC64;
     return Op;
   }
-
-  static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
-                                               bool IsPPC64, bool IsMemOp = false) {
+  static std::unique_ptr<PPCOperand>
+  CreateImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64, bool IsMemOpBase = false) {
     auto Op = std::make_unique<PPCOperand>(Immediate);
     Op->Imm.Val = Val;
-    Op->Imm.IsMemOp = IsMemOp;
+    Op->Imm.IsMemOpBase = IsMemOpBase;
     Op->StartLoc = S;
     Op->EndLoc = E;
     Op->IsPPC64 = IsPPC64;
@@ -1262,6 +1257,15 @@ void PPCAsmParser::processInstruction(MCInst &Inst,
 static std::string PPCMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
                                          unsigned VariantID = 0);
 
+static bool hasMemOp(const OperandVector &Operands) {
+  for (const auto &Operand : Operands) {
+    const PPCOperand &Op = static_cast<const PPCOperand &>(*Operand);
+    if (Op.isMemOpBase())
+      return true;
+  }
+  return false;
+}
+
 bool PPCAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
                                            OperandVector &Operands,
                                            MCStreamer &Out, uint64_t &ErrorInfo,
@@ -1630,7 +1634,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(), /*IsMemOp=*/true));
+    Operands.push_back(
+        PPCOperand::CreateImm(IntVal, S, E, isPPC64(), /*IsMemOpBase=*/true));
   }
 
   return false;
@@ -1918,12 +1923,3 @@ PPCAsmParser::applyModifierToExpr(const MCExpr *E,
     return nullptr;
   }
 }
-
-bool PPCAsmParser::hasMemOp(const OperandVector &Operands) {
-  for (const auto &Operand : Operands) {
-    const PPCOperand &Op = static_cast<const PPCOperand &>(*Operand);
-    if (Op.isMemOp())
-      return true;
-  }
-  return false;
-}

>From e8b839fe0a7d2da80491bca562d7d3f7fbc141aa Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Tue, 5 Nov 2024 11:58:43 -0500
Subject: [PATCH 4/6] Formatting

---
 llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index ca1b97506a2032..8b03fef5c1c5e5 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -699,8 +699,9 @@ struct PPCOperand : public MCParsedAsmOperand {
     Op->IsPPC64 = IsPPC64;
     return Op;
   }
-  static std::unique_ptr<PPCOperand>
-  CreateImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64, bool IsMemOpBase = false) {
+  static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
+                                               bool IsPPC64,
+                                               bool IsMemOpBase = false) {
     auto Op = std::make_unique<PPCOperand>(Immediate);
     Op->Imm.Val = Val;
     Op->Imm.IsMemOpBase = IsMemOpBase;

>From 15e252ff070c72188c6954c2f25bd64a13c3c010 Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Tue, 5 Nov 2024 12:00:28 -0500
Subject: [PATCH 5/6] Add space back

---
 llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 8b03fef5c1c5e5..e1596a4c381169 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -699,6 +699,7 @@ struct PPCOperand : public MCParsedAsmOperand {
     Op->IsPPC64 = IsPPC64;
     return Op;
   }
+
   static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
                                                bool IsPPC64,
                                                bool IsMemOpBase = false) {

>From 42fbf347bc383b742f628f64a3cb4aae4942c6b2 Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Thu, 7 Nov 2024 13:27:50 -0500
Subject: [PATCH 6/6] Address comments

---
 .../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 18 +++++++-----
 .../PowerPC/MCTargetDesc/PPCMCTargetDesc.h    |  4 +--
 llvm/lib/Target/PowerPC/PPCInstr64Bit.td      |  2 +-
 llvm/lib/Target/PowerPC/PPCInstrFormats.td    | 28 ++++++++-----------
 llvm/lib/Target/PowerPC/PPCInstrInfo.h        |  4 +--
 llvm/lib/Target/PowerPC/PPCInstrInfo.td       | 10 +++----
 llvm/lib/Target/PowerPC/PPCInstrP10.td        | 28 +++++++++----------
 llvm/lib/Target/PowerPC/PPCInstrSPE.td        |  2 +-
 llvm/test/MC/PowerPC/ppc64-errors.s           |  5 ++++
 9 files changed, 53 insertions(+), 48 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index e1596a4c381169..e7cd255d5d34ca 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -1259,13 +1259,17 @@ void PPCAsmParser::processInstruction(MCInst &Inst,
 static std::string PPCMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
                                          unsigned VariantID = 0);
 
-static bool hasMemOp(const OperandVector &Operands) {
-  for (const auto &Operand : Operands) {
-    const PPCOperand &Op = static_cast<const PPCOperand &>(*Operand);
-    if (Op.isMemOpBase())
-      return true;
+// Check that the register+immediate memory operand is in the right position and
+// is expected by the instruction
+static bool validateMemOp(const OperandVector &Operands, bool isMemriOp) {
+  for (size_t idx = 0; idx < Operands.size(); ++idx) {
+    const PPCOperand &Op = static_cast<const PPCOperand &>(*Operands[idx]);
+    if ((idx == 3 && Op.isMemOpBase() != isMemriOp) ||
+        (idx != 3 && Op.isMemOpBase())) {
+        return false;
+    }
   }
-  return false;
+  return true;
 }
 
 bool PPCAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
@@ -1277,7 +1281,7 @@ bool PPCAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
 
   switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
   case Match_Success:
-    if (hasMemOp(Operands) != TII->isMemOp(Inst.getOpcode()))
+    if (!validateMemOp(Operands, TII->isMemriOp(Inst.getOpcode())))
       return Error(IDLoc, "invalid operand for instruction");
     // Post-process instructions (typically extended mnemonics)
     processInstruction(Inst, Operands);
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
index caa3ad0d22e3bd..579ee5e8facb60 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
@@ -172,8 +172,8 @@ enum {
   SExt32To64 = 0x1 << (NewDef_Shift + 2),
   /// This instruction produced a zero extended result.
   ZExt32To64 = 0x1 << (NewDef_Shift + 3),
-  /// This instruction uses a memory operand.
-  MemOp = 0x1 << (NewDef_Shift + 4)
+  /// This instruction takes a register+immediate memory operand.
+  MemriOp = 0x1 << (NewDef_Shift + 4)
 };
 } // end namespace PPCII
 
diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index 9bee26307fc420..68d1209d741c08 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -777,7 +777,7 @@ def ADDIS8 : DForm_2<15, (outs g8rc:$RST), (ins g8rc_nox0:$RA, s17imm64:$D),
 def LA8     : DForm_2<14, (outs g8rc:$RST), (ins g8rc_nox0:$RA, s16imm64:$D),
                      "la $RST, $D($RA)", IIC_IntGeneral,
                      [(set i64:$RST, (add i64:$RA,
-                                    (PPClo tglobaladdr:$D, 0)))]>, MemOp;
+                                    (PPClo tglobaladdr:$D, 0)))]>, MemriOp;
 
 let Defs = [CARRY] in {
 def SUBFIC8: DForm_2< 8, (outs g8rc:$RST), (ins g8rc:$RA, s16imm64:$D),
diff --git a/llvm/lib/Target/PowerPC/PPCInstrFormats.td b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
index 99ef4fbfdd1ffb..2ced3fe80ea991 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrFormats.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
@@ -55,9 +55,9 @@ class I<bits<6> opcode, dag OOL, dag IOL, string asmstr, InstrItinClass itin>
   bits<1> ZExt32To64 = 0;
   let TSFlags{9} = ZExt32To64;
 
-  // Indicate that this instruction uses a memory operand.
-  bits<1> MemOp = 0;
-  let TSFlags{10} = MemOp;
+  // Indicate that this instruction takes a register+immediate memory operand.
+  bits<1> MemriOp = 0;
+  let TSFlags{10} = MemriOp;
 
   // Fields used for relation models.
   string BaseName = "";
@@ -86,7 +86,7 @@ class PPC970_Unit_BRU      { bits<3> PPC970_Unit = 7;   }
 class XFormMemOp { bits<1> XFormMemOp = 1; }
 class SExt32To64 { bits<1> SExt32To64 = 1; }
 class ZExt32To64 { bits<1> ZExt32To64 = 1; }
-class MemOp      { bits<1> MemOp = 1;      }
+class MemriOp      { bits<1> MemriOp = 1;      }
 
 // Two joined instructions; used to emit two adjacent instructions as one.
 // The itinerary from the first instruction is used for scheduling and
@@ -120,10 +120,6 @@ class I2<bits<6> opcode1, bits<6> opcode2, dag OOL, dag IOL, string asmstr,
   let TSFlags{2}   = PPC970_Cracked;
   let TSFlags{5-3} = PPC970_Unit;
 
-  // Indicate that this instruction uses a memory operand.
-  bits<1> MemOp = 0;
-  let TSFlags{10} = MemOp;
-
   // Fields used for relation models.
   string BaseName = "";
   bit Interpretation64Bit = 0;
@@ -259,7 +255,7 @@ class DForm_base<bits<6> opcode, dag OOL, dag IOL, string asmstr,
 
 class DForm_1<bits<6> opcode, dag OOL, dag IOL, string asmstr,
               InstrItinClass itin, list<dag> pattern>
-  : DForm_base<opcode, OOL, IOL, asmstr, itin, pattern>, MemOp {
+  : DForm_base<opcode, OOL, IOL, asmstr, itin, pattern>, MemriOp {
 }
 
 class DForm_2<bits<6> opcode, dag OOL, dag IOL, string asmstr,
@@ -304,7 +300,7 @@ class DForm_4_zero<bits<6> opcode, dag OOL, dag IOL, string asmstr,
   let RST = 0;
   let RA = 0;
   let D = 0;
-  let MemOp = 0;
+  let MemriOp = 0;
 }
 
 class DForm_4_fixedreg_zero<bits<6> opcode, bits<5> R, dag OOL, dag IOL,
@@ -382,7 +378,7 @@ class DForm_6_ext<bits<6> opcode, dag OOL, dag IOL, string asmstr,
 // 1.7.5 DS-Form
 class DSForm_1<bits<6> opcode, bits<2> xo, dag OOL, dag IOL, string asmstr,
                InstrItinClass itin, list<dag> pattern>
-         : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
+         : I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
   bits<5>  RST;
   bits<5>  RA;
   bits<14> D;
@@ -414,7 +410,7 @@ class DXForm<bits<6> opcode, bits<5> xo, dag OOL, dag IOL, string asmstr,
 // DQ-Form: [PO T RA DQ TX XO] or [PO S RA DQ SX XO]
 class DQ_RD6_RS5_DQ12<bits<6> opcode, bits<3> xo, dag OOL, dag IOL,
                       string asmstr, InstrItinClass itin, list<dag> pattern>
-  : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
+  : I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
   bits<6>  XT;
   bits<5> RA;
   bits<12> DQ;
@@ -431,7 +427,7 @@ class DQ_RD6_RS5_DQ12<bits<6> opcode, bits<3> xo, dag OOL, dag IOL,
 class DQForm_RTp5_RA17_MEM<bits<6> opcode, bits<4> xo, dag OOL, dag IOL,
                            string asmstr, InstrItinClass itin,
                            list<dag> pattern>
-  : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
+  : I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
   bits<5> RTp;
   bits<5> RA;
   bits<12> DQ;
@@ -1256,7 +1252,7 @@ class XX2_RD6_DCMX7_RS6<bits<6> opcode, bits<4> xo1, bits<3> xo2,
 
 class XForm_XD6_RA5_RB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
                         string asmstr, InstrItinClass itin, list<dag> pattern>
-  : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
+  : I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
   bits<5> RA;
   bits<6> D;
   bits<5> RB;
@@ -1665,7 +1661,7 @@ class XLForm_2_ext_and_DSForm_1<bits<6> opcode1, bits<10> xo1,
                                 dag OOL, dag IOL, string asmstr,
                                 InstrItinClass itin, list<dag> pattern>
   : XLForm_2_and_DSForm_1<opcode1, xo1, lk, opcode2, xo2,
-                          OOL, IOL, asmstr, itin, pattern>, MemOp {
+                          OOL, IOL, asmstr, itin, pattern> {
   let BO = bo;
   let BI = bi;
   let BH = 0;
@@ -1675,7 +1671,7 @@ class XLForm_2_ext_and_DForm_1<bits<6> opcode1, bits<10> xo1, bits<5> bo,
                                bits<5> bi, bit lk, bits<6> opcode2, dag OOL,
                                dag IOL, string asmstr, InstrItinClass itin,
                                list<dag> pattern>
-  : I2<opcode1, opcode2, OOL, IOL, asmstr, itin>, MemOp {
+  : I2<opcode1, opcode2, OOL, IOL, asmstr, itin> {
 
   bits<5>  RST;
   bits<5>  RA;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.h b/llvm/lib/Target/PowerPC/PPCInstrInfo.h
index 0c9b9207f5fe75..d45f481f7b9be7 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.h
@@ -285,8 +285,8 @@ class PPCInstrInfo : public PPCGenInstrInfo {
   bool isZExt32To64(unsigned Opcode) const {
     return get(Opcode).TSFlags & PPCII::ZExt32To64;
   }
-  bool isMemOp(unsigned Opcode) const {
-    return get(Opcode).TSFlags & PPCII::MemOp;
+  bool isMemriOp(unsigned Opcode) const {
+    return get(Opcode).TSFlags & PPCII::MemriOp;
   }
 
   static bool isSameClassPhysRegCopy(unsigned Opcode) {
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index f896ca5a551e2a..1d8a372fe7632d 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -2303,7 +2303,7 @@ let isCodeGenOnly = 1 in
 def LA     : DForm_2<14, (outs gprc:$RST), (ins gprc_nor0:$RA, s16imm:$D),
                      "la $RST, $D($RA)", IIC_IntGeneral,
                      [(set i32:$RST, (add i32:$RA,
-                                          (PPClo tglobaladdr:$D, 0)))]>, MemOp;
+                                          (PPClo tglobaladdr:$D, 0)))]>, MemriOp;
 def MULLI  : DForm_2< 7, (outs gprc:$RST), (ins gprc:$RA, s16imm:$D),
                      "mulli $RST, $RA, $D", IIC_IntMulLI,
                      [(set i32:$RST, (mul i32:$RA, imm32SExt16:$D))]>;
@@ -3467,9 +3467,9 @@ class PPCAsmPseudo<string asm, dag iops>
   let isPseudo = 1;
   let hasNoSchedulingInfo = 1;
 
-  // Indicate that this instruction uses a memory operand.
-  bits<1> MemOp = 0;
-  let TSFlags{10} = MemOp;
+  // Indicate that this instruction takes a register+immediate memory operand.
+  bits<1> MemriOp = 0;
+  let TSFlags{10} = MemriOp;
 }
 
 // Prefixed instructions may require access to the above defs at a later
@@ -4718,7 +4718,7 @@ def : InstAlias<"tlbilxva $RA, $RB", (TLBILX 3, gprc:$RA, gprc:$RB)>,
                 Requires<[IsBookE]>;
 def : InstAlias<"tlbilxva $RB", (TLBILX 3, R0, gprc:$RB)>, Requires<[IsBookE]>;
 
-def LAx : PPCAsmPseudo<"la $rA, $addr", (ins gprc:$rA, memri:$addr)>, MemOp;
+def LAx : PPCAsmPseudo<"la $rA, $addr", (ins gprc:$rA, memri:$addr)>, MemriOp;
 
 def SUBI : PPCAsmPseudo<"subi $rA, $rB, $imm",
                         (ins gprc:$rA, gprc:$rB, s16imm:$imm)>;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrP10.td b/llvm/lib/Target/PowerPC/PPCInstrP10.td
index cb3532f892cb15..9e3b38fe02dd06 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrP10.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrP10.td
@@ -138,9 +138,9 @@ class PI<bits<6> pref, bits<6> opcode, dag OOL, dag IOL, string asmstr,
   bits<1> Prefixed = 1;  // This is a prefixed instruction.
   let TSFlags{7}  = Prefixed;
 
-  // Indicate that this instruction uses a memory operand.
-  bits<1> MemOp = 0;
-  let TSFlags{10} = MemOp;
+  // Indicate that this instruction takes a register+immediate memory operand.
+  bits<1> MemriOp = 0;
+  let TSFlags{10} = MemriOp;
 
   // For cases where multiple instruction definitions really represent the
   // same underlying instruction but with one definition for 64-bit arguments
@@ -187,7 +187,7 @@ multiclass VXForm_VTB5_RCr<bits<10> xo, bits<5> R, dag OOL, dag IOL,
 
 class MLS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
                                 InstrItinClass itin, list<dag> pattern>
-  : PI<1, opcode, OOL, IOL, asmstr, itin>, MemOp {
+  : PI<1, opcode, OOL, IOL, asmstr, itin>, MemriOp {
   bits<5> RST;
   bits<5> RA;
   bits<34> D;
@@ -261,7 +261,7 @@ multiclass MLS_DForm_R_SI34_RTA5_p<bits<6> opcode, dag OOL, dag IOL,
 
 class 8LS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
                                 InstrItinClass itin, list<dag> pattern>
-  : PI<1, opcode, OOL, IOL, asmstr, itin>, MemOp {
+  : PI<1, opcode, OOL, IOL, asmstr, itin>, MemriOp {
   bits<5> RST;
   bits<5> RA;
   bits<34> D;
@@ -285,7 +285,7 @@ class 8LS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
 class 8LS_DForm_R_SI34_XT6_RA5_MEM<bits<5> opcode, dag OOL, dag IOL,
                                    string asmstr, InstrItinClass itin,
                                    list<dag> pattern>
-  : PI<1, { opcode, ? }, OOL, IOL, asmstr, itin>, MemOp {
+  : PI<1, { opcode, ? }, OOL, IOL, asmstr, itin>, MemriOp {
   bits<6> XST;
   bits<5> RA;
   bits<34> D;
@@ -589,7 +589,7 @@ multiclass MLS_DForm_R_SI34_RTA5_MEM_p<bits<6> opcode, dag OOL, dag IOL,
                                      isPCRel;
   let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
     def nopc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
-    let RA = 0, MemOp = 0 in
+    let RA = 0, MemriOp = 0 in
       def onlypc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRelOnly_IOL,
                                              asmstr_pcext, itin, []>, isPCRel;
   }
@@ -606,7 +606,7 @@ multiclass 8LS_DForm_R_SI34_RTA5_MEM_p<bits<6> opcode, dag OOL, dag IOL,
                                      isPCRel;
   let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
     def nopc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
-    let RA = 0, MemOp = 0 in
+    let RA = 0, MemriOp = 0 in
       def onlypc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRelOnly_IOL,
                                              asmstr_pcext, itin, []>, isPCRel;
   }
@@ -623,7 +623,7 @@ multiclass 8LS_DForm_R_SI34_XT6_RA5_MEM_p<bits<5> opcode, dag OOL, dag IOL,
                                         isPCRel;
   let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
     def nopc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
-    let RA = 0, MemOp = 0 in
+    let RA = 0, MemriOp = 0 in
       def onlypc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, PCRelOnly_IOL,
                                                 asmstr_pcext, itin, []>, isPCRel;
   }
@@ -851,7 +851,7 @@ let Predicates = [PrefixInstrs, HasP10Vector] in {
 
 class DQForm_XTp5_RA17_MEM<bits<6> opcode, bits<4> xo, dag OOL, dag IOL,
                            string asmstr, InstrItinClass itin, list<dag> pattern>
-  : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
+  : I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
   bits<5> XTp;
   bits<5> RA;
   bits<12> DQ;
@@ -883,7 +883,7 @@ class XForm_XTp5_XAB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
 
 class 8LS_DForm_R_XTp5_SI34_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
                                 InstrItinClass itin, list<dag> pattern>
-  : PI<1, opcode, OOL, IOL, asmstr, itin>, MemOp {
+  : PI<1, opcode, OOL, IOL, asmstr, itin>, MemriOp {
   bits<5> XTp;
   bits<5> RA;
   bits<34> D;
@@ -914,7 +914,7 @@ multiclass 8LS_DForm_R_XTp5_SI34_MEM_p<bits<6> opcode, dag OOL,
                                      isPCRel;
   let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
     def nopc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, IOL, asmstr, itin, []>;
-    let RA = 0, MemOp = 0 in
+    let RA = 0, MemriOp = 0 in
       def onlypc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, PCRelOnly_IOL,
                                              asmstr_pcext, itin, []>, isPCRel;
   }
@@ -2510,7 +2510,7 @@ let Predicates = [IsISA3_1, PrefixInstrs], isAsmParserOnly = 1, hasNoSchedulingI
   let Interpretation64Bit = 1 in {
     def PLA8 : MLS_DForm_SI34_RT5<14, (outs g8rc:$RT),
                                   (ins g8rc_nox0:$RA, s34imm:$SI),
-                                  "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemOp;
+                                  "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemriOp;
     def PLA8pc : MLS_DForm_SI34_RT5<14, (outs g8rc:$RT),
                                     (ins s34imm_pcrel:$SI),
                                     "pla $RT, $SI", IIC_IntSimple, []>, isPCRel;
@@ -2521,7 +2521,7 @@ let Predicates = [IsISA3_1, PrefixInstrs], isAsmParserOnly = 1, hasNoSchedulingI
 
   def PLA : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
                                (ins gprc_nor0:$RA, s34imm:$SI),
-                               "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemOp; 
+                               "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemriOp;
   def PLApc : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
                                  (ins s34imm_pcrel:$SI),
                                  "pla $RT, $SI", IIC_IntSimple, []>, isPCRel;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrSPE.td b/llvm/lib/Target/PowerPC/PPCInstrSPE.td
index b7e670413d4ff2..e91cae349e0826 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrSPE.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrSPE.td
@@ -114,7 +114,7 @@ class EVXForm_4<bits<8> xo, dag OOL, dag IOL, string asmstr,
 
 class EVXForm_D<bits<11> xo, dag OOL, dag IOL, string asmstr,
                InstrItinClass itin, list<dag> pattern> :
-               I<4, OOL, IOL, asmstr, itin>, MemOp {
+               I<4, OOL, IOL, asmstr, itin>, MemriOp {
   bits<5> RT;
   bits<5> RA;
   bits<5> D;
diff --git a/llvm/test/MC/PowerPC/ppc64-errors.s b/llvm/test/MC/PowerPC/ppc64-errors.s
index 85b98d07540a47..17905a396885a0 100644
--- a/llvm/test/MC/PowerPC/ppc64-errors.s
+++ b/llvm/test/MC/PowerPC/ppc64-errors.s
@@ -153,3 +153,8 @@
 # CHECK: error: invalid operand for instruction
 # CHECK-NEXT: addi 3, 10(3)
               addi 3, 10(3)
+
+# Invalid memory operand position
+# CHECK: error: invalid operand for instruction
+# CHECK-NEXT: la 0(3), 3
+              la 0(3), 3



More information about the llvm-commits mailing list