1 //===- X86EvexToVex.cpp ---------------------------------------------------===// 2 // Compress EVEX instructions to VEX encoding when possible to reduce code size 3 // 4 // The LLVM Compiler Infrastructure 5 // 6 // This file is distributed under the University of Illinois Open Source 7 // License. See LICENSE.TXT for details. 8 // 9 //===----------------------------------------------------------------------===// 10 // 11 /// \file 12 /// This file defines the pass that goes over all AVX-512 instructions which 13 /// are encoded using the EVEX prefix and if possible replaces them by their 14 /// corresponding VEX encoding which is usually shorter by 2 bytes. 15 /// EVEX instructions may be encoded via the VEX prefix when the AVX-512 16 /// instruction has a corresponding AVX/AVX2 opcode and when it does not 17 /// use the xmm or the mask registers or xmm/ymm registers with indexes 18 /// higher than 15. 19 /// The pass applies code reduction on the generated code for AVX-512 instrs. 20 // 21 //===----------------------------------------------------------------------===// 22 23 #include "InstPrinter/X86InstComments.h" 24 #include "MCTargetDesc/X86BaseInfo.h" 25 #include "X86.h" 26 #include "X86InstrInfo.h" 27 #include "X86Subtarget.h" 28 #include "llvm/ADT/DenseMap.h" 29 #include "llvm/ADT/StringRef.h" 30 #include "llvm/CodeGen/MachineFunction.h" 31 #include "llvm/CodeGen/MachineFunctionPass.h" 32 #include "llvm/CodeGen/MachineInstr.h" 33 #include "llvm/CodeGen/MachineOperand.h" 34 #include "llvm/MC/MCInstrDesc.h" 35 #include "llvm/Pass.h" 36 #include <cassert> 37 #include <cstdint> 38 39 using namespace llvm; 40 41 // Including the generated EVEX2VEX tables. 42 struct X86EvexToVexCompressTableEntry { 43 uint16_t EvexOpcode; 44 uint16_t VexOpcode; 45 }; 46 #include "X86GenEVEX2VEXTables.inc" 47 48 #define EVEX2VEX_DESC "Compressing EVEX instrs to VEX encoding when possible" 49 #define EVEX2VEX_NAME "x86-evex-to-vex-compress" 50 51 #define DEBUG_TYPE EVEX2VEX_NAME 52 53 namespace { 54 55 class EvexToVexInstPass : public MachineFunctionPass { 56 57 /// X86EvexToVexCompressTable - Evex to Vex encoding opcode map. 58 using EvexToVexTableType = DenseMap<unsigned, uint16_t>; 59 EvexToVexTableType EvexToVex128Table; 60 EvexToVexTableType EvexToVex256Table; 61 62 /// For EVEX instructions that can be encoded using VEX encoding, replace 63 /// them by the VEX encoding in order to reduce size. 64 bool CompressEvexToVexImpl(MachineInstr &MI) const; 65 66 /// For initializing the hash map tables of all AVX-512 EVEX 67 /// corresponding to AVX/AVX2 opcodes. 68 void AddTableEntry(EvexToVexTableType &EvexToVexTable, uint16_t EvexOp, 69 uint16_t VexOp); 70 71 public: 72 static char ID; 73 74 EvexToVexInstPass() : MachineFunctionPass(ID) { 75 initializeEvexToVexInstPassPass(*PassRegistry::getPassRegistry()); 76 77 // Initialize the EVEX to VEX 128 table map. 78 for (X86EvexToVexCompressTableEntry Entry : X86EvexToVex128CompressTable) { 79 AddTableEntry(EvexToVex128Table, Entry.EvexOpcode, Entry.VexOpcode); 80 } 81 82 // Initialize the EVEX to VEX 256 table map. 83 for (X86EvexToVexCompressTableEntry Entry : X86EvexToVex256CompressTable) { 84 AddTableEntry(EvexToVex256Table, Entry.EvexOpcode, Entry.VexOpcode); 85 } 86 } 87 88 StringRef getPassName() const override { return EVEX2VEX_DESC; } 89 90 /// Loop over all of the basic blocks, replacing EVEX instructions 91 /// by equivalent VEX instructions when possible for reducing code size. 92 bool runOnMachineFunction(MachineFunction &MF) override; 93 94 // This pass runs after regalloc and doesn't support VReg operands. 95 MachineFunctionProperties getRequiredProperties() const override { 96 return MachineFunctionProperties().set( 97 MachineFunctionProperties::Property::NoVRegs); 98 } 99 100 private: 101 /// Machine instruction info used throughout the class. 102 const X86InstrInfo *TII; 103 }; 104 105 } // end anonymous namespace 106 107 char EvexToVexInstPass::ID = 0; 108 109 bool EvexToVexInstPass::runOnMachineFunction(MachineFunction &MF) { 110 TII = MF.getSubtarget<X86Subtarget>().getInstrInfo(); 111 112 const X86Subtarget &ST = MF.getSubtarget<X86Subtarget>(); 113 if (!ST.hasAVX512()) 114 return false; 115 116 bool Changed = false; 117 118 /// Go over all basic blocks in function and replace 119 /// EVEX encoded instrs by VEX encoding when possible. 120 for (MachineBasicBlock &MBB : MF) { 121 122 // Traverse the basic block. 123 for (MachineInstr &MI : MBB) 124 Changed |= CompressEvexToVexImpl(MI); 125 } 126 127 return Changed; 128 } 129 130 void EvexToVexInstPass::AddTableEntry(EvexToVexTableType &EvexToVexTable, 131 uint16_t EvexOp, uint16_t VexOp) { 132 EvexToVexTable[EvexOp] = VexOp; 133 } 134 135 // For EVEX instructions that can be encoded using VEX encoding 136 // replace them by the VEX encoding in order to reduce size. 137 bool EvexToVexInstPass::CompressEvexToVexImpl(MachineInstr &MI) const { 138 // VEX format. 139 // # of bytes: 0,2,3 1 1 0,1 0,1,2,4 0,1 140 // [Prefixes] [VEX] OPCODE ModR/M [SIB] [DISP] [IMM] 141 // 142 // EVEX format. 143 // # of bytes: 4 1 1 1 4 / 1 1 144 // [Prefixes] EVEX Opcode ModR/M [SIB] [Disp32] / [Disp8*N] [Immediate] 145 146 const MCInstrDesc &Desc = MI.getDesc(); 147 148 // Check for EVEX instructions only. 149 if ((Desc.TSFlags & X86II::EncodingMask) != X86II::EVEX) 150 return false; 151 152 // Check for EVEX instructions with mask or broadcast as in these cases 153 // the EVEX prefix is needed in order to carry this information 154 // thus preventing the transformation to VEX encoding. 155 if (Desc.TSFlags & (X86II::EVEX_K | X86II::EVEX_B)) 156 return false; 157 158 // Check for non EVEX_V512 instrs only. 159 // EVEX_V512 instr: bit EVEX_L2 = 1; bit VEX_L = 0. 160 if ((Desc.TSFlags & X86II::EVEX_L2) && !(Desc.TSFlags & X86II::VEX_L)) 161 return false; 162 163 // EVEX_V128 instr: bit EVEX_L2 = 0, bit VEX_L = 0. 164 bool IsEVEX_V128 = 165 (!(Desc.TSFlags & X86II::EVEX_L2) && !(Desc.TSFlags & X86II::VEX_L)); 166 167 // EVEX_V256 instr: bit EVEX_L2 = 0, bit VEX_L = 1. 168 bool IsEVEX_V256 = 169 (!(Desc.TSFlags & X86II::EVEX_L2) && (Desc.TSFlags & X86II::VEX_L)); 170 171 unsigned NewOpc = 0; 172 173 // Check for EVEX_V256 instructions. 174 if (IsEVEX_V256) { 175 // Search for opcode in the EvexToVex256 table. 176 auto It = EvexToVex256Table.find(MI.getOpcode()); 177 if (It != EvexToVex256Table.end()) 178 NewOpc = It->second; 179 } 180 // Check for EVEX_V128 or Scalar instructions. 181 else if (IsEVEX_V128) { 182 // Search for opcode in the EvexToVex128 table. 183 auto It = EvexToVex128Table.find(MI.getOpcode()); 184 if (It != EvexToVex128Table.end()) 185 NewOpc = It->second; 186 } 187 188 if (!NewOpc) 189 return false; 190 191 auto isHiRegIdx = [](unsigned Reg) { 192 // Check for XMM register with indexes between 16 - 31. 193 if (Reg >= X86::XMM16 && Reg <= X86::XMM31) 194 return true; 195 196 // Check for YMM register with indexes between 16 - 31. 197 if (Reg >= X86::YMM16 && Reg <= X86::YMM31) 198 return true; 199 200 return false; 201 }; 202 203 // Check that operands are not ZMM regs or 204 // XMM/YMM regs with hi indexes between 16 - 31. 205 for (const MachineOperand &MO : MI.explicit_operands()) { 206 if (!MO.isReg()) 207 continue; 208 209 unsigned Reg = MO.getReg(); 210 211 assert (!(Reg >= X86::ZMM0 && Reg <= X86::ZMM31)); 212 213 if (isHiRegIdx(Reg)) 214 return false; 215 } 216 217 const MCInstrDesc &MCID = TII->get(NewOpc); 218 MI.setDesc(MCID); 219 MI.setAsmPrinterFlag(AC_EVEX_2_VEX); 220 return true; 221 } 222 223 INITIALIZE_PASS(EvexToVexInstPass, EVEX2VEX_NAME, EVEX2VEX_DESC, false, false) 224 225 FunctionPass *llvm::createX86EvexToVexInsts() { 226 return new EvexToVexInstPass(); 227 } 228