[llvm] [CodeGen] Add MO_LaneMask type and a new COPY_LANEMASK instruction (PR #151944)

Vikash Gupta via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 22 00:10:16 PDT 2025


https://github.com/vg0204 updated https://github.com/llvm/llvm-project/pull/151944

>From 4c7f52d999740d2499ccf3270f984ddb09292d34 Mon Sep 17 00:00:00 2001
From: vikashgu <Vikash.Gupta at amd.com>
Date: Mon, 4 Aug 2025 11:04:28 +0000
Subject: [PATCH 1/6] [CodeGen][NFC] Add laneBitmask as new MachineOperand Type

This patch adds a new MachineOperand type to represent the
laneBitmask as MO_LaneMask that can be used in the instructions
to represent the relevant information associated with the register
operands of the same such as liveness.
---
 llvm/docs/MIRLangRef.rst                      |  1 +
 .../llvm/CodeGen/MachineInstrBuilder.h        |  5 ++++
 llvm/include/llvm/CodeGen/MachineOperand.h    | 17 ++++++++++-
 llvm/lib/CodeGen/MIRParser/MILexer.cpp        |  1 +
 llvm/lib/CodeGen/MIRParser/MILexer.h          |  1 +
 llvm/lib/CodeGen/MIRParser/MIParser.cpp       | 29 +++++++++++++++++++
 llvm/lib/CodeGen/MIRPrinter.cpp               |  3 +-
 llvm/lib/CodeGen/MIRVRegNamerUtils.cpp        |  1 +
 llvm/lib/CodeGen/MachineOperand.cpp           | 19 ++++++++++--
 llvm/lib/CodeGen/MachineStableHash.cpp        |  4 +++
 llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp  |  1 +
 llvm/unittests/CodeGen/MachineOperandTest.cpp | 17 +++++++++++
 12 files changed, 94 insertions(+), 5 deletions(-)

diff --git a/llvm/docs/MIRLangRef.rst b/llvm/docs/MIRLangRef.rst
index a505c1ea4b0aa..4e12239e0e68f 100644
--- a/llvm/docs/MIRLangRef.rst
+++ b/llvm/docs/MIRLangRef.rst
@@ -819,6 +819,7 @@ For an int eq predicate ``ICMP_EQ``, the syntax is:
 .. TODO: Describe the syntax of the metadata machine operands, and the
    instructions debug location attribute.
 .. TODO: Describe the syntax of the register live out machine operands.
+.. TODO: Describe the syntax of the lanemask machine operands.
 .. TODO: Describe the syntax of the machine memory operands.
 
 Comments
diff --git a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
index e705d7d99544c..a07fea19a4785 100644
--- a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
+++ b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
@@ -292,6 +292,11 @@ class MachineInstrBuilder {
     return *this;
   }
 
+  const MachineInstrBuilder &addLaneMask(LaneBitmask LaneMask) const {
+    MI->addOperand(*MF, MachineOperand::CreateLaneMask(LaneMask));
+    return *this;
+  }
+
   const MachineInstrBuilder &addSym(MCSymbol *Sym,
                                     unsigned char TargetFlags = 0) const {
     MI->addOperand(*MF, MachineOperand::CreateMCSymbol(Sym, TargetFlags));
diff --git a/llvm/include/llvm/CodeGen/MachineOperand.h b/llvm/include/llvm/CodeGen/MachineOperand.h
index 646588a2a92a5..0fd999364234b 100644
--- a/llvm/include/llvm/CodeGen/MachineOperand.h
+++ b/llvm/include/llvm/CodeGen/MachineOperand.h
@@ -16,6 +16,7 @@
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/CodeGen/Register.h"
 #include "llvm/IR/Intrinsics.h"
+#include "llvm/MC/LaneBitmask.h"
 #include "llvm/Support/Compiler.h"
 #include <cassert>
 
@@ -69,7 +70,8 @@ class MachineOperand {
     MO_Predicate,         ///< Generic predicate for ISel
     MO_ShuffleMask,       ///< Other IR Constant for ISel (shuffle masks)
     MO_DbgInstrRef, ///< Integer indices referring to an instruction+operand
-    MO_Last = MO_DbgInstrRef
+    MO_LaneMask,    ///< Mask to represent active parts of registers
+    MO_Last = MO_LaneMask
   };
 
 private:
@@ -178,6 +180,7 @@ class MachineOperand {
     Intrinsic::ID IntrinsicID; // For MO_IntrinsicID.
     unsigned Pred;           // For MO_Predicate
     ArrayRef<int> ShuffleMask; // For MO_ShuffleMask
+    LaneBitmask LaneMask;      // For MO_LaneMask
 
     struct {                  // For MO_Register.
       // Register number is in SmallContents.RegNo.
@@ -360,6 +363,7 @@ class MachineOperand {
   bool isIntrinsicID() const { return OpKind == MO_IntrinsicID; }
   bool isPredicate() const { return OpKind == MO_Predicate; }
   bool isShuffleMask() const { return OpKind == MO_ShuffleMask; }
+  bool isLaneMask() const { return OpKind == MO_LaneMask; }
   //===--------------------------------------------------------------------===//
   // Accessors for Register Operands
   //===--------------------------------------------------------------------===//
@@ -624,6 +628,11 @@ class MachineOperand {
     return Contents.ShuffleMask;
   }
 
+  LaneBitmask getLaneMask() const {
+    assert(isLaneMask() && "Wrong MachineOperand accessor");
+    return Contents.LaneMask;
+  }
+
   /// Return the offset from the symbol in this operand. This always returns 0
   /// for ExternalSymbol operands.
   int64_t getOffset() const {
@@ -989,6 +998,12 @@ class MachineOperand {
     return Op;
   }
 
+  static MachineOperand CreateLaneMask(LaneBitmask LaneMask) {
+    MachineOperand Op(MachineOperand::MO_LaneMask);
+    Op.Contents.LaneMask = LaneMask;
+    return Op;
+  }
+
   friend class MachineInstr;
   friend class MachineRegisterInfo;
 
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
index 8b72c295416a2..bb714653d79dc 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
@@ -266,6 +266,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
       .Case("constant-pool", MIToken::kw_constant_pool)
       .Case("call-entry", MIToken::kw_call_entry)
       .Case("custom", MIToken::kw_custom)
+      .Case("lanemask", MIToken::kw_lanemask)
       .Case("liveout", MIToken::kw_liveout)
       .Case("landing-pad", MIToken::kw_landing_pad)
       .Case("inlineasm-br-indirect-target",
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h
index 0627f176b9e00..8c4fb0e63895a 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.h
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.h
@@ -122,6 +122,7 @@ struct MIToken {
     kw_constant_pool,
     kw_call_entry,
     kw_custom,
+    kw_lanemask,
     kw_liveout,
     kw_landing_pad,
     kw_inlineasm_br_indirect_target,
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 6a464d9dd6886..c09734ab8f87c 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -496,6 +496,7 @@ class MIParser {
   bool parseTargetIndexOperand(MachineOperand &Dest);
   bool parseDbgInstrRefOperand(MachineOperand &Dest);
   bool parseCustomRegisterMaskOperand(MachineOperand &Dest);
+  bool parseLaneMaskOperand(MachineOperand &Dest);
   bool parseLiveoutRegisterMaskOperand(MachineOperand &Dest);
   bool parseMachineOperand(const unsigned OpCode, const unsigned OpIdx,
                            MachineOperand &Dest,
@@ -2870,6 +2871,32 @@ bool MIParser::parseCustomRegisterMaskOperand(MachineOperand &Dest) {
   return false;
 }
 
+bool MIParser::parseLaneMaskOperand(MachineOperand &Dest) {
+  assert(Token.is(MIToken::kw_lanemask));
+
+  lex();
+  if (expectAndConsume(MIToken::lparen))
+    return error("expected syntax lanemask(...)");
+
+  LaneBitmask LaneMask = LaneBitmask::getAll();
+  // Parse lanemask.
+  if (Token.isNot(MIToken::IntegerLiteral) && Token.isNot(MIToken::HexLiteral))
+    return error("expected a lane mask");
+  static_assert(sizeof(LaneBitmask::Type) == sizeof(uint64_t),
+                "Use correct get-function for lane mask");
+  LaneBitmask::Type V;
+  if (getUint64(V))
+    return error("invalid lanemask value");
+  LaneMask = LaneBitmask(V);
+  lex();
+
+  if (expectAndConsume(MIToken::rparen))
+    return error("lanemask should be terminated by ')'.");
+
+  Dest = MachineOperand::CreateLaneMask(LaneMask);
+  return false;
+}
+
 bool MIParser::parseLiveoutRegisterMaskOperand(MachineOperand &Dest) {
   assert(Token.is(MIToken::kw_liveout));
   uint32_t *Mask = MF.allocateRegMask();
@@ -2970,6 +2997,8 @@ bool MIParser::parseMachineOperand(const unsigned OpCode, const unsigned OpIdx,
     return parseIntrinsicOperand(Dest);
   case MIToken::kw_target_index:
     return parseTargetIndexOperand(Dest);
+  case MIToken::kw_lanemask:
+    return parseLaneMaskOperand(Dest);
   case MIToken::kw_liveout:
     return parseLiveoutRegisterMaskOperand(Dest);
   case MIToken::kw_floatpred:
diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index ce1834a90ca54..3945acbb505fe 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -928,7 +928,8 @@ static void printMIOperand(raw_ostream &OS, MFPrintState &State,
   case MachineOperand::MO_Predicate:
   case MachineOperand::MO_BlockAddress:
   case MachineOperand::MO_DbgInstrRef:
-  case MachineOperand::MO_ShuffleMask: {
+  case MachineOperand::MO_ShuffleMask:
+  case MachineOperand::MO_LaneMask: {
     unsigned TiedOperandIdx = 0;
     if (ShouldPrintRegisterTies && Op.isReg() && Op.isTied() && !Op.isDef())
       TiedOperandIdx = Op.getParent()->findTiedOperandIdx(OpIdx);
diff --git a/llvm/lib/CodeGen/MIRVRegNamerUtils.cpp b/llvm/lib/CodeGen/MIRVRegNamerUtils.cpp
index a22cc91b90542..0afb53e1d8f2c 100644
--- a/llvm/lib/CodeGen/MIRVRegNamerUtils.cpp
+++ b/llvm/lib/CodeGen/MIRVRegNamerUtils.cpp
@@ -106,6 +106,7 @@ std::string VRegRenamer::getInstructionOpcodeHash(MachineInstr &MI) {
     case MachineOperand::MO_ExternalSymbol:
     case MachineOperand::MO_GlobalAddress:
     case MachineOperand::MO_BlockAddress:
+    case MachineOperand::MO_LaneMask:
     case MachineOperand::MO_RegisterMask:
     case MachineOperand::MO_RegisterLiveOut:
     case MachineOperand::MO_Metadata:
diff --git a/llvm/lib/CodeGen/MachineOperand.cpp b/llvm/lib/CodeGen/MachineOperand.cpp
index c612f8de7b50b..4d1ce8894e0d0 100644
--- a/llvm/lib/CodeGen/MachineOperand.cpp
+++ b/llvm/lib/CodeGen/MachineOperand.cpp
@@ -380,6 +380,8 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const {
     return getPredicate() == Other.getPredicate();
   case MachineOperand::MO_ShuffleMask:
     return getShuffleMask() == Other.getShuffleMask();
+  case MachineOperand::MO_LaneMask:
+    return getLaneMask() == Other.getLaneMask();
   }
   llvm_unreachable("Invalid machine operand type");
 }
@@ -445,6 +447,9 @@ hash_code llvm::hash_value(const MachineOperand &MO) {
     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getPredicate());
   case MachineOperand::MO_ShuffleMask:
     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getShuffleMask());
+  case MachineOperand::MO_LaneMask:
+    return hash_combine(MO.getType(), MO.getTargetFlags(),
+                        MO.getLaneMask().getAsInteger());
   }
   llvm_unreachable("Invalid machine operand type");
 }
@@ -1004,11 +1009,11 @@ void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST,
   }
   case MachineOperand::MO_Predicate: {
     auto Pred = static_cast<CmpInst::Predicate>(getPredicate());
-    OS << (CmpInst::isIntPredicate(Pred) ? "int" : "float") << "pred("
-       << Pred << ')';
+    OS << (CmpInst::isIntPredicate(Pred) ? "int" : "float") << "pred(" << Pred
+       << ')';
     break;
   }
-  case MachineOperand::MO_ShuffleMask:
+  case MachineOperand::MO_ShuffleMask: {
     OS << "shufflemask(";
     ArrayRef<int> Mask = getShuffleMask();
     StringRef Separator;
@@ -1023,6 +1028,14 @@ void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST,
     OS << ')';
     break;
   }
+  case MachineOperand::MO_LaneMask: {
+    OS << "lanemask(";
+    LaneBitmask LaneMask = getLaneMask();
+    OS << "0x" << PrintLaneMask(LaneMask);
+    OS << ')';
+    break;
+  }
+  }
 }
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
diff --git a/llvm/lib/CodeGen/MachineStableHash.cpp b/llvm/lib/CodeGen/MachineStableHash.cpp
index 9d56696079478..70e66e712b8f1 100644
--- a/llvm/lib/CodeGen/MachineStableHash.cpp
+++ b/llvm/lib/CodeGen/MachineStableHash.cpp
@@ -164,6 +164,10 @@ stable_hash llvm::stableHashValue(const MachineOperand &MO) {
     return stable_hash_combine(MO.getType(), MO.getTargetFlags(),
                                stable_hash_name(SymbolName));
   }
+  case MachineOperand::MO_LaneMask: {
+    return stable_hash_combine(MO.getType(), MO.getTargetFlags(),
+                               MO.getLaneMask().getAsInteger());
+  }
   case MachineOperand::MO_CFIIndex:
     return stable_hash_combine(MO.getType(), MO.getTargetFlags(),
                                MO.getCFIIndex());
diff --git a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
index 57141ab69223f..0dc54b4f4aad1 100644
--- a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
@@ -930,6 +930,7 @@ static bool IsAnAddressOperand(const MachineOperand &MO) {
     return true;
   case MachineOperand::MO_RegisterMask:
   case MachineOperand::MO_RegisterLiveOut:
+  case MachineOperand::MO_LaneMask:
     return false;
   case MachineOperand::MO_Metadata:
   case MachineOperand::MO_MCSymbol:
diff --git a/llvm/unittests/CodeGen/MachineOperandTest.cpp b/llvm/unittests/CodeGen/MachineOperandTest.cpp
index 3f3f48fcc7c58..dcd731e5cb896 100644
--- a/llvm/unittests/CodeGen/MachineOperandTest.cpp
+++ b/llvm/unittests/CodeGen/MachineOperandTest.cpp
@@ -288,6 +288,23 @@ TEST(MachineOperandTest, PrintGlobalAddress) {
   }
 }
 
+TEST(MachineOperandTest, PrintLaneMask) {
+  // Create a MachineOperand with a lanemask and print it.
+  LaneBitmask LaneMask = LaneBitmask(12);
+  MachineOperand MO = MachineOperand::CreateLaneMask(LaneMask);
+
+  // Checking some preconditions on the newly created
+  // MachineOperand.
+  ASSERT_TRUE(MO.isLaneMask());
+  ASSERT_TRUE(MO.getLaneMask() == LaneMask);
+
+  std::string str;
+  // Print a MachineOperand that is lanemask as in HEX representation.
+  raw_string_ostream OS(str);
+  MO.print(OS, /*TRI=*/nullptr);
+  ASSERT_TRUE(str == "lanemask(0x000000000000000C)");
+}
+
 TEST(MachineOperandTest, PrintRegisterLiveOut) {
   // Create a MachineOperand with a register live out list and print it.
   uint32_t Mask = 0;

>From 98ee227ae4bbc54914901832efcf6c995621d3bb Mon Sep 17 00:00:00 2001
From: vikashgu <Vikash.Gupta at amd.com>
Date: Wed, 6 Aug 2025 11:15:38 +0000
Subject: [PATCH 2/6] [CodeGen]Added support for COPY_LANEMASK instruction

This new instruction takes laneMask as an operand with
respect to the input operand storing the essential information.
---
 llvm/include/llvm/CodeGen/MachineInstr.h      |  4 ++-
 llvm/include/llvm/Support/TargetOpcodes.def   |  5 ++++
 llvm/include/llvm/Target/Target.td            |  7 +++++
 llvm/lib/CodeGen/MIRParser/MIParser.cpp       |  6 ++--
 llvm/lib/CodeGen/MachineVerifier.cpp          | 28 +++++++++++++++++++
 .../parse-lanemask-operand-invalid-0.mir      | 13 +++++++++
 .../parse-lanemask-operand-invalid-1.mir      | 13 +++++++++
 .../parse-lanemask-operand-invalid-2.mir      | 13 +++++++++
 .../MIR/AMDGPU/parse-lanemask-operand.mir     | 17 +++++++++++
 .../verifier-copyLanemask0.mir                | 24 ++++++++++++++++
 .../verifier-copyLanemask1.mir                | 28 +++++++++++++++++++
 11 files changed, 154 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-0.mir
 create mode 100644 llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-1.mir
 create mode 100644 llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-2.mir
 create mode 100644 llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand.mir
 create mode 100644 llvm/test/MachineVerifier/verifier-copyLanemask0.mir
 create mode 100644 llvm/test/MachineVerifier/verifier-copyLanemask1.mir

diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index 10a9b1ff1411d..afbb3ae4d33d7 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -1429,7 +1429,8 @@ class MachineInstr
   }
 
   bool isCopy() const {
-    return getOpcode() == TargetOpcode::COPY;
+    return (getOpcode() == TargetOpcode::COPY ||
+            getOpcode() == TargetOpcode::COPY_LANEMASK);
   }
 
   bool isFullCopy() const {
@@ -1465,6 +1466,7 @@ class MachineInstr
     case TargetOpcode::PHI:
     case TargetOpcode::G_PHI:
     case TargetOpcode::COPY:
+    case TargetOpcode::COPY_LANEMASK:
     case TargetOpcode::INSERT_SUBREG:
     case TargetOpcode::SUBREG_TO_REG:
     case TargetOpcode::REG_SEQUENCE:
diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def
index b905576b61791..570ed3ec30491 100644
--- a/llvm/include/llvm/Support/TargetOpcodes.def
+++ b/llvm/include/llvm/Support/TargetOpcodes.def
@@ -114,6 +114,11 @@ HANDLE_TARGET_OPCODE(REG_SEQUENCE)
 /// used to copy between subregisters of virtual registers.
 HANDLE_TARGET_OPCODE(COPY)
 
+/// COPY_LANEMASK - Target-independent register copy for active mask in 
+/// register as represented by the lanemask. This instruction can only be 
+/// used to copy between physical registers.
+HANDLE_TARGET_OPCODE(COPY_LANEMASK)
+
 /// BUNDLE - This instruction represents an instruction bundle. Instructions
 /// which immediately follow a BUNDLE instruction which are marked with
 /// 'InsideBundle' flag are inside the bundle.
diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td
index 4c83f8a580aa0..0b7a6ee81c29f 100644
--- a/llvm/include/llvm/Target/Target.td
+++ b/llvm/include/llvm/Target/Target.td
@@ -1329,6 +1329,13 @@ def COPY : StandardPseudoInstruction {
   let isAsCheapAsAMove = true;
   let hasNoSchedulingInfo = false;
 }
+def COPY_LANEMASK : StandardPseudoInstruction {
+  let OutOperandList = (outs unknown:$dst);
+  let InOperandList = (ins unknown:$src, unknown:$lanemask);
+  let AsmString = "";
+  let hasSideEffects = false;
+  let isAsCheapAsAMove = true;
+}
 def BUNDLE : StandardPseudoInstruction {
   let OutOperandList = (outs);
   let InOperandList = (ins variable_ops);
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index c09734ab8f87c..6a42c924d161f 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -2876,14 +2876,14 @@ bool MIParser::parseLaneMaskOperand(MachineOperand &Dest) {
 
   lex();
   if (expectAndConsume(MIToken::lparen))
-    return error("expected syntax lanemask(...)");
+    return error("lanemask should begin with '('.");
 
   LaneBitmask LaneMask = LaneBitmask::getAll();
   // Parse lanemask.
   if (Token.isNot(MIToken::IntegerLiteral) && Token.isNot(MIToken::HexLiteral))
-    return error("expected a lane mask");
+    return error("expected a valid lane mask value.");
   static_assert(sizeof(LaneBitmask::Type) == sizeof(uint64_t),
-                "Use correct get-function for lane mask");
+                "Use correct get-function for lane mask.");
   LaneBitmask::Type V;
   if (getUint64(V))
     return error("invalid lanemask value");
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index 01703fe09b79a..3f7d361f09647 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -2414,6 +2414,34 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
     }
     break;
   }
+  case TargetOpcode::COPY_LANEMASK: {
+    const MachineOperand &DstOp = MI->getOperand(0);
+    const MachineOperand &SrcOp = MI->getOperand(1);
+    const MachineOperand &LaneMaskOp = MI->getOperand(2);
+    const Register SrcReg = SrcOp.getReg();
+    const Register DstReg = DstOp.getReg();
+    const LaneBitmask LaneMask = LaneMaskOp.getLaneMask();
+
+    if (!SrcReg.isPhysical() || !DstReg.isPhysical()) {
+      if (!SrcReg.isPhysical()) {
+        report("Copy with lanemask Instruction uses virtual register", &SrcOp,
+               1);
+      }
+      if (!DstReg.isPhysical()) {
+        report("Copy with lanemask Instruction uses virtual register", &DstOp,
+               0);
+      }
+      break;
+    }
+
+    if (LaneMask.none())
+      report("Lanemask takes up the zero value", MI);
+
+    if (LaneMask.all())
+      report("Copy Instruction can be used instead of copy with lanemask", MI);
+
+    break;
+  }
   case TargetOpcode::STATEPOINT: {
     StatepointOpers SO(MI);
     if (!MI->getOperand(SO.getIDPos()).isImm() ||
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-0.mir b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-0.mir
new file mode 100644
index 0000000000000..5bb397e8bcd08
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-0.mir
@@ -0,0 +1,13 @@
+# RUN: not llc -mtriple=amdgcn-amd-amdhsa -run-pass=none -verify-machineinstrs %s -o /dev/null 2>&1 | FileCheck %s
+
+---
+name: test_missing_rparen
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0
+
+    ; CHECK: [[@LINE+1]]:47: lanemask should be terminated by ')'. 
+    $vgpr1 = COPY_LANEMASK $vgpr0, lanemask(16
+    S_ENDPGM 0
+...
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-1.mir b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-1.mir
new file mode 100644
index 0000000000000..bb4ca36e29511
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-1.mir
@@ -0,0 +1,13 @@
+# RUN: not llc -mtriple=amdgcn-amd-amdhsa -run-pass=none -verify-machineinstrs %s -o /dev/null 2>&1 | FileCheck %s
+
+---
+name: test_missing_lparen
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0
+
+    ; CHECK: [[@LINE+1]]:45: lanemask should begin with '('. 
+    $vgpr1 = COPY_LANEMASK $vgpr0, lanemask 14)
+    S_ENDPGM 0
+...
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-2.mir b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-2.mir
new file mode 100644
index 0000000000000..fe520056f475c
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-2.mir
@@ -0,0 +1,13 @@
+# RUN: not llc -mtriple=amdgcn-amd-amdhsa -run-pass=none -verify-machineinstrs %s -o /dev/null 2>&1 | FileCheck %s
+
+---
+name: test_wrong_lanemask_type
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0
+
+    ; CHECK: [[@LINE+1]]:45: expected a valid lane mask value. 
+    $vgpr1 = COPY_LANEMASK $vgpr0, lanemask(undef)
+    S_ENDPGM 0
+...
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand.mir b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand.mir
new file mode 100644
index 0000000000000..92c58826a5031
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand.mir
@@ -0,0 +1,17 @@
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -run-pass=none -verify-machineinstrs -o - %s | FileCheck %s
+
+# This test checks for the correctness of the MIR parser for lanemask
+
+# CHECK-LABEL: name: test_lanemask_operand
+# CHECK: COPY_LANEMASK $vgpr0, lanemask(0x0000000000000020)
+---
+name: test_lanemask_operand
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0
+
+    $vgpr1 = COPY_LANEMASK $vgpr0, lanemask(32)
+    S_ENDPGM 0
+...
+
diff --git a/llvm/test/MachineVerifier/verifier-copyLanemask0.mir b/llvm/test/MachineVerifier/verifier-copyLanemask0.mir
new file mode 100644
index 0000000000000..88d368c98ba32
--- /dev/null
+++ b/llvm/test/MachineVerifier/verifier-copyLanemask0.mir
@@ -0,0 +1,24 @@
+# RUN: not --crash llc -o - -mtriple=amdgcn-amd-amdhsa -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
+# REQUIRES: amdgpu-registered-target
+
+# CHECK: *** Bad machine code: Lanemask takes up the zero value ***
+# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
+# CHECK-NEXT: - basic block: %bb.0
+# CHECK-NEXT: - instruction: $vgpr2 = COPY_LANEMASK $vgpr0, lanemask(0x0000000000000000)
+
+# CHECK: *** Bad machine code: Copy Instruction can be used instead of copy with lanemask ***
+# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
+# CHECK-NEXT: - basic block: %bb.0
+# CHECK-NEXT: - instruction: $vgpr3 = COPY_LANEMASK $vgpr1, lanemask(0xFFFFFFFFFFFFFFFF)
+
+---
+name: test_copy_lanemask_instruction_0
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0, $vgpr1
+
+    $vgpr2 = COPY_LANEMASK $vgpr0, lanemask(0)
+    $vgpr3 = COPY_LANEMASK $vgpr1, lanemask(0xFFFFFFFFFFFFFFFF)
+    S_ENDPGM 0
+...
diff --git a/llvm/test/MachineVerifier/verifier-copyLanemask1.mir b/llvm/test/MachineVerifier/verifier-copyLanemask1.mir
new file mode 100644
index 0000000000000..b4386dcae7760
--- /dev/null
+++ b/llvm/test/MachineVerifier/verifier-copyLanemask1.mir
@@ -0,0 +1,28 @@
+# RUN: not --crash llc -o - -mtriple=amdgcn-amd-amdhsa -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
+# REQUIRES: amdgpu-registered-target
+
+# CHECK: *** Bad machine code: Copy with lanemask Instruction uses virtual register ***
+# CHECK-NEXT: - function:    test_copy_lanemask_instruction_1
+# CHECK-NEXT: - basic block: %bb.0 
+# CHECK-NEXT: - instruction: $vgpr2 = COPY_LANEMASK %0:vgpr_32, lanemask(0x0000000000000018)
+# CHECK-NEXT: - operand 1:   %0:vgpr_32
+
+# CHECK: *** Bad machine code: Copy with lanemask Instruction uses virtual register ***
+# CHECK-NEXT: - function:    test_copy_lanemask_instruction_1
+# CHECK-NEXT: - basic block: %bb.0 
+# CHECK-NEXT: - instruction: %1:vgpr_32 = COPY_LANEMASK $vgpr1, lanemask(0x00000000000000FF)
+# CHECK-NEXT: - operand 0:   %1:vgpr_32
+
+---
+name: test_copy_lanemask_instruction_1
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0, $vgpr1
+
+    %0:vgpr_32 = COPY $vgpr0
+    $vgpr2 = COPY_LANEMASK %0, lanemask(24)
+    %1:vgpr_32 = COPY_LANEMASK $vgpr1, lanemask(0x000000000000FF)
+    S_ENDPGM 0
+...
+

>From d4089f8271e8fbd75755ac52e68a6fa23eade61f Mon Sep 17 00:00:00 2001
From: vikashgu <Vikash.Gupta at amd.com>
Date: Wed, 6 Aug 2025 11:54:12 +0000
Subject: [PATCH 3/6] Updated the existing LIT tests to accomodate this patch.

---
 .../CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir  | 4 ++--
 .../CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir    | 4 ++--
 .../TableGen/GlobalISelCombinerEmitter/match-table-cxx.td     | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index 5c164bf672082..508c1d225680d 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -70,11 +70,11 @@
 # DEBUG-NEXT: .. the first uncovered type index: 1, OK
 # DEBUG-NEXT: .. the first uncovered imm index: 0, OK
 #
-# DEBUG-NEXT: G_ABDS (opcode 65): 1 type index, 0 imm indices
+# DEBUG-NEXT: G_ABDS (opcode 66): 1 type index, 0 imm indices
 # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
 #
-# DEBUG-NEXT: G_ABDU (opcode 66): 1 type index, 0 imm indices
+# DEBUG-NEXT: G_ABDU (opcode 67): 1 type index, 0 imm indices
 # DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
 # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
index 82cc6829838a0..a92bd47847e8b 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
@@ -72,11 +72,11 @@
 # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
 #
-# DEBUG-NEXT: G_ABDS (opcode 65): 1 type index, 0 imm indices
+# DEBUG-NEXT: G_ABDS (opcode 66): 1 type index, 0 imm indices
 # DEBUG-NEXT:.. type index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT:.. imm index coverage check SKIPPED: no rules defined
 #
-# DEBUG-NEXT:G_ABDU (opcode 66): 1 type index, 0 imm indices
+# DEBUG-NEXT:G_ABDU (opcode 67): 1 type index, 0 imm indices
 # DEBUG-NEXT:.. type index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT:.. imm index coverage check SKIPPED: no rules defined
 #
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
index ce4f0108b4843..9a7e21f0a9b07 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
@@ -96,7 +96,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 
 // CHECK:      const uint8_t *GenMyCombiner::getMatchTable() const {
 // CHECK-NEXT:   constexpr static uint8_t MatchTable0[] = {
-// CHECK-NEXT:      /*   0 */ GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(99), GIMT_Encode2(210), /*)*//*default:*//*Label 5*/ GIMT_Encode4(520),
+// CHECK-NEXT:      /*   0 */ GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(100), GIMT_Encode2(211), /*)*//*default:*//*Label 5*/ GIMT_Encode4(520),
 // CHECK-NEXT:      /* 10 */ /*TargetOpcode::G_STORE*//*Label 0*/ GIMT_Encode4(454), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0),
 // CHECK-NEXT:      /* 182 */ /*TargetOpcode::G_SEXT*//*Label 1*/ GIMT_Encode4(472), GIMT_Encode4(0),
 // CHECK-NEXT:      /* 190 */ /*TargetOpcode::G_ZEXT*//*Label 2*/ GIMT_Encode4(484), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0),

>From 8b4def7607f5617bb00fcb924d1bbf0a9055170a Mon Sep 17 00:00:00 2001
From: vikashgu <Vikash.Gupta at amd.com>
Date: Wed, 13 Aug 2025 10:17:49 +0000
Subject: [PATCH 4/6] Addressed reviewed changes making changes in LIT tests
 mainly.

---
 llvm/docs/MIRLangRef.rst                      | 14 ++++-
 llvm/include/llvm/CodeGen/MachineInstr.h      |  7 ++-
 llvm/lib/CodeGen/MachineVerifier.cpp          | 29 +++++-----
 .../parse-lanemask-operand-invalid-0.mir      |  2 +-
 .../parse-lanemask-operand-invalid-1.mir      |  2 +-
 .../parse-lanemask-operand-invalid-2.mir      |  2 +-
 .../parse-lanemask-operand-invalid-3.mir      | 13 +++++
 .../AMDGPU/verifier-copyLanemask0.mir         | 58 +++++++++++++++++++
 .../AMDGPU/verifier-copyLanemask1.mir         | 19 ++++++
 .../verifier-copyLanemask0.mir                | 24 --------
 .../verifier-copyLanemask1.mir                | 28 ---------
 llvm/unittests/CodeGen/MachineOperandTest.cpp |  4 +-
 12 files changed, 128 insertions(+), 74 deletions(-)
 create mode 100644 llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-3.mir
 create mode 100644 llvm/test/MachineVerifier/AMDGPU/verifier-copyLanemask0.mir
 create mode 100644 llvm/test/MachineVerifier/AMDGPU/verifier-copyLanemask1.mir
 delete mode 100644 llvm/test/MachineVerifier/verifier-copyLanemask0.mir
 delete mode 100644 llvm/test/MachineVerifier/verifier-copyLanemask1.mir

diff --git a/llvm/docs/MIRLangRef.rst b/llvm/docs/MIRLangRef.rst
index 4e12239e0e68f..f211aff9ea96f 100644
--- a/llvm/docs/MIRLangRef.rst
+++ b/llvm/docs/MIRLangRef.rst
@@ -807,6 +807,19 @@ For an int eq predicate ``ICMP_EQ``, the syntax is:
 
    %2:gpr(s32) = G_ICMP intpred(eq), %0, %1
 
+Lanemask Operands
+^^^^^^^^^^^^^^^^^^
+
+A Lanemask operand is 64-bit unsigned value that holds the lane information 
+corrseponding to the source register operand in the instruction.
+
+For example, the COPY_LANEMASK instruction using this operand would look 
+like:
+
+.. code-block:: text
+
+   $vgpr1 = COPY_LANEMASK $vgpr0, lanemask(00000000000000C0)
+   
 .. TODO: Describe the parsers default behaviour when optional YAML attributes
    are missing.
 .. TODO: Describe the syntax for virtual register YAML definitions.
@@ -819,7 +832,6 @@ For an int eq predicate ``ICMP_EQ``, the syntax is:
 .. TODO: Describe the syntax of the metadata machine operands, and the
    instructions debug location attribute.
 .. TODO: Describe the syntax of the register live out machine operands.
-.. TODO: Describe the syntax of the lanemask machine operands.
 .. TODO: Describe the syntax of the machine memory operands.
 
 Comments
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index afbb3ae4d33d7..187f4dea52eb7 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -1428,9 +1428,10 @@ class MachineInstr
     return getOpcode() == TargetOpcode::BUNDLE;
   }
 
-  bool isCopy() const {
-    return (getOpcode() == TargetOpcode::COPY ||
-            getOpcode() == TargetOpcode::COPY_LANEMASK);
+  bool isCopy() const { return getOpcode() == TargetOpcode::COPY; }
+
+  bool isCopyLanemask() const {
+    return getOpcode() == TargetOpcode::COPY_LANEMASK;
   }
 
   bool isFullCopy() const {
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index 3f7d361f09647..a39d789a61544 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -2421,24 +2421,27 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
     const Register SrcReg = SrcOp.getReg();
     const Register DstReg = DstOp.getReg();
     const LaneBitmask LaneMask = LaneMaskOp.getLaneMask();
+    LaneBitmask SrcMaxLanemask = LaneBitmask::getAll();
 
-    if (!SrcReg.isPhysical() || !DstReg.isPhysical()) {
-      if (!SrcReg.isPhysical()) {
-        report("Copy with lanemask Instruction uses virtual register", &SrcOp,
-               1);
-      }
-      if (!DstReg.isPhysical()) {
-        report("Copy with lanemask Instruction uses virtual register", &DstOp,
-               0);
-      }
-      break;
+    if (DstOp.getSubReg())
+      report("COPY_LANEMASK must use no sub-register index.", &DstOp, 0);
+
+    if (SrcOp.getSubReg())
+      report("COPY_LANEMASK must use no sub-register index.", &SrcOp, 1);
+
+    if (SrcReg.isVirtual()) {
+      SrcMaxLanemask = MRI->getMaxLaneMaskForVReg(SrcReg);
     }
 
     if (LaneMask.none())
-      report("Lanemask takes up the zero value", MI);
+      report("COPY_LANEMASK copies no lanes.", MI);
 
-    if (LaneMask.all())
-      report("Copy Instruction can be used instead of copy with lanemask", MI);
+    // In case of Src as virtual register, all lanes active implies the max
+    // lanemask bits active for that register class, else all bits would be set.
+    if (LaneMask.all() || (SrcMaxLanemask == LaneMask))
+      report(
+          "COPY should be instead of COPY_LANEMASK, as all lanes are copied.",
+          MI);
 
     break;
   }
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-0.mir b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-0.mir
index 5bb397e8bcd08..ded2c5fca5789 100644
--- a/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-0.mir
+++ b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-0.mir
@@ -1,4 +1,4 @@
-# RUN: not llc -mtriple=amdgcn-amd-amdhsa -run-pass=none -verify-machineinstrs %s -o /dev/null 2>&1 | FileCheck %s
+# RUN: not llc -mtriple=amdgcn-amd-amdhsa -run-pass=none -filetype=null %s 2>&1 | FileCheck %s
 
 ---
 name: test_missing_rparen
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-1.mir b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-1.mir
index bb4ca36e29511..d3d3d3526261f 100644
--- a/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-1.mir
+++ b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-1.mir
@@ -1,4 +1,4 @@
-# RUN: not llc -mtriple=amdgcn-amd-amdhsa -run-pass=none -verify-machineinstrs %s -o /dev/null 2>&1 | FileCheck %s
+# RUN: not llc -mtriple=amdgcn-amd-amdhsa -run-pass=none -filetype=null %s 2>&1 | FileCheck %s
 
 ---
 name: test_missing_lparen
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-2.mir b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-2.mir
index fe520056f475c..310051b6bee52 100644
--- a/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-2.mir
+++ b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-2.mir
@@ -1,4 +1,4 @@
-# RUN: not llc -mtriple=amdgcn-amd-amdhsa -run-pass=none -verify-machineinstrs %s -o /dev/null 2>&1 | FileCheck %s
+# RUN: not llc -mtriple=amdgcn-amd-amdhsa -run-pass=none -filetype=null %s 2>&1 | FileCheck %s
 
 ---
 name: test_wrong_lanemask_type
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-3.mir b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-3.mir
new file mode 100644
index 0000000000000..0b4e4d1ef4ffa
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand-invalid-3.mir
@@ -0,0 +1,13 @@
+# RUN: not llc -mtriple=amdgcn-amd-amdhsa -run-pass=none -filetype=null %s 2>&1 | FileCheck %s
+
+---
+name: test_empty_lanemask_type
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0
+
+    ; CHECK: [[@LINE+1]]:45: expected a valid lane mask value. 
+    $vgpr1 = COPY_LANEMASK $vgpr0, lanemask()
+    S_ENDPGM 0
+...
diff --git a/llvm/test/MachineVerifier/AMDGPU/verifier-copyLanemask0.mir b/llvm/test/MachineVerifier/AMDGPU/verifier-copyLanemask0.mir
new file mode 100644
index 0000000000000..e16deadec39fe
--- /dev/null
+++ b/llvm/test/MachineVerifier/AMDGPU/verifier-copyLanemask0.mir
@@ -0,0 +1,58 @@
+# RUN: not --crash llc -o - -mtriple=amdgcn-amd-amdhsa -run-pass=none %s 2>&1 | FileCheck %s
+
+# CHECK: *** Bad machine code: COPY_LANEMASK copies no lanes. ***
+# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
+# CHECK-NEXT: - basic block: %bb.0
+# CHECK-NEXT: - instruction: $vgpr2 = COPY_LANEMASK $vgpr0, lanemask(0x0000000000000000)
+
+# CHECK: *** Bad machine code: COPY should be instead of COPY_LANEMASK, as all lanes are copied. ***
+# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
+# CHECK-NEXT: - basic block: %bb.0
+# CHECK-NEXT: - instruction: $vgpr3 = COPY_LANEMASK $vgpr1, lanemask(0xFFFFFFFFFFFFFFFF)
+
+# CHECK: *** Bad machine code: COPY should be instead of COPY_LANEMASK, as all lanes are copied. ***
+# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
+# CHECK-NEXT: - basic block: %bb.0
+# CHECK-NEXT: - instruction: %1:vgpr_32 = COPY_LANEMASK %0:vgpr_32, lanemask(0x0000000000000003)
+
+# CHECK: *** Bad machine code: COPY should be instead of COPY_LANEMASK, as all lanes are copied. ***
+# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
+# CHECK-NEXT: - basic block: %bb.0
+# CHECK-NEXT: - instruction: %2:vgpr_32 = COPY_LANEMASK %1:vgpr_32, lanemask(0xFFFFFFFFFFFFFFFF)
+
+# CHECK: *** Bad machine code: COPY should be instead of COPY_LANEMASK, as all lanes are copied. ***
+# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
+# CHECK-NEXT: - basic block: %bb.0
+# CHECK-NEXT: - instruction: %3:vreg_64 = COPY_LANEMASK $vgpr4_vgpr5, lanemask(0xFFFFFFFFFFFFFFFF)
+
+# CHECK: *** Bad machine code: COPY should be instead of COPY_LANEMASK, as all lanes are copied. ***
+# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
+# CHECK-NEXT: - basic block: %bb.0
+# CHECK-NEXT: - instruction: $vgpr6_vgpr7 = COPY_LANEMASK %3:vreg_64, lanemask(0x000000000000000F)
+
+# CHECK: *** Bad machine code: COPY_LANEMASK must use no sub-register index. ***
+# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
+# CHECK-NEXT: - basic block: %bb.0
+# CHECK-NEXT: - instruction: %4:vgpr_32 = COPY_LANEMASK %3.sub0:vreg_64, lanemask(0x0000000000000003)
+
+# NOTE: For physical register, as we don't have way to obtain their maximal lanemask directly, so 
+# COPY_LANEMASK is illegal only if all lane bits are active irrespective.
+
+---
+name: test_copy_lanemask_instruction_0
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0, $vgpr1
+
+    %0:vgpr_32 = IMPLICIT_DEF
+    $vgpr2 = COPY_LANEMASK $vgpr0, lanemask(0)
+    $vgpr3 = COPY_LANEMASK $vgpr1, lanemask(0xFFFFFFFFFFFFFFFF)
+    $vgpr4_vgpr5 = COPY_LANEMASK $vgpr2_vgpr3, lanemask(0x000000000000000F)
+    %1:vgpr_32 = COPY_LANEMASK %0, lanemask(0x0000000000000003)
+    %2:vgpr_32 = COPY_LANEMASK %1, lanemask(0xFFFFFFFFFFFFFFFF)
+    %3:vreg_64 = COPY_LANEMASK $vgpr4_vgpr5, lanemask(0xFFFFFFFFFFFFFFFF)
+    $vgpr6_vgpr7 = COPY_LANEMASK %3, lanemask(0x000000000000000F)
+    %4:vgpr_32 = COPY_LANEMASK %3.sub0, lanemask(0x0000000000000003)
+    S_ENDPGM 0
+...
diff --git a/llvm/test/MachineVerifier/AMDGPU/verifier-copyLanemask1.mir b/llvm/test/MachineVerifier/AMDGPU/verifier-copyLanemask1.mir
new file mode 100644
index 0000000000000..d4338da717ba2
--- /dev/null
+++ b/llvm/test/MachineVerifier/AMDGPU/verifier-copyLanemask1.mir
@@ -0,0 +1,19 @@
+# RUN: not --crash llc -o - -mtriple=amdgcn-amd-amdhsa -run-pass=none %s 2>&1 | FileCheck %s
+
+# CHECK: *** Bad machine code: Too few operands ***
+# CHECK-NEXT: - function:    test_copy_lanemask_instruction_1
+# CHECK-NEXT: - basic block: %bb.0 
+# CHECK-NEXT: - instruction: $vgpr2 = COPY_LANEMASK %0:vgpr_32
+
+---
+name: test_copy_lanemask_instruction_1
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0, $vgpr1
+
+    %0:vgpr_32 = COPY $vgpr0
+    $vgpr2 = COPY_LANEMASK %0
+    S_ENDPGM 0
+...
+
diff --git a/llvm/test/MachineVerifier/verifier-copyLanemask0.mir b/llvm/test/MachineVerifier/verifier-copyLanemask0.mir
deleted file mode 100644
index 88d368c98ba32..0000000000000
--- a/llvm/test/MachineVerifier/verifier-copyLanemask0.mir
+++ /dev/null
@@ -1,24 +0,0 @@
-# RUN: not --crash llc -o - -mtriple=amdgcn-amd-amdhsa -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
-# REQUIRES: amdgpu-registered-target
-
-# CHECK: *** Bad machine code: Lanemask takes up the zero value ***
-# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
-# CHECK-NEXT: - basic block: %bb.0
-# CHECK-NEXT: - instruction: $vgpr2 = COPY_LANEMASK $vgpr0, lanemask(0x0000000000000000)
-
-# CHECK: *** Bad machine code: Copy Instruction can be used instead of copy with lanemask ***
-# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
-# CHECK-NEXT: - basic block: %bb.0
-# CHECK-NEXT: - instruction: $vgpr3 = COPY_LANEMASK $vgpr1, lanemask(0xFFFFFFFFFFFFFFFF)
-
----
-name: test_copy_lanemask_instruction_0
-tracksRegLiveness: true
-body:             |
-  bb.0:
-    liveins: $vgpr0, $vgpr1
-
-    $vgpr2 = COPY_LANEMASK $vgpr0, lanemask(0)
-    $vgpr3 = COPY_LANEMASK $vgpr1, lanemask(0xFFFFFFFFFFFFFFFF)
-    S_ENDPGM 0
-...
diff --git a/llvm/test/MachineVerifier/verifier-copyLanemask1.mir b/llvm/test/MachineVerifier/verifier-copyLanemask1.mir
deleted file mode 100644
index b4386dcae7760..0000000000000
--- a/llvm/test/MachineVerifier/verifier-copyLanemask1.mir
+++ /dev/null
@@ -1,28 +0,0 @@
-# RUN: not --crash llc -o - -mtriple=amdgcn-amd-amdhsa -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
-# REQUIRES: amdgpu-registered-target
-
-# CHECK: *** Bad machine code: Copy with lanemask Instruction uses virtual register ***
-# CHECK-NEXT: - function:    test_copy_lanemask_instruction_1
-# CHECK-NEXT: - basic block: %bb.0 
-# CHECK-NEXT: - instruction: $vgpr2 = COPY_LANEMASK %0:vgpr_32, lanemask(0x0000000000000018)
-# CHECK-NEXT: - operand 1:   %0:vgpr_32
-
-# CHECK: *** Bad machine code: Copy with lanemask Instruction uses virtual register ***
-# CHECK-NEXT: - function:    test_copy_lanemask_instruction_1
-# CHECK-NEXT: - basic block: %bb.0 
-# CHECK-NEXT: - instruction: %1:vgpr_32 = COPY_LANEMASK $vgpr1, lanemask(0x00000000000000FF)
-# CHECK-NEXT: - operand 0:   %1:vgpr_32
-
----
-name: test_copy_lanemask_instruction_1
-tracksRegLiveness: true
-body:             |
-  bb.0:
-    liveins: $vgpr0, $vgpr1
-
-    %0:vgpr_32 = COPY $vgpr0
-    $vgpr2 = COPY_LANEMASK %0, lanemask(24)
-    %1:vgpr_32 = COPY_LANEMASK $vgpr1, lanemask(0x000000000000FF)
-    S_ENDPGM 0
-...
-
diff --git a/llvm/unittests/CodeGen/MachineOperandTest.cpp b/llvm/unittests/CodeGen/MachineOperandTest.cpp
index dcd731e5cb896..e3c1512af30ef 100644
--- a/llvm/unittests/CodeGen/MachineOperandTest.cpp
+++ b/llvm/unittests/CodeGen/MachineOperandTest.cpp
@@ -296,13 +296,13 @@ TEST(MachineOperandTest, PrintLaneMask) {
   // Checking some preconditions on the newly created
   // MachineOperand.
   ASSERT_TRUE(MO.isLaneMask());
-  ASSERT_TRUE(MO.getLaneMask() == LaneMask);
+  ASSERT_EQ(MO.getLaneMask(), LaneMask);
 
   std::string str;
   // Print a MachineOperand that is lanemask as in HEX representation.
   raw_string_ostream OS(str);
   MO.print(OS, /*TRI=*/nullptr);
-  ASSERT_TRUE(str == "lanemask(0x000000000000000C)");
+  ASSERT_EQ(str, "lanemask(0x000000000000000C)");
 }
 
 TEST(MachineOperandTest, PrintRegisterLiveOut) {

>From 78fc32c4f294d261b9a7bb426b0420e8e378bb33 Mon Sep 17 00:00:00 2001
From: vikashgu <Vikash.Gupta at amd.com>
Date: Mon, 18 Aug 2025 10:25:55 +0000
Subject: [PATCH 5/6] Added support to find SrcLaneMask for PhysReg & updated
 LIT tests.

---
 llvm/docs/MIRLangRef.rst                      |  2 +-
 llvm/include/llvm/MC/LaneBitmask.h            |  1 +
 llvm/lib/CodeGen/MachineVerifier.cpp          | 26 ++++----
 .../MIR/AMDGPU/parse-lanemask-operand.mir     |  4 +-
 .../AMDGPU/verifier-copyLanemask0.mir         | 59 ++++++-------------
 5 files changed, 37 insertions(+), 55 deletions(-)

diff --git a/llvm/docs/MIRLangRef.rst b/llvm/docs/MIRLangRef.rst
index f211aff9ea96f..93370e649a0f5 100644
--- a/llvm/docs/MIRLangRef.rst
+++ b/llvm/docs/MIRLangRef.rst
@@ -818,7 +818,7 @@ like:
 
 .. code-block:: text
 
-   $vgpr1 = COPY_LANEMASK $vgpr0, lanemask(00000000000000C0)
+   $vgpr1 = COPY_LANEMASK $vgpr0, lanemask(0x00000000000000C0)
    
 .. TODO: Describe the parsers default behaviour when optional YAML attributes
    are missing.
diff --git a/llvm/include/llvm/MC/LaneBitmask.h b/llvm/include/llvm/MC/LaneBitmask.h
index c06ca7dd5b8fc..b487947dcac96 100644
--- a/llvm/include/llvm/MC/LaneBitmask.h
+++ b/llvm/include/llvm/MC/LaneBitmask.h
@@ -49,6 +49,7 @@ namespace llvm {
     constexpr bool operator== (LaneBitmask M) const { return Mask == M.Mask; }
     constexpr bool operator!= (LaneBitmask M) const { return Mask != M.Mask; }
     constexpr bool operator< (LaneBitmask M)  const { return Mask < M.Mask; }
+    constexpr bool operator<=(LaneBitmask M) const { return Mask <= M.Mask; }
     constexpr bool none() const { return Mask == 0; }
     constexpr bool any()  const { return Mask != 0; }
     constexpr bool all()  const { return ~Mask == 0; }
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index a39d789a61544..4da467dff1a1a 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -2424,24 +2424,26 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
     LaneBitmask SrcMaxLanemask = LaneBitmask::getAll();
 
     if (DstOp.getSubReg())
-      report("COPY_LANEMASK must use no sub-register index.", &DstOp, 0);
+      report("COPY_LANEMASK must not use a subregister index", &DstOp, 0);
 
     if (SrcOp.getSubReg())
-      report("COPY_LANEMASK must use no sub-register index.", &SrcOp, 1);
+      report("COPY_LANEMASK must not use a subregister index", &SrcOp, 1);
 
-    if (SrcReg.isVirtual()) {
+    if (LaneMask.none())
+      report("COPY_LANEMASK must read at least one lane", MI);
+
+    if (SrcReg.isPhysical()) {
+      const TargetRegisterClass *SrcRC = TRI->getMinimalPhysRegClass(SrcReg);
+      if (SrcRC)
+        SrcMaxLanemask = SrcRC->getLaneMask();
+    } else {
       SrcMaxLanemask = MRI->getMaxLaneMaskForVReg(SrcReg);
     }
 
-    if (LaneMask.none())
-      report("COPY_LANEMASK copies no lanes.", MI);
-
-    // In case of Src as virtual register, all lanes active implies the max
-    // lanemask bits active for that register class, else all bits would be set.
-    if (LaneMask.all() || (SrcMaxLanemask == LaneMask))
-      report(
-          "COPY should be instead of COPY_LANEMASK, as all lanes are copied.",
-          MI);
+    // If LaneMask is equal to OR greater than the SrcMaxLanemask, it
+    // impliess COPY_LANEMASK is trying to copy all lanes.
+    if (SrcMaxLanemask <= LaneMask)
+      report("COPY_LANEMASK cannot read all lanes", MI);
 
     break;
   }
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand.mir b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand.mir
index 92c58826a5031..066bc8e79a56e 100644
--- a/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand.mir
+++ b/llvm/test/CodeGen/MIR/AMDGPU/parse-lanemask-operand.mir
@@ -3,7 +3,7 @@
 # This test checks for the correctness of the MIR parser for lanemask
 
 # CHECK-LABEL: name: test_lanemask_operand
-# CHECK: COPY_LANEMASK $vgpr0, lanemask(0x0000000000000020)
+# CHECK: COPY_LANEMASK $vgpr0, lanemask(0x0000000000000002)
 ---
 name: test_lanemask_operand
 tracksRegLiveness: true
@@ -11,7 +11,7 @@ body:             |
   bb.0:
     liveins: $vgpr0
 
-    $vgpr1 = COPY_LANEMASK $vgpr0, lanemask(32)
+    $vgpr1 = COPY_LANEMASK $vgpr0, lanemask(2)
     S_ENDPGM 0
 ...
 
diff --git a/llvm/test/MachineVerifier/AMDGPU/verifier-copyLanemask0.mir b/llvm/test/MachineVerifier/AMDGPU/verifier-copyLanemask0.mir
index e16deadec39fe..f976ffa24a23a 100644
--- a/llvm/test/MachineVerifier/AMDGPU/verifier-copyLanemask0.mir
+++ b/llvm/test/MachineVerifier/AMDGPU/verifier-copyLanemask0.mir
@@ -1,43 +1,5 @@
 # RUN: not --crash llc -o - -mtriple=amdgcn-amd-amdhsa -run-pass=none %s 2>&1 | FileCheck %s
 
-# CHECK: *** Bad machine code: COPY_LANEMASK copies no lanes. ***
-# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
-# CHECK-NEXT: - basic block: %bb.0
-# CHECK-NEXT: - instruction: $vgpr2 = COPY_LANEMASK $vgpr0, lanemask(0x0000000000000000)
-
-# CHECK: *** Bad machine code: COPY should be instead of COPY_LANEMASK, as all lanes are copied. ***
-# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
-# CHECK-NEXT: - basic block: %bb.0
-# CHECK-NEXT: - instruction: $vgpr3 = COPY_LANEMASK $vgpr1, lanemask(0xFFFFFFFFFFFFFFFF)
-
-# CHECK: *** Bad machine code: COPY should be instead of COPY_LANEMASK, as all lanes are copied. ***
-# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
-# CHECK-NEXT: - basic block: %bb.0
-# CHECK-NEXT: - instruction: %1:vgpr_32 = COPY_LANEMASK %0:vgpr_32, lanemask(0x0000000000000003)
-
-# CHECK: *** Bad machine code: COPY should be instead of COPY_LANEMASK, as all lanes are copied. ***
-# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
-# CHECK-NEXT: - basic block: %bb.0
-# CHECK-NEXT: - instruction: %2:vgpr_32 = COPY_LANEMASK %1:vgpr_32, lanemask(0xFFFFFFFFFFFFFFFF)
-
-# CHECK: *** Bad machine code: COPY should be instead of COPY_LANEMASK, as all lanes are copied. ***
-# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
-# CHECK-NEXT: - basic block: %bb.0
-# CHECK-NEXT: - instruction: %3:vreg_64 = COPY_LANEMASK $vgpr4_vgpr5, lanemask(0xFFFFFFFFFFFFFFFF)
-
-# CHECK: *** Bad machine code: COPY should be instead of COPY_LANEMASK, as all lanes are copied. ***
-# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
-# CHECK-NEXT: - basic block: %bb.0
-# CHECK-NEXT: - instruction: $vgpr6_vgpr7 = COPY_LANEMASK %3:vreg_64, lanemask(0x000000000000000F)
-
-# CHECK: *** Bad machine code: COPY_LANEMASK must use no sub-register index. ***
-# CHECK-NEXT: - function:    test_copy_lanemask_instruction_0
-# CHECK-NEXT: - basic block: %bb.0
-# CHECK-NEXT: - instruction: %4:vgpr_32 = COPY_LANEMASK %3.sub0:vreg_64, lanemask(0x0000000000000003)
-
-# NOTE: For physical register, as we don't have way to obtain their maximal lanemask directly, so 
-# COPY_LANEMASK is illegal only if all lane bits are active irrespective.
-
 ---
 name: test_copy_lanemask_instruction_0
 tracksRegLiveness: true
@@ -46,13 +8,30 @@ body:             |
     liveins: $vgpr0, $vgpr1
 
     %0:vgpr_32 = IMPLICIT_DEF
+
+    ; CHECK: *** Bad machine code: COPY_LANEMASK must read at least one lane ***
     $vgpr2 = COPY_LANEMASK $vgpr0, lanemask(0)
+
+    ; CHECK: *** Bad machine code: COPY_LANEMASK cannot read all lanes ***
     $vgpr3 = COPY_LANEMASK $vgpr1, lanemask(0xFFFFFFFFFFFFFFFF)
+
+    ; CHECK: *** Bad machine code: COPY_LANEMASK cannot read all lanes ***
     $vgpr4_vgpr5 = COPY_LANEMASK $vgpr2_vgpr3, lanemask(0x000000000000000F)
+
+    ; CHECK: *** Bad machine code: COPY_LANEMASK cannot read all lanes ***
     %1:vgpr_32 = COPY_LANEMASK %0, lanemask(0x0000000000000003)
-    %2:vgpr_32 = COPY_LANEMASK %1, lanemask(0xFFFFFFFFFFFFFFFF)
-    %3:vreg_64 = COPY_LANEMASK $vgpr4_vgpr5, lanemask(0xFFFFFFFFFFFFFFFF)
+
+    ; CHECK: *** Bad machine code: COPY_LANEMASK cannot read all lanes ***
+    %2:vgpr_32 = COPY_LANEMASK %1, lanemask(0x0000000FFFFFFFFF)
+
+    ; CHECK: *** Bad machine code: COPY_LANEMASK cannot read all lanes ***
+    %3:vreg_64 = COPY_LANEMASK $vgpr4_vgpr5, lanemask(0x00000000000000FF)
+
+    ; CHECK: *** Bad machine code: COPY_LANEMASK cannot read all lanes ***
     $vgpr6_vgpr7 = COPY_LANEMASK %3, lanemask(0x000000000000000F)
+
+    ; CHECK: *** Bad machine code: COPY_LANEMASK must not use a subregister index ***
     %4:vgpr_32 = COPY_LANEMASK %3.sub0, lanemask(0x0000000000000003)
+
     S_ENDPGM 0
 ...

>From 333ab5d68e56b48612db85b1058ca75173318c6e Mon Sep 17 00:00:00 2001
From: vikashgu <Vikash.Gupta at amd.com>
Date: Fri, 22 Aug 2025 06:57:15 +0000
Subject: [PATCH 6/6] Updated the MIRLangRef document & COPY_LANEMASK defintion
 in comments.

---
 llvm/docs/MIRLangRef.rst                    | 10 ++++++----
 llvm/include/llvm/CodeGen/MachineInstr.h    |  4 +++-
 llvm/include/llvm/Support/TargetOpcodes.def |  4 ++--
 3 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/llvm/docs/MIRLangRef.rst b/llvm/docs/MIRLangRef.rst
index 93370e649a0f5..8af3f0cadfd38 100644
--- a/llvm/docs/MIRLangRef.rst
+++ b/llvm/docs/MIRLangRef.rst
@@ -810,11 +810,13 @@ For an int eq predicate ``ICMP_EQ``, the syntax is:
 Lanemask Operands
 ^^^^^^^^^^^^^^^^^^
 
-A Lanemask operand is 64-bit unsigned value that holds the lane information 
-corrseponding to the source register operand in the instruction.
+A Lanemask operand is 64-bit unsigned value that can the store lane information 
+for a register operand in the instruction. It can be used as many times as needed
+in an instruction, with one (atleast) or more register operands associated with it.
 
-For example, the COPY_LANEMASK instruction using this operand would look 
-like:
+
+For example, the COPY_LANEMASK instruction uses this operand to copy only active 
+lanes(of the source register) in the mask. The syntax for it would look:
 
 .. code-block:: text
 
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index 187f4dea52eb7..150959d49a5bd 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -1428,7 +1428,9 @@ class MachineInstr
     return getOpcode() == TargetOpcode::BUNDLE;
   }
 
-  bool isCopy() const { return getOpcode() == TargetOpcode::COPY; }
+  bool isCopy() const {
+    return getOpcode() == TargetOpcode::COPY;
+  }
 
   bool isCopyLanemask() const {
     return getOpcode() == TargetOpcode::COPY_LANEMASK;
diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def
index 570ed3ec30491..ec86db3a4489b 100644
--- a/llvm/include/llvm/Support/TargetOpcodes.def
+++ b/llvm/include/llvm/Support/TargetOpcodes.def
@@ -115,8 +115,8 @@ HANDLE_TARGET_OPCODE(REG_SEQUENCE)
 HANDLE_TARGET_OPCODE(COPY)
 
 /// COPY_LANEMASK - Target-independent register copy for active mask in 
-/// register as represented by the lanemask. This instruction can only be 
-/// used to copy between physical registers.
+/// register as represented by the lanemask. This instruction cannot be 
+/// only used to copy from the subregisters of virtual registers.
 HANDLE_TARGET_OPCODE(COPY_LANEMASK)
 
 /// BUNDLE - This instruction represents an instruction bundle. Instructions



More information about the llvm-commits mailing list