Skip to content

Commit 50ba89a

Browse files
authored
[VectorCombine] support mismatching extract/insert indices for foldInsExtFNeg (#126408)
insertelt DestVec, (fneg (extractelt SrcVec, Index)), Index -> shuffle DestVec, (shuffle (fneg SrcVec), poison, SrcMask), Mask In previous, the above transform was only possible if the Extract/Insert Index was the same; this patch makes the above transform possible even if the two indexes are different. Proof: https://alive2.llvm.org/ce/z/aDfdyG Fixes: #125675
1 parent b78f6fc commit 50ba89a

File tree

4 files changed

+156
-73
lines changed

4 files changed

+156
-73
lines changed

llvm/lib/Transforms/Vectorize/VectorCombine.cpp

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -696,79 +696,86 @@ bool VectorCombine::foldExtractExtract(Instruction &I) {
696696
/// shuffle.
697697
bool VectorCombine::foldInsExtFNeg(Instruction &I) {
698698
// Match an insert (op (extract)) pattern.
699-
Value *DestVec;
700-
uint64_t Index;
699+
Value *DstVec;
700+
uint64_t ExtIdx, InsIdx;
701701
Instruction *FNeg;
702-
if (!match(&I, m_InsertElt(m_Value(DestVec), m_OneUse(m_Instruction(FNeg)),
703-
m_ConstantInt(Index))))
702+
if (!match(&I, m_InsertElt(m_Value(DstVec), m_OneUse(m_Instruction(FNeg)),
703+
m_ConstantInt(InsIdx))))
704704
return false;
705705

706706
// Note: This handles the canonical fneg instruction and "fsub -0.0, X".
707707
Value *SrcVec;
708708
Instruction *Extract;
709709
if (!match(FNeg, m_FNeg(m_CombineAnd(
710710
m_Instruction(Extract),
711-
m_ExtractElt(m_Value(SrcVec), m_SpecificInt(Index))))))
711+
m_ExtractElt(m_Value(SrcVec), m_ConstantInt(ExtIdx))))))
712712
return false;
713713

714-
auto *VecTy = cast<FixedVectorType>(I.getType());
715-
auto *ScalarTy = VecTy->getScalarType();
714+
auto *DstVecTy = cast<FixedVectorType>(DstVec->getType());
715+
auto *DstVecScalarTy = DstVecTy->getScalarType();
716716
auto *SrcVecTy = dyn_cast<FixedVectorType>(SrcVec->getType());
717-
if (!SrcVecTy || ScalarTy != SrcVecTy->getScalarType())
717+
if (!SrcVecTy || DstVecScalarTy != SrcVecTy->getScalarType())
718718
return false;
719719

720-
// Ignore bogus insert/extract index.
721-
unsigned NumElts = VecTy->getNumElements();
722-
if (Index >= NumElts)
720+
// Ignore if insert/extract index is out of bounds or destination vector has
721+
// one element
722+
unsigned NumDstElts = DstVecTy->getNumElements();
723+
unsigned NumSrcElts = SrcVecTy->getNumElements();
724+
if (ExtIdx > NumSrcElts || InsIdx >= NumDstElts || NumDstElts == 1)
723725
return false;
724726

725727
// We are inserting the negated element into the same lane that we extracted
726728
// from. This is equivalent to a select-shuffle that chooses all but the
727729
// negated element from the destination vector.
728-
SmallVector<int> Mask(NumElts);
730+
SmallVector<int> Mask(NumDstElts);
729731
std::iota(Mask.begin(), Mask.end(), 0);
730-
Mask[Index] = Index + NumElts;
732+
Mask[InsIdx] = (ExtIdx % NumDstElts) + NumDstElts;
731733
InstructionCost OldCost =
732-
TTI.getArithmeticInstrCost(Instruction::FNeg, ScalarTy, CostKind) +
733-
TTI.getVectorInstrCost(I, VecTy, CostKind, Index);
734+
TTI.getArithmeticInstrCost(Instruction::FNeg, DstVecScalarTy, CostKind) +
735+
TTI.getVectorInstrCost(I, DstVecTy, CostKind, InsIdx);
734736

