diff options
Diffstat (limited to 'lib/Target/X86/X86EvexToVex.cpp')
| -rwxr-xr-x | lib/Target/X86/X86EvexToVex.cpp | 133 |
1 files changed, 90 insertions, 43 deletions
diff --git a/lib/Target/X86/X86EvexToVex.cpp b/lib/Target/X86/X86EvexToVex.cpp index 6472bbbc90169..6dd4631a48448 100755 --- a/lib/Target/X86/X86EvexToVex.cpp +++ b/lib/Target/X86/X86EvexToVex.cpp @@ -1,4 +1,4 @@ -//===----------------------- X86EvexToVex.cpp ----------------------------===// +//===- X86EvexToVex.cpp ---------------------------------------------------===// // Compress EVEX instructions to VEX encoding when possible to reduce code size // // The LLVM Compiler Infrastructure @@ -6,18 +6,19 @@ // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // -//===---------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// /// \file /// This file defines the pass that goes over all AVX-512 instructions which /// are encoded using the EVEX prefix and if possible replaces them by their /// corresponding VEX encoding which is usually shorter by 2 bytes. /// EVEX instructions may be encoded via the VEX prefix when the AVX-512 /// instruction has a corresponding AVX/AVX2 opcode and when it does not -/// use the xmm or the mask registers or xmm/ymm registers wuith indexes +/// use the xmm or the mask registers or xmm/ymm registers with indexes /// higher than 15. /// The pass applies code reduction on the generated code for AVX-512 instrs. -/// -//===---------------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// #include "InstPrinter/X86InstComments.h" #include "MCTargetDesc/X86BaseInfo.h" @@ -54,7 +55,7 @@ namespace { class EvexToVexInstPass : public MachineFunctionPass { /// X86EvexToVexCompressTable - Evex to Vex encoding opcode map. - typedef DenseMap<unsigned, uint16_t> EvexToVexTableType; + using EvexToVexTableType = DenseMap<unsigned, uint16_t>; EvexToVexTableType EvexToVex128Table; EvexToVexTableType EvexToVex256Table; @@ -101,10 +102,10 @@ private: const X86InstrInfo *TII; }; -char EvexToVexInstPass::ID = 0; - } // end anonymous namespace +char EvexToVexInstPass::ID = 0; + bool EvexToVexInstPass::runOnMachineFunction(MachineFunction &MF) { TII = MF.getSubtarget<X86Subtarget>().getInstrInfo(); @@ -118,8 +119,8 @@ bool EvexToVexInstPass::runOnMachineFunction(MachineFunction &MF) { /// EVEX encoded instrs by VEX encoding when possible. for (MachineBasicBlock &MBB : MF) { - // Traverse the basic block. - for (MachineInstr &MI : MBB) + // Traverse the basic block. + for (MachineInstr &MI : MBB) Changed |= CompressEvexToVexImpl(MI); } @@ -131,6 +132,75 @@ void EvexToVexInstPass::AddTableEntry(EvexToVexTableType &EvexToVexTable, EvexToVexTable[EvexOp] = VexOp; } +static bool usesExtendedRegister(const MachineInstr &MI) { + auto isHiRegIdx = [](unsigned Reg) { + // Check for XMM register with indexes between 16 - 31. + if (Reg >= X86::XMM16 && Reg <= X86::XMM31) + return true; + + // Check for YMM register with indexes between 16 - 31. + if (Reg >= X86::YMM16 && Reg <= X86::YMM31) + return true; + + return false; + }; + + // Check that operands are not ZMM regs or + // XMM/YMM regs with hi indexes between 16 - 31. + for (const MachineOperand &MO : MI.explicit_operands()) { + if (!MO.isReg()) + continue; + + unsigned Reg = MO.getReg(); + + assert(!(Reg >= X86::ZMM0 && Reg <= X86::ZMM31) && + "ZMM instructions should not be in the EVEX->VEX tables"); + + if (isHiRegIdx(Reg)) + return true; + } + + return false; +} + +// Do any custom cleanup needed to finalize the conversion. +static void performCustomAdjustments(MachineInstr &MI, unsigned NewOpc) { + (void)NewOpc; + unsigned Opc = MI.getOpcode(); + switch (Opc) { + case X86::VALIGNDZ128rri: + case X86::VALIGNDZ128rmi: + case X86::VALIGNQZ128rri: + case X86::VALIGNQZ128rmi: { + assert((NewOpc == X86::VPALIGNRrri || NewOpc == X86::VPALIGNRrmi) && + "Unexpected new opcode!"); + unsigned Scale = (Opc == X86::VALIGNQZ128rri || + Opc == X86::VALIGNQZ128rmi) ? 8 : 4; + MachineOperand &Imm = MI.getOperand(MI.getNumExplicitOperands()-1); + Imm.setImm(Imm.getImm() * Scale); + break; + } + case X86::VSHUFF32X4Z256rmi: + case X86::VSHUFF32X4Z256rri: + case X86::VSHUFF64X2Z256rmi: + case X86::VSHUFF64X2Z256rri: + case X86::VSHUFI32X4Z256rmi: + case X86::VSHUFI32X4Z256rri: + case X86::VSHUFI64X2Z256rmi: + case X86::VSHUFI64X2Z256rri: { + assert((NewOpc == X86::VPERM2F128rr || NewOpc == X86::VPERM2I128rr || + NewOpc == X86::VPERM2F128rm || NewOpc == X86::VPERM2I128rm) && + "Unexpected new opcode!"); + MachineOperand &Imm = MI.getOperand(MI.getNumExplicitOperands()-1); + int64_t ImmVal = Imm.getImm(); + // Set bit 5, move bit 1 to bit 4, copy bit 0. + Imm.setImm(0x20 | ((ImmVal & 2) << 3) | (ImmVal & 1)); + break; + } + } +} + + // For EVEX instructions that can be encoded using VEX encoding // replace them by the VEX encoding in order to reduce size. bool EvexToVexInstPass::CompressEvexToVexImpl(MachineInstr &MI) const { @@ -147,18 +217,18 @@ bool EvexToVexInstPass::CompressEvexToVexImpl(MachineInstr &MI) const { // Check for EVEX instructions only. if ((Desc.TSFlags & X86II::EncodingMask) != X86II::EVEX) return false; - - // Check for EVEX instructions with mask or broadcast as in these cases - // the EVEX prefix is needed in order to carry this information + + // Check for EVEX instructions with mask or broadcast as in these cases + // the EVEX prefix is needed in order to carry this information // thus preventing the transformation to VEX encoding. if (Desc.TSFlags & (X86II::EVEX_K | X86II::EVEX_B)) return false; - + // Check for non EVEX_V512 instrs only. // EVEX_V512 instr: bit EVEX_L2 = 1; bit VEX_L = 0. if ((Desc.TSFlags & X86II::EVEX_L2) && !(Desc.TSFlags & X86II::VEX_L)) - return false; - + return false; + // EVEX_V128 instr: bit EVEX_L2 = 0, bit VEX_L = 0. bool IsEVEX_V128 = (!(Desc.TSFlags & X86II::EVEX_L2) && !(Desc.TSFlags & X86II::VEX_L)); @@ -176,7 +246,6 @@ bool EvexToVexInstPass::CompressEvexToVexImpl(MachineInstr &MI) const { if (It != EvexToVex256Table.end()) NewOpc = It->second; } - // Check for EVEX_V128 or Scalar instructions. else if (IsEVEX_V128) { // Search for opcode in the EvexToVex128 table. @@ -188,36 +257,14 @@ bool EvexToVexInstPass::CompressEvexToVexImpl(MachineInstr &MI) const { if (!NewOpc) return false; - auto isHiRegIdx = [](unsigned Reg) { - // Check for XMM register with indexes between 16 - 31. - if (Reg >= X86::XMM16 && Reg <= X86::XMM31) - return true; - - // Check for YMM register with indexes between 16 - 31. - if (Reg >= X86::YMM16 && Reg <= X86::YMM31) - return true; - + if (usesExtendedRegister(MI)) return false; - }; - - // Check that operands are not ZMM regs or - // XMM/YMM regs with hi indexes between 16 - 31. - for (const MachineOperand &MO : MI.explicit_operands()) { - if (!MO.isReg()) - continue; - unsigned Reg = MO.getReg(); - - assert (!(Reg >= X86::ZMM0 && Reg <= X86::ZMM31)); + performCustomAdjustments(MI, NewOpc); - if (isHiRegIdx(Reg)) - return false; - } - - const MCInstrDesc &MCID = TII->get(NewOpc); - MI.setDesc(MCID); + MI.setDesc(TII->get(NewOpc)); MI.setAsmPrinterFlag(AC_EVEX_2_VEX); - return true; + return true; } INITIALIZE_PASS(EvexToVexInstPass, EVEX2VEX_NAME, EVEX2VEX_DESC, false, false) |
