Skip to content

Commit 48adc07

Browse files
committed
[GlobalISel] Introduce G_POISON
1 parent 0de2cca commit 48adc07

18 files changed

+200
-35
lines changed

llvm/docs/GlobalISel/GenericOpcode.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ An undefined value.
2424
2525
%0:_(s32) = G_IMPLICIT_DEF
2626
27+
G_POISON
28+
^^^^^^^^
29+
30+
A poison value.
31+
32+
.. code-block:: none
33+
34+
%0:_(s32) = G_POISON
35+
2736
G_CONSTANT
2837
^^^^^^^^^^
2938

llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,16 +431,27 @@ class CombinerHelper {
431431
/// G_IMPLICIT_DEF.
432432
bool matchAnyExplicitUseIsUndef(MachineInstr &MI) const;
433433

434+
/// Return true if any explicit use operand on \p MI is defined by a
435+
/// G_POISON.
436+
bool matchAnyExplicitUseIsPoison(MachineInstr &MI) const;
437+
434438
/// Return true if all register explicit use operands on \p MI are defined by
435439
/// a G_IMPLICIT_DEF.
436440
bool matchAllExplicitUsesAreUndef(MachineInstr &MI) const;
437441

442+
/// Return true if all register explicit use operands on \p MI are defined by
443+
/// a G_POISON.
444+
bool matchAllExplicitUsesArePoison(MachineInstr &MI) const;
445+
438446
/// Return true if a G_SHUFFLE_VECTOR instruction \p MI has an undef mask.
439447
bool matchUndefShuffleVectorMask(MachineInstr &MI) const;
440448

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

452+
/// Return true if a G_STORE instruction \p MI is storing a poison value.
453+
bool matchPoisonStore(MachineInstr &MI) const;
454+
444455
/// Return true if a G_SELECT instruction \p MI has an undef comparison.
445456
bool matchUndefSelectCmp(MachineInstr &MI) const;
446457

@@ -466,6 +477,9 @@ class CombinerHelper {
466477
/// Replace an instruction with a G_IMPLICIT_DEF.
467478
void replaceInstWithUndef(MachineInstr &MI) const;
468479

480+
/// Replace an instruction with a G_POISON.
481+
void replaceInstWithPoison(MachineInstr &MI) const;
482+
469483
/// Delete \p MI and replace all of its uses with its \p OpIdx-th operand.
470484
void replaceSingleDefInstWithOperand(MachineInstr &MI, unsigned OpIdx) const;
471485

@@ -506,6 +520,9 @@ class CombinerHelper {
506520
/// Check if operand \p OpIdx is undef.
507521
bool matchOperandIsUndef(MachineInstr &MI, unsigned OpIdx) const;
508522

523+
/// Check if operand \p OpIdx is poison.
524+
bool matchOperandIsPoison(MachineInstr &MI, unsigned OpIdx) const;
525+
509526
/// Check if operand \p OpIdx is known to be a power of 2.
510527
bool matchOperandIsKnownToBeAPowerOfTwo(MachineInstr &MI,
511528
unsigned OpIdx) const;

llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,14 @@ class GImplicitDef : public GenericMachineInstr {
343343
}
344344
};
345345

346+
/// Represents a G_POISON.
347+
class GPoison : public GenericMachineInstr {
348+
public:
349+
static bool classof(const MachineInstr *MI) {
350+
return MI->getOpcode() == TargetOpcode::G_POISON;
351+
}
352+
};
353+
346354
/// Represents a G_SELECT.
347355
class GSelect : public GenericMachineInstr {
348356
public:

llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1017,9 +1017,12 @@ class MachineIRBuilder {
10171017
/// \return a MachineInstrBuilder for the newly created instruction.
10181018
MachineInstrBuilder buildExtract(const DstOp &Res, const SrcOp &Src, uint64_t Index);
10191019

1020-
/// Build and insert \p Res = IMPLICIT_DEF.
1020+
/// Build and insert \p Res = G_IMPLICIT_DEF.
10211021
MachineInstrBuilder buildUndef(const DstOp &Res);
10221022

1023+
/// Build and insert \p Res = G_POISON.
1024+
MachineInstrBuilder buildPoison(const DstOp &Res);
1025+
10231026
/// Build and insert \p Res = G_MERGE_VALUES \p Op0, ...
10241027
///
10251028
/// G_MERGE_VALUES combines the input elements contiguously into a larger

llvm/include/llvm/Support/TargetOpcodes.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,12 @@ HANDLE_TARGET_OPCODE(G_ABDS)
295295
/// Generic absolute difference unsigned instruction.
296296
HANDLE_TARGET_OPCODE(G_ABDU)
297297

298-
298+
// Generic implicit definition.
299299
HANDLE_TARGET_OPCODE(G_IMPLICIT_DEF)
300300

301+
// Generic poison value.
302+
HANDLE_TARGET_OPCODE(G_POISON)
303+
301304
/// Generic PHI instruction with types.
302305
HANDLE_TARGET_OPCODE(G_PHI)
303306

llvm/include/llvm/Target/GenericOpcodes.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ def G_IMPLICIT_DEF : GenericInstruction {
9292
let hasSideEffects = false;
9393
}
9494

95+
def G_POISON : GenericInstruction {
96+
let OutOperandList = (outs type0:$dst);
97+
let InOperandList = (ins);
98+
let hasSideEffects = false;
99+
}
100+
95101
def G_PHI : GenericInstruction {
96102
let OutOperandList = (outs type0:$dst);
97103
let InOperandList = (ins variable_ops);

llvm/include/llvm/Target/GlobalISel/Combine.td

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,12 @@ def binop_right_undef_to_undef: GICombineRule<
430430
[{ return Helper.matchOperandIsUndef(*${root}, 2); }]),
431431
(apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
432432

433+
def binop_right_poison_to_poison
434+
: GICombineRule<(defs root:$root),
435+
(match(wip_match_opcode G_SHL, G_ASHR, G_LSHR):$root,
436+
[{ return Helper.matchOperandIsPoison(*${root}, 2); }]),
437+
(apply [{ Helper.replaceInstWithPoison(*${root}); }])>;
438+
433439
def unary_undef_to_zero: GICombineRule<
434440
(defs root:$root),
435441
(match (wip_match_opcode G_ABS):$root,
@@ -447,6 +453,17 @@ def unary_undef_to_undef : GICombineRule<
447453
(match (unary_undef_to_undef_frags $dst)),
448454
(apply [{ Helper.replaceInstWithUndef(*${dst}.getParent()); }])>;
449455

456+
def unary_poison_to_poison_frags
457+
: GICombinePatFrag<(outs root:$dst), (ins),
458+
!foreach(op,
459+
[G_TRUNC, G_BITCAST, G_ANYEXT, G_PTRTOINT,
460+
G_INTTOPTR, G_FPTOSI, G_FPTOUI],
461+
(pattern(op $dst, $x), (G_POISON $x)))>;
462+
def unary_poison_to_poison
463+
: GICombineRule<
464+
(defs root:$dst), (match(unary_poison_to_poison_frags $dst)),
465+
(apply [{ Helper.replaceInstWithPoison(*${dst}.getParent()); }])>;
466+
450467
// Instructions where if any source operand is undef, the instruction can be
451468
// replaced with undef.
452469
def propagate_undef_any_op: GICombineRule<
@@ -455,6 +472,15 @@ def propagate_undef_any_op: GICombineRule<
455472
[{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
456473
(apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
457474

475+
// Instructions where if any source operand is poison, the instruction can be
476+
// replaced with poison.
477+
def propagate_poison_any_op
478+
: GICombineRule<
479+
(defs root:$root),
480+
(match(wip_match_opcode G_ADD, G_SUB, G_XOR):$root,
481+
[{ return Helper.matchAnyExplicitUseIsPoison(*${root}); }]),
482+
(apply [{ Helper.replaceInstWithPoison(*${root}); }])>;
483+
458484
// Instructions where if all source operands are undef, the instruction can be
459485
// replaced with undef.
460486
def propagate_undef_all_ops: GICombineRule<
@@ -463,6 +489,15 @@ def propagate_undef_all_ops: GICombineRule<
463489
[{ return Helper.matchAllExplicitUsesAreUndef(*${root}); }]),
464490
(apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
465491

492+
// Instructions where if all source operands are poison, the instruction can be
493+
// replaced with poison.
494+
def propagate_poison_all_ops
495+
: GICombineRule<
496+
(defs root:$root),
497+
(match(wip_match_opcode G_SHUFFLE_VECTOR, G_BUILD_VECTOR):$root,
498+
[{ return Helper.matchAllExplicitUsesArePoison(*${root}); }]),
499+
(apply [{ Helper.replaceInstWithPoison(*${root}); }])>;
500+
466501
// Replace a G_SHUFFLE_VECTOR with an undef mask with a G_IMPLICIT_DEF.
467502
def propagate_undef_shuffle_mask: GICombineRule<
468503
(defs root:$root),
@@ -654,6 +689,13 @@ def erase_undef_store : GICombineRule<
654689
(apply [{ Helper.eraseInst(*${root}); }])
655690
>;
656691

692+
// Erase stores of poison values.
693+
def erase_poison_store
694+
: GICombineRule<(defs root:$root),
695+
(match(wip_match_opcode G_STORE):$root,
696+
[{ return Helper.matchPoisonStore(*${root}); }]),
697+
(apply [{ Helper.eraseInst(*${root}); }])>;
698+
657699
def simplify_add_to_sub_matchinfo: GIDefMatchData<"std::tuple<Register, Register>">;
658700
def simplify_add_to_sub: GICombineRule <
659701
(defs root:$root, simplify_add_to_sub_matchinfo:$info),
@@ -1955,6 +1997,11 @@ def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
19551997
erase_undef_store,
19561998
insert_extract_vec_elt_out_of_bounds]>;
19571999

2000+
def poison_combines
2001+
: GICombineGroup<[binop_right_poison_to_poison, unary_poison_to_poison,
2002+
propagate_poison_any_op, propagate_poison_all_ops,
2003+
erase_poison_store]>;
2004+
19582005
def identity_combines : GICombineGroup<[select_same_val, right_identity_zero,
19592006
binop_same_val, binop_left_to_zero,
19602007
binop_right_to_zero, p2i_to_i2p,
@@ -2006,29 +2053,29 @@ def shuffle_combines : GICombineGroup<[combine_shuffle_concat,
20062053
combine_shuffle_undef_rhs,
20072054
combine_shuffle_disjoint_mask]>;
20082055

2009-
def all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines,
2010-
vector_ops_combines, freeze_combines, cast_combines,
2011-
insert_vec_elt_combines, extract_vec_elt_combines, combines_for_extload,
2012-
combine_extracted_vector_load,
2013-
undef_combines, identity_combines, phi_combines,
2014-
simplify_add_to_sub, hoist_logic_op_with_same_opcode_hands, shifts_too_big,
2015-
reassocs, ptr_add_immed_chain, cmp_combines,
2016-
shl_ashr_to_sext_inreg, sext_inreg_of_load,
2017-
width_reduction_combines, select_combines,
2018-
known_bits_simplifications, trunc_shift,
2019-
not_cmp_fold, opt_brcond_by_inverting_cond,
2020-
const_combines, xor_of_and_with_same_reg, ptr_add_with_zero,
2021-
shift_immed_chain, shift_of_shifted_logic_chain, load_or_combine,
2022-
div_rem_to_divrem, funnel_shift_combines, bitreverse_shift, commute_shift,
2023-
form_bitfield_extract, constant_fold_binops, constant_fold_fma,
2024-
constant_fold_cast_op, fabs_fneg_fold,
2025-
intdiv_combines, mulh_combines, redundant_neg_operands,
2026-
and_or_disjoint_mask, fma_combines, fold_binop_into_select,
2027-
sub_add_reg, select_to_minmax,
2028-
fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors,
2029-
simplify_neg_minmax, combine_concat_vector,
2030-
sext_trunc, zext_trunc, prefer_sign_combines, shuffle_combines,
2031-
combine_use_vector_truncate, merge_combines, overflow_combines]>;
2056+
def all_combines
2057+
: GICombineGroup<
2058+
[integer_reassoc_combines, trivial_combines, vector_ops_combines,
2059+
freeze_combines, cast_combines, insert_vec_elt_combines,
2060+
extract_vec_elt_combines, combines_for_extload,
2061+
combine_extracted_vector_load, undef_combines, poison_combines,
2062+
identity_combines, phi_combines, simplify_add_to_sub,
2063+
hoist_logic_op_with_same_opcode_hands, shifts_too_big, reassocs,
2064+
ptr_add_immed_chain, cmp_combines, shl_ashr_to_sext_inreg,
2065+
sext_inreg_of_load, width_reduction_combines, select_combines,
2066+
known_bits_simplifications, trunc_shift, not_cmp_fold,
2067+
opt_brcond_by_inverting_cond, const_combines,
2068+
xor_of_and_with_same_reg, ptr_add_with_zero, shift_immed_chain,
2069+
shift_of_shifted_logic_chain, load_or_combine, div_rem_to_divrem,
2070+
funnel_shift_combines, bitreverse_shift, commute_shift,
2071+
form_bitfield_extract, constant_fold_binops, constant_fold_fma,
2072+
constant_fold_cast_op, fabs_fneg_fold, intdiv_combines,
2073+
mulh_combines, redundant_neg_operands, and_or_disjoint_mask,
2074+
fma_combines, fold_binop_into_select, sub_add_reg, select_to_minmax,
2075+
fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors,
2076+
simplify_neg_minmax, combine_concat_vector, sext_trunc, zext_trunc,
2077+
prefer_sign_combines, shuffle_combines, combine_use_vector_truncate,
2078+
merge_combines, overflow_combines]>;
20322079

20332080
// A combine group used to for prelegalizer combiners at -O0. The combines in
20342081
// this group have been selected based on experiments to balance code size and

llvm/lib/CodeGen/GlobalISel/CSEInfo.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ bool CSEConfigFull::shouldCSEOpc(unsigned Opc) {
5454
case TargetOpcode::G_CONSTANT:
5555
case TargetOpcode::G_FCONSTANT:
5656
case TargetOpcode::G_IMPLICIT_DEF:
57+
case TargetOpcode::G_POISON:
5758
case TargetOpcode::G_ZEXT:
5859
case TargetOpcode::G_SEXT:
5960
case TargetOpcode::G_ANYEXT:
@@ -82,7 +83,7 @@ bool CSEConfigFull::shouldCSEOpc(unsigned Opc) {
8283

8384
bool CSEConfigConstantOnly::shouldCSEOpc(unsigned Opc) {
8485
return Opc == TargetOpcode::G_CONSTANT || Opc == TargetOpcode::G_FCONSTANT ||
85-
Opc == TargetOpcode::G_IMPLICIT_DEF;
86+
Opc == TargetOpcode::G_IMPLICIT_DEF || Opc == TargetOpcode::G_POISON;
8687
}
8788

8889
std::unique_ptr<CSEConfigBase>

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ bool CombinerHelper::matchCombineConcatVectors(
328328
for (const MachineOperand &BuildVecMO : Def->uses())
329329
Ops.push_back(BuildVecMO.getReg());
330330
break;
331+
case TargetOpcode::G_POISON:
331332
case TargetOpcode::G_IMPLICIT_DEF: {
332333
LLT OpType = MRI.getType(Reg);
333334
// Keep one undef value for all the undef operands.
@@ -2695,13 +2696,26 @@ bool CombinerHelper::matchAnyExplicitUseIsUndef(MachineInstr &MI) const {
26952696
});
26962697
}
26972698

2699+
bool CombinerHelper::matchAnyExplicitUseIsPoison(MachineInstr &MI) const {
2700+
return any_of(MI.explicit_uses(), [this](const MachineOperand &MO) {
2701+
return MO.isReg() && getOpcodeDef(TargetOpcode::G_POISON, MO.getReg(), MRI);
2702+
});
2703+
}
2704+
26982705
bool CombinerHelper::matchAllExplicitUsesAreUndef(MachineInstr &MI) const {
26992706
return all_of(MI.explicit_uses(), [this](const MachineOperand &MO) {
27002707
return !MO.isReg() ||
27012708
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI);
27022709
});
27032710
}
27042711

2712+
bool CombinerHelper::matchAllExplicitUsesArePoison(MachineInstr &MI) const {
2713+
return all_of(MI.explicit_uses(), [this](const MachineOperand &MO) {
2714+
return !MO.isReg() ||
2715+
getOpcodeDef(TargetOpcode::G_POISON, MO.getReg(), MRI);
2716+
});
2717+
}
2718+
27052719
bool CombinerHelper::matchUndefShuffleVectorMask(MachineInstr &MI) const {
27062720
assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
27072721
ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask();
@@ -2714,6 +2728,11 @@ bool CombinerHelper::matchUndefStore(MachineInstr &MI) const {
27142728
MRI);
27152729
}
27162730

2731+
bool CombinerHelper::matchPoisonStore(MachineInstr &MI) const {
2732+
assert(MI.getOpcode() == TargetOpcode::G_STORE);
2733+
return getOpcodeDef(TargetOpcode::G_POISON, MI.getOperand(0).getReg(), MRI);
2734+
}
2735+
27172736
bool CombinerHelper::matchUndefSelectCmp(MachineInstr &MI) const {
27182737
assert(MI.getOpcode() == TargetOpcode::G_SELECT);
27192738
return getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MI.getOperand(1).getReg(),
@@ -2953,6 +2972,12 @@ bool CombinerHelper::matchOperandIsUndef(MachineInstr &MI,
29532972
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI);
29542973
}
29552974

2975+
bool CombinerHelper::matchOperandIsPoison(MachineInstr &MI,
2976+
unsigned OpIdx) const {
2977+
MachineOperand &MO = MI.getOperand(OpIdx);
2978+
return MO.isReg() && getOpcodeDef(TargetOpcode::G_POISON, MO.getReg(), MRI);
2979+
}
2980+
29562981
bool CombinerHelper::matchOperandIsKnownToBeAPowerOfTwo(MachineInstr &MI,
29572982
unsigned OpIdx) const {
29582983
MachineOperand &MO = MI.getOperand(OpIdx);
@@ -2992,6 +3017,12 @@ void CombinerHelper::replaceInstWithUndef(MachineInstr &MI) const {
29923017
MI.eraseFromParent();
29933018
}
29943019

3020+
void CombinerHelper::replaceInstWithPoison(MachineInstr &MI) const {
3021+
assert(MI.getNumDefs() == 1 && "Expected only one def?");
3022+
Builder.buildPoison(MI.getOperand(0));
3023+
MI.eraseFromParent();
3024+
}
3025+
29953026
bool CombinerHelper::matchSimplifyAddToSub(
29963027
MachineInstr &MI, std::tuple<Register, Register> &MatchInfo) const {
29973028
Register LHS = MI.getOperand(1).getReg();
@@ -3056,6 +3087,7 @@ bool CombinerHelper::matchCombineInsertVecElts(
30563087
// If we didn't end in a G_IMPLICIT_DEF and the source is not fully
30573088
// overwritten, bail out.
30583089
return TmpInst->getOpcode() == TargetOpcode::G_IMPLICIT_DEF ||
3090+
TmpInst->getOpcode() == TargetOpcode::G_POISON ||
30593091
all_of(MatchInfo, [](Register Reg) { return !!Reg; });
30603092
}
30613093

@@ -3426,12 +3458,13 @@ bool CombinerHelper::matchUseVectorTruncate(MachineInstr &MI,
34263458
if (I < 2)
34273459
return false;
34283460

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

3434-
if (SrcMIOpc != TargetOpcode::G_IMPLICIT_DEF)
3466+
if (SrcMIOpc != TargetOpcode::G_IMPLICIT_DEF &&
3467+
SrcMIOpc != TargetOpcode::G_POISON)
34353468
return false;
34363469
}
34373470

@@ -7892,6 +7925,12 @@ bool CombinerHelper::matchShuffleDisjointMask(MachineInstr &MI,
78927925
if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc2Reg(), MRI))
78937926
return false;
78947927

7928+
if (getOpcodeDef(TargetOpcode::G_POISON, Shuffle.getSrc1Reg(), MRI))
7929+
return false;
7930+
7931+
if (getOpcodeDef(TargetOpcode::G_POISON, Shuffle.getSrc2Reg(), MRI))
7932+
return false;
7933+
78957934
const LLT DstTy = MRI.getType(Shuffle.getReg(0));
78967935
const LLT Src1Ty = MRI.getType(Shuffle.getSrc1Reg());
78977936
if (!isLegalOrBeforeLegalizer(

llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3660,6 +3660,8 @@ bool IRTranslator::translate(const Constant &C, Register Reg) {
36603660
EntryBuilder->buildConstant(Reg, *CI);
36613661
else if (auto CF = dyn_cast<ConstantFP>(&C))
36623662
EntryBuilder->buildFConstant(Reg, *CF);
3663+
else if (isa<PoisonValue>(C))
3664+
EntryBuilder->buildPoison(Reg);
36633665
else if (isa<UndefValue>(C))
36643666
EntryBuilder->buildUndef(Reg);
36653667
else if (isa<ConstantPointerNull>(C))

0 commit comments

Comments
 (0)