[llvm] 991fd93 - [MIR] Support symbolic inline asm operands (#185893)

via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 13 06:50:21 PDT 2026


Author: Ivan Kosarev
Date: 2026-03-13T13:50:16Z
New Revision: 991fd93780097d3a8f6a729e2fe2c599ef78b538

URL: https://github.com/llvm/llvm-project/commit/991fd93780097d3a8f6a729e2fe2c599ef78b538
DIFF: https://github.com/llvm/llvm-project/commit/991fd93780097d3a8f6a729e2fe2c599ef78b538.diff

LOG: [MIR] Support symbolic inline asm operands (#185893)

Support parsing and printing inline assembly operands in MIR using the
symbolic form instead of numeric register class IDs, thus removing the
need to update tests when the numbers change.

The numeric form remains supported.

---------

Co-authored-by: Claude Opus 4.6 <noreply at anthropic.com>

Added: 
    llvm/test/CodeGen/MIR/Generic/inline-asm-bad-mem-constraint.mir
    llvm/test/CodeGen/MIR/Generic/inline-asm-bad-regclass.mir
    llvm/test/CodeGen/MIR/Generic/inline-asm-no-constraint.mir

Modified: 
    llvm/lib/CodeGen/MIRParser/MIParser.cpp
    llvm/lib/CodeGen/MIRPrinter.cpp
    llvm/test/CodeGen/AMDGPU/dst-sel-hazard.mir

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index c1ad33bf5efb7..3ddb793fb2fcb 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -46,6 +46,7 @@
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DebugLoc.h"
 #include "llvm/IR/Function.h"
+#include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Intrinsics.h"
@@ -460,6 +461,7 @@ class MIParser {
                             std::optional<unsigned> &TiedDefIdx,
                             bool IsDef = false);
   bool parseImmediateOperand(MachineOperand &Dest);
+  bool parseInlineAsmOperand(MachineOperand &Dest);
   bool parseIRConstant(StringRef::iterator Loc, StringRef StringValue,
                        const Constant *&C);
   bool parseIRConstant(StringRef::iterator Loc, const Constant *&C);
@@ -1901,6 +1903,89 @@ bool MIParser::parseImmediateOperand(MachineOperand &Dest) {
   return false;
 }
 
+bool MIParser::parseInlineAsmOperand(MachineOperand &Dest) {
+  // Parse symbolic form: kind[:constraint].
+  assert(Token.is(MIToken::Identifier) && "expected inline asm operand kind");
+  StringRef KindStr = Token.stringValue();
+  constexpr auto InvalidKind = static_cast<InlineAsm::Kind>(0);
+  InlineAsm::Kind K =
+      StringSwitch<InlineAsm::Kind>(KindStr)
+          .Case("regdef", InlineAsm::Kind::RegDef)
+          .Case("reguse", InlineAsm::Kind::RegUse)
+          .Case("regdef-ec", InlineAsm::Kind::RegDefEarlyClobber)
+          .Case("clobber", InlineAsm::Kind::Clobber)
+          .Case("imm", InlineAsm::Kind::Imm)
+          .Case("mem", InlineAsm::Kind::Mem)
+          .Default(InvalidKind);
+  assert(K != InvalidKind && "unknown inline asm operand kind");
+
+  lex();
+
+  // Create the flag with default of 1 operand.
+  InlineAsm::Flag F(K, 1);
+
+  // Parse optional constraint after ':'.
+  if (Token.isNot(MIToken::colon)) {
+    Dest = MachineOperand::CreateImm(F);
+    return false;
+  }
+
+  lex();
+
+  if (Token.isNot(MIToken::Identifier))
+    return error("expected register class or memory constraint name after ':'");
+
+  StringRef ConstraintStr = Token.stringValue();
+  if (K == InlineAsm::Kind::Mem) {
+    InlineAsm::ConstraintCode CC =
+        StringSwitch<InlineAsm::ConstraintCode>(ConstraintStr)
+            .Case("es", InlineAsm::ConstraintCode::es)
+            .Case("i", InlineAsm::ConstraintCode::i)
+            .Case("k", InlineAsm::ConstraintCode::k)
+            .Case("m", InlineAsm::ConstraintCode::m)
+            .Case("o", InlineAsm::ConstraintCode::o)
+            .Case("v", InlineAsm::ConstraintCode::v)
+            .Case("A", InlineAsm::ConstraintCode::A)
+            .Case("Q", InlineAsm::ConstraintCode::Q)
+            .Case("R", InlineAsm::ConstraintCode::R)
+            .Case("S", InlineAsm::ConstraintCode::S)
+            .Case("T", InlineAsm::ConstraintCode::T)
+            .Case("Um", InlineAsm::ConstraintCode::Um)
+            .Case("Un", InlineAsm::ConstraintCode::Un)
+            .Case("Uq", InlineAsm::ConstraintCode::Uq)
+            .Case("Us", InlineAsm::ConstraintCode::Us)
+            .Case("Ut", InlineAsm::ConstraintCode::Ut)
+            .Case("Uv", InlineAsm::ConstraintCode::Uv)
+            .Case("Uy", InlineAsm::ConstraintCode::Uy)
+            .Case("X", InlineAsm::ConstraintCode::X)
+            .Case("Z", InlineAsm::ConstraintCode::Z)
+            .Case("ZB", InlineAsm::ConstraintCode::ZB)
+            .Case("ZC", InlineAsm::ConstraintCode::ZC)
+            .Case("Zy", InlineAsm::ConstraintCode::Zy)
+            .Case("p", InlineAsm::ConstraintCode::p)
+            .Case("ZQ", InlineAsm::ConstraintCode::ZQ)
+            .Case("ZR", InlineAsm::ConstraintCode::ZR)
+            .Case("ZS", InlineAsm::ConstraintCode::ZS)
+            .Case("ZT", InlineAsm::ConstraintCode::ZT)
+            .Default(InlineAsm::ConstraintCode::Unknown);
+    if (CC == InlineAsm::ConstraintCode::Unknown)
+      return error("unknown memory constraint '" + ConstraintStr + "'");
+    F.setMemConstraint(CC);
+  } else if (K == InlineAsm::Kind::RegDef || K == InlineAsm::Kind::RegUse ||
+             K == InlineAsm::Kind::RegDefEarlyClobber) {
+    const TargetRegisterClass *RC =
+        PFS.Target.getRegClass(ConstraintStr.lower());
+    if (!RC)
+      return error("unknown register class '" + ConstraintStr + "'");
+    F.setRegClass(RC->getID());
+  }
+
+  lex();
+
+  Dest = MachineOperand::CreateImm(F);
+  return false;
+}
+
 bool MIParser::parseTargetImmMnemonic(const unsigned OpCode,
                                       const unsigned OpIdx,
                                       MachineOperand &Dest,
@@ -2997,6 +3082,8 @@ bool MIParser::parseMachineOperand(const unsigned OpCode, const unsigned OpIdx,
   case MIToken::NamedVirtualRegister:
     return parseRegisterOperand(Dest, TiedDefIdx);
   case MIToken::IntegerLiteral:
+    // TODO: Forbid numeric operands for INLINEASM once the transition to the
+    // symbolic form is over.
     return parseImmediateOperand(Dest);
   case MIToken::kw_half:
   case MIToken::kw_bfloat:
@@ -3065,16 +3152,25 @@ bool MIParser::parseMachineOperand(const unsigned OpCode, const unsigned OpIdx,
     return parseDbgInstrRefOperand(Dest);
   case MIToken::Error:
     return true;
-  case MIToken::Identifier:
-    if (const auto *RegMask = PFS.Target.getRegMask(Token.stringValue())) {
+  case MIToken::Identifier: {
+    StringRef Id = Token.stringValue();
+    bool IsInlineAsmOperand = (OpCode == TargetOpcode::INLINEASM ||
+                               OpCode == TargetOpcode::INLINEASM_BR) &&
+                              OpIdx >= InlineAsm::MIOp_FirstOperand;
+    if (IsInlineAsmOperand &&
+        (Id == "regdef" || Id == "reguse" || Id == "regdef-ec" ||
+         Id == "clobber" || Id == "imm" || Id == "mem"))
+      return parseInlineAsmOperand(Dest);
+    if (const auto *RegMask = PFS.Target.getRegMask(Id)) {
       Dest = MachineOperand::CreateRegMask(RegMask);
       lex();
       break;
-    } else if (Token.stringValue() == "CustomRegMask") {
+    } else if (Id == "CustomRegMask") {
       return parseCustomRegisterMaskOperand(Dest);
     } else {
       return parseTypedImmediateOperand(Dest);
     }
+  }
   case MIToken::dot: {
     const auto *TII = MF.getSubtarget().getInstrInfo();
     if (const auto *Formatter = TII->getMIRFormatter()) {

diff  --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index 7cba47c38b8fc..7cddb0d7e92e0 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -42,6 +42,7 @@
 #include "llvm/IR/DebugLoc.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/ModuleSlotTracker.h"
@@ -73,6 +74,12 @@ static cl::opt<bool> SimplifyMIR(
 static cl::opt<bool> PrintLocations("mir-debug-loc", cl::Hidden, cl::init(true),
                                     cl::desc("Print MIR debug-locations"));
 
+// TODO: Remove once the transition to the symbolic form is over.
+static cl::opt<bool>
+    PrintSymbolicInlineAsmOps("print-symbolic-inline-asm-ops", cl::Hidden,
+                              cl::init(false),
+                              cl::desc("Print inline asm operands as names"));
+
 namespace {
 
 /// This structure describes how to print out stack object references.
@@ -967,6 +974,25 @@ static void printMIOperand(raw_ostream &OS, MFPrintState &State,
       MachineOperand::printSubRegIdx(OS, Op.getImm(), TRI);
       break;
     }
+    if (PrintSymbolicInlineAsmOps && MI.isInlineAsm()) {
+      int FlagIdx = MI.findInlineAsmFlagIdx(OpIdx);
+      if (FlagIdx >= 0 && (unsigned)FlagIdx == OpIdx) {
+        InlineAsm::Flag F(Op.getImm());
+        OS << F.getKindName();
+
+        unsigned RCID;
+        if ((F.isRegDefKind() || F.isRegUseKind() ||
+             F.isRegDefEarlyClobberKind()) &&
+            F.hasRegClassConstraint(RCID))
+          OS << ':' << TRI->getRegClassName(TRI->getRegClass(RCID));
+
+        if (F.isMemKind()) {
+          InlineAsm::ConstraintCode MCID = F.getMemoryConstraintID();
+          OS << ':' << InlineAsm::getMemConstraintName(MCID);
+        }
+        break;
+      }
+    }
     [[fallthrough]];
   case MachineOperand::MO_Register:
   case MachineOperand::MO_CImmediate:

diff  --git a/llvm/test/CodeGen/AMDGPU/dst-sel-hazard.mir b/llvm/test/CodeGen/AMDGPU/dst-sel-hazard.mir
index 70d1d4f1e7b3c..77029d109a6be 100644
--- a/llvm/test/CodeGen/AMDGPU/dst-sel-hazard.mir
+++ b/llvm/test/CodeGen/AMDGPU/dst-sel-hazard.mir
@@ -1,9 +1,9 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
-# RUN: llc -mtriple=amdgcn -mcpu=gfx942 -run-pass post-RA-hazard-rec -o - %s | FileCheck -check-prefix=HAZARD %s
-# RUN: llc -mtriple=amdgcn -mcpu=gfx9-4-generic -run-pass post-RA-hazard-rec -o - %s | FileCheck -check-prefix=HAZARD %s
-# RUN: llc -mtriple=amdgcn -mcpu=gfx90a -run-pass post-RA-hazard-rec -o - %s | FileCheck -check-prefix=NOHAZARD %s
+# RUN: llc -mtriple=amdgcn -mcpu=gfx942 -run-pass post-RA-hazard-rec -print-symbolic-inline-asm-ops -o - %s | FileCheck -check-prefix=HAZARD %s
+# RUN: llc -mtriple=amdgcn -mcpu=gfx9-4-generic -run-pass post-RA-hazard-rec -print-symbolic-inline-asm-ops -o - %s | FileCheck -check-prefix=HAZARD %s
+# RUN: llc -mtriple=amdgcn -mcpu=gfx90a -run-pass post-RA-hazard-rec -print-symbolic-inline-asm-ops -o - %s | FileCheck -check-prefix=NOHAZARD %s
 
-# RUN: llc -mtriple=amdgcn -mcpu=gfx90a -passes post-RA-hazard-rec -o - %s | FileCheck -check-prefix=NOHAZARD %s
+# RUN: llc -mtriple=amdgcn -mcpu=gfx90a -passes post-RA-hazard-rec -print-symbolic-inline-asm-ops -o - %s | FileCheck -check-prefix=NOHAZARD %s
 
 ---
 name:            sdwa_opsel_hazard
@@ -370,7 +370,7 @@ body:            |
     ; HAZARD-LABEL: name: inline_sdwa_hazard
     ; HAZARD: liveins: $vgpr0, $vgpr1, $vgpr2, $vgpr3, $vgpr4, $exec, $mode
     ; HAZARD-NEXT: {{  $}}
-    ; HAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, 1179658 /* regdef:VGPR_32 */, def $vgpr0, 1179657 /* reguse:VGPR_32 */, $vgpr1
+    ; HAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, regdef:VGPR_32, def $vgpr0, reguse:VGPR_32, $vgpr1
     ; HAZARD-NEXT: S_NOP 0
     ; HAZARD-NEXT: renamable $vgpr0 = V_ADD_U16_sdwa 0, $vgpr1, 0, $vgpr2, 0, 1, 0, 3, 3, implicit $exec, implicit killed $vgpr0(tied-def 0)
     ; HAZARD-NEXT: S_ENDPGM 0
@@ -378,10 +378,10 @@ body:            |
     ; NOHAZARD-LABEL: name: inline_sdwa_hazard
     ; NOHAZARD: liveins: $vgpr0, $vgpr1, $vgpr2, $vgpr3, $vgpr4, $exec, $mode
     ; NOHAZARD-NEXT: {{  $}}
-    ; NOHAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, 1179658 /* regdef:VGPR_32 */, def $vgpr0, 1179657 /* reguse:VGPR_32 */, $vgpr1
+    ; NOHAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, regdef:VGPR_32, def $vgpr0, reguse:VGPR_32, $vgpr1
     ; NOHAZARD-NEXT: renamable $vgpr0 = V_ADD_U16_sdwa 0, $vgpr1, 0, $vgpr2, 0, 1, 0, 3, 3, implicit $exec, implicit killed $vgpr0(tied-def 0)
     ; NOHAZARD-NEXT: S_ENDPGM 0
-  INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, 1179658 /* regdef:VGPR_32 */, def $vgpr0, 1179657 /* reguse:VGPR_32 */, $vgpr1
+  INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, regdef:VGPR_32, def $vgpr0, reguse:VGPR_32, $vgpr1
   renamable $vgpr0 = V_ADD_U16_sdwa 0, $vgpr1, 0, $vgpr2, 0, 1, 0, 3, 3, implicit $exec, implicit killed $vgpr0(tied-def 0)
   S_ENDPGM 0
 ...
@@ -397,17 +397,17 @@ body:            |
     ; HAZARD-NEXT: {{  $}}
     ; HAZARD-NEXT: renamable $vgpr0 = V_ADD_U16_sdwa 0, $vgpr1, 0, $vgpr2, 0, 1, 0, 3, 3, implicit $exec, implicit killed $vgpr0(tied-def 0)
     ; HAZARD-NEXT: S_NOP 0
-    ; HAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, 1179658 /* regdef:VGPR_32 */, def $vgpr0, 1179657 /* reguse:VGPR_32 */, $vgpr1
+    ; HAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, regdef:VGPR_32, def $vgpr0, reguse:VGPR_32, $vgpr1
     ; HAZARD-NEXT: S_ENDPGM 0
     ;
     ; NOHAZARD-LABEL: name: sdwa_inline_hazard
     ; NOHAZARD: liveins: $vgpr0, $vgpr1, $vgpr2, $vgpr3, $vgpr4, $exec, $mode
     ; NOHAZARD-NEXT: {{  $}}
     ; NOHAZARD-NEXT: renamable $vgpr0 = V_ADD_U16_sdwa 0, $vgpr1, 0, $vgpr2, 0, 1, 0, 3, 3, implicit $exec, implicit killed $vgpr0(tied-def 0)
-    ; NOHAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, 1179658 /* regdef:VGPR_32 */, def $vgpr0, 1179657 /* reguse:VGPR_32 */, $vgpr1
+    ; NOHAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, regdef:VGPR_32, def $vgpr0, reguse:VGPR_32, $vgpr1
     ; NOHAZARD-NEXT: S_ENDPGM 0
   renamable $vgpr0 = V_ADD_U16_sdwa 0, $vgpr1, 0, $vgpr2, 0, 1, 0, 3, 3, implicit $exec, implicit killed $vgpr0(tied-def 0)
-  INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, 1179658 /* regdef:VGPR_32 */, def $vgpr0, 1179657 /* reguse:VGPR_32 */, $vgpr1
+  INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, regdef:VGPR_32, def $vgpr0, reguse:VGPR_32, $vgpr1
   S_ENDPGM 0
 ...
 
@@ -421,19 +421,19 @@ body:            |
     ; HAZARD-LABEL: name: inline_inline_hazard
     ; HAZARD: liveins: $vgpr0, $vgpr1, $vgpr2, $vgpr3, $vgpr4, $exec, $mode
     ; HAZARD-NEXT: {{  $}}
-    ; HAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, 1179658 /* regdef:VGPR_32 */, def $vgpr0, 1179657 /* reguse:VGPR_32 */, $vgpr1
+    ; HAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, regdef:VGPR_32, def $vgpr0, reguse:VGPR_32, $vgpr1
     ; HAZARD-NEXT: S_NOP 0
-    ; HAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, 1179658 /* regdef:VGPR_32 */, def $vgpr0, 1179657 /* reguse:VGPR_32 */, $vgpr1
+    ; HAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, regdef:VGPR_32, def $vgpr0, reguse:VGPR_32, $vgpr1
     ; HAZARD-NEXT: S_ENDPGM 0
     ;
     ; NOHAZARD-LABEL: name: inline_inline_hazard
     ; NOHAZARD: liveins: $vgpr0, $vgpr1, $vgpr2, $vgpr3, $vgpr4, $exec, $mode
     ; NOHAZARD-NEXT: {{  $}}
-    ; NOHAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, 1179658 /* regdef:VGPR_32 */, def $vgpr0, 1179657 /* reguse:VGPR_32 */, $vgpr1
-    ; NOHAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, 1179658 /* regdef:VGPR_32 */, def $vgpr0, 1179657 /* reguse:VGPR_32 */, $vgpr1
+    ; NOHAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, regdef:VGPR_32, def $vgpr0, reguse:VGPR_32, $vgpr1
+    ; NOHAZARD-NEXT: INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, regdef:VGPR_32, def $vgpr0, reguse:VGPR_32, $vgpr1
     ; NOHAZARD-NEXT: S_ENDPGM 0
-  INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, 1179658 /* regdef:VGPR_32 */, def $vgpr0, 1179657 /* reguse:VGPR_32 */, $vgpr1
-  INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, 1179658 /* regdef:VGPR_32 */, def $vgpr0, 1179657 /* reguse:VGPR_32 */, $vgpr1
+  INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, regdef:VGPR_32, def $vgpr0, reguse:VGPR_32, $vgpr1
+  INLINEASM &"v_or_b32 $0, 0, $1", 0 /* attdialect */, regdef:VGPR_32, def $vgpr0, reguse:VGPR_32, $vgpr1
   S_ENDPGM 0
 ...
 

diff  --git a/llvm/test/CodeGen/MIR/Generic/inline-asm-bad-mem-constraint.mir b/llvm/test/CodeGen/MIR/Generic/inline-asm-bad-mem-constraint.mir
new file mode 100644
index 0000000000000..14e23c6d483ec
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/Generic/inline-asm-bad-mem-constraint.mir
@@ -0,0 +1,11 @@
+# RUN: not llc -run-pass=none -filetype=null %s 2>&1 | FileCheck %s
+
+# Test parsing error for unknown memory constraint.
+
+# CHECK: [[@LINE+5]]:{{[0-9]+}}: unknown memory constraint 'badmem'
+---
+name: foo
+body: |
+  bb.0:
+    INLINEASM &"", 0 /* attdialect */, mem:badmem
+...

diff  --git a/llvm/test/CodeGen/MIR/Generic/inline-asm-bad-regclass.mir b/llvm/test/CodeGen/MIR/Generic/inline-asm-bad-regclass.mir
new file mode 100644
index 0000000000000..fb88f0fe9dba0
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/Generic/inline-asm-bad-regclass.mir
@@ -0,0 +1,11 @@
+# RUN: not llc -run-pass=none -filetype=null %s 2>&1 | FileCheck %s
+
+# Test parsing error for unknown register class.
+
+# CHECK: [[@LINE+5]]:{{[0-9]+}}: unknown register class 'badreg'
+---
+name: foo
+body: |
+  bb.0:
+    INLINEASM &"", 0 /* attdialect */, regdef:badreg
+...

diff  --git a/llvm/test/CodeGen/MIR/Generic/inline-asm-no-constraint.mir b/llvm/test/CodeGen/MIR/Generic/inline-asm-no-constraint.mir
new file mode 100644
index 0000000000000..0b4c6f2292ec3
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/Generic/inline-asm-no-constraint.mir
@@ -0,0 +1,11 @@
+# RUN: not llc -run-pass=none -filetype=null %s 2>&1 | FileCheck %s
+
+# Test parsing error when a register class or memory constraint name is expected after ':'.
+
+# CHECK: [[@LINE+5]]:{{[0-9]+}}: expected register class or memory constraint name after ':'
+---
+name: foo
+body: |
+  bb.0:
+    INLINEASM &"", 0 /* attdialect */, regdef:123
+...


        


More information about the llvm-commits mailing list