Skip to content

Commit 957eed0

Browse files
committed
[InstCombine] Remove redundant splats in InstCombineVectorOps
Splatting the first vector element of the result of a BinOp, where any of the BinOp's operands are the result of a first vector element splat can be simplified to splatting the first vector element of the result of the BinOp Differential Revision: https://reviews.llvm.org/D135876
1 parent 093200f commit 957eed0

File tree

4 files changed

+78
-231
lines changed

4 files changed

+78
-231
lines changed

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
167167
Instruction *visitInsertValueInst(InsertValueInst &IV);
168168
Instruction *visitInsertElementInst(InsertElementInst &IE);
169169
Instruction *visitExtractElementInst(ExtractElementInst &EI);
170+
Instruction *simplifyBinOpSplats(ShuffleVectorInst &SVI);
170171
Instruction *visitShuffleVectorInst(ShuffleVectorInst &SVI);
171172
Instruction *visitExtractValueInst(ExtractValueInst &EV);
172173
Instruction *visitLandingPadInst(LandingPadInst &LI);

llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2598,6 +2598,34 @@ static Instruction *foldIdentityPaddedShuffles(ShuffleVectorInst &Shuf) {
25982598
return new ShuffleVectorInst(X, Y, NewMask);
25992599
}
26002600

2601+
// Splatting the first element of the result of a BinOp, where any of the
2602+
// BinOp's operands are the result of a first element splat can be simplified to
2603+
// splatting the first element of the result of the BinOp
2604+
Instruction *InstCombinerImpl::simplifyBinOpSplats(ShuffleVectorInst &SVI) {
2605+
if (!SVI.isZeroEltSplat())
2606+
return nullptr;
2607+
2608+
Value *Op0 = SVI.getOperand(0);
2609+
Value *X, *Y;
2610+
if (!match(Op0, m_BinOp(m_Shuffle(m_Value(X), m_Undef(), m_ZeroMask()),
2611+
m_Value(Y))) &&
2612+
!match(Op0, m_BinOp(m_Value(X),
2613+
m_Shuffle(m_Value(Y), m_Undef(), m_ZeroMask()))))
2614+
return nullptr;
2615+
if (X->getType() != Y->getType())
2616+
return nullptr;
2617+
2618+
auto *BinOp = cast<BinaryOperator>(Op0);
2619+
if (!isSafeToSpeculativelyExecute(BinOp))
2620+
return nullptr;
2621+
2622+
Value *NewBO = Builder.CreateBinOp(BinOp->getOpcode(), X, Y);
2623+
if (auto NewBOI = dyn_cast<Instruction>(NewBO))
2624+
NewBOI->copyIRFlags(BinOp);
2625+
2626+
return new ShuffleVectorInst(NewBO, SVI.getShuffleMask());
2627+
}
2628+
26012629
Instruction *InstCombinerImpl::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
26022630
Value *LHS = SVI.getOperand(0);
26032631
Value *RHS = SVI.getOperand(1);
@@ -2606,7 +2634,9 @@ Instruction *InstCombinerImpl::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
26062634
SVI.getType(), ShufQuery))
26072635
return replaceInstUsesWith(SVI, V);
26082636

2609-
// Bail out for scalable vectors
2637+
if (Instruction *I = simplifyBinOpSplats(SVI))
2638+
return I;
2639+
26102640
if (isa<ScalableVectorType>(LHS->getType()))
26112641
return nullptr;
26122642

