Skip to content
Draft
Show file tree
Hide file tree
Changes from 7 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
9 changes: 9 additions & 0 deletions llvm/docs/GlobalISel/GenericOpcode.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ An undefined value.
%0:_(s32) = G_IMPLICIT_DEF
G_POISON
^^^^^^^^

A poison value.

.. code-block:: none
%0:_(s32) = G_POISON
G_CONSTANT
^^^^^^^^^^

Expand Down
17 changes: 17 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -432,16 +432,27 @@ class CombinerHelper {
/// G_IMPLICIT_DEF.
bool matchAnyExplicitUseIsUndef(MachineInstr &MI) const;

/// Return true if any explicit use operand on \p MI is defined by a
/// G_POISON.
bool matchAnyExplicitUseIsPoison(MachineInstr &MI) const;

/// Return true if all register explicit use operands on \p MI are defined by
/// a G_IMPLICIT_DEF.
bool matchAllExplicitUsesAreUndef(MachineInstr &MI) const;

/// Return true if all register explicit use operands on \p MI are defined by
/// a G_POISON.
bool matchAllExplicitUsesArePoison(MachineInstr &MI) const;

/// Return true if a G_SHUFFLE_VECTOR instruction \p MI has an undef mask.
bool matchUndefShuffleVectorMask(MachineInstr &MI) const;

/// Return true if a G_STORE instruction \p MI is storing an undef value.
bool matchUndefStore(MachineInstr &MI) const;

/// Return true if a G_STORE instruction \p MI is storing a poison value.
bool matchPoisonStore(MachineInstr &MI) const;

/// Return true if a G_SELECT instruction \p MI has an undef comparison.
bool matchUndefSelectCmp(MachineInstr &MI) const;

Expand All @@ -467,6 +478,9 @@ class CombinerHelper {
/// Replace an instruction with a G_IMPLICIT_DEF.
void replaceInstWithUndef(MachineInstr &MI) const;

/// Replace an instruction with a G_POISON.
void replaceInstWithPoison(MachineInstr &MI) const;

/// Delete \p MI and replace all of its uses with its \p OpIdx-th operand.
void replaceSingleDefInstWithOperand(MachineInstr &MI, unsigned OpIdx) const;

Expand Down Expand Up @@ -507,6 +521,9 @@ class CombinerHelper {
/// Check if operand \p OpIdx is undef.
bool matchOperandIsUndef(MachineInstr &MI, unsigned OpIdx) const;

/// Check if operand \p OpIdx is poison.
bool matchOperandIsPoison(MachineInstr &MI, unsigned OpIdx) const;

/// Check if operand \p OpIdx is known to be a power of 2.
bool matchOperandIsKnownToBeAPowerOfTwo(MachineInstr &MI,
unsigned OpIdx) const;
Expand Down
8 changes: 8 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,14 @@ class GImplicitDef : public GenericMachineInstr {
}
};

/// Represents a G_POISON.
class GPoison : public GenericMachineInstr {
public:
static bool classof(const MachineInstr *MI) {
return MI->getOpcode() == TargetOpcode::G_POISON;
}
};

/// Represents a G_SELECT.
class GSelect : public GenericMachineInstr {
public:
Expand Down
5 changes: 4 additions & 1 deletion llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1017,9 +1017,12 @@ class MachineIRBuilder {
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildExtract(const DstOp &Res, const SrcOp &Src, uint64_t Index);

/// Build and insert \p Res = IMPLICIT_DEF.
/// Build and insert \p Res = G_IMPLICIT_DEF.
MachineInstrBuilder buildUndef(const DstOp &Res);

/// Build and insert \p Res = G_POISON.
MachineInstrBuilder buildPoison(const DstOp &Res);

/// Build and insert \p Res = G_MERGE_VALUES \p Op0, ...
///
/// G_MERGE_VALUES combines the input elements contiguously into a larger
Expand Down
5 changes: 4 additions & 1 deletion llvm/include/llvm/Support/TargetOpcodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -295,9 +295,12 @@ HANDLE_TARGET_OPCODE(G_ABDS)
/// Generic absolute difference unsigned instruction.
HANDLE_TARGET_OPCODE(G_ABDU)


// Generic implicit definition.
HANDLE_TARGET_OPCODE(G_IMPLICIT_DEF)

// Generic poison value.
HANDLE_TARGET_OPCODE(G_POISON)

/// Generic PHI instruction with types.
HANDLE_TARGET_OPCODE(G_PHI)

Expand Down
6 changes: 6 additions & 0 deletions llvm/include/llvm/Target/GenericOpcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ def G_IMPLICIT_DEF : GenericInstruction {
let hasSideEffects = false;
}

def G_POISON : GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins);
let hasSideEffects = false;
}

def G_PHI : GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins variable_ops);
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/CodeGen/GlobalISel/CSEInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ bool CSEConfigFull::shouldCSEOpc(unsigned Opc) {
case TargetOpcode::G_CONSTANT:
case TargetOpcode::G_FCONSTANT:
case TargetOpcode::G_IMPLICIT_DEF:
case TargetOpcode::G_POISON:
case TargetOpcode::G_ZEXT:
case TargetOpcode::G_SEXT:
case TargetOpcode::G_ANYEXT:
Expand Down Expand Up @@ -82,7 +83,7 @@ bool CSEConfigFull::shouldCSEOpc(unsigned Opc) {

bool CSEConfigConstantOnly::shouldCSEOpc(unsigned Opc) {
return Opc == TargetOpcode::G_CONSTANT || Opc == TargetOpcode::G_FCONSTANT ||
Opc == TargetOpcode::G_IMPLICIT_DEF;
Opc == TargetOpcode::G_IMPLICIT_DEF || Opc == TargetOpcode::G_POISON;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beyond the scope of this patch, but we probably should stop CSEing G_IMPLICIT_DEF, and only do it for G_POISON

}

std::unique_ptr<CSEConfigBase>
Expand Down
59 changes: 51 additions & 8 deletions llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ bool CombinerHelper::matchCombineConcatVectors(
for (const MachineOperand &BuildVecMO : Def->uses())
Ops.push_back(BuildVecMO.getReg());
break;
case TargetOpcode::G_POISON:
case TargetOpcode::G_IMPLICIT_DEF: {
LLT OpType = MRI.getType(Reg);
// Keep one undef value for all the undef operands.
Expand Down Expand Up @@ -454,7 +455,8 @@ bool CombinerHelper::matchCombineShuffleConcat(
return false;
}
if (!isLegalOrBeforeLegalizer(
{TargetOpcode::G_IMPLICIT_DEF, {ConcatSrcTy}}))
{TargetOpcode::G_IMPLICIT_DEF, {ConcatSrcTy}}) ||
!isLegalOrBeforeLegalizer({TargetOpcode::G_POISON, {ConcatSrcTy}}))
return false;
Ops.push_back(0);
} else if (Mask[i] % ConcatSrcNumElt == 0) {
Expand Down Expand Up @@ -2732,14 +2734,29 @@ void CombinerHelper::applyCombineTruncOfShift(
bool CombinerHelper::matchAnyExplicitUseIsUndef(MachineInstr &MI) const {
return any_of(MI.explicit_uses(), [this](const MachineOperand &MO) {
return MO.isReg() &&
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI);
(getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI) ||
getOpcodeDef(TargetOpcode::G_POISON, MO.getReg(), MRI));
Comment on lines +2739 to +2740
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a fixme? We shouldn't look up copy chains twice just to check 2 opcodes. We should delete getOpcodeDef as a helper, it's not good

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! In the next patch I can come up with some helpers where getOpcodeDef accepts a set of opcodes.

});
}

bool CombinerHelper::matchAnyExplicitUseIsPoison(MachineInstr &MI) const {
return any_of(MI.explicit_uses(), [this](const MachineOperand &MO) {
return MO.isReg() && getOpcodeDef(TargetOpcode::G_POISON, MO.getReg(), MRI);
});
}

bool CombinerHelper::matchAllExplicitUsesAreUndef(MachineInstr &MI) const {
return all_of(MI.explicit_uses(), [this](const MachineOperand &MO) {
return !MO.isReg() ||
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI);
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI) ||
getOpcodeDef(TargetOpcode::G_POISON, MO.getReg(), MRI);
});
}

