From 5f671bae7c5501fb301ebeffc8746559366f668c Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Wed, 24 Sep 2014 02:16:12 +0000 Subject: [PATCH] [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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218357 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86MCInstLower.cpp | 189 ++++++++++++++++-------------- 1 file changed, 102 insertions(+), 87 deletions(-) diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp index bc02d6bac3e..411b046f71c 100644 --- a/lib/Target/X86/X86MCInstLower.cpp +++ b/lib/Target/X86/X86MCInstLower.cpp @@ -864,6 +864,104 @@ PrevCrossBBInst(MachineBasicBlock::const_iterator MBBI) { return --MBBI; } +static std::string getShuffleComment(const MachineInstr &MI) { + std::string Comment; + SmallVector 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 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(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( @@ -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 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 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(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); -- 2.34.1