Skip to content

Commit cd86b2a

Browse files
authored
[CodeGen] Add MO_LaneMask type and a new COPY_LANEMASK instruction (#151944)
Introduce MO_LaneMask as new machine operand type. This can be used to hold liveness infomation at sub-register granularity for register-type operands. We also introduce a new COPY_LANEMASK instruction that uses MO_lanemask operand to perform partial copy from source register opernad. One such use case of MO_LaneMask can be seen in #151123, where it can be used to store live regUnits information corresponding to the source register of the COPY instructions, later can be used during CopyPhysReg expansion.
1 parent ae4289f commit cd86b2a

27 files changed

+298
-8
lines changed

llvm/docs/MIRLangRef.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,22 @@ For an int eq predicate ``ICMP_EQ``, the syntax is:
807807
808808
%2:gpr(s32) = G_ICMP intpred(eq), %0, %1
809809
810+
LaneMask Operands
811+
^^^^^^^^^^^^^^^^^
812+
813+
A LaneMask operand contains a LaneBitmask struct representing the covering of a
814+
register with sub-registers. Instructions typically associate a LaneMask operand
815+
with one or more Register operands, and use it to represent sub-register
816+
granularity information like liveness for those associated Register operands.
817+
818+
819+
For example, the COPY_LANEMASK instruction uses this operand to copy only active
820+
lanes (of the source register) in the mask. The syntax for it would look like:
821+
822+
.. code-block:: text
823+
824+
$vgpr1 = COPY_LANEMASK $vgpr0, lanemask(0x00000000000000C0)
825+
810826
.. TODO: Describe the parsers default behaviour when optional YAML attributes
811827
are missing.
812828
.. TODO: Describe the syntax for virtual register YAML definitions.

llvm/include/llvm/CodeGen/MIR2Vec.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ class MIRVocabulary {
139139
"FrameIndex", "ConstantPoolIndex", "TargetIndex", "JumpTableIndex",
140140
"ExternalSymbol", "GlobalAddress", "BlockAddress", "RegisterMask",
141141
"RegisterLiveOut", "Metadata", "MCSymbol", "CFIIndex",
142-
"IntrinsicID", "Predicate", "ShuffleMask"};
142+
"IntrinsicID", "Predicate", "ShuffleMask", "LaneMask"};
143143
static_assert(std::size(CommonOperandNames) == MachineOperand::MO_Last - 1 &&
144144
"Common operand names size changed, update accordingly");
145145

llvm/include/llvm/CodeGen/MachineInstr.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,6 +1451,10 @@ class MachineInstr
14511451
return getOpcode() == TargetOpcode::COPY;
14521452
}
14531453

1454+
bool isCopyLaneMask() const {
1455+
return getOpcode() == TargetOpcode::COPY_LANEMASK;
1456+
}
1457+
14541458
bool isFullCopy() const {
14551459
return isCopy() && !getOperand(0).getSubReg() && !getOperand(1).getSubReg();
14561460
}
@@ -1484,6 +1488,7 @@ class MachineInstr
14841488
case TargetOpcode::PHI:
14851489
case TargetOpcode::G_PHI:
14861490
case TargetOpcode::COPY:
1491+
case TargetOpcode::COPY_LANEMASK:
14871492
case TargetOpcode::INSERT_SUBREG:
14881493
case TargetOpcode::SUBREG_TO_REG:
14891494
case TargetOpcode::REG_SEQUENCE:

llvm/include/llvm/CodeGen/MachineInstrBuilder.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,11 @@ class MachineInstrBuilder {
307307
return *this;
308308
}
309309