bool CombinerHelper::matchAllExplicitUsesArePoison(MachineInstr &MI) const {
return all_of(MI.explicit_uses(), [this](const MachineOperand &MO) {
return !MO.isReg() ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't need to check if the operand is a register, but this is consistent with the other cases

getOpcodeDef(TargetOpcode::G_POISON, MO.getReg(), MRI);
});
}

Expand All @@ -2752,12 +2769,21 @@ bool CombinerHelper::matchUndefShuffleVectorMask(MachineInstr &MI) const {
bool CombinerHelper::matchUndefStore(MachineInstr &MI) const {
assert(MI.getOpcode() == TargetOpcode::G_STORE);
return getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MI.getOperand(0).getReg(),
MRI) ||
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MI.getOperand(0).getReg(),
MRI);
}

bool CombinerHelper::matchPoisonStore(MachineInstr &MI) const {
assert(MI.getOpcode() == TargetOpcode::G_STORE);
return getOpcodeDef(TargetOpcode::G_POISON, MI.getOperand(0).getReg(), MRI);
}

bool CombinerHelper::matchUndefSelectCmp(MachineInstr &MI) const {
assert(MI.getOpcode() == TargetOpcode::G_SELECT);
return getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MI.getOperand(1).getReg(),
MRI) ||
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MI.getOperand(1).getReg(),
MRI);
}

