Skip to content

Commit 8c65515

Browse files
committed
[InstCombine] fix undef propagation bug with shuffle+binop
When we have a shuffle that extends a source vector with undefs and then do some binop on that, we must make sure that the extra elements remain undef with that binop if we reverse the order of the binop and shuffle. 'or' is probably the easiest example to show the bug because 'or C, undef --> -1' (not undef). But there are other opcode/constant combinations where this is true as shown by the 'shl' test. llvm-svn: 348191
1 parent 660f9c9 commit 8c65515

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,6 +1455,22 @@ Instruction *InstCombiner::foldVectorBinop(BinaryOperator &Inst) {
14551455
}
14561456
NewVecC[ShMask[I]] = CElt;
14571457
}
1458+
// If this is a widening shuffle, we must be able to extend with undef
1459+
// elements. If the original binop does not produce an undef in the high
1460+
// lanes, then this transform is not safe.
1461+
// TODO: We could shuffle those non-undef constant values into the
1462+
// result by using a constant vector (rather than an undef vector)
1463+
// as operand 1 of the new binop, but that might be too aggressive
1464+
// for target-independent shuffle creation.
1465+
if (I >= SrcVecNumElts) {
1466+
Constant *MaybeUndef =
1467+
ConstOp1 ? ConstantExpr::get(Opcode, UndefScalar, CElt)
1468+
: ConstantExpr::get(Opcode, CElt, UndefScalar);
1469+
if (!isa<UndefValue>(MaybeUndef)) {
1470+
MayChange = false;
1471+
break;
1472+
}
1473+
}
14581474
}
14591475
if (MayChange) {
14601476
Constant *NewC = ConstantVector::get(NewVecC);

llvm/test/Transforms/InstCombine/vec_shuffle.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -633,27 +633,27 @@ define <4 x i16> @widening_shuffle_shl_constant_op1(<2 x i16> %v) {
633633
ret <4 x i16> %bo
634634
}
635635

636-
; FIXME: A binop that does not produce undef in the high lanes can not be moved before the shuffle.
636+
; A binop that does not produce undef in the high lanes can not be moved before the shuffle.
637637
; This is not ok because 'shl undef, 1 (or 2)' --> 0' but moving the shuffle results in undef instead.
638638

639639
define <4 x i16> @widening_shuffle_shl_constant_op1_non0(<2 x i16> %v) {
640640
; CHECK-LABEL: @widening_shuffle_shl_constant_op1_non0(
641-
; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i16> [[V:%.*]], <i16 2, i16 4>
642-
; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
641+
; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i16> [[V:%.*]], <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
642+
; CHECK-NEXT: [[BO:%.*]] = shl <4 x i16> [[SHUF]], <i16 2, i16 4, i16 1, i16 2>
643643
; CHECK-NEXT: ret <4 x i16> [[BO]]
644644
;
645645
%shuf = shufflevector <2 x i16> %v, <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
646646
%bo = shl <4 x i16> %shuf, <i16 2, i16 4, i16 1, i16 2>
647647
ret <4 x i16> %bo
648648
}
649649

650-
; FIXME: A binop that does not produce undef in the high lanes can not be moved before the shuffle.
650+
; A binop that does not produce undef in the high lanes can not be moved before the shuffle.
651651
; This is not ok because 'or -1, undef --> -1' but moving the shuffle results in undef instead.
652652

653653
define <4 x i16> @widening_shuffle_or(<2 x i16> %v) {
654654
; CHECK-LABEL: @widening_shuffle_or(
655-
; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i16> [[V:%.*]], <i16 42, i16 -42>
656-
; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
655+
; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i16> [[V:%.*]], <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
656+
; CHECK-NEXT: [[BO:%.*]] = or <4 x i16> [[SHUF]], <i16 42, i16 -42, i16 -1, i16 -1>
657657
; CHECK-NEXT: ret <4 x i16> [[BO]]
658658
;
659659
%shuf = shufflevector <2 x i16> %v, <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>

0 commit comments

Comments
 (0)