[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.
This commit is contained in:
Nikita Popov
2023-12-18 16:49:30 +01:00
parent fd527def7e
commit cd54c47424
3 changed files with 81 additions and 109 deletions

View File

@@ -1770,9 +1770,9 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
Constant *C;
auto *InstVTy = dyn_cast<FixedVectorType>(Inst.getType());
if (InstVTy &&
match(&Inst,
m_c_BinOp(m_OneUse(m_Shuffle(m_Value(V1), m_Undef(), m_Mask(Mask))),
m_ImmConstant(C))) &&
match(&Inst, m_c_BinOp(m_OneUse(m_Shuffle(m_Value(V1), m_Poison(),
m_Mask(Mask))),
m_ImmConstant(C))) &&
cast<FixedVectorType>(V1->getType())->getNumElements() <=
InstVTy->getNumElements()) {
assert(InstVTy->getScalarType() == V1->getType()->getScalarType() &&
@@ -1787,8 +1787,8 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
ArrayRef<int> ShMask = Mask;
unsigned SrcVecNumElts =
cast<FixedVectorType>(V1->getType())->getNumElements();
UndefValue *UndefScalar = UndefValue::get(C->getType()->getScalarType());
SmallVector<Constant *, 16> NewVecC(SrcVecNumElts, UndefScalar);
PoisonValue *PoisonScalar = PoisonValue::get(C->getType()->getScalarType());
SmallVector<Constant *, 16> NewVecC(SrcVecNumElts, PoisonScalar);
bool MayChange = true;
unsigned NumElts = InstVTy->getNumElements();
for (unsigned I = 0; I < NumElts; ++I) {
@@ -1801,29 +1801,29 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
// 2. The shuffle needs an element of the constant vector that can't
// be mapped to a new constant vector.
// 3. This is a widening shuffle that copies elements of V1 into the
// extended elements (extending with undef is allowed).
if (!CElt || (!isa<UndefValue>(NewCElt) && NewCElt != CElt) ||
// extended elements (extending with poison is allowed).
if (!CElt || (!isa<PoisonValue>(NewCElt) && NewCElt != CElt) ||
I >= SrcVecNumElts) {
MayChange = false;
break;
}
NewVecC[ShMask[I]] = CElt;
}
// If this is a widening shuffle, we must be able to extend with undef
// elements. If the original binop does not produce an undef in the high
// If this is a widening shuffle, we must be able to extend with poison
// elements. If the original binop does not produce a poison in the high
// lanes, then this transform is not safe.
// Similarly for undef lanes due to the shuffle mask, we can only
// transform binops that preserve undef.
// TODO: We could shuffle those non-undef constant values into the
// result by using a constant vector (rather than an undef vector)
// Similarly for poison lanes due to the shuffle mask, we can only
// transform binops that preserve poison.
// TODO: We could shuffle those non-poison constant values into the
// result by using a constant vector (rather than an poison vector)
// as operand 1 of the new binop, but that might be too aggressive
// for target-independent shuffle creation.
if (I >= SrcVecNumElts || ShMask[I] < 0) {
Constant *MaybeUndef =
Constant *MaybePoison =
ConstOp1
? ConstantFoldBinaryOpOperands(Opcode, UndefScalar, CElt, DL)
: ConstantFoldBinaryOpOperands(Opcode, CElt, UndefScalar, DL);
if (!MaybeUndef || !match(MaybeUndef, m_Undef())) {
? ConstantFoldBinaryOpOperands(Opcode, PoisonScalar, CElt, DL)
: ConstantFoldBinaryOpOperands(Opcode, CElt, PoisonScalar, DL);
if (!MaybePoison || !isa<PoisonValue>(MaybePoison)) {
MayChange = false;
break;
}
@@ -1831,9 +1831,10 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
}
if (MayChange) {
Constant *NewC = ConstantVector::get(NewVecC);
// It may not be safe to execute a binop on a vector with undef elements
// It may not be safe to execute a binop on a vector with poison elements
// because the entire instruction can be folded to undef or create poison
// that did not exist in the original code.
// TODO: The shift case should not be necessary.
if (Inst.isIntDivRem() || (Inst.isShift() && ConstOp1))
NewC = getSafeVectorConstantForBinop(Opcode, NewC, ConstOp1);

View File

@@ -557,7 +557,7 @@ define <4 x i32> @mul_const_splat(<4 x i32> %v) {
define <4 x i32> @lshr_const_half_splat(<4 x i32> %v) {
; CHECK-LABEL: @lshr_const_half_splat(
; CHECK-NEXT: [[TMP1:%.*]] = lshr <4 x i32> <i32 undef, i32 8, i32 9, i32 undef>, [[V:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = lshr <4 x i32> <i32 poison, i32 8, i32 9, i32 poison>, [[V:%.*]]
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 1, i32 2, i32 2>
; CHECK-NEXT: ret <4 x i32> [[R]]
;
@@ -659,13 +659,12 @@ define <4 x i16> @widening_shuffle_shl_constant_op1(<2 x i16> %v) {
ret <4 x i16> %bo
}
; A binop that does not produce undef in the high lanes can not be moved before the shuffle.
; This is not ok because 'shl undef, 1 (or 2)' --> 0' but moving the shuffle results in undef instead.
; This is valid for poison, but would not be valid for undef.
define <4 x i16> @widening_shuffle_shl_constant_op1_non0(<2 x i16> %v) {
; CHECK-LABEL: @widening_shuffle_shl_constant_op1_non0(
; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i16> [[V:%.*]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
; CHECK-NEXT: [[BO:%.*]] = shl <4 x i16> [[SHUF]], <i16 2, i16 4, i16 1, i16 2>
; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i16> [[V:%.*]], <i16 2, i16 4>
; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
; CHECK-NEXT: ret <4 x i16> [[BO]]
;
%shuf = shufflevector <2 x i16> %v, <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
@@ -673,13 +672,10 @@ define <4 x i16> @widening_shuffle_shl_constant_op1_non0(<2 x i16> %v) {
ret <4 x i16> %bo
}
; A binop that does not produce undef in the high lanes can not be moved before the shuffle.
; This is not ok because 'or -1, undef --> -1' but moving the shuffle results in undef instead.
define <4 x i16> @widening_shuffle_or(<2 x i16> %v) {
; CHECK-LABEL: @widening_shuffle_or(
; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i16> [[V:%.*]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
; CHECK-NEXT: [[BO:%.*]] = or <4 x i16> [[SHUF]], <i16 42, i16 -42, i16 -1, i16 -1>
; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i16> [[V:%.*]], <i16 42, i16 -42>
; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
; CHECK-NEXT: ret <4 x i16> [[BO]]
;
%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) {
define <2 x i32> @shl_splat_constant0(<2 x i32> %x) {
; CHECK-LABEL: @shl_splat_constant0(
; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> <i32 5, i32 undef>, [[X:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> <i32 5, i32 poison>, [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: ret <2 x i32> [[R]]
;
@@ -878,7 +874,7 @@ define <2 x i32> @shl_splat_constant1(<2 x i32> %x) {
define <2 x i32> @ashr_splat_constant0(<2 x i32> %x) {
; CHECK-LABEL: @ashr_splat_constant0(
; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i32> <i32 5, i32 undef>, [[X:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> <i32 5, i32 poison>, [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: ret <2 x i32> [[R]]
;
@@ -900,7 +896,7 @@ define <2 x i32> @ashr_splat_constant1(<2 x i32> %x) {
define <2 x i32> @lshr_splat_constant0(<2 x i32> %x) {
; CHECK-LABEL: @lshr_splat_constant0(
; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> <i32 5, i32 undef>, [[X:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> <i32 5, i32 poison>, [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: ret <2 x i32> [[R]]
;
@@ -1019,13 +1015,10 @@ define <2 x i32> @and_splat_constant(<2 x i32> %x) {
ret <2 x i32> %r
}
; AND does not fold to undef for undef operands, we cannot move it
; across a shuffle with undef masks.
define <4 x i16> @and_constant_mask_undef(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_undef(
define <4 x i16> @and_constant_mask_poison(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_poison(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
; CHECK-NEXT: [[AND:%.*]] = and <4 x i16> [[SHUFFLE]], <i16 0, i16 0, i16 -1, i16 -1>
; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
; CHECK-NEXT: ret <4 x i16> [[AND]]
;
entry:
@@ -1034,13 +1027,10 @@ entry:
ret <4 x i16> %and
}
; AND does not fold to undef for undef operands, we cannot move it
; across a shuffle with undef masks.
define <4 x i16> @and_constant_mask_undef_2(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_undef_2(
define <4 x i16> @and_constant_mask_poison_2(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_poison_2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 poison>
; CHECK-NEXT: [[AND:%.*]] = and <4 x i16> [[SHUFFLE]], <i16 -1, i16 -1, i16 -1, i16 0>
; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 poison>
; CHECK-NEXT: ret <4 x i16> [[AND]]
;
entry:
@@ -1050,8 +1040,8 @@ entry:
}
; We can move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes.
define <4 x i16> @and_constant_mask_undef_3(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_undef_3(
define <4 x i16> @and_constant_mask_poison_3(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_poison_3(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <4 x i16> <i16 0, i16 0, i16 0, i16 undef>
;
@@ -1062,8 +1052,8 @@ entry:
}
; We can move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes.
define <4 x i16> @and_constant_mask_undef_4(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_undef_4(
define <4 x i16> @and_constant_mask_poison_4(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_poison_4(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = and <4 x i16> [[ADD:%.*]], <i16 9, i16 20, i16 poison, i16 poison>
; 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:
ret <4 x i16> %and
}
; OR does not fold to undef for undef operands, we cannot move it
; across a shuffle with undef masks.
define <4 x i16> @or_constant_mask_undef(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_undef(
define <4 x i16> @or_constant_mask_poison(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_poison(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
; CHECK-NEXT: [[OR:%.*]] = or <4 x i16> [[SHUFFLE]], <i16 -1, i16 -1, i16 0, i16 0>
; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
; CHECK-NEXT: ret <4 x i16> [[OR]]
;
entry:
@@ -1103,13 +1090,10 @@ entry:
ret <4 x i16> %or
}
; OR does not fold to undef for undef operands, we cannot move it
; across a shuffle with undef masks.
define <4 x i16> @or_constant_mask_undef_2(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_undef_2(
define <4 x i16> @or_constant_mask_poison_2(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_poison_2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison>
; CHECK-NEXT: [[OR:%.*]] = or <4 x i16> [[SHUFFLE]], <i16 -1, i16 0, i16 0, i16 -1>
; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison>
; CHECK-NEXT: ret <4 x i16> [[OR]]
;
entry:
@@ -1119,8 +1103,8 @@ entry:
}
; We can move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes.
define <4 x i16> @or_constant_mask_undef_3(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_undef_3(
define <4 x i16> @or_constant_mask_poison_3(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_poison_3(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <4 x i16> <i16 undef, i16 -1, i16 -1, i16 undef>
;
@@ -1131,8 +1115,8 @@ entry:
}
; We can move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes.
define <4 x i16> @or_constant_mask_undef_4(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_undef_4(
define <4 x i16> @or_constant_mask_poison_4(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_poison_4(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = or <4 x i16> [[IN:%.*]], <i16 poison, i16 99, i16 poison, i16 poison>
; 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:
define <4 x i16> @shl_constant_mask_undef(<4 x i16> %in) {
; CHECK-LABEL: @shl_constant_mask_undef(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 0, i32 poison, i32 1, i32 1>
; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i16> [[SHUFFLE]], <i16 10, i16 3, i16 0, i16 0>
; CHECK-NEXT: [[TMP0:%.*]] = shl <4 x i16> [[IN:%.*]], <i16 10, i16 0, i16 0, i16 0>
; CHECK-NEXT: [[SHL:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 0, i32 poison, i32 1, i32 1>
; CHECK-NEXT: ret <4 x i16> [[SHL]]
;
entry:

View File

@@ -564,7 +564,7 @@ define <4 x i32> @mul_const_splat(<4 x i32> %v) {
define <4 x i32> @lshr_const_half_splat(<4 x i32> %v) {
; CHECK-LABEL: @lshr_const_half_splat(
; CHECK-NEXT: [[TMP1:%.*]] = lshr <4 x i32> <i32 undef, i32 8, i32 9, i32 undef>, [[V:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = lshr <4 x i32> <i32 poison, i32 8, i32 9, i32 poison>, [[V:%.*]]
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 1, i32 2, i32 2>
; CHECK-NEXT: ret <4 x i32> [[R]]
;
@@ -666,13 +666,12 @@ define <4 x i16> @widening_shuffle_shl_constant_op1(<2 x i16> %v) {
ret <4 x i16> %bo
}
; A binop that does not produce undef in the high lanes can not be moved before the shuffle.
; This is not ok because 'shl undef, 1 (or 2)' --> 0' but moving the shuffle results in undef instead.
; This is valid for poison, but would not be valid for undef.
define <4 x i16> @widening_shuffle_shl_constant_op1_non0(<2 x i16> %v) {
; CHECK-LABEL: @widening_shuffle_shl_constant_op1_non0(
; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i16> [[V:%.*]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
; CHECK-NEXT: [[BO:%.*]] = shl <4 x i16> [[SHUF]], <i16 2, i16 4, i16 1, i16 2>
; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i16> [[V:%.*]], <i16 2, i16 4>
; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
; CHECK-NEXT: ret <4 x i16> [[BO]]
;
%shuf = shufflevector <2 x i16> %v, <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
@@ -685,8 +684,8 @@ define <4 x i16> @widening_shuffle_shl_constant_op1_non0(<2 x i16> %v) {
define <4 x i16> @widening_shuffle_or(<2 x i16> %v) {
; CHECK-LABEL: @widening_shuffle_or(
; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i16> [[V:%.*]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
; CHECK-NEXT: [[BO:%.*]] = or <4 x i16> [[SHUF]], <i16 42, i16 -42, i16 -1, i16 -1>
; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i16> [[V:%.*]], <i16 42, i16 -42>
; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
; CHECK-NEXT: ret <4 x i16> [[BO]]
;
%shuf = shufflevector <2 x i16> %v, <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
@@ -863,7 +862,7 @@ define <2 x i32> @mul_splat_constant(<2 x i32> %x) {
define <2 x i32> @shl_splat_constant0(<2 x i32> %x) {
; CHECK-LABEL: @shl_splat_constant0(
; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> <i32 5, i32 undef>, [[X:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> <i32 5, i32 poison>, [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: ret <2 x i32> [[R]]
;
@@ -885,7 +884,7 @@ define <2 x i32> @shl_splat_constant1(<2 x i32> %x) {
define <2 x i32> @ashr_splat_constant0(<2 x i32> %x) {
; CHECK-LABEL: @ashr_splat_constant0(
; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i32> <i32 5, i32 undef>, [[X:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> <i32 5, i32 poison>, [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: ret <2 x i32> [[R]]
;
@@ -907,7 +906,7 @@ define <2 x i32> @ashr_splat_constant1(<2 x i32> %x) {
define <2 x i32> @lshr_splat_constant0(<2 x i32> %x) {
; CHECK-LABEL: @lshr_splat_constant0(
; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> <i32 5, i32 undef>, [[X:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> <i32 5, i32 poison>, [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: ret <2 x i32> [[R]]
;
@@ -1026,13 +1025,10 @@ define <2 x i32> @and_splat_constant(<2 x i32> %x) {
ret <2 x i32> %r
}
; AND does not fold to undef for undef operands, we cannot move it
; across a shuffle with undef masks.
define <4 x i16> @and_constant_mask_undef(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_undef(
define <4 x i16> @and_constant_mask_poison(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_poison(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
; CHECK-NEXT: [[AND:%.*]] = and <4 x i16> [[SHUFFLE]], <i16 0, i16 0, i16 -1, i16 -1>
; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
; CHECK-NEXT: ret <4 x i16> [[AND]]
;
entry:
@@ -1041,13 +1037,10 @@ entry:
ret <4 x i16> %and
}
; AND does not fold to undef for undef operands, we cannot move it
; across a shuffle with undef masks.
define <4 x i16> @and_constant_mask_undef_2(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_undef_2(
define <4 x i16> @and_constant_mask_poison_2(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_poison_2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 poison>
; CHECK-NEXT: [[AND:%.*]] = and <4 x i16> [[SHUFFLE]], <i16 -1, i16 -1, i16 -1, i16 0>
; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 poison>
; CHECK-NEXT: ret <4 x i16> [[AND]]
;
entry:
@@ -1057,8 +1050,8 @@ entry:
}
; We can move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes.
define <4 x i16> @and_constant_mask_undef_3(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_undef_3(
define <4 x i16> @and_constant_mask_poison_3(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_poison_3(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <4 x i16> <i16 0, i16 0, i16 0, i16 undef>
;
@@ -1069,8 +1062,8 @@ entry:
}
; We can move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes.
define <4 x i16> @and_constant_mask_undef_4(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_undef_4(
define <4 x i16> @and_constant_mask_poison_4(<4 x i16> %add) {
; CHECK-LABEL: @and_constant_mask_poison_4(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = and <4 x i16> [[ADD:%.*]], <i16 9, i16 20, i16 poison, i16 poison>
; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 0, i32 1, i32 1, i32 poison>
@@ -1095,13 +1088,10 @@ entry:
ret <4 x i16> %and
}
; OR does not fold to undef for undef operands, we cannot move it
; across a shuffle with undef masks.
define <4 x i16> @or_constant_mask_undef(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_undef(
define <4 x i16> @or_constant_mask_poison(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_poison(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
; CHECK-NEXT: [[OR:%.*]] = or <4 x i16> [[SHUFFLE]], <i16 -1, i16 -1, i16 0, i16 0>
; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1>
; CHECK-NEXT: ret <4 x i16> [[OR]]
;
entry:
@@ -1110,13 +1100,10 @@ entry:
ret <4 x i16> %or
}
; OR does not fold to undef for undef operands, we cannot move it
; across a shuffle with undef masks.
define <4 x i16> @or_constant_mask_undef_2(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_undef_2(
define <4 x i16> @or_constant_mask_poison_2(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_poison_2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison>
; CHECK-NEXT: [[OR:%.*]] = or <4 x i16> [[SHUFFLE]], <i16 -1, i16 0, i16 0, i16 -1>
; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison>
; CHECK-NEXT: ret <4 x i16> [[OR]]
;
entry:
@@ -1126,8 +1113,8 @@ entry:
}
; We can move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes.
define <4 x i16> @or_constant_mask_undef_3(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_undef_3(
define <4 x i16> @or_constant_mask_poison_3(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_poison_3(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <4 x i16> <i16 undef, i16 -1, i16 -1, i16 undef>
;
@@ -1138,8 +1125,8 @@ entry:
}
; We can move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes.
define <4 x i16> @or_constant_mask_undef_4(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_undef_4(
define <4 x i16> @or_constant_mask_poison_4(<4 x i16> %in) {
; CHECK-LABEL: @or_constant_mask_poison_4(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = or <4 x i16> [[IN:%.*]], <i16 poison, i16 99, i16 poison, i16 poison>
; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison>
@@ -1167,8 +1154,8 @@ entry:
define <4 x i16> @shl_constant_mask_undef(<4 x i16> %in) {
; CHECK-LABEL: @shl_constant_mask_undef(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 0, i32 poison, i32 1, i32 1>
; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i16> [[SHUFFLE]], <i16 10, i16 3, i16 0, i16 0>
; CHECK-NEXT: [[TMP0:%.*]] = shl <4 x i16> [[IN:%.*]], <i16 10, i16 0, i16 0, i16 0>
; CHECK-NEXT: [[SHL:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 0, i32 poison, i32 1, i32 1>
; CHECK-NEXT: ret <4 x i16> [[SHL]]
;
entry: