Skip to content

Commit 1ee6ec2

Browse files
committed
Remove "mask" operand from shufflevector.
Instead, represent the mask as out-of-line data in the instruction. This should be more efficient in the places that currently use getShuffleVector(), and paves the way for further changes to add new shuffles for scalable vectors. This doesn't change the syntax in textual IR. And I don't currently plan to change the bitcode encoding in this patch, although we'll probably need to do something once we extend shufflevector for scalable types. I expect that once this is finished, we can then replace the raw "mask" with something more appropriate for scalable vectors. Not sure exactly what this looks like at the moment, but there are a few different ways we could handle it. Maybe we could try to describe specific shuffles. Or maybe we could define it in terms of a function to convert a fixed-length array into an appropriate scalable vector, using a "step", or something like that. Differential Revision: https://reviews.llvm.org/D72467
1 parent c538c57 commit 1ee6ec2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+672
-383
lines changed

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1675,7 +1675,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
16751675

16761676
// Shuffle vector to get vec3.
16771677
V = Builder.CreateShuffleVector(V, llvm::UndefValue::get(vec4Ty),
1678-
{0, 1, 2}, "extractVec");
1678+
ArrayRef<int>{0, 1, 2}, "extractVec");
16791679
return EmitFromMemory(V, Ty);
16801680
}
16811681
}

llvm/include/llvm/ADT/ArrayRef.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,11 +532,21 @@ namespace llvm {
532532
return LHS.equals(RHS);
533533
}
534534

535-
template<typename T>
535+
template <typename T>
536+
inline bool operator==(SmallVectorImpl<T> &LHS, ArrayRef<T> RHS) {
537+
return ArrayRef<T>(LHS).equals(RHS);
538+
}
539+
540+
template <typename T>
536541
inline bool operator!=(ArrayRef<T> LHS, ArrayRef<T> RHS) {
537542
return !(LHS == RHS);
538543
}
539544

545+
template <typename T>
546+
inline bool operator!=(SmallVectorImpl<T> &LHS, ArrayRef<T> RHS) {
547+
return !(LHS == RHS);
548+
}
549+
540550
/// @}
541551

542552
template <typename T> hash_code hash_value(ArrayRef<T> S) {

llvm/include/llvm/Analysis/ConstantFolding.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,11 @@ Constant *ConstantFoldInsertElementInstruction(Constant *Val,
119119
Constant *ConstantFoldExtractElementInstruction(Constant *Val, Constant *Idx);
120120

121121
/// Attempt to constant fold a shufflevector instruction with the
122-
/// specified operands and indices. The constant result is returned if
123-
/// successful; if not, null is returned.
122+
/// specified operands and mask. See class ShuffleVectorInst for a description
123+
/// of the mask representation. The constant result is returned if successful;
124+
/// if not, null is returned.
124125
Constant *ConstantFoldShuffleVectorInstruction(Constant *V1, Constant *V2,
125-
Constant *Mask);
126+
ArrayRef<int> Mask);
126127

127128
/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would
128129
/// produce if it is constant and determinable. If this is not determinable,

llvm/include/llvm/Analysis/InstructionSimplify.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ Value *SimplifyCastInst(unsigned CastOpc, Value *Op, Type *Ty,
230230
const SimplifyQuery &Q);
231231

232232
/// Given operands for a ShuffleVectorInst, fold the result or return null.
233-
Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
233+
/// See class ShuffleVectorInst for a description of the mask representation.
234+
Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, ArrayRef<int> Mask,
234235
Type *RetTy, const SimplifyQuery &Q);
235236

236237
//=== Helper functions for higher up the class hierarchy.

llvm/include/llvm/Analysis/TargetFolder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ class TargetFolder final : public IRBuilderFolder {
259259
}
260260

261261
Constant *CreateShuffleVector(Constant *V1, Constant *V2,
262-
Constant *Mask) const override {
262+
ArrayRef<int> Mask) const override {
263263
return Fold(ConstantExpr::getShuffleVector(V1, V2, Mask));
264264
}
265265

