//===----------------------------------------------------------------------===//
#include "X86ShuffleDecode.h"
+#include "llvm/IR/Constants.h"
#include "llvm/CodeGen/MachineValueType.h"
//===----------------------------------------------------------------------===//
}
}
+/// \brief Decode PSHUFB masks stored in an LLVM Constant.
+void DecodePSHUFBMask(const ConstantDataSequential *C,
+ SmallVectorImpl<int> &ShuffleMask) {
+ Type *MaskTy = C->getType();
+ assert(MaskTy->isVectorTy() && "Expected a vector constant mask!");
+ Type *EltTy = MaskTy->getVectorElementType();
+ assert(EltTy->isIntegerTy(8) && "Expected i8 constant mask elements!");
+ int NumElements = MaskTy->getVectorNumElements();
+ // FIXME: Add support for AVX-512.
+ assert((NumElements == 16 || NumElements == 32) &&
+ "Only 128-bit and 256-bit vectors supported!");
+ assert((unsigned)NumElements == C->getNumElements() &&
+ "Constant mask has a different number of elements!");
+
+ ShuffleMask.reserve(NumElements);
+ for (int i = 0; i < NumElements; ++i) {
+ // For AVX vectors with 32 bytes the base of the shuffle is the half of the
+ // vector we're inside.
+ int Base = i < 16 ? 0 : 16;
+ uint64_t Element = C->getElementAsInteger(i);
+ // If the high bit (7) of the byte is set, the element is zeroed.
+ if (Element & (1 << 7))
+ ShuffleMask.push_back(SM_SentinelZero);
+ else {
+ int Index = Base + Element;
+ assert((Index >= 0 && Index < NumElements) ||
+ "Out of bounds shuffle index for pshub instruction!");
+ ShuffleMask.push_back(Index);
+ }
+ }
+}
+
/// DecodeVPERMMask - this decodes the shuffle masks for VPERMQ/VPERMPD.
/// No VT provided since it only works on 256-bit, 4 element vectors.
void DecodeVPERMMask(unsigned Imm, SmallVectorImpl<int> &ShuffleMask) {
#include "X86RegisterInfo.h"
#include "InstPrinter/X86ATTInstPrinter.h"
#include "MCTargetDesc/X86BaseInfo.h"
+#include "Utils/X86ShuffleDecode.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/CodeGen/StackMaps.h"
#include "llvm/IR/DataLayout.h"
case X86::SEH_EndPrologue:
OutStreamer.EmitWinCFIEndProlog();
return;
+
+ case X86::PSHUFBrm:
+ // Lower PSHUFB normally but add a comment if we can find a constant
+ // shuffle mask. We won't be able to do this at the MC layer because the
+ // mask isn't an immediate.
+ std::string Comment;
+ raw_string_ostream CS(Comment);
+ SmallVector<int, 16> Mask;
+
+ assert(MI->getNumOperands() == 7 &&
+ "Wrong number of operansd for PSHUFBrm");
+ const MachineOperand &DstOp = MI->getOperand(0);
+ const MachineOperand &SrcOp = MI->getOperand(1);
+ const MachineOperand &MaskOp = MI->getOperand(5);
+
+ // Compute the name for a register. This is really goofy because we have
+ // multiple instruction printers that could (in theory) use different
+ // names. Fortunately most people use the ATT style (outside of Windows)
+ // and they actually agree on register naming here. Ultimately, this is
+ // a comment, and so its OK if it isn't perfect.
+ auto GetRegisterName = [](unsigned RegNum) -> StringRef {
+ return X86ATTInstPrinter::getRegisterName(RegNum);
+ };
+
+ StringRef DstName = DstOp.isReg() ? GetRegisterName(DstOp.getReg()) : "mem";
+ StringRef SrcName = SrcOp.isReg() ? GetRegisterName(SrcOp.getReg()) : "mem";
+ CS << DstName << " = ";
+
+ if (MaskOp.isCPI()) {
+ ArrayRef<MachineConstantPoolEntry> Constants =
+ MI->getParent()->getParent()->getConstantPool()->getConstants();
+ const MachineConstantPoolEntry &MaskConstantEntry =
+ Constants[MI->getOperand(5).getIndex()];
+ Type *MaskTy = MaskConstantEntry.getType();
+ if (!MaskConstantEntry.isMachineConstantPoolEntry())
+ if (auto *C = dyn_cast<ConstantDataSequential>(
+ MaskConstantEntry.Val.ConstVal)) {
+ assert(MaskTy == C->getType() &&
+ "Expected a constant of the same type!");
+
+ DecodePSHUFBMask(C, Mask);
+ assert(Mask.size() == MaskTy->getVectorNumElements() &&
+ "Shuffle mask has a different size than its type!");
+ }
+ }
+
+ if (!Mask.empty()) {
+ 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)
+ CS << ",";
+ else
+ NeedComma = true;
+
+ // Print this shuffle...
+ if (M == SM_SentinelZero) {
+ CS << "zero";
+ } else {
+ if (!InSrc) {
+ InSrc = true;
+ CS << SrcName << "[";
+ }
+ CS << M;
+ }
+ }
+ if (InSrc)
+ CS << "]";
+
+ OutStreamer.AddComment(CS.str());
+ }
+ break;
}
MCInst TmpInst;