Skip to content

Commit 7ef2cf1

Browse files
davemgreenaokblast
authored andcommitted
[GlobalISel] Make scalar G_SHUFFLE_VECTOR illegal. (llvm#140508)
I'm not sure if this is the best way forward or not, but we have a lot of issues with forgetting that shuffle_vectors can be scalar again and again. (There is another example from the recent known-bits code added recently). As a scalar-dst shuffle vector is just an extract, and a scalar-source shuffle vector is just a build vector, this patch makes scalar shuffle vector illegal and adjusts the irbuilder to create the correct node as required. Most targets do this already through lowering or combines. Making scalar shuffles illegal simplifies gisel as a whole, it just requires that transforms that create shuffles of new sizes to account for the scalar shuffle being illegal (mostly IRBuilder and LessElements).
1 parent 4dcd6bf commit 7ef2cf1

24 files changed

+135
-390
lines changed

llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,6 @@ class CombinerHelper {
276276
SmallVector<Register> &Ops) const;
277277

278278
/// Replace \p MI with a build_vector.
279-
bool matchCombineShuffleToBuildVector(MachineInstr &MI) const;
280279
void applyCombineShuffleToBuildVector(MachineInstr &MI) const;
281280

282281
/// Try to combine G_SHUFFLE_VECTOR into G_CONCAT_VECTORS.
@@ -295,8 +294,6 @@ class CombinerHelper {
295294
/// Replace \p MI with a concat_vectors with \p Ops.
296295
void applyCombineShuffleVector(MachineInstr &MI,
297296
const ArrayRef<Register> Ops) const;
298-
bool matchShuffleToExtract(MachineInstr &MI) const;
299-
void applyShuffleToExtract(MachineInstr &MI) const;
300297

301298
/// Optimize memcpy intrinsics et al, e.g. constant len calls.
302299
/// /p MaxLen if non-zero specifies the max length of a mem libcall to inline.

llvm/include/llvm/Target/GlobalISel/Combine.td

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -484,13 +484,6 @@ def propagate_undef_shuffle_mask: GICombineRule<
484484
[{ return Helper.matchUndefShuffleVectorMask(*${root}); }]),
485485
(apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
486486

487-
// Replace a G_SHUFFLE_VECTOR with a G_EXTRACT_VECTOR_ELT.
488-
def shuffle_to_extract: GICombineRule<
489-
(defs root:$root),
490-
(match (wip_match_opcode G_SHUFFLE_VECTOR):$root,
491-
[{ return Helper.matchShuffleToExtract(*${root}); }]),
492-
(apply [{ Helper.applyShuffleToExtract(*${root}); }])>;
493-
494487
// Replace an insert/extract element of an out of bounds index with undef.
495488
def insert_extract_vec_elt_out_of_bounds : GICombineRule<
496489
(defs root:$root),
@@ -1674,8 +1667,7 @@ def combine_shuffle_concat : GICombineRule<
16741667
// Combines shuffles of vector into build_vector
16751668
def combine_shuffle_vector_to_build_vector : GICombineRule<
16761669
(defs root:$root),
1677-
(match (G_SHUFFLE_VECTOR $dst, $src1, $src2, $mask):$root,
1678-
[{ return Helper.matchCombineShuffleToBuildVector(*${root}); }]),
1670+
(match (G_SHUFFLE_VECTOR $dst, $src1, $src2, $mask):$root),
16791671
(apply [{ Helper.applyCombineShuffleToBuildVector(*${root}); }])>;
16801672

16811673
def insert_vector_element_idx_undef : GICombineRule<

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 5 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -391,19 +391,6 @@ void CombinerHelper::applyCombineConcatVectors(
391391
MI.eraseFromParent();
392392
}
393393

394-
bool CombinerHelper::matchCombineShuffleToBuildVector(MachineInstr &MI) const {
395-
assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR &&
396-
"Invalid instruction");
397-
auto &Shuffle = cast<GShuffleVector>(MI);
398-
399-
Register SrcVec1 = Shuffle.getSrc1Reg();
400-
Register SrcVec2 = Shuffle.getSrc2Reg();
401-
402-
LLT SrcVec1Type = MRI.getType(SrcVec1);
403-
LLT SrcVec2Type = MRI.getType(SrcVec2);
404-
return SrcVec1Type.isVector() && SrcVec2Type.isVector();
405-
}
406-
407394
void CombinerHelper::applyCombineShuffleToBuildVector(MachineInstr &MI) const {
408395
auto &Shuffle = cast<GShuffleVector>(MI);
409396

@@ -535,11 +522,9 @@ bool CombinerHelper::matchCombineShuffleVector(
535522
LLT DstType = MRI.getType(MI.getOperand(0).getReg());
536523
Register Src1 = MI.getOperand(1).getReg();
537524
LLT SrcType = MRI.getType(Src1);
538-
// As bizarre as it may look, shuffle vector can actually produce
539-
// scalar! This is because at the IR level a <1 x ty> shuffle
540-
// vector is perfectly valid.
541-
unsigned DstNumElts = DstType.isVector() ? DstType.getNumElements() : 1;
542-
unsigned SrcNumElts = SrcType.isVector() ? SrcType.getNumElements() : 1;
525+
526+
unsigned DstNumElts = DstType.getNumElements();
527+
unsigned SrcNumElts = SrcType.getNumElements();
543528

544529
// If the resulting vector is smaller than the size of the source
545530
// vectors being concatenated, we won't be able to replace the
@@ -556,7 +541,7 @@ bool CombinerHelper::matchCombineShuffleVector(
556541
//
557542
// TODO: If the size between the source and destination don't match
558543
// we could still emit an extract vector element in that case.
559-
if (DstNumElts < 2 * SrcNumElts && DstNumElts != 1)
544+
if (DstNumElts < 2 * SrcNumElts)
560545
return false;
561546

562547
// Check that the shuffle mask can be broken evenly between the
@@ -619,39 +604,6 @@ void CombinerHelper::applyCombineShuffleVector(
619604
MI.eraseFromParent();
620605
}
621606

622-
bool CombinerHelper::matchShuffleToExtract(MachineInstr &MI) const {
623-
assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR &&
624-
"Invalid instruction kind");
625-
626-
ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask();
627-
return Mask.size() == 1;
628-
}
629-
630-
void CombinerHelper::applyShuffleToExtract(MachineInstr &MI) const {
631-
Register DstReg = MI.getOperand(0).getReg();
632-
Builder.setInsertPt(*MI.getParent(), MI);
633-
634-
int I = MI.getOperand(3).getShuffleMask()[0];
635-
Register Src1 = MI.getOperand(1).getReg();
636-
LLT Src1Ty = MRI.getType(Src1);
637-
int Src1NumElts = Src1Ty.isVector() ? Src1Ty.getNumElements() : 1;
638-
Register SrcReg;
639-
if (I >= Src1NumElts) {
640-
SrcReg = MI.getOperand(2).getReg();
641-
I -= Src1NumElts;
642-
} else if (I >= 0)
643-
SrcReg = Src1;
644-
645-
if (I < 0)
646-
Builder.buildUndef(DstReg);
647-
else if (!MRI.getType(SrcReg).isVector())
648-
Builder.buildCopy(DstReg, SrcReg);
649-
else
650-
Builder.buildExtractVectorElementConstant(DstReg, SrcReg, I);
651-
652-
MI.eraseFromParent();
653-
}
654-
655607
namespace {
656608

657609
/// Select a preference between two uses. CurrentUse is the current preference
@@ -8369,7 +8321,7 @@ bool CombinerHelper::matchShuffleDisjointMask(MachineInstr &MI,
83698321
return false;
83708322

83718323
ArrayRef<int> Mask = Shuffle.getMask();
8372-
const unsigned NumSrcElems = Src1Ty.isVector() ? Src1Ty.getNumElements() : 1;
8324+
const unsigned NumSrcElems = Src1Ty.getNumElements();
83738325

83748326
bool TouchesSrc1 = false;
83758327
bool TouchesSrc2 = false;

llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,8 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known,
602602
Depth + 1);
603603
computeKnownBitsImpl(MI.getOperand(3).getReg(), WidthKnown, DemandedElts,
604604
Depth + 1);
605+
OffsetKnown = OffsetKnown.sext(BitWidth);
606+
WidthKnown = WidthKnown.sext(BitWidth);
605607
Known = extractBits(BitWidth, SrcOpKnown, OffsetKnown, WidthKnown);
606608
// Sign extend the extracted value using shift left and arithmetic shift
607609
// right.

llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3359,6 +3359,54 @@ bool IRTranslator::translateShuffleVector(const User &U,
33593359
Mask = SVI->getShuffleMask();
33603360
else
33613361
Mask = cast<ConstantExpr>(U).getShuffleMask();
3362+
3363+
// As GISel does not represent <1 x > vectors as a separate type from scalars,
3364+
// we transform shuffle_vector with a scalar output to an
3365+
// ExtractVectorElement. If the input type is also scalar it becomes a Copy.
3366+
unsigned DstElts = cast<FixedVectorType>(U.getType())->getNumElements();
3367+
unsigned SrcElts =
3368+
cast<FixedVectorType>(U.getOperand(0)->getType())->getNumElements();
3369+
if (DstElts == 1) {
3370+
unsigned M = Mask[0];
3371+
if (SrcElts == 1) {
3372+
if (M == 0 || M == 1)
3373+
return translateCopy(U, *U.getOperand(M), MIRBuilder);
3374+
MIRBuilder.buildUndef(getOrCreateVReg(U));
3375+
} else {
3376+
Register Dst = getOrCreateVReg(U);
3377+
if (M < SrcElts) {
3378+
MIRBuilder.buildExtractVectorElementConstant(
3379+
Dst, getOrCreateVReg(*U.getOperand(0)), M);
3380+
} else if (M < SrcElts * 2) {
3381+
MIRBuilder.buildExtractVectorElementConstant(
3382+
Dst, getOrCreateVReg(*U.getOperand(1)), M - SrcElts);
3383+
} else {
3384+
MIRBuilder.buildUndef(Dst);
3385+
}
3386+
}
3387+
return true;
3388+
}
3389+
3390+
// A single element src is transformed to a build_vector.
3391+
if (SrcElts == 1) {
3392+
SmallVector<Register> Ops;
3393+
Register Undef;
3394+
for (int M : Mask) {
3395+
LLT SrcTy = getLLTForType(*U.getOperand(0)->getType(), *DL);
3396+
if (M == 0 || M == 1) {
3397+
Ops.push_back(getOrCreateVReg(*U.getOperand(M)));
3398+
} else {
3399+
if (!Undef.isValid()) {
3400+
Undef = MRI->createGenericVirtualRegister(SrcTy);
3401+
MIRBuilder.buildUndef(Undef);
3402+
}
3403+
Ops.push_back(Undef);
3404+
}
3405+
}
3406+
MIRBuilder.buildBuildVector(getOrCreateVReg(U), Ops);
3407+
return true;
3408+
}
3409+
33623410
ArrayRef<int> MaskAlloc = MF->allocateShuffleMask(Mask);
33633411
MIRBuilder
33643412
.buildInstr(TargetOpcode::G_SHUFFLE_VECTOR, {getOrCreateVReg(U)},

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5819,6 +5819,8 @@ LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorShuffle(
58195819
} else if (InputUsed[0] == -1U) {
58205820
// No input vectors were used! The result is undefined.
58215821
Output = MIRBuilder.buildUndef(NarrowTy).getReg(0);
5822+
} else if (NewElts == 1) {
5823+
Output = MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
58225824
} else {
58235825
Register Op0 = Inputs[InputUsed[0]];
58245826
// If only one input was used, use an undefined vector for the other.
@@ -9016,22 +9018,18 @@ LegalizerHelper::lowerShuffleVector(MachineInstr &MI) {
90169018
continue;
90179019
}
90189020

9019-
if (Src0Ty.isScalar()) {
9020-
BuildVec.push_back(Idx == 0 ? Src0Reg : Src1Reg);
9021-
} else {
9022-
int NumElts = Src0Ty.getNumElements();
9023-
Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9024-
int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9025-
auto IdxK = MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9026-
auto Extract = MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK);
9027-
BuildVec.push_back(Extract.getReg(0));
9028-
}
9021+
assert(!Src0Ty.isScalar() && "Unexpected scalar G_SHUFFLE_VECTOR");
9022+
9023+
int NumElts = Src0Ty.getNumElements();
9024+
Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9025+
int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9026+
auto IdxK = MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9027+
auto Extract = MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK);
9028+
BuildVec.push_back(Extract.getReg(0));
90299029
}
90309030

9031-
if (DstTy.isVector())
9032-
MIRBuilder.buildBuildVector(DstReg, BuildVec);
9033-
else
9034-
MIRBuilder.buildCopy(DstReg, BuildVec[0]);
9031+
assert(DstTy.isVector() && "Unexpected scalar G_SHUFFLE_VECTOR");
9032+
MIRBuilder.buildBuildVector(DstReg, BuildVec);
90359033
MI.eraseFromParent();
90369034
return Legalized;
90379035
}

llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -800,10 +800,11 @@ MachineInstrBuilder MachineIRBuilder::buildShuffleVector(const DstOp &Res,
800800
LLT DstTy = Res.getLLTTy(*getMRI());
801801
LLT Src1Ty = Src1.getLLTTy(*getMRI());
802802
LLT Src2Ty = Src2.getLLTTy(*getMRI());
803-
const LLT DstElemTy = DstTy.isVector() ? DstTy.getElementType() : DstTy;
804-
const LLT ElemTy1 = Src1Ty.isVector() ? Src1Ty.getElementType() : Src1Ty;
805-
const LLT ElemTy2 = Src2Ty.isVector() ? Src2Ty.getElementType() : Src2Ty;
803+
const LLT DstElemTy = DstTy.getScalarType();
804+
const LLT ElemTy1 = Src1Ty.getScalarType();
805+
const LLT ElemTy2 = Src2Ty.getScalarType();
806806
assert(DstElemTy == ElemTy1 && DstElemTy == ElemTy2);
807+
assert(Mask.size() > 1 && "Scalar G_SHUFFLE_VECTOR are not supported");
807808
(void)DstElemTy;
808809
(void)ElemTy1;
809810
(void)ElemTy2;

llvm/lib/CodeGen/MIRParser/MIParser.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2788,6 +2788,9 @@ bool MIParser::parseShuffleMaskOperand(MachineOperand &Dest) {
27882788
if (expectAndConsume(MIToken::rparen))
27892789
return error("shufflemask should be terminated by ')'.");
27902790

2791+
if (ShufMask.size() < 2)
2792+
return error("shufflemask should have > 1 element");
2793+
27912794
ArrayRef<int> MaskAlloc = MF.allocateShuffleMask(ShufMask);
27922795
Dest = MachineOperand::CreateShuffleMask(MaskAlloc);
27932796
return false;

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,13 +1924,23 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
19241924
if (Src0Ty != Src1Ty)
19251925
report("Source operands must be the same type", MI);
19261926

1927-
if (Src0Ty.getScalarType() != DstTy.getScalarType())
1927+
if (Src0Ty.getScalarType() != DstTy.getScalarType()) {
19281928
report("G_SHUFFLE_VECTOR cannot change element type", MI);
1929+
break;
1930+
}
1931+
if (!Src0Ty.isVector()) {
1932+
report("G_SHUFFLE_VECTOR must have vector src", MI);
1933+
break;
1934+
}
1935+
if (!DstTy.isVector()) {
1936+
report("G_SHUFFLE_VECTOR must have vector dst", MI);
1937+
break;
1938+
}
19291939

19301940
// Don't check that all operands are vector because scalars are used in
19311941
// place of 1 element vectors.
1932-
int SrcNumElts = Src0Ty.isVector() ? Src0Ty.getNumElements() : 1;
1933-
int DstNumElts = DstTy.isVector() ? DstTy.getNumElements() : 1;
1942+
int SrcNumElts = Src0Ty.getNumElements();
1943+
int DstNumElts = DstTy.getNumElements();
19341944

19351945
ArrayRef<int> MaskIdxes = MaskOp.getShuffleMask();
19361946

llvm/lib/Target/AArch64/AArch64Combine.td

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ def AArch64PreLegalizerCombiner: GICombiner<
7171
"AArch64PreLegalizerCombinerImpl", [all_combines,
7272
icmp_redundant_trunc,
7373
fold_global_offset,
74-
shuffle_to_extract,
7574
ext_addv_to_udot_addv,
7675
ext_uaddv_to_uaddlv,
7776
push_sub_through_zext,

0 commit comments

Comments
 (0)