OLD | NEW |
---|---|
(Empty) | |
1 //===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===// | |
2 // | |
3 // The Subzero Code Generator | |
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 file declares the IceInst class and its target-independent | |
11 // subclasses, which represent the high-level Vanilla ICE instructions | |
12 // and map roughly 1:1 to LLVM instructions. | |
13 // | |
14 //===----------------------------------------------------------------------===// | |
15 | |
16 #ifndef SUBZERO_ICEINST_H | |
17 #define SUBZERO_ICEINST_H | |
18 | |
19 #include "IceDefs.h" | |
20 #include "IceTypes.h" | |
21 | |
22 class IceInst { | |
23 public: | |
24 enum InstKind { | |
25 Alloca, | |
26 Arithmetic, | |
27 Assign, // not part of LLVM/PNaCl bitcode | |
28 Br, | |
29 Call, | |
30 Cast, | |
31 Fcmp, | |
32 Icmp, | |
33 Load, | |
34 Phi, | |
35 Ret, | |
36 Select, | |
37 Store, | |
38 Switch, | |
39 }; | |
40 InstKind getKind() const { return Kind; } | |
41 | |
42 int32_t getNumber() const { return Number; } | |
43 | |
44 bool isDeleted() const { return Deleted; } | |
45 void setDeleted() { Deleted = true; } | |
46 | |
47 bool hasSideEffects() const { return HasSideEffects; } | |
48 | |
49 IceVariable *getDest() const { return Dest; } | |
50 | |
51 uint32_t getSrcSize() const { return NumSrcs; } | |
52 IceOperand *getSrc(uint32_t I) const { | |
53 assert(I < getSrcSize()); | |
54 return Srcs[I]; | |
55 } | |
56 | |
57 // Returns a list of out-edges corresponding to a terminator | |
58 // instruction, which is the last instruction of the block. | |
59 virtual IceNodeList getTerminatorEdges() const { | |
60 assert(0); | |
jvoung (off chromium)
2014/03/22 00:29:39
assert(0) ?
Jim Stichnoth
2014/03/24 13:18:53
To catch errors in case some IceCfgNode is constru
| |
61 return IceNodeList(); | |
62 } | |
63 | |
64 // Updates the status of the IceVariables contained within the | |
65 // instruction. In particular, it marks where the Dest variable is | |
66 // first assigned, and it tracks whether variables are live across | |
67 // basic blocks, i.e. used in a different block from their definition. | |
68 void updateVars(IceCfgNode *Node); | |
69 | |
70 virtual void dump(IceOstream &Str) const; | |
71 void dumpSources(IceOstream &Str) const; | |
72 void dumpDest(IceOstream &Str) const; | |
73 | |
74 virtual ~IceInst() {} | |
75 | |
76 protected: | |
77 IceInst(IceCfg *Cfg, InstKind Kind, uint32_t MaxSrcs, IceVariable *Dest); | |
78 void addSource(IceOperand *Src) { | |
79 assert(Src); | |
80 assert(NumSrcs < MaxSrcs); | |
81 Srcs[NumSrcs++] = Src; | |
82 } | |
83 | |
84 const InstKind Kind; | |
85 // Number is the instruction number for describing live ranges. | |
86 int32_t Number; | |
87 // Deleted means irrevocably deleted. | |
88 bool Deleted; | |
89 // HasSideEffects means the instruction is something like a function | |
90 // call or a volatile load that can't be removed even if its Dest | |
91 // variable is not live. | |
92 bool HasSideEffects; | |
93 | |
94 IceVariable *Dest; | |
95 const uint32_t MaxSrcs; // only used for assert | |
96 uint32_t NumSrcs; | |
97 IceOperand **Srcs; | |
98 }; | |
99 | |
100 IceOstream &operator<<(IceOstream &Str, const IceInst *I); | |
101 | |
102 // Alloca instruction. This captures the size in bytes as getSrc(0), | |
103 // and the alignment. | |
104 class IceInstAlloca : public IceInst { | |
105 public: | |
106 static IceInstAlloca *create(IceCfg *Cfg, IceOperand *ByteCount, | |
107 uint32_t Align, IceVariable *Dest) { | |
108 return new (Cfg->allocateInst<IceInstAlloca>()) | |
109 IceInstAlloca(Cfg, ByteCount, Align, Dest); | |
110 } | |
111 uint32_t getAlign() const { return Align; } | |
112 virtual void dump(IceOstream &Str) const; | |
113 static bool classof(const IceInst *Inst) { return Inst->getKind() == Alloca; } | |
114 | |
115 protected: | |
116 private: | |
117 IceInstAlloca(IceCfg *Cfg, IceOperand *ByteCount, uint32_t Align, | |
118 IceVariable *Dest); | |
119 const uint32_t Align; | |
120 }; | |
121 | |
122 // Binary arithmetic instruction. The source operands are captured in | |
123 // getSrc(0) and getSrc(1). | |
124 class IceInstArithmetic : public IceInst { | |
125 public: | |
126 enum OpKind { | |
127 // Ordered by http://llvm.org/docs/LangRef.html#binary-operations | |
128 Add, | |
129 Fadd, | |
130 Sub, | |
131 Fsub, | |
132 Mul, | |
133 Fmul, | |
134 Udiv, | |
135 Sdiv, | |
136 Fdiv, | |
137 Urem, | |
138 Srem, | |
139 Frem, | |
140 // Ordered by http://llvm.org/docs/LangRef.html#bitwise-binary-operations | |
141 Shl, | |
142 Lshr, | |
143 Ashr, | |
144 And, | |
145 Or, | |
146 Xor | |
147 }; | |
148 static IceInstArithmetic *create(IceCfg *Cfg, OpKind Op, IceVariable *Dest, | |
149 IceOperand *Source1, IceOperand *Source2) { | |
150 return new (Cfg->allocateInst<IceInstArithmetic>()) | |
151 IceInstArithmetic(Cfg, Op, Dest, Source1, Source2); | |
152 } | |
153 OpKind getOp() const { return Op; } | |
154 bool isCommutative() const; | |
155 virtual void dump(IceOstream &Str) const; | |
156 static bool classof(const IceInst *Inst) { | |
157 return Inst->getKind() == Arithmetic; | |
158 } | |
159 | |
160 private: | |
161 IceInstArithmetic(IceCfg *Cfg, OpKind Op, IceVariable *Dest, | |
162 IceOperand *Source1, IceOperand *Source2); | |
163 | |
164 const OpKind Op; | |
165 }; | |
166 | |
167 // Assignment instruction. The source operand is captured in | |
168 // getSrc(0). This is not part of the LLVM bitcode, but is a useful | |
169 // abstraction for some of the lowering. E.g., if Phi instruction | |
170 // lowering happens before target lowering, or for representing an | |
171 // Inttoptr instruction, or as an intermediate step for lowering a | |
172 // Load instruction. | |
173 class IceInstAssign : public IceInst { | |
174 public: | |
175 static IceInstAssign *create(IceCfg *Cfg, IceVariable *Dest, | |
176 IceOperand *Source) { | |
177 return new (Cfg->allocateInst<IceInstAssign>()) | |
178 IceInstAssign(Cfg, Dest, Source); | |
179 } | |
180 virtual void dump(IceOstream &Str) const; | |
181 static bool classof(const IceInst *Inst) { return Inst->getKind() == Assign; } | |
182 | |
183 private: | |
184 IceInstAssign(IceCfg *Cfg, IceVariable *Dest, IceOperand *Source); | |
185 }; | |
186 | |
187 // Branch instruction. This represents both conditional and | |
188 // unconditional branches. | |
189 class IceInstBr : public IceInst { | |
190 public: | |
191 static IceInstBr *create(IceCfg *Cfg, IceOperand *Source, | |
192 IceCfgNode *TargetTrue, IceCfgNode *TargetFalse) { | |
193 return new (Cfg->allocateInst<IceInstBr>()) | |
194 IceInstBr(Cfg, Source, TargetTrue, TargetFalse); | |
195 } | |
196 static IceInstBr *create(IceCfg *Cfg, IceCfgNode *Target) { | |
197 return new (Cfg->allocateInst<IceInstBr>()) IceInstBr(Cfg, Target); | |
198 } | |
199 bool isUnconditional() const { return getTargetTrue() == NULL; } | |
200 IceCfgNode *getTargetTrue() const { return TargetTrue; } | |
201 IceCfgNode *getTargetFalse() const { return TargetFalse; } | |
202 IceCfgNode *getTargetUnconditional() const { | |
203 assert(isUnconditional()); | |
204 return getTargetFalse(); | |
205 } | |
206 virtual IceNodeList getTerminatorEdges() const; | |
207 virtual void dump(IceOstream &Str) const; | |
208 static bool classof(const IceInst *Inst) { return Inst->getKind() == Br; } | |
209 | |
210 private: | |
211 // Conditional branch | |
212 IceInstBr(IceCfg *Cfg, IceOperand *Source, IceCfgNode *TargetTrue, | |
213 IceCfgNode *TargetFalse); | |
214 // Unconditional branch | |
215 IceInstBr(IceCfg *Cfg, IceCfgNode *Target); | |
216 | |
217 IceCfgNode *const TargetFalse; // Doubles as unconditional branch target | |
218 IceCfgNode *const TargetTrue; // NULL if unconditional branch | |
219 }; | |
220 | |
221 // Call instruction. The call target is captured as getSrc(0), and | |
222 // arg I is captured as getSrc(I+1). | |
223 class IceInstCall : public IceInst { | |
224 public: | |
225 static IceInstCall *create(IceCfg *Cfg, uint32_t NumArgs, IceVariable *Dest, | |
226 IceOperand *CallTarget, bool Tail) { | |
227 return new (Cfg->allocateInst<IceInstCall>()) | |
228 IceInstCall(Cfg, NumArgs, Dest, CallTarget, Tail); | |
229 } | |
230 void addArg(IceOperand *Arg) { addSource(Arg); } | |
231 IceOperand *getCallTarget() const { return getSrc(0); } | |
232 IceOperand *getArg(uint32_t I) const { return getSrc(I + 1); } | |
233 uint32_t getNumArgs() const { return getSrcSize() - 1; } | |
234 bool isTail() const { return Tail; } | |
235 virtual void dump(IceOstream &Str) const; | |
236 static bool classof(const IceInst *Inst) { return Inst->getKind() == Call; } | |
237 | |
238 private: | |
239 IceInstCall(IceCfg *Cfg, uint32_t NumArgs, IceVariable *Dest, | |
240 IceOperand *CallTarget, bool Tail) | |
241 : IceInst(Cfg, IceInst::Call, NumArgs + 1, Dest), Tail(Tail) { | |
242 // Set HasSideEffects so that the call instruction can't be | |
243 // dead-code eliminated. Don't set this for a deletable intrinsic | |
244 // call. | |
245 HasSideEffects = true; | |
246 addSource(CallTarget); | |
247 } | |
248 const bool Tail; | |
249 }; | |
250 | |
251 // Cast instruction (a.k.a. conversion operation). | |
252 class IceInstCast : public IceInst { | |
253 public: | |
254 enum OpKind { | |
255 // Ordered by http://llvm.org/docs/LangRef.html#conversion-operations | |
256 Trunc, | |
257 Zext, | |
258 Sext, | |
259 Fptrunc, | |
260 Fpext, | |
261 Fptoui, | |
262 Fptosi, | |
263 Uitofp, | |
264 Sitofp, | |
265 }; | |
266 static IceInstCast *create(IceCfg *Cfg, OpKind CastKind, IceVariable *Dest, | |
267 IceOperand *Source) { | |
268 return new (Cfg->allocateInst<IceInstCast>()) | |
269 IceInstCast(Cfg, CastKind, Dest, Source); | |
270 } | |
271 OpKind getCastKind() const { return CastKind; } | |
272 virtual void dump(IceOstream &Str) const; | |
273 static bool classof(const IceInst *Inst) { return Inst->getKind() == Cast; } | |
274 | |
275 private: | |
276 IceInstCast(IceCfg *Cfg, OpKind CastKind, IceVariable *Dest, | |
277 IceOperand *Source); | |
278 OpKind CastKind; | |
279 }; | |
280 | |
281 // Floating-point comparison instruction. The source operands are | |
282 // captured in getSrc(0) and getSrc(1). | |
283 class IceInstFcmp : public IceInst { | |
284 public: | |
285 enum FCond { | |
286 // Ordered by http://llvm.org/docs/LangRef.html#id254 | |
287 False, | |
288 Oeq, | |
289 Ogt, | |
290 Oge, | |
291 Olt, | |
292 Ole, | |
293 One, | |
294 Ord, | |
295 Ueq, | |
296 Ugt, | |
297 Uge, | |
298 Ult, | |
299 Ule, | |
300 Une, | |
301 Uno, | |
302 True | |
303 }; | |
304 static IceInstFcmp *create(IceCfg *Cfg, FCond Condition, IceVariable *Dest, | |
305 IceOperand *Source1, IceOperand *Source2) { | |
306 return new (Cfg->allocateInst<IceInstFcmp>()) | |
307 IceInstFcmp(Cfg, Condition, Dest, Source1, Source2); | |
308 } | |
309 FCond getCondition() const { return Condition; } | |
310 virtual void dump(IceOstream &Str) const; | |
311 static bool classof(const IceInst *Inst) { return Inst->getKind() == Fcmp; } | |
312 | |
313 private: | |
314 IceInstFcmp(IceCfg *Cfg, FCond Condition, IceVariable *Dest, | |
315 IceOperand *Source1, IceOperand *Source2); | |
316 FCond Condition; | |
317 }; | |
318 | |
319 // Integer comparison instruction. The source operands are captured | |
320 // in getSrc(0) and getSrc(1). | |
321 class IceInstIcmp : public IceInst { | |
322 public: | |
323 enum ICond { | |
324 // Ordered by http://llvm.org/docs/LangRef.html#id249 | |
325 Eq, | |
326 Ne, | |
327 Ugt, | |
328 Uge, | |
329 Ult, | |
330 Ule, | |
331 Sgt, | |
332 Sge, | |
333 Slt, | |
334 Sle | |
335 }; | |
336 static IceInstIcmp *create(IceCfg *Cfg, ICond Condition, IceVariable *Dest, | |
337 IceOperand *Source1, IceOperand *Source2) { | |
338 return new (Cfg->allocateInst<IceInstIcmp>()) | |
339 IceInstIcmp(Cfg, Condition, Dest, Source1, Source2); | |
340 } | |
341 ICond getCondition() const { return Condition; } | |
342 virtual void dump(IceOstream &Str) const; | |
343 static bool classof(const IceInst *Inst) { return Inst->getKind() == Icmp; } | |
344 | |
345 private: | |
346 IceInstIcmp(IceCfg *Cfg, ICond Condition, IceVariable *Dest, | |
347 IceOperand *Source1, IceOperand *Source2); | |
348 ICond Condition; | |
349 }; | |
350 | |
351 // Load instruction. The source address is captured in getSrc(0); | |
352 class IceInstLoad : public IceInst { | |
353 public: | |
354 static IceInstLoad *create(IceCfg *Cfg, IceVariable *Dest, | |
355 IceOperand *SourceAddr) { | |
356 return new (Cfg->allocateInst<IceInstLoad>()) | |
357 IceInstLoad(Cfg, Dest, SourceAddr); | |
358 } | |
359 virtual void dump(IceOstream &Str) const; | |
360 static bool classof(const IceInst *Inst) { return Inst->getKind() == Load; } | |
361 | |
362 private: | |
363 IceInstLoad(IceCfg *Cfg, IceVariable *Dest, IceOperand *SourceAddr); | |
364 }; | |
365 | |
366 // Phi instruction. For incoming edge I, the node is Labels[I] and | |
367 // the Phi source operand is getSrc(I). | |
368 class IceInstPhi : public IceInst { | |
369 public: | |
370 static IceInstPhi *create(IceCfg *Cfg, uint32_t MaxSrcs, IceVariable *Dest) { | |
371 return new (Cfg->allocateInst<IceInstPhi>()) IceInstPhi(Cfg, MaxSrcs, Dest); | |
372 } | |
373 void addArgument(IceOperand *Source, IceCfgNode *Label); | |
374 virtual void dump(IceOstream &Str) const; | |
375 static bool classof(const IceInst *Inst) { return Inst->getKind() == Phi; } | |
376 | |
377 private: | |
378 IceInstPhi(IceCfg *Cfg, uint32_t MaxSrcs, IceVariable *Dest); | |
379 // Labels[] duplicates the InEdges[] information in the enclosing | |
380 // IceCfgNode, but the Phi instruction is created before InEdges[] | |
381 // is available, so it's more complicated to share the list. | |
382 IceCfgNode **Labels; | |
383 }; | |
384 | |
385 // Ret instruction. The return value is captured in getSrc(0), but if | |
386 // there is no return value (void-type function), then | |
387 // getSrcSize()==0. | |
388 class IceInstRet : public IceInst { | |
389 public: | |
390 static IceInstRet *create(IceCfg *Cfg, IceOperand *Source = NULL) { | |
391 return new (Cfg->allocateInst<IceInstRet>()) IceInstRet(Cfg, Source); | |
392 } | |
393 virtual IceNodeList getTerminatorEdges() const { return IceNodeList(); } | |
394 virtual void dump(IceOstream &Str) const; | |
395 static bool classof(const IceInst *Inst) { return Inst->getKind() == Ret; } | |
396 | |
397 private: | |
398 IceInstRet(IceCfg *Cfg, IceOperand *Source); | |
399 }; | |
400 | |
401 // Select instruction. The condition, true, and false operands are captured. | |
402 class IceInstSelect : public IceInst { | |
403 public: | |
404 static IceInstSelect *create(IceCfg *Cfg, IceVariable *Dest, | |
405 IceOperand *Condition, IceOperand *SourceTrue, | |
406 IceOperand *SourceFalse) { | |
407 return new (Cfg->allocateInst<IceInstSelect>()) | |
408 IceInstSelect(Cfg, Dest, Condition, SourceTrue, SourceFalse); | |
409 } | |
410 IceOperand *getCondition() const { return getSrc(0); } | |
411 IceOperand *getTrueOperand() const { return getSrc(1); } | |
412 IceOperand *getFalseOperand() const { return getSrc(2); } | |
413 virtual void dump(IceOstream &Str) const; | |
414 static bool classof(const IceInst *Inst) { return Inst->getKind() == Select; } | |
415 | |
416 private: | |
417 IceInstSelect(IceCfg *Cfg, IceVariable *Dest, IceOperand *Condition, | |
418 IceOperand *Source1, IceOperand *Source2); | |
419 }; | |
420 | |
421 // Store instruction. The address operand is captured, along with the | |
422 // data operand to be stored into the address. | |
423 class IceInstStore : public IceInst { | |
424 public: | |
425 static IceInstStore *create(IceCfg *Cfg, IceOperand *Data, IceOperand *Addr) { | |
426 return new (Cfg->allocateInst<IceInstStore>()) | |
427 IceInstStore(Cfg, Data, Addr); | |
428 } | |
429 IceOperand *getAddr() const { return getSrc(1); } | |
430 IceOperand *getData() const { return getSrc(0); } | |
431 virtual void dump(IceOstream &Str) const; | |
432 static bool classof(const IceInst *Inst) { return Inst->getKind() == Store; } | |
433 | |
434 private: | |
435 IceInstStore(IceCfg *Cfg, IceOperand *Data, IceOperand *Addr); | |
436 }; | |
437 | |
438 // Switch instruction. The single source operand is captured as | |
439 // getSrc(0). | |
440 class IceInstSwitch : public IceInst { | |
441 public: | |
442 static IceInstSwitch *create(IceCfg *Cfg, uint32_t NumCases, | |
443 IceOperand *Source, IceCfgNode *LabelDefault) { | |
444 return new (Cfg->allocateInst<IceInstSwitch>()) | |
445 IceInstSwitch(Cfg, NumCases, Source, LabelDefault); | |
446 } | |
447 IceCfgNode *getLabelDefault() const { return LabelDefault; } | |
448 uint32_t getNumCases() const { return NumCases; } | |
449 uint64_t getValue(uint32_t I) const { | |
450 assert(I < NumCases); | |
451 return Values[I]; | |
452 } | |
453 IceCfgNode *getLabel(uint32_t I) const { | |
454 assert(I < NumCases); | |
455 return Labels[I]; | |
456 } | |
457 void addBranch(uint32_t CaseIndex, uint64_t Value, IceCfgNode *Label); | |
458 virtual IceNodeList getTerminatorEdges() const; | |
459 virtual void dump(IceOstream &Str) const; | |
460 static bool classof(const IceInst *Inst) { return Inst->getKind() == Switch; } | |
461 | |
462 private: | |
463 IceInstSwitch(IceCfg *Cfg, uint32_t NumCases, IceOperand *Source, | |
464 IceCfgNode *LabelDefault); | |
465 IceCfgNode *LabelDefault; | |
466 uint32_t NumCases; // not including the default case | |
467 uint64_t *Values; // size is NumCases | |
468 IceCfgNode **Labels; // size is NumCases | |
469 }; | |
470 | |
471 #endif // SUBZERO_ICEINST_H | |
OLD | NEW |