735737
// If the extract has one use, it will be eliminated, so count it in the
736738
// original cost. If it has more than one use, ignore the cost because it will
737739
// be the same before/after.
738740
if (Extract->hasOneUse())
739-
OldCost += TTI.getVectorInstrCost(*Extract, VecTy, CostKind, Index);
741+
OldCost += TTI.getVectorInstrCost(*Extract, SrcVecTy, CostKind, ExtIdx);
740742

741743
InstructionCost NewCost =
742-
TTI.getArithmeticInstrCost(Instruction::FNeg, VecTy, CostKind) +
743-
TTI.getShuffleCost(TargetTransformInfo::SK_PermuteTwoSrc, VecTy, VecTy,
744-
Mask, CostKind);
744+
TTI.getArithmeticInstrCost(Instruction::FNeg, SrcVecTy, CostKind) +
745+
TTI.getShuffleCost(TargetTransformInfo::SK_PermuteTwoSrc, DstVecTy,
746+
DstVecTy, Mask, CostKind);
745747

746-
bool NeedLenChg = SrcVecTy->getNumElements() != NumElts;
748+
bool NeedLenChg = SrcVecTy->getNumElements() != NumDstElts;
747749
// If the lengths of the two vectors are not equal,
748750
// we need to add a length-change vector. Add this cost.
749751
SmallVector<int> SrcMask;
750752
if (NeedLenChg) {
751-
SrcMask.assign(NumElts, PoisonMaskElem);
752-
SrcMask[Index] = Index;
753+
SrcMask.assign(NumDstElts, PoisonMaskElem);
754+
SrcMask[ExtIdx % NumDstElts] = ExtIdx;
753755
NewCost += TTI.getShuffleCost(TargetTransformInfo::SK_PermuteSingleSrc,
754-
VecTy, SrcVecTy, SrcMask, CostKind);
756+
DstVecTy, SrcVecTy, SrcMask, CostKind);
755757
}
756758

759+
LLVM_DEBUG(dbgs() << "Found an insertion of (extract)fneg : " << I
760+
<< "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
761+
<< "\n");
757762
if (NewCost > OldCost)
758763
return false;
759764

760-
Value *NewShuf;
761-
// insertelt DestVec, (fneg (extractelt SrcVec, Index)), Index
765+
Value *NewShuf, *LenChgShuf = nullptr;
766+
// insertelt DstVec, (fneg (extractelt SrcVec, Index)), Index
762767
Value *VecFNeg = Builder.CreateFNegFMF(SrcVec, FNeg);
763768
if (NeedLenChg) {
764-
// shuffle DestVec, (shuffle (fneg SrcVec), poison, SrcMask), Mask
765-
Value *LenChgShuf = Builder.CreateShuffleVector(VecFNeg, SrcMask);
766-
NewShuf = Builder.CreateShuffleVector(DestVec, LenChgShuf, Mask);
769+
// shuffle DstVec, (shuffle (fneg SrcVec), poison, SrcMask), Mask
770+
LenChgShuf = Builder.CreateShuffleVector(VecFNeg, SrcMask);
771+
NewShuf = Builder.CreateShuffleVector(DstVec, LenChgShuf, Mask);
772+
Worklist.pushValue(LenChgShuf);
767773
} else {
768-
// shuffle DestVec, (fneg SrcVec), Mask
769-
NewShuf = Builder.CreateShuffleVector(DestVec, VecFNeg, Mask);
774+
// shuffle DstVec, (fneg SrcVec), Mask
775+
NewShuf = Builder.CreateShuffleVector(DstVec, VecFNeg, Mask);
770776
}
771777

778+
Worklist.pushValue(VecFNeg);
772779
replaceValue(I, *NewShuf);
773780
return true;
774781
}

