Skip to content

Commit cd54c47

Browse files
committed
[InstCombine] Match poison instead of undef in foldVectorBinop()
Some negative tests turn into positive tests, as the differences between undef and poison propagation allow additional transforms.
1 parent fd527de commit cd54c47

File tree

3 files changed

+81
-109
lines changed

3 files changed

+81
-109
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1770,9 +1770,9 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
17701770
Constant *C;
17711771
auto *InstVTy = dyn_cast<FixedVectorType>(Inst.getType());
17721772
if (InstVTy &&
1773-
match(&Inst,
1774-
m_c_BinOp(m_OneUse(m_Shuffle(m_Value(V1), m_Undef(), m_Mask(Mask))),
1775-
m_ImmConstant(C))) &&
1773+
match(&Inst, m_c_BinOp(m_OneUse(m_Shuffle(m_Value(V1), m_Poison(),
1774+
m_Mask(Mask))),
1775+
m_ImmConstant(C))) &&
17761776
cast<FixedVectorType>(V1->getType())->getNumElements() <=
17771777
InstVTy->getNumElements()) {
17781778
assert(InstVTy->getScalarType() == V1->getType()->getScalarType() &&
@@ -1787,8 +1787,8 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
17871787
ArrayRef<int> ShMask = Mask;
17881788
unsigned SrcVecNumElts =
17891789
cast<FixedVectorType>(V1->getType())->getNumElements();
1790-
UndefValue *UndefScalar = UndefValue::get(C->getType()->getScalarType());
1791-
SmallVector<Constant *, 16> NewVecC(SrcVecNumElts, UndefScalar);
1790+
PoisonValue *PoisonScalar = PoisonValue::get(C->getType()->getScalarType());
1791+
SmallVector<Constant *, 16> NewVecC(SrcVecNumElts, PoisonScalar);
17921792
bool MayChange = true;
17931793
unsigned NumElts = InstVTy->getNumElements();
17941794
for (unsigned I = 0; I < NumElts; ++I) {
@@ -1801,39 +1801,40 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
18011801
// 2. The shuffle needs an element of the constant vector that can't
18021802
// be mapped to a new constant vector.
18031803
// 3. This is a widening shuffle that copies elements of V1 into the
1804-
// extended elements (extending with undef is allowed).
1805-
if (!CElt || (!isa<UndefValue>(NewCElt) && NewCElt != CElt) ||
1804+
// extended elements (extending with poison is allowed).
1805+
if (!CElt || (!isa<PoisonValue>(NewCElt) && NewCElt != CElt) ||
18061806
I >= SrcVecNumElts) {
18071807
MayChange = false;
18081808
break;
18091809
}
18101810
NewVecC[ShMask[I]] = CElt;
18111811
}
1812-
// If this is a widening shuffle, we must be able to extend with undef
1813-
// elements. If the original binop does not produce an undef in the high
1812+
// If this is a widening shuffle, we must be able to extend with poison
1813+
// elements. If the original binop does not produce a poison in the high
18141814
// lanes, then this transform is not safe.
1815-
// Similarly for undef lanes due to the shuffle mask, we can only
1816-
// transform binops that preserve undef.
1817-
// TODO: We could shuffle those non-undef constant values into the
1818-
// result by using a constant vector (rather than an undef vector)
1815+
// Similarly for poison lanes due to the shuffle mask, we can only
1816+
// transform binops that preserve poison.
1817+
// TODO: We could shuffle those non-poison constant values into the
1818+
// result by using a constant vector (rather than an poison vector)
18191819
// as operand 1 of the new binop, but that might be too aggressive
18201820
// for target-independent shuffle creation.
18211821
if (I >= SrcVecNumElts || ShMask[I] < 0) {
1822-
Constant *MaybeUndef =
1822+
Constant *MaybePoison =
18231823
ConstOp1
1824-
? ConstantFoldBinaryOpOperands(Opcode, UndefScalar, CElt, DL)
1825-
: ConstantFoldBinaryOpOperands(Opcode, CElt, UndefScalar, DL);
1826-
if (!MaybeUndef || !match(MaybeUndef, m_Undef())) {
1824+
? ConstantFoldBinaryOpOperands(Opcode, PoisonScalar, CElt, DL)
1825+
: ConstantFoldBinaryOpOperands(Opcode, CElt, PoisonScalar, DL);
1826+
if (!MaybePoison || !isa<PoisonValue>(MaybePoison)) {
18271827
MayChange = false;
18281828
break;
18291829
}
18301830
}
18311831
}
18321832
if (MayChange) {
18331833
Constant *NewC = ConstantVector::get(NewVecC);
1834-
// It may not be safe to execute a binop on a vector with undef elements
1834+
// It may not be safe to execute a binop on a vector with poison elements
18351835
// because the entire instruction can be folded to undef or create poison
18361836
// that did not exist in the original code.
1837+
// TODO: The shift case should not be necessary.
18371838
if (Inst.isIntDivRem() || (Inst.isShift() && ConstOp1))
18381839
NewC = getSafeVectorConstantForBinop(Opcode, NewC, ConstOp1);
18391840

llvm/test/Transforms/InstCombine/vec_shuffle-inseltpoison.ll

Lines changed: 31 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ define <4 x i32> @mul_const_splat(<4 x i32> %v) {
557557

558558
define <4 x i32> @lshr_const_half_splat(<4 x i32> %v) {
559559
; CHECK-LABEL: @lshr_const_half_splat(
560-
; CHECK-NEXT: [[TMP1:%.*]] = lshr <4 x i32> <i32 undef, i32 8, i32 9, i32 undef>, [[V:%.*]]
560+
; CHECK-NEXT: [[TMP1:%.*]] = lshr <4 x i32> <i32 poison, i32 8, i32 9, i32 poison>, [[V:%.*]]
561561
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 1, i32 2, i32 2>
562562
; CHECK-NEXT: ret <4 x i32> [[R]]
563563
;
@@ -659,27 +659,23 @@ define <4 x i16> @widening_shuffle_shl_constant_op1(<2 x i16> %v) {
659659
ret <4 x i16> %bo
660660
}
661661

662-
; A binop that does not produce undef in the high lanes can not be moved before the shuffle.
663-
; This is not ok because 'shl undef, 1 (or 2)' --> 0' but moving the shuffle results in undef instead.
662+
; This is valid for poison, but would not be valid for undef.
664663

665664
define <4 x i16> @widening_shuffle_shl_constant_op1_non0(<2 x i16> %v) {
666665
; CHECK-LABEL: @widening_shuffle_shl_constant_op1_non0(
667-
; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i16> [[V:%.*]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
668-
; CHECK-NEXT: [[BO:%.*]] = shl <4 x i16> [[SHUF]], <i16 2, i16 4, i16 1, i16 2>
666+
; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i16> [[V:%.*]], <i16 2, i16 4>
667+
; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
669668
; CHECK-NEXT: ret <4 x i16> [[BO]]
670669
;
671670
%shuf = shufflevector <2 x i16> %v, <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
672671
%bo = shl <4 x i16> %shuf, <i16 2, i16 4, i16 1, i16 2>
673672
ret <4 x i16> %bo
674673
}
675674

676-
; A binop that does not produce undef in the high lanes can not be moved before the shuffle.
677-
; This is not ok because 'or -1, undef --> -1' but moving the shuffle results in undef instead.
678-
679675
define <4 x i16> @widening_shuffle_or(<2 x i16> %v) {
680676
; CHECK-LABEL: @widening_shuffle_or(
681-
; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i16> [[V:%.*]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
682-
; CHECK-NEXT: [[BO:%.*]] = or <4 x i16> [[SHUF]], <i16 42, i16 -42, i16 -1, i16 -1>
677+
; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i16> [[V:%.*]], <i16 42, i16 -42>
678+
; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
683679
; CHECK-NEXT: ret <4 x i16> [[BO]]
684680
;
685681
%shuf = shufflevector <2 x i16> %v, <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
@@ -856,7 +852,7 @@ define <2 x i32> @mul_splat_constant(<2 x i32> %x) {
856852

857853
define <2 x i32> @shl_splat_constant0(<2 x i32> %x) {
858854
; CHECK-LABEL: @shl_splat_constant0(
859-
; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> <i32 5, i32 undef>, [[X:%.*]]
855+
; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> <i32 5, i32 poison>, [[X:%.*]]
860856
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
861857
; CHECK-NEXT: ret <2 x i32> [[R]]
862858
;
@@ -878,7 +874,7 @@ define <2 x i32> @shl_splat_constant1(<2 x i32> %x) {
878874

879875
define <2 x i32> @ashr_splat_constant0(<2 x i32> %x) {
880876
; CHECK-LABEL: @ashr_splat_constant0(
881-
; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i32> <i32 5, i32 undef>, [[X:%.*]]
877+
; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> <i32 5, i32 poison>, [[X:%.*]]
882878
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
883879
; CHECK-NEXT: ret <2 x i32> [[R]]
884880
;
@@ -900,7 +896,7 @@ define <2 x i32> @ashr_splat_constant1(<2 x i32> %x) {
900896

901897
define <2 x i32> @lshr_splat_constant0(<2 x i32> %x) {
902898
; CHECK-LABEL: @lshr_splat_constant0(
903-
; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> <i32 5, i32 undef>, [[X:%.*]]
899+
; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> <i32 5, i32 poison>, [[X:%.*]]
904900
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
905901
; CHECK-NEXT: ret <2 x i32> [[R]]
906902
;
@@ -1019,13 +1015,10 @@ define <2 x i32> @and_splat_constant(<2 x i32> %x) {
10191015
ret <2 x i32> %r
10201016
}
10211017

1022-
; AND does not fold to undef for undef operands, we cannot move it
1023-
; across a shuffle with undef masks.
1024-
define <4 x i16> @and_constant_mask_undef(<4 x i16> %add) {
1025-
; CHECK-LABEL: @and_constant_mask_undef(
1018+
define <4 x i16> @and_constant_mask_poison(<4 x i16> %add) {
1019+
; CHECK-LABEL: @and_constant_mask_poison(
10261020
; CHECK-NEXT: entry:
1027-
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
1028-
; CHECK-NEXT: [[AND:%.*]] = and <4 x i16> [[SHUFFLE]], <i16 0, i16 0, i16 -1, i16 -1>
1021+
; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
10291022
; CHECK-NEXT: ret <4 x i16> [[AND]]
10301023
;
10311024
entry:
@@ -1034,13 +1027,10 @@ entry:
10341027
ret <4 x i16> %and
10351028
}
10361029

1037-
; AND does not fold to undef for undef operands, we cannot move it
1038-
; across a shuffle with undef masks.
1039-
define <4 x i16> @and_constant_mask_undef_2(<4 x i16> %add) {
1040-
; CHECK-LABEL: @and_constant_mask_undef_2(
1030+
define <4 x i16> @and_constant_mask_poison_2(<4 x i16> %add) {
1031+
; CHECK-LABEL: @and_constant_mask_poison_2(
10411032
; CHECK-NEXT: entry:
1042-
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 poison>
1043-
; CHECK-NEXT: [[AND:%.*]] = and <4 x i16> [[SHUFFLE]], <i16 -1, i16 -1, i16 -1, i16 0>
1033+
; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 poison>
10441034
; CHECK-NEXT: ret <4 x i16> [[AND]]
10451035
;
10461036
entry:
@@ -1050,8 +1040,8 @@ entry:
10501040
}
10511041

10521042
; We can move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes.
1053-
define <4 x i16> @and_constant_mask_undef_3(<4 x i16> %add) {
1054-
; CHECK-LABEL: @and_constant_mask_undef_3(
1043+
define <4 x i16> @and_constant_mask_poison_3(<4 x i16> %add) {
1044+
; CHECK-LABEL: @and_constant_mask_poison_3(
10551045
; CHECK-NEXT: entry:
10561046
; CHECK-NEXT: ret <4 x i16> <i16 0, i16 0, i16 0, i16 undef>
10571047
;
@@ -1062,8 +1052,8 @@ entry:
10621052
}
10631053

10641054
; We can move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes.
1065-
define <4 x i16> @and_constant_mask_undef_4(<4 x i16> %add) {
1066-
; CHECK-LABEL: @and_constant_mask_undef_4(
1055+
define <4 x i16> @and_constant_mask_poison_4(<4 x i16> %add) {
1056+
; CHECK-LABEL: @and_constant_mask_poison_4(
10671057
; CHECK-NEXT: entry:
10681058
; CHECK-NEXT: [[TMP0:%.*]] = and <4 x i16> [[ADD:%.*]], <i16 9, i16 20, i16 poison, i16 poison>
10691059
; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 0, i32 1, i32 1, i32 poison>
@@ -1088,13 +1078,10 @@ entry:
10881078
ret <4 x i16> %and
10891079
}
10901080

1091-
; OR does not fold to undef for undef operands, we cannot move it
1092-
; across a shuffle with undef masks.
1093-
define <4 x i16> @or_constant_mask_undef(<4 x i16> %in) {
1094-
; CHECK-LABEL: @or_constant_mask_undef(
1081+
define <4 x i16> @or_constant_mask_poison(<4 x i16> %in) {
1082+
; CHECK-LABEL: @or_constant_mask_poison(
10951083
; CHECK-NEXT: entry:
1096-
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
1097-
; CHECK-NEXT: [[OR:%.*]] = or <4 x i16> [[SHUFFLE]], <i16 -1, i16 -1, i16 0, i16 0>
1084+
; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
10981085
; CHECK-NEXT: ret <4 x i16> [[OR]]
10991086
;
11001087
entry:
@@ -1103,13 +1090,10 @@ entry:
11031090
ret <4 x i16> %or
11041091
}
11051092

1106-
; OR does not fold to undef for undef operands, we cannot move it
1107-
; across a shuffle with undef masks.
1108-
define <4 x i16> @or_constant_mask_undef_2(<4 x i16> %in) {
1109-
; CHECK-LABEL: @or_constant_mask_undef_2(
1093+
define <4 x i16> @or_constant_mask_poison_2(<4 x i16> %in) {
1094+
; CHECK-LABEL: @or_constant_mask_poison_2(
11101095
; CHECK-NEXT: entry:
1111-
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison>
1112-
; CHECK-NEXT: [[OR:%.*]] = or <4 x i16> [[SHUFFLE]], <i16 -1, i16 0, i16 0, i16 -1>
1096+
; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison>
11131097
; CHECK-NEXT: ret <4 x i16> [[OR]]
11141098
;
11151099
entry:
@@ -1119,8 +1103,8 @@ entry:
11191103
}
11201104

11211105
; We can move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes.
1122-
define <4 x i16> @or_constant_mask_undef_3(<4 x i16> %in) {
1123-
; CHECK-LABEL: @or_constant_mask_undef_3(
1106+
define <4 x i16> @or_constant_mask_poison_3(<4 x i16> %in) {
1107+
; CHECK-LABEL: @or_constant_mask_poison_3(
11241108
; CHECK-NEXT: entry:
11251109
; CHECK-NEXT: ret <4 x i16> <i16 undef, i16 -1, i16 -1, i16 undef>
11261110
;
@@ -1131,8 +1115,8 @@ entry:
11311115
}
11321116

11331117
; We can move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes.
1134-
define <4 x i16> @or_constant_mask_undef_4(<4 x i16> %in) {
1135-
; CHECK-LABEL: @or_constant_mask_undef_4(
1118+
define <4 x i16> @or_constant_mask_poison_4(<4 x i16> %in) {
1119+
; CHECK-LABEL: @or_constant_mask_poison_4(
11361120
; CHECK-NEXT: entry:
11371121
; CHECK-NEXT: [[TMP0:%.*]] = or <4 x i16> [[IN:%.*]], <i16 poison, i16 99, i16 poison, i16 poison>
11381122
; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison>
@@ -1160,8 +1144,8 @@ entry:
11601144
define <4 x i16> @shl_constant_mask_undef(<4 x i16> %in) {
11611145
; CHECK-LABEL: @shl_constant_mask_undef(
11621146
; CHECK-NEXT: entry:
1163-
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 0, i32 poison, i32 1, i32 1>
1164-
; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i16> [[SHUFFLE]], <i16 10, i16 3, i16 0, i16 0>
1147+
; CHECK-NEXT: [[TMP0:%.*]] = shl <4 x i16> [[IN:%.*]], <i16 10, i16 0, i16 0, i16 0>
1148+
; CHECK-NEXT: [[SHL:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 0, i32 poison, i32 1, i32 1>
11651149
; CHECK-NEXT: ret <4 x i16> [[SHL]]
11661150
;
11671151
entry:

0 commit comments

Comments
 (0)