LLVM学习笔记(50)

Posted wuhui_gdnt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LLVM学习笔记(50)相关的知识,希望对你有一定的参考价值。

3.9. X86 EVEX2VEX映射表的生成(v7.0)

VEX编码方案支持现有指令编码的扩展或修改,以及新指令定义。(维基

EVEX方案是VEX方案的一个4字节扩展,它支持AVX-512指令集,并允许访问新的512ZMM寄存器以及新的掩码寄存器。(维基

这个X86特定的TableGen处理生成一张表,将EVEX编码的指令映射到等价VEX编码指令。这样做通常可以将指令长度减少2字节。在V7.0中有一个EvexToVexInstPass遍将这张表用于这个目的。

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    

这个函数的处理并不复杂,其中涉及的指令域最开始都是来自X86Inst定义,由各个派生定义进行改写。上面201行条件如果成立,表示指令使用VEX编码,把该指令记录在VEXInsts容器中(类型std::map<uint64_t, std::vector<const CodeGenInstruction *>>),以操作码为键值。

207行条件筛选出EVEX编码的指令:该指令不使用掩码、不设置EVEX.B域及EVEX.L2域、不禁止EVEXEVX的转换,把这些指令保存在容器EVEXInsts(类型std::vector<const CodeGenInstruction *>)中。接着在216遍历这些EVEX编码指令,如果指令的EVEX2VEXOverride域给出了等价的VEX编码指令,尝试获取对应的CodeGenInstruction对象(不少AVX-512指令把自己设为等价VEX编码指令)。

如果没有设置EVEX2VEXOverride域,则尝试通过IsMatchoperator()方法来获取:它遍历所有具有指定操作码的VEX编码指令,找出其中匹配的那个。

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     ;

匹配与指令的前缀、操作数类型、操作数保存的位置都有关。

最后,输出的表是这样的(表太长,只节选部分):

// X86 EVEX encoded instructions that have a VEX 128 encoding

// (table format: <EVEX opcode, VEX-128 opcode>).

static const X86EvexToVexCompressTableEntry X86EvexToVex128CompressTable[] =

  // EVEX scalar with corresponding VEX.

  X86::VADDPDZ128rm, X86::VADDPDrm ,

  X86::VADDPDZ128rr, X86::VADDPDrr ,

  X86::VADDPSZ128rm, X86::VADDPSrm ,

  X86::VADDPSZ128rr, X86::VADDPSrr ,

  X86::VADDSDZrm, X86::VADDSDrm ,

  …

  X86::VXORPDZ128rm, X86::VXORPDrm ,

  X86::VXORPDZ128rr, X86::VXORPDrr ,

  X86::VXORPSZ128rm, X86::VXORPSrm ,

  X86::VXORPSZ128rr, X86::VXORPSrr ,

;

 

// X86 EVEX encoded instructions that have a VEX 256 encoding

// (table format: <EVEX opcode, VEX-256 opcode>).

static const X86EvexToVexCompressTableEntry X86EvexToVex256CompressTable[] =

  // EVEX scalar with corresponding VEX.

  X86::VADDPDZ256rm, X86::VADDPDYrm ,

  X86::VADDPDZ256rr, X86::VADDPDYrr ,

  X86::VADDPSZ256rm, X86::VADDPSYrm ,

  X86::VADDPSZ256rr, X86::VADDPSYrr ,

  X86::VAESDECLASTZ256rm, X86::VAESDECLASTYrm ,

  …

  X86::VXORPDZ256rm, X86::VXORPDYrm ,

  X86::VXORPDZ256rr, X86::VXORPDYrr ,

  X86::VXORPSZ256rm, X86::VXORPSYrm ,

  X86::VXORPSZ256rr, X86::VXORPSYrr ,

;

其中X86EvexToVexCompressTableEntry是这样的结构:

41       struct X86EvexToVexCompressTableEntry

42         uint16_t EvexOpcode;

43         uint16_t VexOpcode;

44      

45         bool operator<(const X86EvexToVexCompressTableEntry &RHS) const

46           return EvexOpcode < RHS.EvexOpcode;

47        

48      

49         friend bool operator<(const X86EvexToVexCompressTableEntry &TE,

50                               unsigned Opc)

51           return TE.EvexOpcode < Opc;

52        

53       ;

这张映射表就是遍EvexToVexInstPass使用的武器。

以上是关于LLVM学习笔记(50)的主要内容,如果未能解决你的问题,请参考以下文章

LLVM学习笔记(52)

LLVM学习笔记(43-2)

LLVM学习笔记(54)

LLVM学习笔记(54)

LLVM学习笔记(44-2)

LLVM学习笔记(53)