summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorSimon Pilgrim <llvm-dev@redking.me.uk>2016-04-09 14:51:26 +0000
committerSimon Pilgrim <llvm-dev@redking.me.uk>2016-04-09 14:51:26 +0000
commit1cc5712763e6af3aa1f181680a9359280e6adc14 (patch)
tree8ffd32585e824cff6e3665a70b26bd9143dba0cd /llvm/lib/Target
parentb3410db2b7dfd9ccec9d782b74477a1d0a2febad (diff)
downloadbcm5719-llvm-1cc5712763e6af3aa1f181680a9359280e6adc14.tar.gz
bcm5719-llvm-1cc5712763e6af3aa1f181680a9359280e6adc14.zip
[X86][XOP] Support for VPPERM 2-input shuffle mask decoding
This patch adds support for decoding XOP VPPERM instruction when it represents a basic shuffle. The mask decoding required the existing MCInstrLowering code to be updated to support binary shuffles - the implementation now matches what is done in X86InstrComments.cpp. Differential Revision: http://reviews.llvm.org/D18441 llvm-svn: 265874
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/X86/X86MCInstLower.cpp83
-rw-r--r--llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp68
-rw-r--r--llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.h3
3 files changed, 127 insertions, 27 deletions
diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp
index 45380e09ab3..d02786cf562 100644
--- a/llvm/lib/Target/X86/X86MCInstLower.cpp
+++ b/llvm/lib/Target/X86/X86MCInstLower.cpp
@@ -1018,7 +1018,8 @@ static const Constant *getConstantFromPool(const MachineInstr &MI,
}
static std::string getShuffleComment(const MachineOperand &DstOp,
- const MachineOperand &SrcOp,
+ const MachineOperand &SrcOp1,
+ const MachineOperand &SrcOp2,
ArrayRef<int> Mask) {
std::string Comment;
@@ -1032,39 +1033,49 @@ static std::string getShuffleComment(const MachineOperand &DstOp,
};
StringRef DstName = DstOp.isReg() ? GetRegisterName(DstOp.getReg()) : "mem";
- StringRef SrcName = SrcOp.isReg() ? GetRegisterName(SrcOp.getReg()) : "mem";
+ StringRef Src1Name =
+ SrcOp1.isReg() ? GetRegisterName(SrcOp1.getReg()) : "mem";
+ StringRef Src2Name =
+ SrcOp2.isReg() ? GetRegisterName(SrcOp2.getReg()) : "mem";
+
+ // One source operand, fix the mask to print all elements in one span.
+ SmallVector<int, 8> ShuffleMask(Mask.begin(), Mask.end());
+ if (Src1Name == Src2Name)
+ for (int i = 0, e = ShuffleMask.size(); i != e; ++i)
+ if (ShuffleMask[i] >= e)
+ ShuffleMask[i] -= e;
raw_string_ostream CS(Comment);
CS << DstName << " = ";
- bool NeedComma = false;
- bool InSrc = false;
- for (int M : Mask) {
- // Wrap up any prior entry...
- if (M == SM_SentinelZero && InSrc) {
- InSrc = false;
- CS << "]";
- }
- if (NeedComma)
+ for (int i = 0, e = ShuffleMask.size(); i != e; ++i) {
+ if (i != 0)
CS << ",";
- else
- NeedComma = true;
-
- // Print this shuffle...
- if (M == SM_SentinelZero) {
+ if (ShuffleMask[i] == SM_SentinelZero) {
CS << "zero";
- } else {
- if (!InSrc) {
- InSrc = true;
- CS << SrcName << "[";
- }
- if (M == SM_SentinelUndef)
+ continue;
+ }
+
+ // Otherwise, it must come from src1 or src2. Print the span of elements
+ // that comes from this src.
+ bool isSrc1 = ShuffleMask[i] < (int)e;
+ CS << (isSrc1 ? Src1Name : Src2Name) << '[';
+
+ bool IsFirst = true;
+ while (i != e && ShuffleMask[i] != SM_SentinelZero &&
+ (ShuffleMask[i] < (int)e) == isSrc1) {
+ if (!IsFirst)
+ CS << ',';
+ else
+ IsFirst = false;
+ if (ShuffleMask[i] == SM_SentinelUndef)
CS << "u";
else
- CS << M;
+ CS << ShuffleMask[i] % (int)e;
+ ++i;
}
+ CS << ']';
+ --i; // For loop increments element #.
}
- if (InSrc)
- CS << "]";
CS.flush();
return Comment;
@@ -1313,7 +1324,7 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
SmallVector<int, 16> Mask;
DecodePSHUFBMask(C, Mask);
if (!Mask.empty())
- OutStreamer->AddComment(getShuffleComment(DstOp, SrcOp, Mask));
+ OutStreamer->AddComment(getShuffleComment(DstOp, SrcOp, SrcOp, Mask));
}
break;
}
@@ -1340,7 +1351,25 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
SmallVector<int, 16> Mask;
DecodeVPERMILPMask(C, ElSize, Mask);
if (!Mask.empty())
- OutStreamer->AddComment(getShuffleComment(DstOp, SrcOp, Mask));
+ OutStreamer->AddComment(getShuffleComment(DstOp, SrcOp, SrcOp, Mask));
+ }
+ break;
+ }
+ case X86::VPPERMrrm: {
+ if (!OutStreamer->isVerboseAsm())
+ break;
+ assert(MI->getNumOperands() > 6 &&
+ "We should always have at least 6 operands!");
+ const MachineOperand &DstOp = MI->getOperand(0);
+ const MachineOperand &SrcOp1 = MI->getOperand(1);
+ const MachineOperand &SrcOp2 = MI->getOperand(2);
+ const MachineOperand &MaskOp = MI->getOperand(6);
+
+ if (auto *C = getConstantFromPool(*MI, MaskOp)) {
+ SmallVector<int, 16> Mask;
+ DecodeVPPERMMask(C, Mask);
+ if (!Mask.empty())
+ OutStreamer->AddComment(getShuffleComment(DstOp, SrcOp1, SrcOp2, Mask));
}
break;
}
diff --git a/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp b/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp
index 4e7714eeb2e..f24f38d4a21 100644
--- a/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp
+++ b/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.cpp
@@ -153,6 +153,74 @@ void DecodeVPERMILPMask(const Constant *C, unsigned ElSize,
// TODO: Handle funny-looking vectors too.
}
+void DecodeVPPERMMask(const Constant *C, SmallVectorImpl<int> &ShuffleMask) {
+ Type *MaskTy = C->getType();
+ assert(MaskTy->getPrimitiveSizeInBits() == 128);
+
+ // Only support vector types.
+ if (!MaskTy->isVectorTy())
+ return;
+
+ // Make sure its an integer type.
+ Type *VecEltTy = MaskTy->getVectorElementType();
+ if (!VecEltTy->isIntegerTy())
+ return;
+
+ // The shuffle mask requires a byte vector - decode cases with
+ // wider elements as well.
+ unsigned BitWidth = cast<IntegerType>(VecEltTy)->getBitWidth();
+ if ((BitWidth % 8) != 0)
+ return;
+
+ int NumElts = MaskTy->getVectorNumElements();
+ int Scale = BitWidth / 8;
+ int NumBytes = NumElts * Scale;
+ ShuffleMask.reserve(NumBytes);
+
+ for (int i = 0; i != NumElts; ++i) {
+ Constant *COp = C->getAggregateElement(i);
+ if (!COp) {
+ ShuffleMask.clear();
+ return;
+ } else if (isa<UndefValue>(COp)) {
+ ShuffleMask.append(Scale, SM_SentinelUndef);
+ continue;
+ }
+
+ // VPPERM Operation
+ // Bits[4:0] - Byte Index (0 - 31)
+ // Bits[7:5] - Permute Operation
+ //
+ // Permute Operation:
+ // 0 - Source byte (no logical operation).
+ // 1 - Invert source byte.
+ // 2 - Bit reverse of source byte.
+ // 3 - Bit reverse of inverted source byte.
+ // 4 - 00h (zero - fill).
+ // 5 - FFh (ones - fill).
+ // 6 - Most significant bit of source byte replicated in all bit positions.
+ // 7 - Invert most significant bit of source byte and replicate in all bit positions.
+ APInt MaskElt = cast<ConstantInt>(COp)->getValue();
+ for (int j = 0; j != Scale; ++j) {
+ APInt Index = MaskElt.getLoBits(5);
+ APInt PermuteOp = MaskElt.lshr(5).getLoBits(3);
+ MaskElt = MaskElt.lshr(8);
+
+ if (PermuteOp == 4) {
+ ShuffleMask.push_back(SM_SentinelZero);
+ continue;
+ }
+ if (PermuteOp != 0) {
+ ShuffleMask.clear();
+ return;
+ }
+ ShuffleMask.push_back((int)Index.getZExtValue());
+ }
+ }
+
+ assert(NumBytes == (int)ShuffleMask.size() && "Unexpected shuffle mask size");
+}
+
void DecodeVPERMVMask(const Constant *C, MVT VT,
SmallVectorImpl<int> &ShuffleMask) {
Type *MaskTy = C->getType();
diff --git a/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.h b/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.h
index bd61e4ba2e8..a07b26c04f7 100644
--- a/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.h
+++ b/llvm/lib/Target/X86/X86ShuffleDecodeConstantPool.h
@@ -32,6 +32,9 @@ void DecodePSHUFBMask(const Constant *C, SmallVectorImpl<int> &ShuffleMask);
void DecodeVPERMILPMask(const Constant *C, unsigned ElSize,
SmallVectorImpl<int> &ShuffleMask);
+/// Decode a VPPERM variable mask from an IR-level vector constant.
+void DecodeVPPERMMask(const Constant *C, SmallVectorImpl<int> &ShuffleMask);
+
/// Decode a VPERM W/D/Q/PS/PD mask from an IR-level vector constant.
void DecodeVPERMVMask(const Constant *C, MVT VT,
SmallVectorImpl<int> &ShuffleMask);
OpenPOWER on IntegriCloud