summaryrefslogtreecommitdiff
path: root/lib/Target/X86/X86EvexToVex.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/X86/X86EvexToVex.cpp')
-rwxr-xr-xlib/Target/X86/X86EvexToVex.cpp133
1 files changed, 90 insertions, 43 deletions
diff --git a/lib/Target/X86/X86EvexToVex.cpp b/lib/Target/X86/X86EvexToVex.cpp
index 6472bbbc9016..6dd4631a4844 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)