llvm/test/Transforms/PhaseOrdering/X86/addsub-inseltpoison.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -498,11 +498,9 @@ define void @add_aggregate_store(<2 x float> %a0, <2 x float> %a1, <2 x float> %
498498
; PR58139
499499
define <2 x double> @_mm_complexmult_pd_naive(<2 x double> %a, <2 x double> %b) {
500500
; SSE-LABEL: @_mm_complexmult_pd_naive(
501-
; SSE-NEXT: [[B1:%.*]] = extractelement <2 x double> [[B:%.*]], i64 1
502-
; SSE-NEXT: [[TMP1:%.*]] = fneg double [[B1]]
503501
; SSE-NEXT: [[TMP2:%.*]] = shufflevector <2 x double> [[A:%.*]], <2 x double> poison, <2 x i32> <i32 1, i32 1>
504-
; SSE-NEXT: [[TMP3:%.*]] = shufflevector <2 x double> [[B]], <2 x double> poison, <2 x i32> <i32 poison, i32 0>
505-
; SSE-NEXT: [[TMP4:%.*]] = insertelement <2 x double> [[TMP3]], double [[TMP1]], i64 0
502+
; SSE-NEXT: [[TMP3:%.*]] = fneg <2 x double> [[B:%.*]]
503+
; SSE-NEXT: [[TMP4:%.*]] = shufflevector <2 x double> [[TMP3]], <2 x double> [[B]], <2 x i32> <i32 1, i32 2>
506504
; SSE-NEXT: [[TMP5:%.*]] = fmul <2 x double> [[TMP2]], [[TMP4]]
507505
; SSE-NEXT: [[TMP6:%.*]] = shufflevector <2 x double> [[A]], <2 x double> poison, <2 x i32> zeroinitializer
508506
; SSE-NEXT: [[TMP7:%.*]] = tail call <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[TMP6]], <2 x double> [[B]], <2 x double> [[TMP5]])

llvm/test/Transforms/PhaseOrdering/X86/addsub.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -502,11 +502,9 @@ define void @add_aggregate_store(<2 x float> %a0, <2 x float> %a1, <2 x float> %
502502
; PR58139
503503
define <2 x double> @_mm_complexmult_pd_naive(<2 x double> %a, <2 x double> %b) {
504504
; SSE-LABEL: @_mm_complexmult_pd_naive(
505-
; SSE-NEXT: [[B1:%.*]] = extractelement <2 x double> [[B:%.*]], i64 1
506-
; SSE-NEXT: [[TMP1:%.*]] = fneg double [[B1]]
507505
; SSE-NEXT: [[TMP2:%.*]] = shufflevector <2 x double> [[A:%.*]], <2 x double> poison, <2 x i32> <i32 1, i32 1>
508-
; SSE-NEXT: [[TMP3:%.*]] = shufflevector <2 x double> [[B]], <2 x double> poison, <2 x i32> <i32 poison, i32 0>
509-
; SSE-NEXT: [[TMP4:%.*]] = insertelement <2 x double> [[TMP3]], double [[TMP1]], i64 0
506+
; SSE-NEXT: [[TMP3:%.*]] = fneg <2 x double> [[B:%.*]]
507+
; SSE-NEXT: [[TMP4:%.*]] = shufflevector <2 x double> [[TMP3]], <2 x double> [[B]], <2 x i32> <i32 1, i32 2>
510508
; SSE-NEXT: [[TMP5:%.*]] = fmul <2 x double> [[TMP2]], [[TMP4]]
511509
; SSE-NEXT: [[TMP6:%.*]] = shufflevector <2 x double> [[A]], <2 x double> poison, <2 x i32> zeroinitializer
512510
; SSE-NEXT: [[TMP7:%.*]] = tail call <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[TMP6]], <2 x double> [[B]], <2 x double> [[TMP5]])

llvm/test/Transforms/VectorCombine/X86/extract-fneg-insert.ll

Lines changed: 115 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,19 @@ define <4 x float> @ext2_v2f32v4f32(<2 x float> %x, <4 x float> %y) {
5858
ret <4 x float> %r
5959
}
6060

61+
define <2 x float> @ext2_v4f32v2f32(<4 x float> %x, <2 x float> %y) {
62+
; CHECK-LABEL: @ext2_v4f32v2f32(
63+
; CHECK-NEXT: [[TMP1:%.*]] = fneg <4 x float> [[X:%.*]]
64+
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x float> [[TMP1]], <4 x float> poison, <2 x i32> <i32 poison, i32 3>
65+
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[Y:%.*]], <2 x float> [[TMP2]], <2 x i32> <i32 0, i32 3>
66+
; CHECK-NEXT: ret <2 x float> [[R]]
67+
;
68+
%e = extractelement <4 x float> %x, i32 3
69+
%n = fneg float %e
70+
%r = insertelement <2 x float> %y, float %n, i32 1
71+
ret <2 x float> %r
72+
}
73+
6174
; Eliminating extract/insert is still profitable. Flags propagate.
6275

6376
define <2 x double> @ext1_v2f64(<2 x double> %x, <2 x double> %y) {
@@ -73,24 +86,31 @@ define <2 x double> @ext1_v2f64(<2 x double> %x, <2 x double> %y) {
7386
}
7487

7588
define <4 x double> @ext1_v2f64v4f64(<2 x double> %x, <4 x double> %y) {
76-
; SSE-LABEL: @ext1_v2f64v4f64(
77-
; SSE-NEXT: [[E:%.*]] = extractelement <2 x double> [[X:%.*]], i32 1
78-
; SSE-NEXT: [[N:%.*]] = fneg nsz double [[E]]
79-
; SSE-NEXT: [[R:%.*]] = insertelement <4 x double> [[Y:%.*]], double [[N]], i32 1
80-
; SSE-NEXT: ret <4 x double> [[R]]
81-
;
82-
; AVX-LABEL: @ext1_v2f64v4f64(
83-
; AVX-NEXT: [[TMP1:%.*]] = fneg nsz <2 x double> [[X:%.*]]
84-
; AVX-NEXT: [[TMP2:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <4 x i32> <i32 poison, i32 1, i32 poison, i32 poison>
85-
; AVX-NEXT: [[R:%.*]] = shufflevector <4 x double> [[Y:%.*]], <4 x double> [[TMP2]], <4 x i32> <i32 0, i32 5, i32 2, i32 3>
86-
; AVX-NEXT: ret <4 x double> [[R]]
89+
; CHECK-LABEL: @ext1_v2f64v4f64(
90+
; CHECK-NEXT: [[TMP1:%.*]] = fneg nsz <2 x double> [[X:%.*]]
91+
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <4 x i32> <i32 poison, i32 1, i32 poison, i32 poison>
92+
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x double> [[Y:%.*]], <4 x double> [[TMP2]], <4 x i32> <i32 0, i32 5, i32 2, i32 3>
93+
; CHECK-NEXT: ret <4 x double> [[R]]
8794
;
8895
%e = extractelement <2 x double> %x, i32 1
8996
%n = fneg nsz double %e
9097
%r = insertelement <4 x double> %y, double %n, i32 1
9198
ret <4 x double> %r
9299
}
93100

101+
define <2 x double> @ext1_v4f64v2f64(<4 x double> %x, <2 x double> %y) {
102+
; CHECK-LABEL: @ext1_v4f64v2f64(
103+
; CHECK-NEXT: [[TMP1:%.*]] = fneg nsz <4 x double> [[X:%.*]]
104+
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x double> [[TMP1]], <4 x double> poison, <2 x i32> <i32 poison, i32 3>
105+
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x double> [[Y:%.*]], <2 x double> [[TMP2]], <2 x i32> <i32 0, i32 3>
106+
; CHECK-NEXT: ret <2 x double> [[R]]
107+
;
108+
%e = extractelement <4 x double> %x, i32 3
109+
%n = fneg nsz double %e
110+
%r = insertelement <2 x double> %y, double %n, i32 1
111+
ret <2 x double> %r
112+
}
113+
94114
define <8 x float> @ext7_v8f32(<8 x float> %x, <8 x float> %y) {
95115
; CHECK-LABEL: @ext7_v8f32(
96116
; CHECK-NEXT: [[TMP1:%.*]] = fneg <8 x float> [[X:%.*]]
@@ -105,9 +125,9 @@ define <8 x float> @ext7_v8f32(<8 x float> %x, <8 x float> %y) {
105125

106126
define <8 x float> @ext7_v4f32v8f32(<4 x float> %x, <8 x float> %y) {
107127
; CHECK-LABEL: @ext7_v4f32v8f32(
108-
; CHECK-NEXT: [[E:%.*]] = extractelement <4 x float> [[X:%.*]], i32 3
109-
; CHECK-NEXT: [[N:%.*]] = fneg float [[E]]
110-
; CHECK-NEXT: [[R:%.*]] = insertelement <8 x float> [[Y:%.*]], float [[N]], i32 7
128+
; CHECK-NEXT: [[TMP1:%.*]] = fneg <4 x float> [[X:%.*]]
129+
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x float> [[TMP1]], <4 x float> poison, <8 x i32> <i32 poison, i32 poison, i32 poison, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
130+
; CHECK-NEXT: [[R:%.*]] = shufflevector <8 x float> [[Y:%.*]], <8 x float> [[TMP2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 11>
111131
; CHECK-NEXT: ret <8 x float> [[R]]
112132
;
113133
%e = extractelement <4 x float> %x, i32 3
@@ -116,6 +136,19 @@ define <8 x float> @ext7_v4f32v8f32(<4 x float> %x, <8 x float> %y) {
116136
ret <8 x float> %r
117137
}
118138

139+
define <4 x float> @ext7_v8f32v4f32(<8 x float> %x, <4 x float> %y) {
140+
; CHECK-LABEL: @ext7_v8f32v4f32(
141+
; CHECK-NEXT: [[TMP1:%.*]] = fneg <8 x float> [[X:%.*]]
142+
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x float> [[TMP1]], <8 x float> poison, <4 x i32> <i32 poison, i32 poison, i32 poison, i32 7>
143+
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x float> [[Y:%.*]], <4 x float> [[TMP2]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>
144+
; CHECK-NEXT: ret <4 x float> [[R]]
145+
;
146+
%e = extractelement <8 x float> %x, i32 7
147+
%n = fneg float %e
148+
%r = insertelement <4 x float> %y, float %n, i32 3
149+
ret <4 x float> %r
150+
}
151+
119152
; Same as above with an extra use of the extracted element.
120153

121154
define <8 x float> @ext7_v8f32_use1(<8 x float> %x, <8 x float> %y) {
@@ -141,12 +174,20 @@ define <8 x float> @ext7_v8f32_use1(<8 x float> %x, <8 x float> %y) {
141174
}
142175

143176
define <8 x float> @ext7_v4f32v8f32_use1(<4 x float> %x, <8 x float> %y) {
144-
; CHECK-LABEL: @ext7_v4f32v8f32_use1(
145-
; CHECK-NEXT: [[E:%.*]] = extractelement <4 x float> [[X:%.*]], i32 3
146-
; CHECK-NEXT: call void @use(float [[E]])
147-
; CHECK-NEXT: [[N:%.*]] = fneg float [[E]]
148-
; CHECK-NEXT: [[R:%.*]] = insertelement <8 x float> [[Y:%.*]], float [[N]], i32 3
149-
; CHECK-NEXT: ret <8 x float> [[R]]
177+
; SSE-LABEL: @ext7_v4f32v8f32_use1(
178+
; SSE-NEXT: [[E:%.*]] = extractelement <4 x float> [[X:%.*]], i32 3
179+
; SSE-NEXT: call void @use(float [[E]])
180+
; SSE-NEXT: [[TMP1:%.*]] = fneg <4 x float> [[X]]
181+
; SSE-NEXT: [[TMP2:%.*]] = shufflevector <4 x float> [[TMP1]], <4 x float> poison, <8 x i32> <i32 poison, i32 poison, i32 poison, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
182+
; SSE-NEXT: [[R:%.*]] = shufflevector <8 x float> [[Y:%.*]], <8 x float> [[TMP2]], <8 x i32> <i32 0, i32 1, i32 2, i32 11, i32 4, i32 5, i32 6, i32 7>
183+
; SSE-NEXT: ret <8 x float> [[R]]
184+
;
185+
; AVX-LABEL: @ext7_v4f32v8f32_use1(
186+
; AVX-NEXT: [[E:%.*]] = extractelement <4 x float> [[X:%.*]], i32 3
187+
; AVX-NEXT: call void @use(float [[E]])
188+
; AVX-NEXT: [[N:%.*]] = fneg float [[E]]
189+
; AVX-NEXT: [[R:%.*]] = insertelement <8 x float> [[Y:%.*]], float [[N]], i32 3
190+
; AVX-NEXT: ret <8 x float> [[R]]
150191
;
151192
%e = extractelement <4 x float> %x, i32 3
152193
call void @use(float %e)
@@ -155,6 +196,29 @@ define <8 x float> @ext7_v4f32v8f32_use1(<4 x float> %x, <8 x float> %y) {
155196
ret <8 x float> %r
156197
}
157198

199+
define <4 x float> @ext7_v8f32v4f32_use1(<8 x float> %x, <4 x float> %y) {
200+
; SSE-LABEL: @ext7_v8f32v4f32_use1(
201+
; SSE-NEXT: [[E:%.*]] = extractelement <8 x float> [[X:%.*]], i32 7
202+
; SSE-NEXT: call void @use(float [[E]])
203+
; SSE-NEXT: [[TMP1:%.*]] = fneg <8 x float> [[X]]
204+
; SSE-NEXT: [[TMP2:%.*]] = shufflevector <8 x float> [[TMP1]], <8 x float> poison, <4 x i32> <i32 poison, i32 poison, i32 poison, i32 7>
205+
; SSE-NEXT: [[R:%.*]] = shufflevector <4 x float> [[Y:%.*]], <4 x float> [[TMP2]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>
206+
; SSE-NEXT: ret <4 x float> [[R]]
207+
;
208+
; AVX-LABEL: @ext7_v8f32v4f32_use1(
209+
; AVX-NEXT: [[E:%.*]] = extractelement <8 x float> [[X:%.*]], i32 7
210+
; AVX-NEXT: call void @use(float [[E]])
211+
; AVX-NEXT: [[N:%.*]] = fneg float [[E]]
212+
; AVX-NEXT: [[R:%.*]] = insertelement <4 x float> [[Y:%.*]], float [[N]], i32 3
213+
; AVX-NEXT: ret <4 x float> [[R]]
214+
;
215+
%e = extractelement <8 x float> %x, i32 7
216+
call void @use(float %e)
217+
%n = fneg float %e
218+
%r = insertelement <4 x float> %y, float %n, i32 3
219+
ret <4 x float> %r
220+
}
221+
158222
; Negative test - the transform is likely not profitable if the fneg has another use.
159223

160224
define <8 x float> @ext7_v8f32_use2(<8 x float> %x, <8 x float> %y) {
@@ -187,6 +251,21 @@ define <8 x float> @ext7_v4f32v8f32_use2(<4 x float> %x, <8 x float> %y) {
187251
ret <8 x float> %r
188252
}
189253

254+
define <4 x float> @ext7_v8f32v4f32_use2(<8 x float> %x, <4 x float> %y) {
255+
; CHECK-LABEL: @ext7_v8f32v4f32_use2(
256+
; CHECK-NEXT: [[E:%.*]] = extractelement <8 x float> [[X:%.*]], i32 7
257+
; CHECK-NEXT: [[N:%.*]] = fneg float [[E]]
258+
; CHECK-NEXT: call void @use(float [[N]])
259+
; CHECK-NEXT: [[R:%.*]] = insertelement <4 x float> [[Y:%.*]], float [[N]], i32 3
260+
; CHECK-NEXT: ret <4 x float> [[R]]
261+
;
262+
%e = extractelement <8 x float> %x, i32 7
263+
%n = fneg float %e
264+
call void @use(float %n)
265+
%r = insertelement <4 x float> %y, float %n, i32 3
266+
ret <4 x float> %r
267+
}
268+
190269
; Negative test - can't convert variable index to a shuffle.
191270

192271
define <2 x double> @ext_index_var_v2f64(<2 x double> %x, <2 x double> %y, i32 %index) {
@@ -215,14 +294,10 @@ define <4 x double> @ext_index_var_v2f64v4f64(<2 x double> %x, <4 x double> %y,
215294
ret <4 x double> %r
216295
}
217296

218-
; Negative test - require same extract/insert index for simple shuffle.
219-
; TODO: We could handle this by adjusting the cost calculation.
220-
221297
define <2 x double> @ext1_v2f64_ins0(<2 x double> %x, <2 x double> %y) {
222298
; CHECK-LABEL: @ext1_v2f64_ins0(
223-
; CHECK-NEXT: [[E:%.*]] = extractelement <2 x double> [[X:%.*]], i32 1
224-
; CHECK-NEXT: [[N:%.*]] = fneg nsz double [[E]]
225-
; CHECK-NEXT: [[R:%.*]] = insertelement <2 x double> [[Y:%.*]], double [[N]], i32 0
299+
; CHECK-NEXT: [[TMP1:%.*]] = fneg nsz <2 x double> [[X:%.*]]
300+
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x double> [[Y:%.*]], <2 x double> [[TMP1]], <2 x i32> <i32 3, i32 1>
226301
; CHECK-NEXT: ret <2 x double> [[R]]
227302
;
228303
%e = extractelement <2 x double> %x, i32 1
@@ -231,12 +306,11 @@ define <2 x double> @ext1_v2f64_ins0(<2 x double> %x, <2 x double> %y) {
231306
ret <2 x double> %r
232307
}
233308

234-
; Negative test - extract from an index greater than the vector width of the destination
235309
define <2 x double> @ext3_v4f64v2f64(<4 x double> %x, <2 x double> %y) {
236310
; CHECK-LABEL: @ext3_v4f64v2f64(
237-
; CHECK-NEXT: [[E:%.*]] = extractelement <4 x double> [[X:%.*]], i32 3
238-
; CHECK-NEXT: [[N:%.*]] = fneg nsz double [[E]]
239-
; CHECK-NEXT: [[R:%.*]] = insertelement <2 x double> [[Y:%.*]], double [[N]], i32 1
311+
; CHECK-NEXT: [[TMP1:%.*]] = fneg nsz <4 x double> [[X:%.*]]
312+
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x double> [[TMP1]], <4 x double> poison, <2 x i32> <i32 poison, i32 3>
313+
; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x double> [[Y:%.*]], <2 x double> [[TMP2]], <2 x i32> <i32 0, i32 3>
240314
; CHECK-NEXT: ret <2 x double> [[R]]
241315
;
242316
%e = extractelement <4 x double> %x, i32 3
@@ -246,11 +320,17 @@ define <2 x double> @ext3_v4f64v2f64(<4 x double> %x, <2 x double> %y) {
246320
}
247321

248322
define <4 x double> @ext1_v2f64v4f64_ins0(<2 x double> %x, <4 x double> %y) {
249-
; CHECK-LABEL: @ext1_v2f64v4f64_ins0(
250-
; CHECK-NEXT: [[E:%.*]] = extractelement <2 x double> [[X:%.*]], i32 1
251-
; CHECK-NEXT: [[N:%.*]] = fneg nsz double [[E]]
252-
; CHECK-NEXT: [[R:%.*]] = insertelement <4 x double> [[Y:%.*]], double [[N]], i32 0
253-
; CHECK-NEXT: ret <4 x double> [[R]]
323+
; SSE-LABEL: @ext1_v2f64v4f64_ins0(
324+
; SSE-NEXT: [[TMP1:%.*]] = fneg nsz <2 x double> [[X:%.*]]
325+
; SSE-NEXT: [[TMP2:%.*]] = shufflevector <2 x double> [[TMP1]], <2 x double> poison, <4 x i32> <i32 poison, i32 1, i32 poison, i32 poison>
326+
; SSE-NEXT: [[R:%.*]] = shufflevector <4 x double> [[Y:%.*]], <4 x double> [[TMP2]], <4 x i32> <i32 5, i32 1, i32 2, i32 3>
327+
; SSE-NEXT: ret <4 x double> [[R]]
328+
;
329+
; AVX-LABEL: @ext1_v2f64v4f64_ins0(
330+
; AVX-NEXT: [[E:%.*]] = extractelement <2 x double> [[X:%.*]], i32 1
331+
; AVX-NEXT: [[N:%.*]] = fneg nsz double [[E]]
332+
; AVX-NEXT: [[R:%.*]] = insertelement <4 x double> [[Y:%.*]], double [[N]], i32 0
333+
; AVX-NEXT: ret <4 x double> [[R]]
254334
;
255335
%e = extractelement <2 x double> %x, i32 1
256336
%n = fneg nsz double %e

0 commit comments

Comments
 (0)