1 //===- utils/TableGen/X86EVEX2VEXTablesEmitter.cpp - X86 backend-*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// This tablegen backend is responsible for emitting the X86 backend EVEX2VEX 11 /// compression tables. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "CodeGenTarget.h" 16 #include "llvm/TableGen/Error.h" 17 #include "llvm/TableGen/TableGenBackend.h" 18 19 using namespace llvm; 20 21 namespace { 22 23 class X86EVEX2VEXTablesEmitter { 24 RecordKeeper &Records; 25 CodeGenTarget Target; 26 27 // Hold all non-masked & non-broadcasted EVEX encoded instructions 28 std::vector<const CodeGenInstruction *> EVEXInsts; 29 // Hold all VEX encoded instructions. Divided into groups with same opcodes 30 // to make the search more efficient 31 std::map<uint64_t, std::vector<const CodeGenInstruction *>> VEXInsts; 32 33 typedef std::pair<const CodeGenInstruction *, const CodeGenInstruction *> Entry; 34 35 // Represent both compress tables 36 std::vector<Entry> EVEX2VEX128; 37 std::vector<Entry> EVEX2VEX256; 38 39 public: 40 X86EVEX2VEXTablesEmitter(RecordKeeper &R) : Records(R), Target(R) {} 41 42 // run - Output X86 EVEX2VEX tables. 43 void run(raw_ostream &OS); 44 45 private: 46 // Prints the given table as a C++ array of type 47 // X86EvexToVexCompressTableEntry 48 void printTable(const std::vector<Entry> &Table, raw_ostream &OS); 49 }; 50 51 void X86EVEX2VEXTablesEmitter::printTable(const std::vector<Entry> &Table, 52 raw_ostream &OS) { 53 StringRef Size = (Table == EVEX2VEX128) ? "128" : "256"; 54 55 OS << "// X86 EVEX encoded instructions that have a VEX " << Size 56 << " encoding\n" 57 << "// (table format: <EVEX opcode, VEX-" << Size << " opcode>).\n" 58 << "static const X86EvexToVexCompressTableEntry X86EvexToVex" << Size 59 << "CompressTable[] = {\n" 60 << " // EVEX scalar with corresponding VEX.\n"; 61 62 // Print all entries added to the table 63 for (auto Pair : Table) { 64 OS << " { X86::" << Pair.first->TheDef->getName() 65 << ", X86::" << Pair.second->TheDef->getName() << " },\n"; 66 } 67 68 OS << "};\n\n"; 69 } 70 71 // Return true if the 2 BitsInits are equal 72 static inline bool equalBitsInits(const BitsInit *B1, const BitsInit *B2) { 73 if (B1->getNumBits() != B2->getNumBits()) 74 PrintFatalError("Comparing two BitsInits with different sizes!"); 75 76 for (unsigned i = 0, e = B1->getNumBits(); i != e; ++i) { 77 if (BitInit *Bit1 = dyn_cast<BitInit>(B1->getBit(i))) { 78 if (BitInit *Bit2 = dyn_cast<BitInit>(B2->getBit(i))) { 79 if (Bit1->getValue() != Bit2->getValue()) 80 return false; 81 } else 82 PrintFatalError("Invalid BitsInit bit"); 83 } else 84 PrintFatalError("Invalid BitsInit bit"); 85 } 86 return true; 87 } 88 89 // Calculates the integer value residing BitsInit object 90 static inline uint64_t getValueFromBitsInit(const BitsInit *B) { 91 uint64_t Value = 0; 92 for (unsigned i = 0, e = B->getNumBits(); i != e; ++i) { 93 if (BitInit *Bit = dyn_cast<BitInit>(B->getBit(i))) 94 Value |= uint64_t(Bit->getValue()) << i; 95 else 96 PrintFatalError("Invalid VectSize bit"); 97 } 98 return Value; 99 } 100 101 // Function object - Operator() returns true if the given VEX instruction 102 // matches the EVEX instruction of this object. 103 class IsMatch { 104 const CodeGenInstruction *EVEXInst; 105 106 public: 107 IsMatch(const CodeGenInstruction *EVEXInst) : EVEXInst(EVEXInst) {} 108 109 bool operator()(const CodeGenInstruction *VEXInst) { 110 Record *RecE = EVEXInst->TheDef; 111 Record *RecV = VEXInst->TheDef; 112 uint64_t EVEX_W = 113 getValueFromBitsInit(RecE->getValueAsBitsInit("VEX_WPrefix")); 114 uint64_t VEX_W = 115 getValueFromBitsInit(RecV->getValueAsBitsInit("VEX_WPrefix")); 116 117 if (RecV->getValueAsDef("OpEnc")->getName().str() != "EncVEX" || 118 // VEX/EVEX fields 119 RecV->getValueAsDef("OpPrefix") != RecE->getValueAsDef("OpPrefix") || 120 RecV->getValueAsDef("OpMap") != RecE->getValueAsDef("OpMap") || 121 RecV->getValueAsBit("hasVEX_4V") != RecE->getValueAsBit("hasVEX_4V") || 122 !equalBitsInits(RecV->getValueAsBitsInit("EVEX_LL"), 123 RecE->getValueAsBitsInit("EVEX_LL")) || 124 // Match is allowed if either is VEX_WIG, or they match, or EVEX 125 // is VEX_W1X and VEX is VEX_W0. 126 (!(EVEX_W == 2 || VEX_W == 2 || EVEX_W == VEX_W || 127 (EVEX_W == 3 && VEX_W == 0))) || 128 // Instruction's format 129 RecV->getValueAsDef("Form") != RecE->getValueAsDef("Form") || 130 RecV->getValueAsBit("isAsmParserOnly") != 131 RecE->getValueAsBit("isAsmParserOnly")) 132 return false; 133 134 // This is needed for instructions with intrinsic version (_Int). 135 // Where the only difference is the size of the operands. 136 // For example: VUCOMISDZrm and Int_VUCOMISDrm 137 // Also for instructions that their EVEX version was upgraded to work with 138 // k-registers. For example VPCMPEQBrm (xmm output register) and 139 // VPCMPEQBZ128rm (k register output register). 140 for (unsigned i = 0, e = EVEXInst->Operands.size(); i < e; i++) { 141 Record *OpRec1 = EVEXInst->Operands[i].Rec; 142 Record *OpRec2 = VEXInst->Operands[i].Rec; 143 144 if (OpRec1 == OpRec2) 145 continue; 146 147 if (isRegisterOperand(OpRec1) && isRegisterOperand(OpRec2)) { 148 if (getRegOperandSize(OpRec1) != getRegOperandSize(OpRec2)) 149 return false; 150 } else if (isMemoryOperand(OpRec1) && isMemoryOperand(OpRec2)) { 151 return false; 152 } else if (isImmediateOperand(OpRec1) && isImmediateOperand(OpRec2)) { 153 if (OpRec1->getValueAsDef("Type") != OpRec2->getValueAsDef("Type")) 154 return false; 155 } else 156 return false; 157 } 158 159 return true; 160 } 161 162 private: 163 static inline bool isRegisterOperand(const Record *Rec) { 164 return Rec->isSubClassOf("RegisterClass") || 165 Rec->isSubClassOf("RegisterOperand"); 166 } 167 168 static inline bool isMemoryOperand(const Record *Rec) { 169 return Rec->isSubClassOf("Operand") && 170 Rec->getValueAsString("OperandType") == "OPERAND_MEMORY"; 171 } 172 173 static inline bool isImmediateOperand(const Record *Rec) { 174 return Rec->isSubClassOf("Operand") && 175 Rec->getValueAsString("OperandType") == "OPERAND_IMMEDIATE"; 176 } 177 178 static inline unsigned int getRegOperandSize(const Record *RegRec) { 179 if (RegRec->isSubClassOf("RegisterClass")) 180 return RegRec->getValueAsInt("Alignment"); 181 if (RegRec->isSubClassOf("RegisterOperand")) 182 return RegRec->getValueAsDef("RegClass")->getValueAsInt("Alignment"); 183 184 llvm_unreachable("Register operand's size not known!"); 185 } 186 }; 187 188 void X86EVEX2VEXTablesEmitter::run(raw_ostream &OS) { 189 emitSourceFileHeader("X86 EVEX2VEX tables", OS); 190 191 ArrayRef<const CodeGenInstruction *> NumberedInstructions = 192 Target.getInstructionsByEnumValue(); 193 194 for (const CodeGenInstruction *Inst : NumberedInstructions) { 195 // Filter non-X86 instructions. 196 if (!Inst->TheDef->isSubClassOf("X86Inst")) 197 continue; 198 199 // Add VEX encoded instructions to one of VEXInsts vectors according to 200 // it's opcode. 201 if (Inst->TheDef->getValueAsDef("OpEnc")->getName() == "EncVEX") { 202 uint64_t Opcode = getValueFromBitsInit(Inst->TheDef-> 203 getValueAsBitsInit("Opcode")); 204 VEXInsts[Opcode].push_back(Inst); 205 } 206 // Add relevant EVEX encoded instructions to EVEXInsts 207 else if (Inst->TheDef->getValueAsDef("OpEnc")->getName() == "EncEVEX" && 208 !Inst->TheDef->getValueAsBit("hasEVEX_K") && 209 !Inst->TheDef->getValueAsBit("hasEVEX_B") && 210 getValueFromBitsInit(Inst->TheDef-> 211 getValueAsBitsInit("EVEX_LL")) != 2 && 212 !Inst->TheDef->getValueAsBit("notEVEX2VEXConvertible")) 213 EVEXInsts.push_back(Inst); 214 } 215 216 for (const CodeGenInstruction *EVEXInst : EVEXInsts) { 217 uint64_t Opcode = getValueFromBitsInit(EVEXInst->TheDef-> 218 getValueAsBitsInit("Opcode")); 219 // For each EVEX instruction look for a VEX match in the appropriate vector 220 // (instructions with the same opcode) using function object IsMatch. 221 // Allow EVEX2VEXOverride to explicitly specify a match. 222 const CodeGenInstruction *VEXInst = nullptr; 223 if (!EVEXInst->TheDef->isValueUnset("EVEX2VEXOverride")) { 224 StringRef AltInstStr = 225 EVEXInst->TheDef->getValueAsString("EVEX2VEXOverride"); 226 Record *AltInstRec = Records.getDef(AltInstStr); 227 assert(AltInstRec && "EVEX2VEXOverride instruction not found!"); 228 VEXInst = &Target.getInstruction(AltInstRec); 229 } else { 230 auto Match = llvm::find_if(VEXInsts[Opcode], IsMatch(EVEXInst)); 231 if (Match != VEXInsts[Opcode].end()) 232 VEXInst = *Match; 233 } 234 235 if (!VEXInst) 236 continue; 237 238 // In case a match is found add new entry to the appropriate table 239 switch (getValueFromBitsInit( 240 EVEXInst->TheDef->getValueAsBitsInit("EVEX_LL"))) { 241 case 0: 242 EVEX2VEX128.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,0} 243 break; 244 case 1: 245 EVEX2VEX256.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,1} 246 break; 247 default: 248 llvm_unreachable("Instruction's size not fit for the mapping!"); 249 } 250 } 251 252 // Print both tables 253 printTable(EVEX2VEX128, OS); 254 printTable(EVEX2VEX256, OS); 255 } 256 } 257 258 namespace llvm { 259 void EmitX86EVEX2VEXTables(RecordKeeper &RK, raw_ostream &OS) { 260 X86EVEX2VEXTablesEmitter(RK).run(OS); 261 } 262 } 263