Skip to content

Reland "[PowerPC] Add error for incorrect use of memory operands (#114277)" #115958

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 14, 2024

Conversation

jakeegan
Copy link
Member

@jakeegan jakeegan commented Nov 12, 2024

Commit 9358905 was reverted because it caused a failure with test lld :: ELF/ppc64-local-exec-tls.s. This relands the commit with a fix for the test.

jakeegan and others added 2 commits November 12, 2024 18:20
If an instruction doesn't support memory operands, but one is provided,
an error should be raised. And conversely, if an instruction requires a
memory operand, but none is given, an error should be raised.

(cherry picked from commit 9358905)
@llvmbot
Copy link
Member

llvmbot commented Nov 12, 2024

@llvm/pr-subscribers-mc
@llvm/pr-subscribers-lld-elf

@llvm/pr-subscribers-backend-powerpc

Author: Jake Egan (jakeegan)

Changes

Commit 9358905 was reverted, but caused a failure with test lld :: ELF/ppc64-local-exec-tls.s. This relands the commit with a fix for the test.


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

12 Files Affected:

  • (modified) lld/test/ELF/ppc64-local-exec-tls.s (+2-2)
  • (modified) llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp (+25-2)
  • (modified) llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h (+3-1)
  • (modified) llvm/lib/Target/PowerPC/PPCInstr64Bit.td (+1-1)
  • (modified) llvm/lib/Target/PowerPC/PPCInstrFormats.td (+11-5)
  • (modified) llvm/lib/Target/PowerPC/PPCInstrInfo.h (+3)
  • (modified) llvm/lib/Target/PowerPC/PPCInstrInfo.td (+6-2)
  • (modified) llvm/lib/Target/PowerPC/PPCInstrP10.td (+15-11)
  • (modified) llvm/lib/Target/PowerPC/PPCInstrSPE.td (+1-1)
  • (modified) llvm/test/CodeGen/PowerPC/2007-01-31-InlineAsmAddrMode.ll (+1-1)
  • (modified) llvm/test/CodeGen/PowerPC/2009-07-16-InlineAsm-M-Operand.ll (+1-1)
  • (modified) llvm/test/MC/PowerPC/ppc64-errors.s (+15)
diff --git a/lld/test/ELF/ppc64-local-exec-tls.s b/lld/test/ELF/ppc64-local-exec-tls.s
index 51dcb1a7395a1c..f5cb683b9fcfc0 100644
--- a/lld/test/ELF/ppc64-local-exec-tls.s
+++ b/lld/test/ELF/ppc64-local-exec-tls.s
@@ -62,7 +62,7 @@ test_ds:
   addi 2, 2, .TOC.-.Lfunc_gep3@l
 .Lfunc_lep3:
   .localentry test_ds, .Lfunc_lep3-.Lfunc_gep3
-  ld 3, b@tprel, 13
+  ld 3, b@tprel(13)
   blr
 
 test_lo_ds:
@@ -71,7 +71,7 @@ test_lo_ds:
   addi 2, 2, .TOC.-.Lfunc_gep4@l
 .Lfunc_lep4:
   .localentry test_lo_ds, .Lfunc_lep4-.Lfunc_gep4
-  ld 3, b@tprel@l, 13
+  ld 3, b@tprel@l(13)
   blr
 
 test_highest_a:
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index abb6bd31c9c599..52cc8f82f50b6e 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -8,6 +8,7 @@
 
 #include "MCTargetDesc/PPCMCExpr.h"
 #include "MCTargetDesc/PPCMCTargetDesc.h"
+#include "PPCInstrInfo.h"
 #include "PPCTargetStreamer.h"
 #include "TargetInfo/PowerPCTargetInfo.h"
 #include "llvm/ADT/STLExtras.h"
