summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR/Instructions.cpp
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2018-06-19 18:44:00 +0000
committerSanjay Patel <spatel@rotateright.com>2018-06-19 18:44:00 +0000
commit2ca3360b11a540d88d6fbf7219d97c10d5b837c7 (patch)
treec7637756e927f5be0c1e6799857e777c75089a15 /llvm/lib/IR/Instructions.cpp
parenta245c765a8fe23c689e34acd29f6f8863a1da369 (diff)
downloadbcm5719-llvm-2ca3360b11a540d88d6fbf7219d97c10d5b837c7.tar.gz
bcm5719-llvm-2ca3360b11a540d88d6fbf7219d97c10d5b837c7.zip
[IR] move shuffle mask queries from TTI to ShuffleVectorInst
The optimizer is getting smarter (eg, D47986) about differentiating shuffles based on its mask values, so we should make queries on the mask constant operand generally available to avoid code duplication. We'll probably use this soon in the vectorizers and instcombine (D48023 and https://bugs.llvm.org/show_bug.cgi?id=37806). We might clean up TTI a bit more once all of its current 'SK_*' options are covered. Differential Revision: https://reviews.llvm.org/D48236 llvm-svn: 335067
Diffstat (limited to 'llvm/lib/IR/Instructions.cpp')
-rw-r--r--llvm/lib/IR/Instructions.cpp106
1 files changed, 104 insertions, 2 deletions
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index e486890e616..58d377c47f6 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -1658,7 +1658,7 @@ bool ShuffleVectorInst::isValidOperands(const Value *V1, const Value *V2,
return false;
}
-int ShuffleVectorInst::getMaskValue(Constant *Mask, unsigned i) {
+int ShuffleVectorInst::getMaskValue(const Constant *Mask, unsigned i) {
assert(i < Mask->getType()->getVectorNumElements() && "Index out of range");
if (auto *CDS = dyn_cast<ConstantDataSequential>(Mask))
return CDS->getElementAsInteger(i);
@@ -1668,7 +1668,7 @@ int ShuffleVectorInst::getMaskValue(Constant *Mask, unsigned i) {
return cast<ConstantInt>(C)->getZExtValue();
}
-void ShuffleVectorInst::getShuffleMask(Constant *Mask,
+void ShuffleVectorInst::getShuffleMask(const Constant *Mask,
SmallVectorImpl<int> &Result) {
unsigned NumElts = Mask->getType()->getVectorNumElements();
@@ -1684,6 +1684,108 @@ void ShuffleVectorInst::getShuffleMask(Constant *Mask,
}
}
+bool ShuffleVectorInst::isSingleSourceMask(ArrayRef<int> Mask) {
+ assert(!Mask.empty() && "Shuffle mask must contain elements");
+ bool UsesLHS = false;
+ bool UsesRHS = false;
+ for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {
+ if (Mask[i] == -1)
+ continue;
+ assert(Mask[i] >= 0 && Mask[i] < (NumElts * 2) &&
+ "Out-of-bounds shuffle mask element");
+ UsesLHS |= (Mask[i] < NumElts);
+ UsesRHS |= (Mask[i] >= NumElts);
+ if (UsesLHS && UsesRHS)
+ return false;
+ }
+ assert((UsesLHS ^ UsesRHS) && "Should have selected from exactly 1 source");
+ return true;
+}
+
+bool ShuffleVectorInst::isIdentityMask(ArrayRef<int> Mask) {
+ if (!isSingleSourceMask(Mask))
+ return false;
+ for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {
+ if (Mask[i] == -1)
+ continue;
+ if (Mask[i] != i && Mask[i] != (NumElts + i))
+ return false;
+ }
+ return true;
+}
+
+bool ShuffleVectorInst::isReverseMask(ArrayRef<int> Mask) {
+ if (!isSingleSourceMask(Mask))
+ return false;
+ for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {
+ if (Mask[i] == -1)
+ continue;
+ if (Mask[i] != (NumElts - 1 - i) && Mask[i] != (NumElts + NumElts - 1 - i))
+ return false;
+ }
+ return true;
+}
+
+bool ShuffleVectorInst::isZeroEltSplatMask(ArrayRef<int> Mask) {
+ if (!isSingleSourceMask(Mask))
+ return false;
+ for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {
+ if (Mask[i] == -1)
+ continue;
+ if (Mask[i] != 0 && Mask[i] != NumElts)
+ return false;
+ }
+ return true;
+}
+
+bool ShuffleVectorInst::isSelectMask(ArrayRef<int> Mask) {
+ // Select is differentiated from identity. It requires using both sources.
+ if (isSingleSourceMask(Mask))
+ return false;
+ for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {
+ if (Mask[i] == -1)
+ continue;
+ if (Mask[i] != i && Mask[i] != (NumElts + i))
+ return false;
+ }
+ return true;
+}
+
+bool ShuffleVectorInst::isTransposeMask(ArrayRef<int> Mask) {
+ // Example masks that will return true:
+ // v1 = <a, b, c, d>
+ // v2 = <e, f, g, h>
+ // trn1 = shufflevector v1, v2 <0, 4, 2, 6> = <a, e, c, g>
+ // trn2 = shufflevector v1, v2 <1, 5, 3, 7> = <b, f, d, h>
+
+ // 1. The number of elements in the mask must be a power-of-2 and at least 2.
+ int NumElts = Mask.size();
+ if (NumElts < 2 || !isPowerOf2_32(NumElts))
+ return false;
+
+ // 2. The first element of the mask must be either a 0 or a 1.
+ if (Mask[0] != 0 && Mask[0] != 1)
+ return false;
+
+ // 3. The difference between the first 2 elements must be equal to the
+ // number of elements in the mask.
+ if ((Mask[1] - Mask[0]) != NumElts)
+ return false;
+
+ // 4. The difference between consecutive even-numbered and odd-numbered
+ // elements must be equal to 2.
+ for (int i = 2; i < NumElts; ++i) {
+ int MaskEltVal = Mask[i];
+ if (MaskEltVal == -1)
+ return false;
+ int MaskEltPrevVal = Mask[i - 2];
+ if (MaskEltVal - MaskEltPrevVal != 2)
+ return false;
+ }
+ return true;
+}
+
+
//===----------------------------------------------------------------------===//
// InsertValueInst Class
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud