llvm学习笔记(5)
来源:互联网 发布:钢结构软件 编辑:程序博客网 时间:2024/05/16 07:54
2.2.4. 匹配模板
在Instruction定义的333行,成员Pattern描述了该指令匹配怎么样的SelectionDAG结构。这是一个list类型,因此存在一条指令匹配多个dag结构的可能。在上面的例子中,这部分就是312~315行的dag。LLVM将对这样的dag生成movq2dq\t{$src,$dst|$dst, $src}形式的汇编代码。
2.2.4.1. SDNode
C++类SDNode是构成LLVM的指令选择器所使用的DAG的节点。在Tablegen根据TD文件为指令选择生成的代码中,其核心函数SelectCode就具有原型:SDNode*SelectCode(SDNode *N),参数N是要进行指令选择的IR形式的DAG,返回值也是SDNode类型,即选中的指令。
TableGen不能直接使用C++类,与之对应,它也有自己的SDNode定义。它主要作为dag值的操作符,描述这个dag所代表的操作、操作数,SDNode派生自TD类SDPatternOperator(这是一个空类)。(在LLVM里,SDNode的定义出现在两处:一是在SelectDAGNodes.h里,是一个C++类。另一处在TargetSelectionDAG.td。每个SelectionDAG节点类型都有一个对应的SDNode定义)。
298 classSDNode<string opcode, SDTypeProfile typeprof,
299 list<SDNodeProperty> props = [], string sdclass ="SDNode">
300 :SDPatternOperator {
301 stringOpcode = opcode;
302 string SDClass= sdclass;
303 list<SDNodeProperty> Properties = props;
304 SDTypeProfileTypeProfile = typeprof;
305 }
虽然TD语言有类似C++的语法,但它更类似于一个函数式语言,或者说更类似于C++的泛型形式,所有类型一旦声明(定义)就不能更改。要表示新的信息,就必须定义新的类,或具现一个尚未存在的模板实例。
2.2.4.1.1. 类型的描述
在上面的SDNode定义里,参数typeprof用来描述这个SDNode的类型要求。其类型SDTypeProfile的定义如下。它用于描述操作的“类型”。
93 classSDTypeProfile<intnumresults, int numoperands,
94 list<SDTypeConstraint>constraints> {
95 int NumResults= numresults;
96 int NumOperands= numoperands;
97 list<SDTypeConstraint> Constraints = constraints;
98 }
很显然NumResults与NumOperands分别说明有几个结果及几个操作数,其中如果NumOperands是-1,则表示操作数的数目不定。Constraints则描述了对操作数类型的约束,SDTypeConstraint是一个简单的类。
22 classSDTypeConstraint<intopnum> {
23 int OperandNum= opnum;
24 }
OperandNum指明该约束适用第几个操作数。显然这个类是足够的,需要高级一点的派生类,于是就有了下面的定义:
27 classSDTCisVT<int OpNum, ValueTypevt> : SDTypeConstraint<OpNum> {
28 ValueType VT =vt;
29 }
这个定义表示OpNum所指向操作数必须具有指定的VT(ValueType)类型。
31 classSDTCisPtrTy<int OpNum> :SDTypeConstraint<OpNum>;
这个定义表示OpNum所指向操作数的类型是指针。
34 classSDTCisInt<int OpNum> : SDTypeConstraint<OpNum>;
这个定义表示OpNum所指向操作数的类型是整形。
37 classSDTCisFP<int OpNum> : SDTypeConstraint<OpNum>;
这个定义表示OpNum所指向操作数的类型是浮点类型。
40 classSDTCisVec<intOpNum> : SDTypeConstraint<OpNum>;
这个定义表示OpNum所指向操作数的类型是向量。
43 classSDTCisSameAs<int OpNum,int OtherOp> : SDTypeConstraint<OpNum> {
44 intOtherOperandNum = OtherOp;
45 }
这个定义表示OpNum所指定操作数与OtherOp所指定的操作数具有相同的类型。
49 classSDTCisVTSmallerThanOp<int OpNum, intOtherOp> : SDTypeConstraint<OpNum> {
50 int OtherOperandNum= OtherOp;
51 }
这个定义表示OpNum所指定操作数必须是VT派生类型,OtherOp所指定操作数则是整形,且前者的长度小于后者。
53 classSDTCisOpSmallerThanOp<int SmallOp, intBigOp> : SDTypeConstraint<SmallOp>{
54 int BigOperandNum = BigOp;
55 }
这个定义表示SmallOp与BigOp类型相同(注意不限定操作数必须VT类型),但前者的长度小于后者。
59 classSDTCisEltOfVec<int ThisOp, int OtherOp>
60 : SDTypeConstraint<ThisOp> {
61 int OtherOpNum = OtherOp;
62 }
这个定义表示ThisOp指定的操作数与OtherOp指定向量的元素具有相同的标量类型。
66 classSDTCisSubVecOfVec<int ThisOp, int OtherOp>
67 : SDTypeConstraint<ThisOp> {
68 int OtherOpNum = OtherOp;
69 }
这个定义表示ThisOp指定的向量类型操作数比OtherOp指定的向量类型操作数长度短。
73 classSDTCVecEltisVT<int OpNum, ValueType vt> :SDTypeConstraint<OpNum> {
74 ValueType VT = vt;
75 }
这个定义表示OpNum指定的操作数与vt指定向量的元素具有相同的向量类型。
79 classSDTCisSameNumEltsAs<int OpNum, intOtherOp> : SDTypeConstraint<OpNum> {
80 int OtherOperandNum = OtherOp;
81 }
这个定义表示OpNum与OtherOp指定的向量类型操作数具有相同的元素数目。
有了上面的基本约束的定义,就可以给出目标机器无关的约束定义了,LLVM-3.6定义了如下的SDNode约束:
101 defSDTIntLeaf: SDTypeProfile<1, 0, [SDTCisInt<0>]>; // for'imm'.
102 defSDTFPLeaf:SDTypeProfile<1, 0, [SDTCisFP<0>]>; // for'fpimm'.
103 defSDTPtrLeaf:SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; // for'&g'.
104 defSDTOther:SDTypeProfile<1, 0, [SDTCisVT<0, OtherVT>]>;// for 'vt'.
105 defSDTUNDEF:SDTypeProfile<1, 0, []>; //for 'undef'.
106 defSDTUnaryOp:SDTypeProfile<1, 1, []>; // for bitconvert.
107
108 defSDTIntBinOp:SDTypeProfile<1, 2, [ // add, and, or, xor, udiv, etc.
109 SDTCisSameAs<0, 1>, SDTCisSameAs<0,2>, SDTCisInt<0>
110 ]>;
111 defSDTIntShiftOp:SDTypeProfile<1, 2, [ // shl, sra, srl
112 SDTCisSameAs<0, 1>, SDTCisInt<0>,SDTCisInt<2>
113 ]>;
114 defSDTIntBinHiLoOp:SDTypeProfile<2, 2, [// mulhi, mullo, sdivrem,udivrem
115 SDTCisSameAs<0, 1>, SDTCisSameAs<0,2>, SDTCisSameAs<0, 3>,SDTCisInt<0>
116 ]>;
117
118 defSDTFPBinOp:SDTypeProfile<1, 2, [ // fadd, fmul, etc.
119 SDTCisSameAs<0, 1>, SDTCisSameAs<0,2>, SDTCisFP<0>
120 ]>;
121 defSDTFPSignOp:SDTypeProfile<1, 2, [ // fcopysign.
122 SDTCisSameAs<0, 1>, SDTCisFP<0>,SDTCisFP<2>
123 ]>;
124 defSDTFPTernaryOp:SDTypeProfile<1, 3, [ // fmadd, fnmsub, etc.
125 SDTCisSameAs<0, 1>, SDTCisSameAs<0,2>, SDTCisSameAs<0, 3>, SDTCisFP<0>
126 ]>;
127 defSDTIntUnaryOp:SDTypeProfile<1, 1, [ // ctlz
128 SDTCisSameAs<0, 1>, SDTCisInt<0>
129 ]>;
130 defSDTIntExtendOp:SDTypeProfile<1, 1, [ // sext, zext, anyext
131 SDTCisInt<0>, SDTCisInt<1>,SDTCisOpSmallerThanOp<1, 0>
132 ]>;
133 defSDTIntTruncOp:SDTypeProfile<1, 1, [ // trunc
134 SDTCisInt<0>, SDTCisInt<1>,SDTCisOpSmallerThanOp<0, 1>
135 ]>;
136 defSDTFPUnaryOp:SDTypeProfile<1, 1, [ // fneg, fsqrt, etc
137 SDTCisSameAs<0, 1>, SDTCisFP<0>
138 ]>;
139 defSDTFPRoundOp:SDTypeProfile<1, 1, [ // fround
140 SDTCisFP<0>, SDTCisFP<1>,SDTCisOpSmallerThanOp<0, 1>
141 ]>;
142 defSDTFPExtendOp: SDTypeProfile<1,1, [ //fextend
143 SDTCisFP<0>, SDTCisFP<1>,SDTCisOpSmallerThanOp<1, 0>
144 ]>;
145 defSDTIntToFPOp:SDTypeProfile<1, 1, [ // [su]int_to_fp
146 SDTCisFP<0>, SDTCisInt<1>
147 ]>;
148 defSDTFPToIntOp:SDTypeProfile<1, 1, [ // fp_to_[su]int
149 SDTCisInt<0>, SDTCisFP<1>
150 ]>;
151 defSDTExtInreg:SDTypeProfile<1, 2, [ // sext_inreg
152 SDTCisSameAs<0, 1>, SDTCisInt<0>,SDTCisVT<2, OtherVT>,
153 SDTCisVTSmallerThanOp<2, 1>
154 ]>;
155
156 defSDTSetCC:SDTypeProfile<1, 3, [ // setcc
157 SDTCisInt<0>, SDTCisSameAs<1, 2>,SDTCisVT<3, OtherVT>
158 ]>;
159
160 defSDTSelect:SDTypeProfile<1, 3, [ // select
161 SDTCisInt<1>, SDTCisSameAs<0, 2>,SDTCisSameAs<2, 3>
162 ]>;
163
164 defSDTVSelect:SDTypeProfile<1, 3, [ // vselect
165 SDTCisInt<1>, SDTCisSameAs<0, 2>,SDTCisSameAs<2, 3>
166 ]>;
167
168 defSDTSelectCC:SDTypeProfile<1, 5, [ // select_cc
169 SDTCisSameAs<1, 2>, SDTCisSameAs<3,4>, SDTCisSameAs<0, 3>,
170 SDTCisVT<5, OtherVT>
171 ]>;
172
173 defSDTBr: SDTypeProfile<0, 1,[ //br
174 SDTCisVT<0, OtherVT>
175 ]>;
176
177 defSDTBrCC: SDTypeProfile<0,4, [ //brcc
178 SDTCisVT<0, OtherVT>,SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT>
179 ]>;
180
181 defSDTBrcond: SDTypeProfile<0,2, [ //brcond
182 SDTCisInt<0>, SDTCisVT<1,OtherVT>
183 ]>;
184
185 defSDTBrind:SDTypeProfile<0, 1, [ // brind
186 SDTCisPtrTy<0>
187 ]>;
188
189 defSDTNone: SDTypeProfile<0,0, []>; //ret, trap
190
191 defSDTLoad: SDTypeProfile<1,1, [ //load
192 SDTCisPtrTy<1>
193 ]>;
194
195 defSDTStore:SDTypeProfile<0, 2, [ // store
196 SDTCisPtrTy<1>
197 ]>;
198
199 defSDTIStore:SDTypeProfile<1, 3, [ // indexed store
200 SDTCisSameAs<0, 2>,SDTCisPtrTy<0>, SDTCisPtrTy<3>
201 ]>;
202
203 defSDTMaskedStore:SDTypeProfile<0, 3, [ // masked store
204 SDTCisPtrTy<0>, SDTCisVec<1>,SDTCisVec<2>
205 ]>;
206
207 defSDTMaskedLoad:SDTypeProfile<1, 3, [ // masked load
208 SDTCisVec<0>, SDTCisPtrTy<1>,SDTCisVec<2>, SDTCisSameAs<0, 3>
209 ]>;
210
211 defSDTMaskedGather:SDTypeProfile<2, 3, [ // masked gather
212 SDTCisVec<0>, SDTCisVec<1>,SDTCisSameAs<0, 2>, SDTCisSameAs<1, 3>,
213 SDTCisPtrTy<4>, SDTCVecEltisVT<1,i1>, SDTCisSameNumEltsAs<0, 1>
214 ]>;
215
216 defSDTMaskedScatter:SDTypeProfile<1, 3, [ // masked scatter
217 SDTCisVec<0>, SDTCisVec<1>,SDTCisSameAs<0, 2>, SDTCisSameNumEltsAs<0, 1>,
218 SDTCVecEltisVT<0, i1>,SDTCisPtrTy<3>
219 ]>;
220
221 defSDTVecShuffle:SDTypeProfile<1, 2, [
222 SDTCisSameAs<0, 1>, SDTCisSameAs<1,2>
223 ]>;
224 defSDTVecExtract:SDTypeProfile<1, 2, [ // vector extract
225 SDTCisEltOfVec<0, 1>,SDTCisPtrTy<2>
226 ]>;
227 defSDTVecInsert:SDTypeProfile<1, 3, [ // vector insert
228 SDTCisEltOfVec<2, 1>,SDTCisSameAs<0, 1>, SDTCisPtrTy<3>
229 ]>;
230
231 defSDTSubVecExtract:SDTypeProfile<1, 2, [// subvector extract
232 SDTCisSubVecOfVec<0,1>,SDTCisInt<2>
233 ]>;
234 defSDTSubVecInsert:SDTypeProfile<1, 3, [// subvector insert
235 SDTCisSubVecOfVec<2, 1>,SDTCisSameAs<0,1>, SDTCisInt<3>
236 ]>;
237
238 defSDTPrefetch:SDTypeProfile<0, 4, [ // prefetch
239 SDTCisPtrTy<0>, SDTCisSameAs<1,2>, SDTCisSameAs<1, 3>, SDTCisInt<1>
240 ]>;
241
242 defSDTMemBarrier:SDTypeProfile<0, 5, [ // memory barrier
243 SDTCisSameAs<0,1>, SDTCisSameAs<0,2>, SDTCisSameAs<0,3>,SDTCisSameAs<0,4>,
244 SDTCisInt<0>
245 ]>;
246 defSDTAtomicFence:SDTypeProfile<0, 2, [
247 SDTCisSameAs<0,1>, SDTCisPtrTy<0>
248 ]>;
249 defSDTAtomic3:SDTypeProfile<1, 3, [
250 SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisInt<0>,SDTCisPtrTy<1>
251 ]>;
252 defSDTAtomic2:SDTypeProfile<1, 2, [
253 SDTCisSameAs<0,2>, SDTCisInt<0>,SDTCisPtrTy<1>
254 ]>;
255 defSDTAtomicStore: SDTypeProfile<0,2, [
256 SDTCisPtrTy<0>, SDTCisInt<1>
257 ]>;
258 defSDTAtomicLoad:SDTypeProfile<1, 1, [
259 SDTCisInt<0>, SDTCisPtrTy<1>
260 ]>;
261
262 defSDTConvertOp:SDTypeProfile<1, 5, [ //cvtss, su, us, uu, ff,fs, fu, sf, su
263 SDTCisVT<2, OtherVT>, SDTCisVT<3,OtherVT>, SDTCisPtrTy<4>, SDTCisPtrTy<5>
264 ]>;
265
266 classSDCallSeqStart<list<SDTypeConstraint>constraints> :
267 SDTypeProfile<0, 1, constraints>;
268 classSDCallSeqEnd<list<SDTypeConstraint>constraints> :
269 SDTypeProfile<0, 2, constraints>;
这些定义都将用于描述特定的指令,从其名字或定义后的注释可以看出这些指令。另外,目标机器也可以根据自己的需要,特别定制约束来描述自己特有的指令。
2.2.4.1.2. 属性的描述
SDNode的属性描述了SDNode所代表操作的特征,它由SDNodeProperty及其派生定义描述,目前LLVM-3.6定义了以下属性:
276 classSDNodeProperty;
277 defSDNPCommutative:SDNodeProperty; // X op Y == Y op X
278 defSDNPAssociative:SDNodeProperty; // (X op Y) op Z == X op (Y op Z)
279 defSDNPHasChain:SDNodeProperty; // R/W chain operand and result
280 defSDNPOutGlue:SDNodeProperty; // Write a flag result
281 defSDNPInGlue: SDNodeProperty; // Read a flagoperand
282 defSDNPOptInGlue:SDNodeProperty; // Optionally read a flag operand
283 defSDNPMayStore:SDNodeProperty; // May write to memory, sets 'mayStore'.
284 defSDNPMayLoad:SDNodeProperty; // May read memory, sets 'mayLoad'.
285 defSDNPSideEffect:SDNodeProperty; // Sets 'HasUnmodelledSideEffects'.
286 defSDNPMemOperand:SDNodeProperty; // Touches memory, has assoc MemOperand
287 defSDNPVariadic:SDNodeProperty; // Node has variable arguments.
288 defSDNPWantRoot:SDNodeProperty; // ComplexPattern gets the root of match
289 defSDNPWantParent: SDNodeProperty; // ComplexPattern gets the parent
注释已经说得足够清楚了,不需要再赘述。比如,前面谈到的指令选择生成器知道加法符合交换律的知识就是由SDNPCommutative提供的。
2.2.4.1.3. SDNode的派生定义
LLVM在TD文件与C++代码中同时维护了两套一一对应的SDNode类型系统。这两套类型系统的纽带就是llvm/include/llvm/CodeGen目录下文件ISDOpcodes.h中定义的枚举类型NodeType。显然,这样做是为了让Tblgen知道如何将SDNode节点匹配到合适的C++对象。这些派生定义的数量相当多(这取决于LLVM IR的复杂性),而且也不复杂,我们就不一一列出了。举例来说,TableGen这样来定义立即数:
313 def imm :SDNode<"ISD::Constant" , SDTIntLeaf , [],"ConstantSDNode">;
Imm对应枚举值ISD::Constant(类型NodeType),LLVM代码中的类ConstantSDNode。
- llvm学习笔记(5)
- llvm学习笔记(1)
- llvm学习笔记(2)
- llvm学习笔记(3)
- llvm学习笔记(4)
- LLVM学习笔记(6)
- LLVM学习笔记(7)
- LLVM学习笔记(8)
- LLVM学习笔记(9)
- LLVM学习笔记(10)
- LLVM学习笔记(11)
- LLVM学习笔记(12)
- LLVM学习笔记(13)
- LLVM学习笔记(14)
- LLVM学习笔记(15)
- LLVM学习笔记(20)
- LLVM学习笔记(16)
- LLVM学习笔记(17)
- ffmpeg for android (windows环境) (一)
- B. Not Afraid STL set
- 批量修改文件名
- OpenCV学习笔记(1)__隐藏 Console 窗口
- 使系统相机相册显示中文
- llvm学习笔记(5)
- 自定义UICollectionView布局(类似集五福)
- jquery dialog-优雅的弹出框
- Django 在iframe里跳转顶层url
- Java开发环境的搭建
- Linux下查看日志
- 使用泛型类生成对象时的一点注意
- Windows下QT搭建OpenCv环境
- android canvas的基本使用