llvm/test/Transforms/InstCombine/shuffle-binop.ll

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ define <4 x i8> @splat_binop_splat_x(<4 x i8> %x, <4 x i8> %y) {
5050
; CHECK-LABEL: @splat_binop_splat_x(
5151
; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> zeroinitializer
5252
; CHECK-NEXT: call void @use(<4 x i8> [[XSPLAT]])
53-
; CHECK-NEXT: [[B:%.*]] = add <4 x i8> [[XSPLAT]], [[Y:%.*]]
54-
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <4 x i8> [[B]], <4 x i8> poison, <4 x i32> zeroinitializer
53+
; CHECK-NEXT: [[TMP1:%.*]] = add nsw <4 x i8> [[X]], [[Y:%.*]]
54+
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <4 x i32> zeroinitializer
5555
; CHECK-NEXT: ret <4 x i8> [[BSPLAT]]
5656
;
5757
%xsplat = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> zeroinitializer
5858
call void @use(<4 x i8> %xsplat)
59-
%b = add <4 x i8> %xsplat, %y
59+
%b = add nsw <4 x i8> %xsplat, %y
6060
%bsplat = shufflevector <4 x i8> %b, <4 x i8> poison, <4 x i32> zeroinitializer
6161
ret <4 x i8> %bsplat
6262
}
@@ -65,14 +65,14 @@ define <4 x i8> @splat_binop_splat_y(<4 x i8> %x, <4 x i8> %y) {
6565
; CHECK-LABEL: @splat_binop_splat_y(
6666
; CHECK-NEXT: [[YSPLAT:%.*]] = shufflevector <4 x i8> [[Y:%.*]], <4 x i8> poison, <4 x i32> zeroinitializer
6767
; CHECK-NEXT: call void @use(<4 x i8> [[YSPLAT]])
68-
; CHECK-NEXT: [[B:%.*]] = sub <4 x i8> [[X:%.*]], [[YSPLAT]]
69-
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <4 x i8> [[B]], <4 x i8> poison, <4 x i32> zeroinitializer
68+
; CHECK-NEXT: [[TMP1:%.*]] = sub <4 x i8> [[X:%.*]], [[Y]]
69+
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <4 x i32> <i32 undef, i32 0, i32 0, i32 0>
7070
; CHECK-NEXT: ret <4 x i8> [[BSPLAT]]
7171
;
7272
%ysplat = shufflevector <4 x i8> %y, <4 x i8> poison, <4 x i32> zeroinitializer
7373
call void @use(<4 x i8> %ysplat)
7474
%b = sub <4 x i8> %x, %ysplat
75-
%bsplat = shufflevector <4 x i8> %b, <4 x i8> poison, <4 x i32> zeroinitializer
75+
%bsplat = shufflevector <4 x i8> %b, <4 x i8> poison, <4 x i32><i32 poison, i32 0, i32 0, i32 0>
7676
ret <4 x i8> %bsplat
7777
}
7878

@@ -82,21 +82,40 @@ define <4 x i8> @splat_binop_splat_x_splat_y(<4 x i8> %x, <4 x i8> %y) {
8282
; CHECK-NEXT: call void @use(<4 x i8> [[XSPLAT]])
8383
; CHECK-NEXT: [[YSPLAT:%.*]] = shufflevector <4 x i8> [[Y:%.*]], <4 x i8> poison, <4 x i32> zeroinitializer
8484
; CHECK-NEXT: call void @use(<4 x i8> [[YSPLAT]])
85-
; CHECK-NEXT: [[B:%.*]] = mul <4 x i8> [[XSPLAT]], [[YSPLAT]]
86-
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <4 x i8> [[B]], <4 x i8> poison, <4 x i32> zeroinitializer
85+
; CHECK-NEXT: [[TMP1:%.*]] = mul nuw <4 x i8> [[Y]], [[X]]
86+
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <4 x i32> zeroinitializer
8787
; CHECK-NEXT: ret <4 x i8> [[BSPLAT]]
8888
;
8989
%xsplat = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> zeroinitializer
9090
call void @use(<4 x i8> %xsplat)
9191
%ysplat = shufflevector <4 x i8> %y, <4 x i8> poison, <4 x i32> zeroinitializer
9292
call void @use(<4 x i8> %ysplat)
93-
%b = mul <4 x i8> %xsplat, %ysplat
93+
%b = mul nuw <4 x i8> %xsplat, %ysplat
9494
%bsplat = shufflevector <4 x i8> %b, <4 x i8> poison, <4 x i32> zeroinitializer
9595
ret <4 x i8> %bsplat
9696
}
9797

98-
define <vscale x 4 x i32> @vscale_splat_binop_splat_x(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {
99-
; CHECK-LABEL: @vscale_splat_binop_splat_x(
98+
define <4 x float> @splat_binop_splat_x_splat_y_fmath_flags(<4 x float> %x, <4 x float> %y) {
99+
; CHECK-LABEL: @splat_binop_splat_x_splat_y_fmath_flags(
100+
; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> poison, <4 x i32> zeroinitializer
101+
; CHECK-NEXT: call void @use(<4 x float> [[XSPLAT]])
102+
; CHECK-NEXT: [[YSPLAT:%.*]] = shufflevector <4 x float> [[Y:%.*]], <4 x float> poison, <4 x i32> zeroinitializer
103+
; CHECK-NEXT: call void @use(<4 x float> [[YSPLAT]])
104+
; CHECK-NEXT: [[TMP1:%.*]] = fmul fast <4 x float> [[Y]], [[X]]
105+
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <4 x float> [[TMP1]], <4 x float> poison, <4 x i32> zeroinitializer
106+
; CHECK-NEXT: ret <4 x float> [[BSPLAT]]
107+
;
108+
%xsplat = shufflevector <4 x float> %x, <4 x float> poison, <4 x i32> zeroinitializer
109+
call void @use(<4 x float> %xsplat)
110+
%ysplat = shufflevector <4 x float> %y, <4 x float> poison, <4 x i32> zeroinitializer
111+
call void @use(<4 x float> %ysplat)
112+
%b = fmul fast <4 x float> %xsplat, %ysplat
113+
%bsplat = shufflevector <4 x float> %b, <4 x float> poison, <4 x i32> zeroinitializer
114+
ret <4 x float> %bsplat
115+
}
116+
117+
define <vscale x 4 x i32> @vscale_splat_udiv_splat_x(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {
118+
; CHECK-LABEL: @vscale_splat_udiv_splat_x(
100119
; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[X:%.*]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
101120
; CHECK-NEXT: [[B:%.*]] = udiv <vscale x 4 x i32> [[XSPLAT]], [[Y:%.*]]
102121
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[B]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
@@ -108,6 +127,19 @@ define <vscale x 4 x i32> @vscale_splat_binop_splat_x(<vscale x 4 x i32> %x, <vs
108127
ret <vscale x 4 x i32> %bsplat
109128
}
110129

130+
define <vscale x 4 x i32> @vscale_splat_urem_splat_x(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {
131+
; CHECK-LABEL: @vscale_splat_urem_splat_x(
132+
; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[X:%.*]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
133+
; CHECK-NEXT: [[B:%.*]] = urem <vscale x 4 x i32> [[XSPLAT]], [[Y:%.*]]
134+
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[B]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
135+
; CHECK-NEXT: ret <vscale x 4 x i32> [[BSPLAT]]
136+
;
137+
%xsplat = shufflevector <vscale x 4 x i32> %x, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
138+
%b = urem <vscale x 4 x i32> %xsplat, %y
139+
%bsplat = shufflevector <vscale x 4 x i32> %b, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
140+
ret <vscale x 4 x i32> %bsplat
141+
}
142+
111143
define <vscale x 4 x i32> @vscale_splat_binop_splat_y(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {
112144
; CHECK-LABEL: @vscale_splat_binop_splat_y(
113145
; CHECK-NEXT: [[YSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[Y:%.*]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
@@ -140,8 +172,8 @@ define <vscale x 4 x i32> @vscale_splat_binop_splat_x_splat_y_calls(<vscale x 4
140172
; CHECK-NEXT: call void @use_v(<vscale x 4 x i32> [[XSPLAT]])
141173
; CHECK-NEXT: [[YSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[Y:%.*]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
142174
; CHECK-NEXT: call void @use_v(<vscale x 4 x i32> [[YSPLAT]])
143-
; CHECK-NEXT: [[B:%.*]] = lshr <vscale x 4 x i32> [[XSPLAT]], [[YSPLAT]]
144-
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[B]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
175+
; CHECK-NEXT: [[TMP1:%.*]] = lshr <vscale x 4 x i32> [[X]], [[Y]]
176+
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[TMP1]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
145177
; CHECK-NEXT: ret <vscale x 4 x i32> [[BSPLAT]]
146178
;
147179
%xsplat = shufflevector <vscale x 4 x i32> %x, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
@@ -154,4 +186,4 @@ define <vscale x 4 x i32> @vscale_splat_binop_splat_x_splat_y_calls(<vscale x 4
154186
}
155187

156188
declare void @use(<4 x i8>)
157-
declare void @use_v(<vscale x 4 x i32>)
189+
declare void @use_v(<vscale x 4 x i32>)

0 commit comments

Comments
 (0)