@@ -182,6 +183,7 @@ struct PPCOperand : public MCParsedAsmOperand {
 
   struct ImmOp {
     int64_t Val;
+    bool IsMemOpBase;
   };
 
   struct ExprOp {
@@ -242,6 +244,9 @@ struct PPCOperand : public MCParsedAsmOperand {
   /// isPPC64 - True if this operand is for an instruction in 64-bit mode.
   bool isPPC64() const { return IsPPC64; }
 
+  /// 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!");
     return Imm.Val;
@@ -694,9 +699,11 @@ struct PPCOperand : public MCParsedAsmOperand {
   }
 
   static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
-                                               bool IsPPC64) {
+                                               bool IsPPC64,
+                                               bool IsMemOpBase = false) {
     auto Op = std::make_unique<PPCOperand>(Immediate);
     Op->Imm.Val = Val;
+    Op->Imm.IsMemOpBase = IsMemOpBase;
     Op->StartLoc = S;
     Op->EndLoc = E;
     Op->IsPPC64 = IsPPC64;
@@ -1250,14 +1257,29 @@ void PPCAsmParser::processInstruction(MCInst &Inst,
 static std::string PPCMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
                                          unsigned VariantID = 0);
 
+// Check that the register+immediate memory operand is in the right position and
+// is expected by the instruction. Returns true if the memory operand syntax is
+// valid; otherwise, returns false.
+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 (Op.isMemOpBase() != (idx == 3 && isMemriOp))
+      return false;
+  }
+  return true;
+}
+
 bool PPCAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
                                            OperandVector &Operands,
                                            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 (!validateMemOp(Operands, TII->isMemriOp(Inst.getOpcode())))
+      return Error(IDLoc, "invalid operand for instruction");
     // Post-process instructions (typically extended mnemonics)
     processInstruction(Inst, Operands);
     Inst.setLoc(IDLoc);
@@ -1615,7 +1637,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()));
+    Operands.push_back(
+        PPCOperand::CreateImm(IntVal, S, E, isPPC64(), /*IsMemOpBase=*/true));
   }
 
   return false;
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
index 16777725990aa1..579ee5e8facb60 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 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 68419068e52a64..bcac0de55d9d34 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)))]>;
+                                    (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 5389f42a325ce6..2ced3fe80ea991 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 takes a register+immediate memory operand.
+  bits<1> MemriOp = 0;
+  let TSFlags{10} = MemriOp;
+
   // 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 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
@@ -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>, MemriOp {
 }
 
 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 MemriOp = 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>, MemriOp {
   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>, MemriOp {
   bits<6>  XT;
   bits<5> RA;
   bits<12> DQ;
@@ -421,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> {
+  : I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
   bits<5> RTp;
   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>, MemriOp {
   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 c2abf2f9427463..cd8ecc2dcfac8e 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.h
@@ -286,6 +286,9 @@ class PPCInstrInfo : public PPCGenInstrInfo {
   bool isZExt32To64(unsigned Opcode) const {
     return get(Opcode).TSFlags & PPCII::ZExt32To64;
   }
+  bool isMemriOp(unsigned Opcode) const {
+    return get(Opcode).TSFlags & PPCII::MemriOp;
+  }
 
   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..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)))]>;
+                                          (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))]>;
@@ -3466,6 +3466,10 @@ class PPCAsmPseudo<string asm, dag iops>
   let isAsmParserOnly = 1;
   let isPseudo = 1;
   let hasNoSchedulingInfo = 1;
+
+  // 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
@@ -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)>, 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 c4b8597b1df9ff..9e3b38fe02dd06 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 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
   // 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>, MemriOp {
   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>, MemriOp {
   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>, MemriOp {
   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, MemriOp = 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, MemriOp = 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, MemriOp = 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>, MemriOp {
   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>, MemriOp {
   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, MemriOp = 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, []>, MemriOp;
     def PLA8pc : MLS_DForm_SI34_RT5<14, (outs g8rc:$RT),
                                     (ins s34imm_pcrel:$SI),
                                     "pla $RT, $SI", IIC_IntSimple, []>, isPCRel;
@@ -2517,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, []>;
+                               "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 5adfbad6ca1186..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> {
+               I<4, OOL, IOL, asmstr, itin>, MemriOp {
   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..17905a396885a0 100644
--- a/llvm/test/MC/PowerPC/ppc64-errors.s
+++ b/llvm/test/MC/PowerPC/ppc64-errors.s
@@ -143,3 +143,18 @@
 # 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)
+
+# Invalid memory operand position
+# CHECK: error: invalid operand for instruction
+# CHECK-NEXT: la 0(3), 3
+              la 0(3), 3

@jakeegan jakeegan merged commit 48cc435 into llvm:main Nov 14, 2024
13 checks passed
@jakeegan jakeegan deleted the bad_asm2 branch November 14, 2024 03:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants