forked from OSchip/llvm-project
[InstCombine] move vector select ahead of select-shuffle
select Cond, (shuf_sel X, Y), X --> shuf_sel X, (select Cond, Y, X) A select of a select-shuffle ("blend" in x86 lingo) can be reversed so that the select is done first. This is a more limited version of what I was trying in D80658, but it enables existing demanded bits transforms to catch some of the motivating cases. The tricky bit in that seems to be that by moving the shuffle later, we can always guarantee that poison is correctly inhibited by the shuffle mask in the final value. Alive2 checks for the basic tests: http://volta.cs.utah.edu:8080/z/Qqd3RK http://volta.cs.utah.edu:8080/z/S4wchM http://volta.cs.utah.edu:8080/z/wf9zPL http://volta.cs.utah.edu:8080/z/wJeEGk Differential Revision: https://reviews.llvm.org/D81013
This commit is contained in:
parent
5f5d972d83
commit
8a96c1f627
|
@ -2403,6 +2403,43 @@ Instruction *InstCombiner::foldVectorSelect(SelectInst &Sel) {
|
|||
return &Sel;
|
||||
}
|
||||
|
||||
// A select of a "select shuffle" with a common operand can be rearranged
|
||||
// to select followed by "select shuffle". Because of poison, this only works
|
||||
// in the case of a shuffle with no undefined mask elements.
|
||||
Value *Cond = Sel.getCondition();
|
||||
Value *TVal = Sel.getTrueValue();
|
||||
Value *FVal = Sel.getFalseValue();
|
||||
Value *X, *Y;
|
||||
ArrayRef<int> Mask;
|
||||
if (match(TVal, m_OneUse(m_Shuffle(m_Value(X), m_Value(Y), m_Mask(Mask)))) &&
|
||||
!is_contained(Mask, UndefMaskElem) &&
|
||||
ShuffleVectorInst::isSelectMask(Mask)) {
|
||||
if (X == FVal) {
|
||||
// select Cond, (shuf_sel X, Y), X --> shuf_sel X, (select Cond, Y, X)
|
||||
Value *NewSel = Builder.CreateSelect(Cond, Y, X, "sel", &Sel);
|
||||
return new ShuffleVectorInst(X, NewSel, Mask);
|
||||
}
|
||||
if (Y == FVal) {
|
||||
// select Cond, (shuf_sel X, Y), Y --> shuf_sel (select Cond, X, Y), Y
|
||||
Value *NewSel = Builder.CreateSelect(Cond, X, Y, "sel", &Sel);
|
||||
return new ShuffleVectorInst(NewSel, Y, Mask);
|
||||
}
|
||||
}
|
||||
if (match(FVal, m_OneUse(m_Shuffle(m_Value(X), m_Value(Y), m_Mask(Mask)))) &&
|
||||
!is_contained(Mask, UndefMaskElem) &&
|
||||
ShuffleVectorInst::isSelectMask(Mask)) {
|
||||
if (X == TVal) {
|
||||
// select Cond, X, (shuf_sel X, Y) --> shuf_sel X, (select Cond, X, Y)
|
||||
Value *NewSel = Builder.CreateSelect(Cond, X, Y, "sel", &Sel);
|
||||
return new ShuffleVectorInst(X, NewSel, Mask);
|
||||
}
|
||||
if (Y == TVal) {
|
||||
// select Cond, Y, (shuf_sel X, Y) --> shuf_sel (select Cond, Y, X), Y
|
||||
Value *NewSel = Builder.CreateSelect(Cond, Y, X, "sel", &Sel);
|
||||
return new ShuffleVectorInst(NewSel, Y, Mask);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,10 +44,12 @@ define <2 x i32> @foo3(<2 x i1> %vec_bool, i1 %bool, <2 x i32> %V) {
|
|||
ret <2 x i32> %sel1
|
||||
}
|
||||
|
||||
; Four variations of (select (select-shuffle)) with a common operand.
|
||||
|
||||
define <4 x i8> @sel_shuf_commute0(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) {
|
||||
; CHECK-LABEL: @sel_shuf_commute0(
|
||||
; CHECK-NEXT: [[BLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
|
||||
; CHECK-NEXT: [[R:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x i8> [[BLEND]], <4 x i8> [[X]]
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x i8> [[Y:%.*]], <4 x i8> [[X:%.*]]
|
||||
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[X]], <4 x i8> [[SEL]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
|
||||
; CHECK-NEXT: ret <4 x i8> [[R]]
|
||||
;
|
||||
%blend = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
|
||||
|
@ -55,10 +57,12 @@ define <4 x i8> @sel_shuf_commute0(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) {
|
|||
ret <4 x i8> %r
|
||||
}
|
||||
|
||||
; Weird types are ok.
|
||||
|
||||
define <5 x i9> @sel_shuf_commute1(<5 x i9> %x, <5 x i9> %y, <5 x i1> %cmp) {
|
||||
; CHECK-LABEL: @sel_shuf_commute1(
|
||||
; CHECK-NEXT: [[BLEND:%.*]] = shufflevector <5 x i9> [[X:%.*]], <5 x i9> [[Y:%.*]], <5 x i32> <i32 0, i32 6, i32 2, i32 8, i32 9>
|
||||
; CHECK-NEXT: [[R:%.*]] = select <5 x i1> [[CMP:%.*]], <5 x i9> [[BLEND]], <5 x i9> [[Y]]
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select <5 x i1> [[CMP:%.*]], <5 x i9> [[X:%.*]], <5 x i9> [[Y:%.*]]
|
||||
; CHECK-NEXT: [[R:%.*]] = shufflevector <5 x i9> [[SEL]], <5 x i9> [[Y]], <5 x i32> <i32 0, i32 6, i32 2, i32 8, i32 9>
|
||||
; CHECK-NEXT: ret <5 x i9> [[R]]
|
||||
;
|
||||
%blend = shufflevector <5 x i9> %x, <5 x i9> %y, <5 x i32> <i32 0, i32 6, i32 2, i32 8, i32 9>
|
||||
|
@ -68,8 +72,8 @@ define <5 x i9> @sel_shuf_commute1(<5 x i9> %x, <5 x i9> %y, <5 x i1> %cmp) {
|
|||
|
||||
define <4 x float> @sel_shuf_commute2(<4 x float> %x, <4 x float> %y, <4 x i1> %cmp) {
|
||||
; CHECK-LABEL: @sel_shuf_commute2(
|
||||
; CHECK-NEXT: [[BLEND:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> [[Y:%.*]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>
|
||||
; CHECK-NEXT: [[R:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x float> [[X]], <4 x float> [[BLEND]]
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x float> [[X:%.*]], <4 x float> [[Y:%.*]]
|
||||
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x float> [[X]], <4 x float> [[SEL]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>
|
||||
; CHECK-NEXT: ret <4 x float> [[R]]
|
||||
;
|
||||
%blend = shufflevector <4 x float> %x, <4 x float> %y, <4 x i32> <i32 0, i32 1, i32 2, i32 7>
|
||||
|
@ -77,10 +81,12 @@ define <4 x float> @sel_shuf_commute2(<4 x float> %x, <4 x float> %y, <4 x i1> %
|
|||
ret <4 x float> %r
|
||||
}
|
||||
|
||||
; Scalar condition is ok.
|
||||
|
||||
define <4 x i8> @sel_shuf_commute3(<4 x i8> %x, <4 x i8> %y, i1 %cmp) {
|
||||
; CHECK-LABEL: @sel_shuf_commute3(
|
||||
; CHECK-NEXT: [[BLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 3>
|
||||
; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP:%.*]], <4 x i8> [[Y]], <4 x i8> [[BLEND]]
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP:%.*]], <4 x i8> [[Y:%.*]], <4 x i8> [[X:%.*]]
|
||||
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[SEL]], <4 x i8> [[Y]], <4 x i32> <i32 0, i32 5, i32 2, i32 3>
|
||||
; CHECK-NEXT: ret <4 x i8> [[R]]
|
||||
;
|
||||
%blend = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 2, i32 3>
|
||||
|
@ -90,6 +96,8 @@ define <4 x i8> @sel_shuf_commute3(<4 x i8> %x, <4 x i8> %y, i1 %cmp) {
|
|||
|
||||
declare void @use(<4 x i8>)
|
||||
|
||||
; Negative test - extra use would require another instruction.
|
||||
|
||||
define <4 x i8> @sel_shuf_use(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) {
|
||||
; CHECK-LABEL: @sel_shuf_use(
|
||||
; CHECK-NEXT: [[BLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
|
||||
|
@ -103,6 +111,8 @@ define <4 x i8> @sel_shuf_use(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) {
|
|||
ret <4 x i8> %r
|
||||
}
|
||||
|
||||
; Negative test - undef in shuffle mask prevents transform.
|
||||
|
||||
define <4 x i8> @sel_shuf_undef(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) {
|
||||
; CHECK-LABEL: @sel_shuf_undef(
|
||||
; CHECK-NEXT: [[BLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 undef>
|
||||
|
@ -114,6 +124,8 @@ define <4 x i8> @sel_shuf_undef(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) {
|
|||
ret <4 x i8> %r
|
||||
}
|
||||
|
||||
; Negative test - not a "select shuffle"
|
||||
|
||||
define <4 x i8> @sel_shuf_not(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) {
|
||||
; CHECK-LABEL: @sel_shuf_not(
|
||||
; CHECK-NEXT: [[NOTBLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 6>
|
||||
|
@ -125,6 +137,8 @@ define <4 x i8> @sel_shuf_not(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) {
|
|||
ret <4 x i8> %r
|
||||
}
|
||||
|
||||
; Negative test - must shuffle one of the select operands
|
||||
|
||||
define <4 x i8> @sel_shuf_no_common_operand(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp, <4 x i8> %z) {
|
||||
; CHECK-LABEL: @sel_shuf_no_common_operand(
|
||||
; CHECK-NEXT: [[BLEND:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 3>
|
||||
|
|
|
@ -677,9 +677,8 @@ bb:
|
|||
|
||||
define <4 x i8> @select_cond_with_eq_true_false_elts(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) {
|
||||
; CHECK-LABEL: @select_cond_with_eq_true_false_elts(
|
||||
; CHECK-NEXT: [[TVAL:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 6, i32 7>
|
||||
; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x i1> [[CMP:%.*]], <4 x i1> undef, <4 x i32> zeroinitializer
|
||||
; CHECK-NEXT: [[R:%.*]] = select <4 x i1> [[SPLAT]], <4 x i8> [[TVAL]], <4 x i8> [[Y]]
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]]
|
||||
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[SEL]], <4 x i8> [[Y]], <4 x i32> <i32 0, i32 5, i32 6, i32 7>
|
||||
; CHECK-NEXT: ret <4 x i8> [[R]]
|
||||
;
|
||||
%tval = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
|
||||
|
@ -692,9 +691,9 @@ define <4 x i8> @select_cond_with_eq_true_false_elts(<4 x i8> %x, <4 x i8> %y, <
|
|||
|
||||
define <4 x i8> @select_cond_with_eq_true_false_elts2(<4 x i8> %x, <4 x i8> %y, <4 x i1> %cmp) {
|
||||
; CHECK-LABEL: @select_cond_with_eq_true_false_elts2(
|
||||
; CHECK-NEXT: [[TVAL:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 6, i32 7>
|
||||
; CHECK-NEXT: [[COND:%.*]] = shufflevector <4 x i1> [[CMP:%.*]], <4 x i1> undef, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
|
||||
; CHECK-NEXT: [[R:%.*]] = select <4 x i1> [[COND]], <4 x i8> [[TVAL]], <4 x i8> [[X]]
|
||||
; CHECK-NEXT: [[COND:%.*]] = shufflevector <4 x i1> [[CMP:%.*]], <4 x i1> undef, <4 x i32> <i32 undef, i32 1, i32 0, i32 1>
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select <4 x i1> [[COND]], <4 x i8> [[Y:%.*]], <4 x i8> [[X:%.*]]
|
||||
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[X]], <4 x i8> [[SEL]], <4 x i32> <i32 0, i32 5, i32 6, i32 7>
|
||||
; CHECK-NEXT: ret <4 x i8> [[R]]
|
||||
;
|
||||
%tval = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
|
||||
|
@ -734,13 +733,12 @@ define <4 x i8> @select_cond_with_undef_true_false_elts(<4 x i8> %x, <4 x i8> %y
|
|||
ret <4 x i8> %r
|
||||
}
|
||||
|
||||
; The insert can not be safely eliminated because cmp[0] might be poison.
|
||||
; The insert can be safely eliminated because the shuffle blocks poison from cmp[0].
|
||||
|
||||
define <4 x i8> @select_cond_(<4 x i8> %x, <4 x i8> %min, <4 x i1> %cmp, i1 %poison_blocker) {
|
||||
; CHECK-LABEL: @select_cond_(
|
||||
; CHECK-NEXT: [[INS:%.*]] = insertelement <4 x i1> [[CMP:%.*]], i1 [[POISON_BLOCKER:%.*]], i32 0
|
||||
; CHECK-NEXT: [[VECINS:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[MIN:%.*]], <4 x i32> <i32 0, i32 5, i32 6, i32 7>
|
||||
; CHECK-NEXT: [[R:%.*]] = select <4 x i1> [[INS]], <4 x i8> [[VECINS]], <4 x i8> [[X]]
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select <4 x i1> [[CMP:%.*]], <4 x i8> [[MIN:%.*]], <4 x i8> [[X:%.*]]
|
||||
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[X]], <4 x i8> [[SEL]], <4 x i32> <i32 0, i32 5, i32 6, i32 7>
|
||||
; CHECK-NEXT: ret <4 x i8> [[R]]
|
||||
;
|
||||
%ins = insertelement <4 x i1> %cmp, i1 %poison_blocker, i32 0
|
||||
|
|
Loading…
Reference in New Issue