Skip to content

Commit 0e5ff35

Browse files
committed
[InstCombine][X86] Fold blendv(x,y,shuffle(bitcast(sext(m)))) -> select(shuffle(m),x,y)
We already handle blendv(x,y,bitcast(sext(m))) -> select(m,x,y) cases, but this adds support for peeking through one-use shuffles as well. VectorCombine should already have canonicalized the IR to shuffle(bitcast(...)) for us. The particular use case is where we have split generic 256/512-bit code to use target-specific blendv intrinsics (e.g. AVX1 spoofing AVX2 256-bit ops). Fixes #58895
1 parent a6d289d commit 0e5ff35

File tree

3 files changed

+175
-184
lines changed

3 files changed

+175
-184
lines changed

llvm/lib/Target/X86/X86InstCombineIntrinsic.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2800,6 +2800,23 @@ X86TTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const {
28002800
return SelectInst::Create(NewSelector, Op1, Op0, "blendv");
28012801
}
28022802

2803+
// Peek through a one-use shuffle - VectorCombine should have simplified
2804+
// this for cases where we're splitting wider vectors to use blendv
2805+
// intrinsics.
2806+
Value *MaskSrc = nullptr;
2807+
ArrayRef<int> ShuffleMask;
2808+
if (match(Mask, PatternMatch::m_OneUse(PatternMatch::m_Shuffle(
2809+
PatternMatch::m_Value(MaskSrc), PatternMatch::m_Undef(),
2810+
PatternMatch::m_Mask(ShuffleMask))))) {
2811+
// Bail if the shuffle was irregular or contains undefs.
2812+
int NumElts = cast<FixedVectorType>(MaskSrc->getType())->getNumElements();
2813+
if (NumElts < ShuffleMask.size() || !isPowerOf2_32(NumElts) ||
2814+
any_of(ShuffleMask,
2815+
[NumElts](int M) { return M < 0 || M >= NumElts; }))
2816+
break;
2817+
Mask = MaskSrc;
2818+
}
2819+
28032820
// Convert to a vector select if we can bypass casts and find a boolean
28042821
// vector condition value.
28052822
Value *BoolVec;
@@ -2809,11 +2826,26 @@ X86TTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const {
28092826
BoolVec->getType()->getScalarSizeInBits() == 1) {
28102827
auto *MaskTy = cast<FixedVectorType>(Mask->getType());
28112828
auto *OpTy = cast<FixedVectorType>(II.getType());
2829+
unsigned NumMaskElts = MaskTy->getNumElements();
2830+
unsigned NumOperandElts = OpTy->getNumElements();
2831+
2832+
// If we peeked through a shuffle, reapply the shuffle to the bool vector.
2833+
if (MaskSrc) {
2834+
unsigned NumMaskSrcElts =
2835+
cast<FixedVectorType>(MaskSrc->getType())->getNumElements();
2836+
NumMaskElts = (ShuffleMask.size() * NumMaskElts) / NumMaskSrcElts;
2837+
// Multiple mask bits maps to the same operand element - bail out.
2838+
if (NumMaskElts > NumOperandElts)
2839+
break;
2840+
SmallVector<int> ScaledMask;
2841+
if (!llvm::scaleShuffleMaskElts(NumMaskElts, ShuffleMask, ScaledMask))
2842+
break;
2843+
BoolVec = IC.Builder.CreateShuffleVector(BoolVec, ScaledMask);
2844+
MaskTy = FixedVectorType::get(MaskTy->getElementType(), NumMaskElts);
2845+
}
28122846
assert(MaskTy->getPrimitiveSizeInBits() ==
28132847
OpTy->getPrimitiveSizeInBits() &&
28142848
"Not expecting mask and operands with different sizes");
2815-
unsigned NumMaskElts = MaskTy->getNumElements();
2816-
unsigned NumOperandElts = OpTy->getNumElements();
28172849

28182850
if (NumMaskElts == NumOperandElts) {
28192851
return SelectInst::Create(BoolVec, Op1, Op0);

0 commit comments

Comments
 (0)