llvm/include/llvm/IR/ConstantFolder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ class ConstantFolder final : public IRBuilderFolder {
265265
}
266266

267267
Constant *CreateShuffleVector(Constant *V1, Constant *V2,
268-
Constant *Mask) const override {
268+
ArrayRef<int> Mask) const override {
269269
return ConstantExpr::getShuffleVector(V1, V2, Mask);
270270
}
271271

llvm/include/llvm/IR/Constants.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,8 @@ class ConstantExpr : public Constant {
12061206
Type *OnlyIfReducedTy = nullptr);
12071207
static Constant *getInsertElement(Constant *Vec, Constant *Elt, Constant *Idx,
12081208
Type *OnlyIfReducedTy = nullptr);
1209-
static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask,
1209+
static Constant *getShuffleVector(Constant *V1, Constant *V2,
1210+
ArrayRef<int> Mask,
12101211
Type *OnlyIfReducedTy = nullptr);
12111212
static Constant *getExtractValue(Constant *Agg, ArrayRef<unsigned> Idxs,
12121213
Type *OnlyIfReducedTy = nullptr);
@@ -1225,6 +1226,16 @@ class ConstantExpr : public Constant {
12251226
/// expression and return the list of indices.
12261227
ArrayRef<unsigned> getIndices() const;
12271228

1229+
/// Assert that this is a shufflevector and return the mask. See class
1230+
/// ShuffleVectorInst for a description of the mask representation.
1231+
ArrayRef<int> getShuffleMask() const;
1232+
1233+
/// Assert that this is a shufflevector and return the mask.
1234+
///
1235+
/// TODO: This is a temporary hack until we update the bitcode format for
1236+
/// shufflevector.
1237+
Constant *getShuffleMaskForBitcode() const;
1238+
12281239
/// Return a string representation for an opcode.
12291240
const char *getOpcodeName() const;
12301241

llvm/include/llvm/IR/IRBuilder.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2617,17 +2617,25 @@ class IRBuilderBase {
26172617

26182618
Value *CreateShuffleVector(Value *V1, Value *V2, Value *Mask,
26192619
const Twine &Name = "") {
2620-
if (auto *V1C = dyn_cast<Constant>(V1))
2621-
if (auto *V2C = dyn_cast<Constant>(V2))
2622-
if (auto *MC = dyn_cast<Constant>(Mask))
2623-
return Insert(Folder.CreateShuffleVector(V1C, V2C, MC), Name);
2624-
return Insert(new ShuffleVectorInst(V1, V2, Mask), Name);
2620+
SmallVector<int, 16> IntMask;
2621+
ShuffleVectorInst::getShuffleMask(cast<Constant>(Mask), IntMask);
2622+
return CreateShuffleVector(V1, V2, IntMask, Name);
26252623
}
26262624

2627-
Value *CreateShuffleVector(Value *V1, Value *V2, ArrayRef<uint32_t> IntMask,
2625+
Value *CreateShuffleVector(Value *V1, Value *V2, ArrayRef<uint32_t> Mask,
26282626
const Twine &Name = "") {
2629-
Value *Mask = ConstantDataVector::get(Context, IntMask);
2630-
return CreateShuffleVector(V1, V2, Mask, Name);
2627+
SmallVector<int, 16> IntMask;
2628+
IntMask.assign(Mask.begin(), Mask.end());
2629+
return CreateShuffleVector(V1, V2, IntMask, Name);
2630+
}
2631+
2632+
/// See class ShuffleVectorInst for a description of the mask representation.
2633+
Value *CreateShuffleVector(Value *V1, Value *V2, ArrayRef<int> Mask,
2634+
const Twine &Name = "") {
2635+
if (auto *V1C = dyn_cast<Constant>(V1))
2636+
if (auto *V2C = dyn_cast<Constant>(V2))
2637+
return Insert(Folder.CreateShuffleVector(V1C, V2C, Mask), Name);
2638+
return Insert(new ShuffleVectorInst(V1, V2, Mask), Name);
26312639
}
26322640

26332641
Value *CreateExtractValue(Value *Agg,

llvm/include/llvm/IR/IRBuilderFolder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class IRBuilderFolder {
129129
virtual Value *CreateInsertElement(Constant *Vec, Constant *NewElt,
130130
Constant *Idx) const = 0;
131131
virtual Value *CreateShuffleVector(Constant *V1, Constant *V2,
132-
Constant *Mask) const = 0;
132+
ArrayRef<int> Mask) const = 0;
133133
virtual Value *CreateExtractValue(Constant *Agg,
134134
ArrayRef<unsigned> IdxList) const = 0;
135135
virtual Value *CreateInsertValue(Constant *Agg, Constant *Val,

llvm/include/llvm/IR/Instructions.h

Lines changed: 49 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,10 +1988,22 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementInst, Value)
19881988
// ShuffleVectorInst Class
19891989
//===----------------------------------------------------------------------===//
19901990

1991+
constexpr int UndefMaskElem = -1;
1992+
19911993
/// This instruction constructs a fixed permutation of two
19921994
/// input vectors.
19931995
///
1996+
/// For each element of the result vector, the shuffle mask selects an element
1997+
/// from one of the input vectors to copy to the result. Non-negative elements
1998+
/// in the mask represent an index into the concatenated pair of input vectors.
1999+
/// UndefMaskElem (-1) specifies that the result element is undefined.
2000+
///
2001+
/// For scalable vectors, all the elements of the mask must be 0 or -1. This
2002+
/// requirement may be relaxed in the future.
19942003
class ShuffleVectorInst : public Instruction {
2004+
SmallVector<int, 4> ShuffleMask;
2005+
Constant *ShuffleMaskForBitcode;
2006+
19952007
protected:
19962008
// Note: Instruction needs to be a friend here to call cloneImpl.
19972009
friend class Instruction;
@@ -2004,20 +2016,24 @@ class ShuffleVectorInst : public Instruction {
20042016
Instruction *InsertBefor = nullptr);
20052017
ShuffleVectorInst(Value *V1, Value *V2, Value *Mask,
20062018
const Twine &NameStr, BasicBlock *InsertAtEnd);
2019+
ShuffleVectorInst(Value *V1, Value *V2, ArrayRef<int> Mask,
2020+
const Twine &NameStr = "",
2021+
Instruction *InsertBefor = nullptr);
2022+
ShuffleVectorInst(Value *V1, Value *V2, ArrayRef<int> Mask,
2023+
const Twine &NameStr, BasicBlock *InsertAtEnd);
20072024

2008-
// allocate space for exactly three operands
2009-
void *operator new(size_t s) {
2010-
return User::operator new(s, 3);
2011-
}
2025+
void *operator new(size_t s) { return User::operator new(s, 2); }
20122026

2013-
/// Swap the first 2 operands and adjust the mask to preserve the semantics
2027+
/// Swap the operands and adjust the mask to preserve the semantics
20142028
/// of the instruction.
20152029
void commute();
20162030

20172031
/// Return true if a shufflevector instruction can be
20182032
/// formed with the specified operands.
20192033
static bool isValidOperands(const Value *V1, const Value *V2,
20202034
const Value *Mask);
2035+
static bool isValidOperands(const Value *V1, const Value *V2,
2036+
ArrayRef<int> Mask);
20212037

20222038
/// Overload to return most specific vector type.
20232039
///
@@ -2028,44 +2044,41 @@ class ShuffleVectorInst : public Instruction {
20282044
/// Transparently provide more efficient getOperand methods.
20292045
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
20302046

2031-
Constant *getMask() const {
2032-
return cast<Constant>(getOperand(2));
2033-
}
2034-
2035-
/// Return the shuffle mask value for the specified element of the mask.
2036-
/// Return -1 if the element is undef.
2037-
static int getMaskValue(const Constant *Mask, unsigned Elt);
2038-
20392047
/// Return the shuffle mask value of this instruction for the given element
2040-
/// index. Return -1 if the element is undef.
2041-
int getMaskValue(unsigned Elt) const {
2042-
return getMaskValue(getMask(), Elt);
2043-
}
2048+
/// index. Return UndefMaskElem if the element is undef.
2049+
int getMaskValue(unsigned Elt) const { return ShuffleMask[Elt]; }
20442050

20452051
/// Convert the input shuffle mask operand to a vector of integers. Undefined
2046-
/// elements of the mask are returned as -1.
2052+
/// elements of the mask are returned as UndefMaskElem.
20472053
static void getShuffleMask(const Constant *Mask,
20482054
SmallVectorImpl<int> &Result);
20492055

20502056
/// Return the mask for this instruction as a vector of integers. Undefined
2051-
/// elements of the mask are returned as -1.
2057+
/// elements of the mask are returned as UndefMaskElem.
20522058
void getShuffleMask(SmallVectorImpl<int> &Result) const {
2053-
return getShuffleMask(getMask(), Result);
2059+
Result.assign(ShuffleMask.begin(), ShuffleMask.end());
20542060
}
20552061

2056-
SmallVector<int, 16> getShuffleMask() const {
2057-
SmallVector<int, 16> Mask;
2058-
getShuffleMask(Mask);
2059-
return Mask;
2060-
}
2062+
/// Return the mask for this instruction, for use in bitcode.
2063+
///
2064+
/// TODO: This is temporary until we decide a new bitcode encoding for
2065+
/// shufflevector.
2066+
Constant *getShuffleMaskForBitcode() const { return ShuffleMaskForBitcode; }
2067+
2068+
static Constant *convertShuffleMaskForBitcode(ArrayRef<int> Mask,
2069+
Type *ResultTy);
2070+
2071+
void setShuffleMask(ArrayRef<int> Mask);
2072+
2073+
ArrayRef<int> getShuffleMask() const { return ShuffleMask; }
20612074

20622075
/// Return true if this shuffle returns a vector with a different number of
20632076
/// elements than its source vectors.
20642077
/// Examples: shufflevector <4 x n> A, <4 x n> B, <1,2,3>
20652078
/// shufflevector <4 x n> A, <4 x n> B, <1,2,3,4,5>
20662079
bool changesLength() const {
20672080
unsigned NumSourceElts = Op<0>()->getType()->getVectorNumElements();
2068-
unsigned NumMaskElts = getMask()->getType()->getVectorNumElements();
2081+
unsigned NumMaskElts = ShuffleMask.size();
20692082
return NumSourceElts != NumMaskElts;
20702083
}
20712084

@@ -2074,7 +2087,7 @@ class ShuffleVectorInst : public Instruction {
20742087
/// Example: shufflevector <2 x n> A, <2 x n> B, <1,2,3>
20752088
bool increasesLength() const {
20762089
unsigned NumSourceElts = Op<0>()->getType()->getVectorNumElements();
2077-
unsigned NumMaskElts = getMask()->getType()->getVectorNumElements();
2090+
unsigned NumMaskElts = ShuffleMask.size();
20782091
return NumSourceElts < NumMaskElts;
20792092
}
20802093

@@ -2095,7 +2108,7 @@ class ShuffleVectorInst : public Instruction {
20952108
/// Example: shufflevector <4 x n> A, <4 x n> B, <3,0,undef,3>
20962109
/// TODO: Optionally allow length-changing shuffles.
20972110
bool isSingleSource() const {
2098-
return !changesLength() && isSingleSourceMask(getMask());
2111+
return !changesLength() && isSingleSourceMask(ShuffleMask);
20992112
}
21002113

21012114
/// Return true if this shuffle mask chooses elements from exactly one source
@@ -2116,7 +2129,7 @@ class ShuffleVectorInst : public Instruction {
21162129
/// from its input vectors.
21172130
/// Example: shufflevector <4 x n> A, <4 x n> B, <4,undef,6,undef>
21182131
bool isIdentity() const {
2119-
return !changesLength() && isIdentityMask(getShuffleMask());
2132+
return !changesLength() && isIdentityMask(ShuffleMask);
21202133
}
21212134

21222135
/// Return true if this shuffle lengthens exactly one source vector with
@@ -2157,7 +2170,7 @@ class ShuffleVectorInst : public Instruction {
21572170
/// In that case, the shuffle is better classified as an identity shuffle.
21582171
/// TODO: Optionally allow length-changing shuffles.
21592172
bool isSelect() const {
2160-
return !changesLength() && isSelectMask(getMask());
2173+
return !changesLength() && isSelectMask(ShuffleMask);
21612174
}
21622175

21632176
/// Return true if this shuffle mask swaps the order of elements from exactly
@@ -2177,7 +2190,7 @@ class ShuffleVectorInst : public Instruction {
21772190
/// Example: shufflevector <4 x n> A, <4 x n> B, <3,undef,1,undef>
21782191
/// TODO: Optionally allow length-changing shuffles.
21792192
bool isReverse() const {
2180-
return !changesLength() && isReverseMask(getMask());
2193+
return !changesLength() && isReverseMask(ShuffleMask);
21812194
}
21822195

21832196
/// Return true if this shuffle mask chooses all elements with the same value
@@ -2199,7 +2212,7 @@ class ShuffleVectorInst : public Instruction {
21992212
/// TODO: Optionally allow length-changing shuffles.
22002213
/// TODO: Optionally allow splats from other elements.
22012214
bool isZeroEltSplat() const {
2202-
return !changesLength() && isZeroEltSplatMask(getMask());
2215+
return !changesLength() && isZeroEltSplatMask(ShuffleMask);
22032216
}
22042217

22052218
/// Return true if this shuffle mask is a transpose mask.
@@ -2248,7 +2261,7 @@ class ShuffleVectorInst : public Instruction {
22482261
/// exact specification.
22492262
/// Example: shufflevector <4 x n> A, <4 x n> B, <0,4,2,6>
22502263
bool isTranspose() const {
2251-
return !changesLength() && isTransposeMask(getMask());
2264+
return !changesLength() && isTransposeMask(ShuffleMask);
22522265
}
22532266

22542267
/// Return true if this shuffle mask is an extract subvector mask.
@@ -2267,7 +2280,7 @@ class ShuffleVectorInst : public Instruction {
22672280
/// Return true if this shuffle mask is an extract subvector mask.
22682281
bool isExtractSubvectorMask(int &Index) const {
22692282
int NumSrcElts = Op<0>()->getType()->getVectorNumElements();
2270-
return isExtractSubvectorMask(getMask(), NumSrcElts, Index);
2283+
return isExtractSubvectorMask(ShuffleMask, NumSrcElts, Index);
22712284
}
22722285

22732286
/// Change values in a shuffle permute mask assuming the two vector operands
@@ -2293,9 +2306,8 @@ class ShuffleVectorInst : public Instruction {
22932306
};
22942307

22952308
template <>
2296-
struct OperandTraits<ShuffleVectorInst> :
2297-
public FixedNumOperandTraits<ShuffleVectorInst, 3> {
2298-
};
2309+
struct OperandTraits<ShuffleVectorInst>
2310+
: public FixedNumOperandTraits<ShuffleVectorInst, 2> {};
22992311

23002312
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorInst, Value)
23012313

llvm/include/llvm/IR/NoFolder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ class NoFolder final : public IRBuilderFolder {
300300
}
301301

302302
Instruction *CreateShuffleVector(Constant *V1, Constant *V2,
303-
Constant *Mask) const override {
303+
ArrayRef<int> Mask) const override {
304304
return new ShuffleVectorInst(V1, V2, Mask);
305305
}
306306

0 commit comments

Comments
 (0)