Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions llvm/docs/MIRLangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,22 @@ For an int eq predicate ``ICMP_EQ``, the syntax is:

%2:gpr(s32) = G_ICMP intpred(eq), %0, %1

LaneMask Operands
^^^^^^^^^^^^^^^^^

A LaneMask operand contains a LaneBitmask struct representing the covering of a
register with sub-registers. Instructions typically associate a LaneMask operand
with one or more Register operands, and use it to represent sub-register
granularity information like liveness for those associated Register operands.


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 like:

.. code-block:: text

$vgpr1 = COPY_LANEMASK $vgpr0, lanemask(0x00000000000000C0)

.. TODO: Describe the parsers default behaviour when optional YAML attributes
are missing.
.. TODO: Describe the syntax for virtual register YAML definitions.
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/CodeGen/MIR2Vec.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class MIRVocabulary {
"FrameIndex", "ConstantPoolIndex", "TargetIndex", "JumpTableIndex",
"ExternalSymbol", "GlobalAddress", "BlockAddress", "RegisterMask",
"RegisterLiveOut", "Metadata", "MCSymbol", "CFIIndex",
"IntrinsicID", "Predicate", "ShuffleMask"};
"IntrinsicID", "Predicate", "ShuffleMask", "LaneMask"};
static_assert(std::size(CommonOperandNames) == MachineOperand::MO_Last - 1 &&
"Common operand names size changed, update accordingly");

Expand Down
5 changes: 5 additions & 0 deletions llvm/include/llvm/CodeGen/MachineInstr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1451,6 +1451,10 @@ class MachineInstr
return getOpcode() == TargetOpcode::COPY;
}

bool isCopyLaneMask() const {
return getOpcode() == TargetOpcode::COPY_LANEMASK;
}

bool isFullCopy() const {
return isCopy() && !getOperand(0).getSubReg() && !getOperand(1).getSubReg();
}
Expand Down Expand Up @@ -1484,6 +1488,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:
Expand Down
5 changes: 5 additions & 0 deletions llvm/include/llvm/CodeGen/MachineInstrBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,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));
Expand Down
17 changes: 16 additions & 1 deletion llvm/include/llvm/CodeGen/MachineOperand.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
//===--------------------------------------------------------------------===//
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -992,6 +1001,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;

Expand Down
6 changes: 6 additions & 0 deletions llvm/include/llvm/Support/TargetOpcodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ HANDLE_TARGET_OPCODE(REG_SEQUENCE)
/// used to copy between subregisters of virtual registers.
HANDLE_TARGET_OPCODE(COPY)

/// COPY_LANEMASK - Target-independent partial register copy. The laneMask
/// operand indicates which parts of the source register are copied to the
/// destination. Other parts of the destination are undefined. It does not
/// support copy between virtual registers having subregister indices.
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.
Expand Down
7 changes: 7 additions & 0 deletions llvm/include/llvm/Target/Target.td
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,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);
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/MIRParser/MILexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/MIRParser/MILexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
28 changes: 28 additions & 0 deletions llvm/lib/CodeGen/MIRParser/MIParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -2886,6 +2887,31 @@ bool MIParser::parseCustomRegisterMaskOperand(MachineOperand &Dest) {
return false;
}

bool MIParser::parseLaneMaskOperand(MachineOperand &Dest) {
assert(Token.is(MIToken::kw_lanemask));

lex();
if (expectAndConsume(MIToken::lparen))
return true;

// Parse lanemask.
if (Token.isNot(MIToken::IntegerLiteral) && Token.isNot(MIToken::HexLiteral))
return error("expected a valid lane mask value");
static_assert(sizeof(LaneBitmask::Type) == sizeof(uint64_t),
"Use correct get-function for lane mask.");
LaneBitmask::Type V;
if (getUint64(V))
return true;
LaneBitmask LaneMask(V);
lex();

if (expectAndConsume(MIToken::rparen))
return true;

Dest = MachineOperand::CreateLaneMask(LaneMask);
return false;
}

bool MIParser::parseLiveoutRegisterMaskOperand(MachineOperand &Dest) {
assert(Token.is(MIToken::kw_liveout));
uint32_t *Mask = MF.allocateRegMask();
Expand Down Expand Up @@ -2986,6 +3012,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:
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/CodeGen/MIRPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,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);
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/CodeGen/MIRVRegNamerUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,12 @@ std::string VRegRenamer::getInstructionOpcodeHash(MachineInstr &MI) {
// is contributing to a hash collision but there's enough information
// (Opcodes,other registers etc) that this will likely not be a problem.

// TODO: Handle the following Index/ID/Predicate cases. They can
// TODO: Handle the following Index/ID/Predicate/LaneMask cases. They can
// be hashed on in a stable manner.
case MachineOperand::MO_CFIIndex:
case MachineOperand::MO_IntrinsicID:
case MachineOperand::MO_Predicate:
case MachineOperand::MO_LaneMask:

// In the cases below we havn't found a way to produce an artifact that will
// result in a stable hash, in most cases because they are pointers. We want
Expand Down
19 changes: 16 additions & 3 deletions llvm/lib/CodeGen/MachineOperand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,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");
}
Expand Down Expand Up @@ -460,6 +462,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");
}
Expand Down Expand Up @@ -1019,11 +1024,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;
Expand All @@ -1038,6 +1043,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)
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/CodeGen/MachineStableHash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,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());
Expand Down
40 changes: 40 additions & 0 deletions llvm/lib/CodeGen/MachineVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2428,6 +2428,46 @@ 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 LaneBitmask LaneMask = LaneMaskOp.getLaneMask();
LaneBitmask SrcMaxLaneMask = LaneBitmask::getAll();

if (DstOp.getSubReg())
report("COPY_LANEMASK must not use a subregister index", &DstOp, 0);

if (SrcOp.getSubReg())
report("COPY_LANEMASK must not use a subregister index", &SrcOp, 1);

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);
}

// COPY_LANEMASK should be used only for partial copy. For full
// copy, one should strictly use the COPY instruction.
if (SrcMaxLaneMask == LaneMask)
report("COPY_LANEMASK cannot be used to do full copy", MI);

// If LaneMask is greater than the SrcMaxLaneMask, it implies
// COPY_LANEMASK is attempting to read from the lanes that
// don't exists in the source register.
if (SrcMaxLaneMask < LaneMask)
report("COPY_LANEMASK attempts to read from the lanes that "
"don't exist in the source register",
MI);

break;
}
case TargetOpcode::STATEPOINT: {
StatepointOpers SO(MI);
if (!MI->getOperand(SO.getIDPos()).isImm() ||
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,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:
Expand Down
Original file line number Diff line number Diff line change
@@ -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
...
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# RUN: not llc -mtriple=amdgcn-amd-amdhsa -run-pass=none -filetype=null %s 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
...
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# RUN: not llc -mtriple=amdgcn-amd-amdhsa -run-pass=none -filetype=null %s 2>&1 | FileCheck %s

---
name: test_missing_lparen
tracksRegLiveness: true
body: |
bb.0:
liveins: $vgpr0

; CHECK: [[@LINE+1]]:45: expected '('
$vgpr1 = COPY_LANEMASK $vgpr0, lanemask 14)
S_ENDPGM 0
...
Loading