310+
const MachineInstrBuilder &addLaneMask(LaneBitmask LaneMask) const {
311+
MI->addOperand(*MF, MachineOperand::CreateLaneMask(LaneMask));
312+
return *this;
313+
}
314+
310315
const MachineInstrBuilder &addSym(MCSymbol *Sym,
311316
unsigned char TargetFlags = 0) const {
312317
MI->addOperand(*MF, MachineOperand::CreateMCSymbol(Sym, TargetFlags));

llvm/include/llvm/CodeGen/MachineOperand.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "llvm/ADT/DenseMapInfo.h"
1717
#include "llvm/CodeGen/Register.h"
1818
#include "llvm/IR/Intrinsics.h"
19+
#include "llvm/MC/LaneBitmask.h"
1920
#include "llvm/Support/Compiler.h"
2021
#include <cassert>
2122

@@ -69,7 +70,8 @@ class MachineOperand {
6970
MO_Predicate, ///< Generic predicate for ISel
7071
MO_ShuffleMask, ///< Other IR Constant for ISel (shuffle masks)
7172
MO_DbgInstrRef, ///< Integer indices referring to an instruction+operand
72-
MO_Last = MO_DbgInstrRef
73+
MO_LaneMask, ///< Mask to represent active parts of registers
74+
MO_Last = MO_LaneMask
7375
};
7476

7577
private:
@@ -178,6 +180,7 @@ class MachineOperand {
178180
Intrinsic::ID IntrinsicID; // For MO_IntrinsicID.
179181
unsigned Pred; // For MO_Predicate
180182
ArrayRef<int> ShuffleMask; // For MO_ShuffleMask
183+
LaneBitmask LaneMask; // For MO_LaneMask
181184

182185
struct { // For MO_Register.
183186
// Register number is in SmallContents.RegNo.
@@ -360,6 +363,7 @@ class MachineOperand {
360363
bool isIntrinsicID() const { return OpKind == MO_IntrinsicID; }
361364
bool isPredicate() const { return OpKind == MO_Predicate; }
362365
bool isShuffleMask() const { return OpKind == MO_ShuffleMask; }
366+
bool isLaneMask() const { return OpKind == MO_LaneMask; }
363367
//===--------------------------------------------------------------------===//
364368
// Accessors for Register Operands
365369
//===--------------------------------------------------------------------===//
@@ -624,6 +628,11 @@ class MachineOperand {
624628
return Contents.ShuffleMask;
625629
}
626630

631+
LaneBitmask getLaneMask() const {
632+
assert(isLaneMask() && "Wrong MachineOperand accessor");
633+
return Contents.LaneMask;
634+
}
635+
627636
/// Return the offset from the symbol in this operand. This always returns 0
628637
/// for ExternalSymbol operands.
629638
int64_t getOffset() const {
@@ -992,6 +1001,12 @@ class MachineOperand {
9921001
return Op;
9931002
}
9941003

1004+
static MachineOperand CreateLaneMask(LaneBitmask LaneMask) {
1005+
MachineOperand Op(MachineOperand::MO_LaneMask);
1006+
Op.Contents.LaneMask = LaneMask;
1007+
return Op;
1008+
}
1009+
9951010
friend class MachineInstr;
9961011
friend class MachineRegisterInfo;
9971012

llvm/include/llvm/Support/TargetOpcodes.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ HANDLE_TARGET_OPCODE(REG_SEQUENCE)
114114
/// used to copy between subregisters of virtual registers.
115115
HANDLE_TARGET_OPCODE(COPY)
116116

117+
/// COPY_LANEMASK - Target-independent partial register copy. The laneMask
118+
/// operand indicates which parts of the source register are copied to the
119+
/// destination. Other parts of the destination are undefined. It does not
120+
/// support copy between virtual registers having subregister indices.
121+
HANDLE_TARGET_OPCODE(COPY_LANEMASK)
122+
117123
/// BUNDLE - This instruction represents an instruction bundle. Instructions
118124
/// which immediately follow a BUNDLE instruction which are marked with
119125
/// 'InsideBundle' flag are inside the bundle.

llvm/include/llvm/Target/Target.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,6 +1352,13 @@ def COPY : StandardPseudoInstruction {
13521352
let isAsCheapAsAMove = true;
13531353
let hasNoSchedulingInfo = false;
13541354
}
1355+
def COPY_LANEMASK : StandardPseudoInstruction {
1356+
let OutOperandList = (outs unknown:$dst);
1357+
let InOperandList = (ins unknown:$src, unknown:$lanemask);
1358+
let AsmString = "";
1359+
let hasSideEffects = false;
1360+
let isAsCheapAsAMove = true;
1361+
}
13551362
def BUNDLE : StandardPseudoInstruction {
13561363
let OutOperandList = (outs);
13571364
let InOperandList = (ins variable_ops);

llvm/lib/CodeGen/MIRParser/MILexer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
266266
.Case("constant-pool", MIToken::kw_constant_pool)
267267
.Case("call-entry", MIToken::kw_call_entry)
268268
.Case("custom", MIToken::kw_custom)
269+
.Case("lanemask", MIToken::kw_lanemask)
269270
.Case("liveout", MIToken::kw_liveout)
270271
.Case("landing-pad", MIToken::kw_landing_pad)
271272
.Case("inlineasm-br-indirect-target",

llvm/lib/CodeGen/MIRParser/MILexer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ struct MIToken {
122122
kw_constant_pool,
123123
kw_call_entry,
124124
kw_custom,
125+
kw_lanemask,
125126
kw_liveout,
126127
kw_landing_pad,
127128
kw_inlineasm_br_indirect_target,

llvm/lib/CodeGen/MIRParser/MIParser.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@ class MIParser {
496496
bool parseTargetIndexOperand(MachineOperand &Dest);
497497
bool parseDbgInstrRefOperand(MachineOperand &Dest);
498498
bool parseCustomRegisterMaskOperand(MachineOperand &Dest);
499+
bool parseLaneMaskOperand(MachineOperand &Dest);
499500
bool parseLiveoutRegisterMaskOperand(MachineOperand &Dest);
500501
bool parseMachineOperand(const unsigned OpCode, const unsigned OpIdx,
501502
MachineOperand &Dest,
@@ -2886,6 +2887,31 @@ bool MIParser::parseCustomRegisterMaskOperand(MachineOperand &Dest) {
28862887
return false;
28872888
}
28882889

2890+
bool MIParser::parseLaneMaskOperand(MachineOperand &Dest) {
2891+
assert(Token.is(MIToken::kw_lanemask));
2892+
2893+
lex();
2894+
if (expectAndConsume(MIToken::lparen))
2895+
return true;
2896+
2897+
// Parse lanemask.
2898+
if (Token.isNot(MIToken::IntegerLiteral) && Token.isNot(MIToken::HexLiteral))
2899+
return error("expected a valid lane mask value");
2900+
static_assert(sizeof(LaneBitmask::Type) == sizeof(uint64_t),
2901+
"Use correct get-function for lane mask.");
2902+
LaneBitmask::Type V;
2903+
if (getUint64(V))
2904+
return true;
2905+
LaneBitmask LaneMask(V);
2906+
lex();
2907+
2908+
if (expectAndConsume(MIToken::rparen))
2909+
return true;
2910+
2911+
Dest = MachineOperand::CreateLaneMask(LaneMask);
2912+
return false;
2913+
}
2914+
28892915
bool MIParser::parseLiveoutRegisterMaskOperand(MachineOperand &Dest) {
28902916
assert(Token.is(MIToken::kw_liveout));
28912917
uint32_t *Mask = MF.allocateRegMask();
@@ -2986,6 +3012,8 @@ bool MIParser::parseMachineOperand(const unsigned OpCode, const unsigned OpIdx,
29863012
return parseIntrinsicOperand(Dest);
29873013
case MIToken::kw_target_index:
29883014
return parseTargetIndexOperand(Dest);
3015+
case MIToken::kw_lanemask:
3016+
return parseLaneMaskOperand(Dest);
29893017
case MIToken::kw_liveout:
29903018
return parseLiveoutRegisterMaskOperand(Dest);
29913019
case MIToken::kw_floatpred:

0 commit comments

Comments
 (0)