From 4c7f52d999740d2499ccf3270f984ddb09292d34 Mon Sep 17 00:00:00 2001 From: vikashgu Date: Mon, 4 Aug 2025 11:04:28 +0000 Subject: [PATCH 1/3] [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 @@ -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 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(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 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 Date: Wed, 6 Aug 2025 11:15:38 +0000 Subject: [PATCH 2/3] [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 Date: Wed, 6 Aug 2025 11:54:12 +0000 Subject: [PATCH 3/3] 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),