Skip to content

Commit b331a7e

Browse files
committed
[InstCombine] canonicalize fneg after shuffle
For the unary shuffle pattern, this is opposite to what we try to do with binops, but it seems better to keep it consistent with the motivating binary shuffle pattern. On that, it is clearly better on the usual no-extra uses case. There is a chance that this will pull an fneg away from some other binop and cause a regression in codegen, but that should be invertible in the backend. The transform is birectional: https://alive2.llvm.org/ce/z/kKaKCU https://alive2.llvm.org/ce/z/3Desfw Fixes #45631
1 parent ef9d39d commit b331a7e

File tree

3 files changed

+64
-19
lines changed

3 files changed

+64
-19
lines changed

llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2242,6 +2242,39 @@ static Instruction *narrowVectorSelect(ShuffleVectorInst &Shuf,
22422242
return SelectInst::Create(NarrowCond, NarrowX, NarrowY);
22432243
}
22442244

2245+
/// Canonicalize FP negate after shuffle.
2246+
static Instruction *foldFNegShuffle(ShuffleVectorInst &Shuf,
2247+
InstCombiner::BuilderTy &Builder) {
2248+
Instruction *FNeg0;
2249+
Value *X;
2250+
if (!match(Shuf.getOperand(0), m_CombineAnd(m_Instruction(FNeg0),
2251+
m_FNeg(m_Value(X)))))
2252+
return nullptr;
2253+
2254+
// shuffle (fneg X), Mask --> fneg (shuffle X, Mask)
2255+
if (FNeg0->hasOneUse() && match(Shuf.getOperand(1), m_Undef())) {
2256+
Value *NewShuf = Builder.CreateShuffleVector(X, Shuf.getShuffleMask());
2257+
return UnaryOperator::CreateFNegFMF(NewShuf, FNeg0);
2258+
}
2259+
2260+
Instruction *FNeg1;
2261+
Value *Y;
2262+
if (!match(Shuf.getOperand(1), m_CombineAnd(m_Instruction(FNeg1),
2263+
m_FNeg(m_Value(Y)))))
2264+
return nullptr;
2265+
2266+
// shuffle (fneg X), (fneg Y), Mask --> fneg (shuffle X, Y, Mask)
2267+
if (FNeg0->hasOneUse() || FNeg1->hasOneUse()) {
2268+
Value *NewShuf = Builder.CreateShuffleVector(X, Y, Shuf.getShuffleMask());
2269+
Instruction *NewFNeg = UnaryOperator::CreateFNeg(NewShuf);
2270+
NewFNeg->copyIRFlags(FNeg0);
2271+
NewFNeg->andIRFlags(FNeg1);
2272+
return NewFNeg;
2273+
}
2274+
2275+
return nullptr;
2276+
}
2277+
22452278
/// Try to fold an extract subvector operation.
22462279
static Instruction *foldIdentityExtractShuffle(ShuffleVectorInst &Shuf) {
22472280
Value *Op0 = Shuf.getOperand(0), *Op1 = Shuf.getOperand(1);
@@ -2537,6 +2570,9 @@ Instruction *InstCombinerImpl::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
25372570
if (Instruction *I = narrowVectorSelect(SVI, Builder))
25382571
return I;
25392572

2573+
if (Instruction *I = foldFNegShuffle(SVI, Builder))
2574+
return I;
2575+
25402576
APInt UndefElts(VWidth, 0);
25412577
APInt AllOnesEltMask(APInt::getAllOnes(VWidth));
25422578
if (Value *V = SimplifyDemandedVectorElts(&SVI, AllOnesEltMask, UndefElts)) {

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -749,8 +749,8 @@ define <8 x i8> @pr19730(<16 x i8> %in0) {
749749

750750
define i32 @pr19737(<4 x i32> %in0) {
751751
; CHECK-LABEL: @pr19737(
752-
; CHECK-NEXT: [[RV:%.*]] = extractelement <4 x i32> [[IN0:%.*]], i64 0
753-
; CHECK-NEXT: ret i32 [[RV]]
752+
; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x i32> [[IN0:%.*]], i64 0
753+
; CHECK-NEXT: ret i32 [[TMP1]]
754754
;
755755
%shuffle.i = shufflevector <4 x i32> zeroinitializer, <4 x i32> %in0, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
756756
%neg.i = xor <4 x i32> %shuffle.i, <i32 -1, i32 -1, i32 -1, i32 -1>
@@ -1277,8 +1277,8 @@ define <2 x float> @fsub_splat_constant1(<2 x float> %x) {
12771277

12781278
define <2 x float> @fneg(<2 x float> %x) {
12791279
; CHECK-LABEL: @fneg(
1280-
; CHECK-NEXT: [[TMP1:%.*]] = fneg <2 x float> [[X:%.*]]
1281-
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer
1280+
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> zeroinitializer
1281+
; CHECK-NEXT: [[R:%.*]] = fneg <2 x float> [[TMP1]]
12821282
; CHECK-NEXT: ret <2 x float> [[R]]
12831283
;
12841284
%splat = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> zeroinitializer

llvm/test/Transforms/InstCombine/vec_shuffle.ll

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,8 +1278,8 @@ define <2 x float> @fsub_splat_constant1(<2 x float> %x) {
12781278

12791279
define <2 x float> @fneg(<2 x float> %x) {
12801280
; CHECK-LABEL: @fneg(
1281-
; CHECK-NEXT: [[TMP1:%.*]] = fneg <2 x float> [[X:%.*]]
1282-
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer
1281+
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> zeroinitializer
1282+
; CHECK-NEXT: [[R:%.*]] = fneg <2 x float> [[TMP1]]
12831283
; CHECK-NEXT: ret <2 x float> [[R]]
12841284
;
12851285
%splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer
@@ -1791,8 +1791,8 @@ define <4 x i32> @PR46872(<4 x i32> %x) {
17911791

17921792
define <2 x float> @fneg_unary_shuf(<2 x float> %x) {
17931793
; CHECK-LABEL: @fneg_unary_shuf(
1794-
; CHECK-NEXT: [[NX:%.*]] = fneg nnan nsz <2 x float> [[X:%.*]]
1795-
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[NX]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
1794+
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0>
1795+
; CHECK-NEXT: [[R:%.*]] = fneg nnan nsz <2 x float> [[TMP1]]
17961796
; CHECK-NEXT: ret <2 x float> [[R]]
17971797
;
17981798
%nx = fneg nsz nnan <2 x float> %x
@@ -1802,8 +1802,8 @@ define <2 x float> @fneg_unary_shuf(<2 x float> %x) {
18021802

18031803
define <4 x half> @fneg_unary_shuf_widen(<2 x half> %x) {
18041804
; CHECK-LABEL: @fneg_unary_shuf_widen(
1805-
; CHECK-NEXT: [[NX:%.*]] = fneg ninf <2 x half> [[X:%.*]]
1806-
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x half> [[NX]], <2 x half> poison, <4 x i32> <i32 1, i32 0, i32 0, i32 undef>
1805+
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x half> [[X:%.*]], <2 x half> poison, <4 x i32> <i32 1, i32 0, i32 0, i32 undef>
1806+
; CHECK-NEXT: [[R:%.*]] = fneg ninf <4 x half> [[TMP1]]
18071807
; CHECK-NEXT: ret <4 x half> [[R]]
18081808
;
18091809
%nx = fneg ninf <2 x half> %x
@@ -1813,15 +1813,17 @@ define <4 x half> @fneg_unary_shuf_widen(<2 x half> %x) {
18131813

18141814
define <2 x double> @fneg_unary_shuf_narrow(<4 x double> %x) {
18151815
; CHECK-LABEL: @fneg_unary_shuf_narrow(
1816-
; CHECK-NEXT: [[NX:%.*]] = fneg nsz <4 x double> [[X:%.*]]
1817-
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x double> [[NX]], <4 x double> poison, <2 x i32> <i32 3, i32 0>
1816+
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x double> [[X:%.*]], <4 x double> poison, <2 x i32> <i32 3, i32 0>
1817+
; CHECK-NEXT: [[R:%.*]] = fneg nsz <2 x double> [[TMP1]]
18181818
; CHECK-NEXT: ret <2 x double> [[R]]
18191819
;
18201820
%nx = fneg nsz <4 x double> %x
18211821
%r = shufflevector <4 x double> %nx, <4 x double> poison, <2 x i32> <i32 3, i32 0>
18221822
ret <2 x double> %r
18231823
}
18241824

1825+
; negative test - extra use prevents canonicalization
1826+
18251827
define <2 x float> @fneg_unary_shuf_use(<2 x float> %x) {
18261828
; CHECK-LABEL: @fneg_unary_shuf_use(
18271829
; CHECK-NEXT: [[NX:%.*]] = fneg nsz <2 x float> [[X:%.*]]
@@ -1835,11 +1837,12 @@ define <2 x float> @fneg_unary_shuf_use(<2 x float> %x) {
18351837
ret <2 x float> %r
18361838
}
18371839

1840+
; intersect FMF
1841+
18381842
define <4 x float> @fneg_shuf(<4 x float> %x, <4 x float> %y) {
18391843
; CHECK-LABEL: @fneg_shuf(
1840-
; CHECK-NEXT: [[NX:%.*]] = fneg ninf nsz <4 x float> [[X:%.*]]
1841-
; CHECK-NEXT: [[NY:%.*]] = fneg nnan ninf <4 x float> [[Y:%.*]]
1842-
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x float> [[NX]], <4 x float> [[NY]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
1844+
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> [[Y:%.*]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
1845+
; CHECK-NEXT: [[R:%.*]] = fneg ninf <4 x float> [[TMP1]]
18431846
; CHECK-NEXT: ret <4 x float> [[R]]
18441847
;
18451848
%nx = fneg nsz ninf <4 x float> %x
@@ -1848,12 +1851,14 @@ define <4 x float> @fneg_shuf(<4 x float> %x, <4 x float> %y) {
18481851
ret <4 x float> %r
18491852
}
18501853

1854+
; length-changing shuffle and extra use are ok
1855+
18511856
define <4 x float> @fneg_shuf_widen_use1(<2 x float> %x, <2 x float> %y) {
18521857
; CHECK-LABEL: @fneg_shuf_widen_use1(
18531858
; CHECK-NEXT: [[NX:%.*]] = fneg nnan <2 x float> [[X:%.*]]
18541859
; CHECK-NEXT: call void @use(<2 x float> [[NX]])
1855-
; CHECK-NEXT: [[NY:%.*]] = fneg nnan <2 x float> [[Y:%.*]]
1856-
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[NX]], <2 x float> [[NY]], <4 x i32> <i32 undef, i32 1, i32 2, i32 3>
1860+
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x float> [[X]], <2 x float> [[Y:%.*]], <4 x i32> <i32 undef, i32 1, i32 2, i32 3>
1861+
; CHECK-NEXT: [[R:%.*]] = fneg nnan <4 x float> [[TMP1]]
18571862
; CHECK-NEXT: ret <4 x float> [[R]]
18581863
;
18591864
%nx = fneg nnan <2 x float> %x
@@ -1863,12 +1868,14 @@ define <4 x float> @fneg_shuf_widen_use1(<2 x float> %x, <2 x float> %y) {
18631868
ret <4 x float> %r
18641869
}
18651870

1871+
; length-changing shuffle and extra use still ok
1872+
18661873
define <2 x float> @fneg_shuf_narrow_use2(<4 x float> %x, <4 x float> %y) {
18671874
; CHECK-LABEL: @fneg_shuf_narrow_use2(
1868-
; CHECK-NEXT: [[NX:%.*]] = fneg nnan nsz <4 x float> [[X:%.*]]
18691875
; CHECK-NEXT: [[NY:%.*]] = fneg nnan nsz <4 x float> [[Y:%.*]]
18701876
; CHECK-NEXT: call void @use4(<4 x float> [[NY]])
1871-
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x float> [[NX]], <4 x float> [[NY]], <2 x i32> <i32 3, i32 5>
1877+
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> [[Y]], <2 x i32> <i32 3, i32 5>
1878+
; CHECK-NEXT: [[R:%.*]] = fneg nnan nsz <2 x float> [[TMP1]]
18721879
; CHECK-NEXT: ret <2 x float> [[R]]
18731880
;
18741881
%nx = fneg nsz nnan <4 x float> %x
@@ -1878,6 +1885,8 @@ define <2 x float> @fneg_shuf_narrow_use2(<4 x float> %x, <4 x float> %y) {
18781885
ret <2 x float> %r
18791886
}
18801887

1888+
; negative test - too many extra uses
1889+
18811890
define <2 x float> @fneg_shuf_use3(<2 x float> %x, <2 x float> %y) {
18821891
; CHECK-LABEL: @fneg_shuf_use3(
18831892
; CHECK-NEXT: [[NX:%.*]] = fneg nnan <2 x float> [[X:%.*]]

0 commit comments

Comments
 (0)