[x86] Start refactoring the comment printing logic in the MC lowering of

vector shuffles.

This is just the beginning by hoisting it into its own function and
making use of early exit to dramatically simplify the flow of the
function. I'm going to be incrementally refactoring this until it is
a bit less magical how this applies to other instructions, and I can
teach it how to dig a shuffle mask out of a register. Then I plan to
hook it up to VPERMD so we get our mask comments for it.

No functionality changed yet.

llvm-svn: 218357
This commit is contained in:
Chandler Carruth 2014-09-24 02:16:12 +00:00
parent 3e0effa223
commit 0b682d42de
1 changed files with 102 additions and 87 deletions

View File

@ -864,6 +864,104 @@ PrevCrossBBInst(MachineBasicBlock::const_iterator MBBI) {
return --MBBI;
}
static std::string getShuffleComment(const MachineInstr &MI) {
std::string Comment;
SmallVector<int, 16> Mask;
// All of these instructions accept a constant pool operand as their fifth.
assert(MI.getNumOperands() > 5 &&
"We should always have at least 5 operands!");
const MachineOperand &DstOp = MI.getOperand(0);
const MachineOperand &SrcOp = MI.getOperand(1);
const MachineOperand &MaskOp = MI.getOperand(5);
if (!MaskOp.isCPI())
return Comment;
ArrayRef<MachineConstantPoolEntry> Constants =
MI.getParent()->getParent()->getConstantPool()->getConstants();
const MachineConstantPoolEntry &MaskConstantEntry =
Constants[MaskOp.getIndex()];
// Bail if this is a machine constant pool entry, we won't be able to dig out
// anything useful.
if (MaskConstantEntry.isMachineConstantPoolEntry())
return Comment;
auto *C = dyn_cast<Constant>(MaskConstantEntry.Val.ConstVal);
if (!C)
return Comment;
assert(MaskConstantEntry.getType() == C->getType() &&
"Expected a constant of the same type!");
switch (MI.getOpcode()) {
case X86::PSHUFBrm:
case X86::VPSHUFBrm:
DecodePSHUFBMask(C, Mask);
break;
case X86::VPERMILPSrm:
case X86::VPERMILPDrm:
case X86::VPERMILPSYrm:
case X86::VPERMILPDYrm:
DecodeVPERMILPMask(C, Mask);
break;
}
if (Mask.empty())
return Comment;
assert(Mask.size() == C->getType()->getVectorNumElements() &&
"Shuffle mask has a different size than its type!");
// 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";
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)
CS << ",";
else
NeedComma = true;
// Print this shuffle...
if (M == SM_SentinelZero) {
CS << "zero";
} else {
if (!InSrc) {
InSrc = true;
CS << SrcName << "[";
}
if (M == SM_SentinelUndef)
CS << "u";
else
CS << M;
}
}
if (InSrc)
CS << "]";
CS.flush();
return Comment;
}
void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
X86MCInstLower MCInstLowering(*MF, *this);
const X86RegisterInfo *RI = static_cast<const X86RegisterInfo *>(
@ -1025,98 +1123,15 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
case X86::VPERMILPSrm:
case X86::VPERMILPDrm:
case X86::VPERMILPSYrm:
case X86::VPERMILPDYrm:
case X86::VPERMILPDYrm: {
// Lower PSHUFB and VPERMILP 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;
// All of these instructions accept a constant pool operand as their fifth.
assert(MI->getNumOperands() > 5 && "We should always have at least 5 operands!");
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[MaskOp.getIndex()];
Type *MaskTy = MaskConstantEntry.getType();
(void)MaskTy;
if (!MaskConstantEntry.isMachineConstantPoolEntry())
if (auto *C = dyn_cast<Constant>(MaskConstantEntry.Val.ConstVal)) {
assert(MaskTy == C->getType() &&
"Expected a constant of the same type!");
switch (MI->getOpcode()) {
case X86::PSHUFBrm:
case X86::VPSHUFBrm:
DecodePSHUFBMask(C, Mask);
break;
case X86::VPERMILPSrm:
case X86::VPERMILPDrm:
case X86::VPERMILPSYrm:
case X86::VPERMILPDYrm:
DecodeVPERMILPMask(C, Mask);
}
assert(
(Mask.empty() || 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 << "[";
}
if (M == SM_SentinelUndef)
CS << "u";
else
CS << M;
}
}
if (InSrc)
CS << "]";
OutStreamer.AddComment(CS.str());
}
std::string Comment = getShuffleComment(*MI);
OutStreamer.AddComment(Comment);
break;
}
}
MCInst TmpInst;
MCInstLowering.Lower(MI, TmpInst);