Expand Down Expand Up @@ -2991,7 +3017,14 @@ bool CombinerHelper::matchOperandIsUndef(MachineInstr &MI,
unsigned OpIdx) const {
MachineOperand &MO = MI.getOperand(OpIdx);
return MO.isReg() &&
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI);
(getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI) ||
getOpcodeDef(TargetOpcode::G_POISON, MO.getReg(), MRI));
}

bool CombinerHelper::matchOperandIsPoison(MachineInstr &MI,
unsigned OpIdx) const {
MachineOperand &MO = MI.getOperand(OpIdx);
return MO.isReg() && getOpcodeDef(TargetOpcode::G_POISON, MO.getReg(), MRI);
}

bool CombinerHelper::matchOperandIsKnownToBeAPowerOfTwo(MachineInstr &MI,
Expand Down Expand Up @@ -3033,6 +3066,12 @@ void CombinerHelper::replaceInstWithUndef(MachineInstr &MI) const {
MI.eraseFromParent();
}

void CombinerHelper::replaceInstWithPoison(MachineInstr &MI) const {
assert(MI.getNumDefs() == 1 && "Expected only one def?");
Builder.buildPoison(MI.getOperand(0));
MI.eraseFromParent();
}

bool CombinerHelper::matchSimplifyAddToSub(
MachineInstr &MI, std::tuple<Register, Register> &MatchInfo) const {
Register LHS = MI.getOperand(1).getReg();
Expand Down Expand Up @@ -3097,6 +3136,7 @@ bool CombinerHelper::matchCombineInsertVecElts(
// If we didn't end in a G_IMPLICIT_DEF and the source is not fully
// overwritten, bail out.
return TmpInst->getOpcode() == TargetOpcode::G_IMPLICIT_DEF ||
TmpInst->getOpcode() == TargetOpcode::G_POISON ||
all_of(MatchInfo, [](Register Reg) { return !!Reg; });
}

Expand Down Expand Up @@ -3467,12 +3507,13 @@ bool CombinerHelper::matchUseVectorTruncate(MachineInstr &MI,
if (I < 2)
return false;

// Check the remaining source elements are only G_IMPLICIT_DEF
// Check the remaining source elements are only G_IMPLICIT_DEF or G_POISON
for (; I < NumOperands; ++I) {
auto SrcMI = MRI.getVRegDef(BuildMI->getSourceReg(I));
auto SrcMIOpc = SrcMI->getOpcode();

if (SrcMIOpc != TargetOpcode::G_IMPLICIT_DEF)
if (SrcMIOpc != TargetOpcode::G_IMPLICIT_DEF &&
SrcMIOpc != TargetOpcode::G_POISON)
return false;
}

Expand Down Expand Up @@ -7927,10 +7968,12 @@ bool CombinerHelper::matchShuffleDisjointMask(MachineInstr &MI,
auto &Shuffle = cast<GShuffleVector>(MI);
// If any of the two inputs is already undef, don't check the mask again to
// prevent infinite loop
if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc1Reg(), MRI))
if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc1Reg(), MRI) ||
getOpcodeDef(TargetOpcode::G_POISON, Shuffle.getSrc1Reg(), MRI))
return false;

if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc2Reg(), MRI))
if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc2Reg(), MRI) ||
getOpcodeDef(TargetOpcode::G_POISON, Shuffle.getSrc2Reg(), MRI))
return false;

const LLT DstTy = MRI.getType(Shuffle.getReg(0));
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3649,6 +3649,8 @@ bool IRTranslator::translate(const Constant &C, Register Reg) {
EntryBuilder->buildConstant(Reg, *CI);
else if (auto CF = dyn_cast<ConstantFP>(&C))
EntryBuilder->buildFConstant(Reg, *CF);
else if (isa<PoisonValue>(C))
EntryBuilder->buildPoison(Reg);
else if (isa<UndefValue>(C))
EntryBuilder->buildUndef(Reg);
else if (isa<ConstantPointerNull>(C))
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/LegacyLegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ LegacyLegalizerInfo::LegacyLegalizerInfo() {

setLegalizeScalarToDifferentSizeStrategy(
TargetOpcode::G_IMPLICIT_DEF, 0, narrowToSmallerAndUnsupportedIfTooSmall);
setLegalizeScalarToDifferentSizeStrategy(
TargetOpcode::G_POISON, 0, narrowToSmallerAndUnsupportedIfTooSmall);
setLegalizeScalarToDifferentSizeStrategy(
TargetOpcode::G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
setLegalizeScalarToDifferentSizeStrategy(
Expand Down
11 changes: 8 additions & 3 deletions llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1425,6 +1425,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
switch (MI.getOpcode()) {
default:
return UnableToLegalize;
case TargetOpcode::G_POISON:
case TargetOpcode::G_IMPLICIT_DEF: {
Register DstReg = MI.getOperand(0).getReg();
LLT DstTy = MRI.getType(DstReg);
Expand Down Expand Up @@ -3082,6 +3083,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
MI.eraseFromParent();
return Legalized;
}
case TargetOpcode::G_POISON:
case TargetOpcode::G_IMPLICIT_DEF: {
Observer.changingInstr(MI);
widenScalarDst(MI, WideTy);
Expand Down Expand Up @@ -5307,6 +5309,7 @@ LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,

switch (MI.getOpcode()) {
case G_IMPLICIT_DEF:
case G_POISON:
case G_TRUNC:
case G_AND:
case G_OR:
Expand Down Expand Up @@ -6047,6 +6050,7 @@ LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
LLT MoreTy) {
unsigned Opc = MI.getOpcode();
switch (Opc) {
case TargetOpcode::G_POISON:
case TargetOpcode::G_IMPLICIT_DEF:
case TargetOpcode::G_LOAD: {
if (TypeIdx != 0)
Expand Down Expand Up @@ -8450,15 +8454,16 @@ LegalizerHelper::lowerVECTOR_COMPRESS(llvm::MachineInstr &MI) {

auto OutPos = MIRBuilder.buildConstant(IdxTy, 0);

bool HasPassthru =
MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
auto *PassthruMI = MRI.getVRegDef(Passthru);
bool HasPassthru = PassthruMI->getOpcode() != TargetOpcode::G_IMPLICIT_DEF &&
PassthruMI->getOpcode() != TargetOpcode::G_POISON;

if (HasPassthru)
MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);

Register LastWriteVal;
std::optional<APInt> PassthruSplatVal =
isConstantOrConstantSplatVector(*MRI.getVRegDef(Passthru), MRI);
isConstantOrConstantSplatVector(*PassthruMI, MRI);

if (PassthruSplatVal.has_value()) {
LastWriteVal =
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/GlobalISel/LostDebugLocObserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ static bool irTranslatorNeverAddsLocations(unsigned Opcode) {
case TargetOpcode::G_CONSTANT:
case TargetOpcode::G_FCONSTANT:
case TargetOpcode::G_IMPLICIT_DEF:
case TargetOpcode::G_POISON:
case TargetOpcode::G_GLOBAL_VALUE:
return true;
}
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,10 @@ MachineInstrBuilder MachineIRBuilder::buildUndef(const DstOp &Res) {
return buildInstr(TargetOpcode::G_IMPLICIT_DEF, {Res}, {});
}

MachineInstrBuilder MachineIRBuilder::buildPoison(const DstOp &Res) {
return buildInstr(TargetOpcode::G_POISON, {Res}, {});
}

MachineInstrBuilder MachineIRBuilder::buildMergeValues(const DstOp &Res,
ArrayRef<Register> Ops) {
// Unfortunately to convert from ArrayRef<LLT> to ArrayRef<SrcOp>,
Expand Down
Loading
Loading