blob: 57f8b9e98d0f64fdcdcb1d311479002cf6b92f8f [file] [log] [blame]
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001//===- 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 Inst 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_SRC_ICEINST_H
17#define SUBZERO_SRC_ICEINST_H
18
19#include "IceDefs.h"
20#include "IceInst.def"
21#include "IceTypes.h"
22
23// TODO: The Cfg structure, and instructions in particular, need to be
24// validated for things like valid operand types, valid branch
25// targets, proper ordering of Phi and non-Phi instructions, etc.
26// Most of the validity checking will be done in the bitcode reader.
27// We need a list of everything that should be validated, and tests
28// for each.
29
30namespace Ice {
31
32class Inst {
33public:
34 enum InstKind {
35 // Arbitrary (alphabetical) order, except put Unreachable first.
36 Unreachable,
37 Alloca,
38 Arithmetic,
39 Assign, // not part of LLVM/PNaCl bitcode
40 Br,
41 Call,
42 Cast,
43 Fcmp,
44 Icmp,
45 Load,
46 Phi,
47 Ret,
48 Select,
49 Store,
50 Switch
51 };
52 InstKind getKind() const { return Kind; }
53
54 int32_t getNumber() const { return Number; }
55
56 bool isDeleted() const { return Deleted; }
57 void setDeleted() { Deleted = true; }
58
59 bool hasSideEffects() const { return HasSideEffects; }
60
61 Variable *getDest() const { return Dest; }
62
63 SizeT getSrcSize() const { return NumSrcs; }
64 Operand *getSrc(SizeT I) const {
65 assert(I < getSrcSize());
66 return Srcs[I];
67 }
68
69 // Returns a list of out-edges corresponding to a terminator
70 // instruction, which is the last instruction of the block.
71 virtual NodeList getTerminatorEdges() const {
72 // All valid terminator instructions override this method. For
73 // the default implementation, we assert in case some CfgNode
74 // is constructed without a terminator instruction at the end.
75 llvm_unreachable(
76 "getTerminatorEdges() called on a non-terminator instruction");
77 return NodeList();
78 }
79
80 // Updates the status of the Variables contained within the
81 // instruction. In particular, it marks where the Dest variable is
82 // first assigned, and it tracks whether variables are live across
83 // basic blocks, i.e. used in a different block from their definition.
84 void updateVars(CfgNode *Node);
85
86 virtual void dump(const Cfg *Func) const;
87 void dumpDecorated(const Cfg *Func) const;
88 void dumpSources(const Cfg *Func) const;
89 void dumpDest(const Cfg *Func) const;
90
91 virtual ~Inst() {}
92
93protected:
94 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
95 void addSource(Operand *Src) {
96 assert(Src);
97 assert(NumSrcs < MaxSrcs);
98 Srcs[NumSrcs++] = Src;
99 }
100 // The destroy() method lets the instruction cleanly release any
101 // memory that was allocated via the Cfg's allocator.
102 virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); }
103
104 const InstKind Kind;
105 // Number is the instruction number for describing live ranges.
106 int32_t Number;
107 // Deleted means irrevocably deleted.
108 bool Deleted;
109 // HasSideEffects means the instruction is something like a function
110 // call or a volatile load that can't be removed even if its Dest
111 // variable is not live.
112 bool HasSideEffects;
113
114 Variable *Dest;
115 const SizeT MaxSrcs; // only used for assert
116 SizeT NumSrcs;
117 Operand **Srcs;
118
119private:
120 Inst(const Inst &) LLVM_DELETED_FUNCTION;
121 Inst &operator=(const Inst &) LLVM_DELETED_FUNCTION;
122};
123
124// Alloca instruction. This captures the size in bytes as getSrc(0),
125// and the required alignment in bytes. The alignment must be either
126// 0 (no alignment required) or a power of 2.
127class InstAlloca : public Inst {
128public:
129 static InstAlloca *create(Cfg *Func, Operand *ByteCount,
130 uint32_t AlignInBytes, Variable *Dest) {
131 return new (Func->allocateInst<InstAlloca>())
132 InstAlloca(Func, ByteCount, AlignInBytes, Dest);
133 }
134 uint32_t getAlignInBytes() const { return AlignInBytes; }
135 Operand *getSizeInBytes() const { return getSrc(0); }
136 virtual void dump(const Cfg *Func) const;
137 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; }
138
139private:
140 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
141 Variable *Dest);
142 InstAlloca(const InstAlloca &) LLVM_DELETED_FUNCTION;
143 InstAlloca &operator=(const InstAlloca &) LLVM_DELETED_FUNCTION;
144 virtual ~InstAlloca() {}
145 const uint32_t AlignInBytes;
146};
147
148// Binary arithmetic instruction. The source operands are captured in
149// getSrc(0) and getSrc(1).
150class InstArithmetic : public Inst {
151public:
152 enum OpKind {
153#define X(tag, str, commutative) tag,
154 ICEINSTARITHMETIC_TABLE
155#undef X
156 };
157 static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
158 Operand *Source1, Operand *Source2) {
159 return new (Func->allocateInst<InstArithmetic>())
160 InstArithmetic(Func, Op, Dest, Source1, Source2);
161 }
162 OpKind getOp() const { return Op; }
163 bool isCommutative() const;
164 virtual void dump(const Cfg *Func) const;
165 static bool classof(const Inst *Inst) {
166 return Inst->getKind() == Arithmetic;
167 }
168
169private:
170 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
171 Operand *Source2);
172 InstArithmetic(const InstArithmetic &) LLVM_DELETED_FUNCTION;
173 InstArithmetic &operator=(const InstArithmetic &) LLVM_DELETED_FUNCTION;
174 virtual ~InstArithmetic() {}
175
176 const OpKind Op;
177};
178
179// Assignment instruction. The source operand is captured in
180// getSrc(0). This is not part of the LLVM bitcode, but is a useful
181// abstraction for some of the lowering. E.g., if Phi instruction
182// lowering happens before target lowering, or for representing an
183// Inttoptr instruction, or as an intermediate step for lowering a
184// Load instruction.
185class InstAssign : public Inst {
186public:
187 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
188 return new (Func->allocateInst<InstAssign>())
189 InstAssign(Func, Dest, Source);
190 }
191 virtual void dump(const Cfg *Func) const;
192 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; }
193
194private:
195 InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
196 InstAssign(const InstAssign &) LLVM_DELETED_FUNCTION;
197 InstAssign &operator=(const InstAssign &) LLVM_DELETED_FUNCTION;
198 virtual ~InstAssign() {}
199};
200
201// Branch instruction. This represents both conditional and
202// unconditional branches.
203class InstBr : public Inst {
204public:
205 // Create a conditional branch. If TargetTrue==TargetFalse, it is
206 // optimized to an unconditional branch.
207 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
208 CfgNode *TargetFalse) {
209 return new (Func->allocateInst<InstBr>())
210 InstBr(Func, Source, TargetTrue, TargetFalse);
211 }
212 // Create an unconditional branch.
213 static InstBr *create(Cfg *Func, CfgNode *Target) {
214 return new (Func->allocateInst<InstBr>()) InstBr(Func, Target);
215 }
216 bool isUnconditional() const { return getTargetTrue() == NULL; }
217 Operand *getCondition() const {
218 assert(!isUnconditional());
219 return getSrc(0);
220 }
221 CfgNode *getTargetTrue() const { return TargetTrue; }
222 CfgNode *getTargetFalse() const { return TargetFalse; }
223 CfgNode *getTargetUnconditional() const {
224 assert(isUnconditional());
225 return getTargetFalse();
226 }
227 virtual NodeList getTerminatorEdges() const;
228 virtual void dump(const Cfg *Func) const;
229 static bool classof(const Inst *Inst) { return Inst->getKind() == Br; }
230
231private:
232 // Conditional branch
233 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
234 // Unconditional branch
235 InstBr(Cfg *Func, CfgNode *Target);
236 InstBr(const InstBr &) LLVM_DELETED_FUNCTION;
237 InstBr &operator=(const InstBr &) LLVM_DELETED_FUNCTION;
238 virtual ~InstBr() {}
239
240 CfgNode *const TargetFalse; // Doubles as unconditional branch target
241 CfgNode *const TargetTrue; // NULL if unconditional branch
242};
243
244// Call instruction. The call target is captured as getSrc(0), and
245// arg I is captured as getSrc(I+1).
246class InstCall : public Inst {
247public:
248 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
249 Operand *CallTarget) {
250 return new (Func->allocateInst<InstCall>())
251 InstCall(Func, NumArgs, Dest, CallTarget);
252 }
253 void addArg(Operand *Arg) { addSource(Arg); }
254 Operand *getCallTarget() const { return getSrc(0); }
255 Operand *getArg(SizeT I) const { return getSrc(I + 1); }
256 SizeT getNumArgs() const { return getSrcSize() - 1; }
257 virtual void dump(const Cfg *Func) const;
258 static bool classof(const Inst *Inst) { return Inst->getKind() == Call; }
259
260private:
261 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget)
262 : Inst(Func, Inst::Call, NumArgs + 1, Dest) {
263 // Set HasSideEffects so that the call instruction can't be
264 // dead-code eliminated. Don't set this for a deletable intrinsic
265 // call.
266 HasSideEffects = true;
267 addSource(CallTarget);
268 }
269 InstCall(const InstCall &) LLVM_DELETED_FUNCTION;
270 InstCall &operator=(const InstCall &) LLVM_DELETED_FUNCTION;
271 virtual ~InstCall() {}
272};
273
274// Cast instruction (a.k.a. conversion operation).
275class InstCast : public Inst {
276public:
277 enum OpKind {
278#define X(tag, str) tag,
279 ICEINSTCAST_TABLE
280#undef X
281 };
282 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
283 Operand *Source) {
284 return new (Func->allocateInst<InstCast>())
285 InstCast(Func, CastKind, Dest, Source);
286 }
287 OpKind getCastKind() const { return CastKind; }
288 virtual void dump(const Cfg *Func) const;
289 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; }
290
291private:
292 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
293 InstCast(const InstCast &) LLVM_DELETED_FUNCTION;
294 InstCast &operator=(const InstCast &) LLVM_DELETED_FUNCTION;
295 virtual ~InstCast() {}
296 const OpKind CastKind;
297};
298
299// Floating-point comparison instruction. The source operands are
300// captured in getSrc(0) and getSrc(1).
301class InstFcmp : public Inst {
302public:
303 enum FCond {
304#define X(tag, str) tag,
305 ICEINSTFCMP_TABLE
306#undef X
307 };
308 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
309 Operand *Source1, Operand *Source2) {
310 return new (Func->allocateInst<InstFcmp>())
311 InstFcmp(Func, Condition, Dest, Source1, Source2);
312 }
313 FCond getCondition() const { return Condition; }
314 virtual void dump(const Cfg *Func) const;
315 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; }
316
317private:
318 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
319 Operand *Source2);
320 InstFcmp(const InstFcmp &) LLVM_DELETED_FUNCTION;
321 InstFcmp &operator=(const InstFcmp &) LLVM_DELETED_FUNCTION;
322 virtual ~InstFcmp() {}
323 const FCond Condition;
324};
325
326// Integer comparison instruction. The source operands are captured
327// in getSrc(0) and getSrc(1).
328class InstIcmp : public Inst {
329public:
330 enum ICond {
331#define X(tag, str) tag,
332 ICEINSTICMP_TABLE
333#undef X
334 };
335 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
336 Operand *Source1, Operand *Source2) {
337 return new (Func->allocateInst<InstIcmp>())
338 InstIcmp(Func, Condition, Dest, Source1, Source2);
339 }
340 ICond getCondition() const { return Condition; }
341 virtual void dump(const Cfg *Func) const;
342 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; }
343
344private:
345 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
346 Operand *Source2);
347 InstIcmp(const InstIcmp &) LLVM_DELETED_FUNCTION;
348 InstIcmp &operator=(const InstIcmp &) LLVM_DELETED_FUNCTION;
349 virtual ~InstIcmp() {}
350 const ICond Condition;
351};
352
353// Load instruction. The source address is captured in getSrc(0).
354class InstLoad : public Inst {
355public:
356 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr) {
357 return new (Func->allocateInst<InstLoad>())
358 InstLoad(Func, Dest, SourceAddr);
359 }
360 Operand *getSourceAddress() const { return getSrc(0); }
361 virtual void dump(const Cfg *Func) const;
362 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; }
363
364private:
365 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
366 InstLoad(const InstLoad &) LLVM_DELETED_FUNCTION;
367 InstLoad &operator=(const InstLoad &) LLVM_DELETED_FUNCTION;
368 virtual ~InstLoad() {}
369};
370
371// Phi instruction. For incoming edge I, the node is Labels[I] and
372// the Phi source operand is getSrc(I).
373class InstPhi : public Inst {
374public:
375 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
376 return new (Func->allocateInst<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
377 }
378 void addArgument(Operand *Source, CfgNode *Label);
379 virtual void dump(const Cfg *Func) const;
380 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; }
381
382private:
383 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
384 InstPhi(const InstPhi &) LLVM_DELETED_FUNCTION;
385 InstPhi &operator=(const InstPhi &) LLVM_DELETED_FUNCTION;
386 virtual void destroy(Cfg *Func) {
387 Func->deallocateArrayOf<CfgNode *>(Labels);
388 Inst::destroy(Func);
389 }
390 virtual ~InstPhi() {}
391
392 // Labels[] duplicates the InEdges[] information in the enclosing
393 // CfgNode, but the Phi instruction is created before InEdges[]
394 // is available, so it's more complicated to share the list.
395 CfgNode **Labels;
396};
397
398// Ret instruction. The return value is captured in getSrc(0), but if
399// there is no return value (void-type function), then
400// getSrcSize()==0 and hasRetValue()==false.
401class InstRet : public Inst {
402public:
403 static InstRet *create(Cfg *Func, Operand *RetValue = NULL) {
404 return new (Func->allocateInst<InstRet>()) InstRet(Func, RetValue);
405 }
406 bool hasRetValue() const { return getSrcSize(); }
407 Operand *getRetValue() const {
408 assert(hasRetValue());
409 return getSrc(0);
410 }
411 virtual NodeList getTerminatorEdges() const { return NodeList(); }
412 virtual void dump(const Cfg *Func) const;
413 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; }
414
415private:
416 InstRet(Cfg *Func, Operand *RetValue);
417 InstRet(const InstRet &) LLVM_DELETED_FUNCTION;
418 InstRet &operator=(const InstRet &) LLVM_DELETED_FUNCTION;
419 virtual ~InstRet() {}
420};
421
422// Select instruction. The condition, true, and false operands are captured.
423class InstSelect : public Inst {
424public:
425 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
426 Operand *SourceTrue, Operand *SourceFalse) {
427 return new (Func->allocateInst<InstSelect>())
428 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
429 }
430 Operand *getCondition() const { return getSrc(0); }
431 Operand *getTrueOperand() const { return getSrc(1); }
432 Operand *getFalseOperand() const { return getSrc(2); }
433 virtual void dump(const Cfg *Func) const;
434 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; }
435
436private:
437 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
438 Operand *Source2);
439 InstSelect(const InstSelect &) LLVM_DELETED_FUNCTION;
440 InstSelect &operator=(const InstSelect &) LLVM_DELETED_FUNCTION;
441 virtual ~InstSelect() {}
442};
443
444// Store instruction. The address operand is captured, along with the
445// data operand to be stored into the address.
446class InstStore : public Inst {
447public:
448 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr) {
449 return new (Func->allocateInst<InstStore>()) InstStore(Func, Data, Addr);
450 }
451 Operand *getAddr() const { return getSrc(1); }
452 Operand *getData() const { return getSrc(0); }
453 virtual void dump(const Cfg *Func) const;
454 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; }
455
456private:
457 InstStore(Cfg *Func, Operand *Data, Operand *Addr);
458 InstStore(const InstStore &) LLVM_DELETED_FUNCTION;
459 InstStore &operator=(const InstStore &) LLVM_DELETED_FUNCTION;
460 virtual ~InstStore() {}
461};
462
463// Switch instruction. The single source operand is captured as
464// getSrc(0).
465class InstSwitch : public Inst {
466public:
467 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
468 CfgNode *LabelDefault) {
469 return new (Func->allocateInst<InstSwitch>())
470 InstSwitch(Func, NumCases, Source, LabelDefault);
471 }
472 Operand *getComparison() const { return getSrc(0); }
473 CfgNode *getLabelDefault() const { return LabelDefault; }
474 SizeT getNumCases() const { return NumCases; }
475 uint64_t getValue(SizeT I) const {
476 assert(I < NumCases);
477 return Values[I];
478 }
479 CfgNode *getLabel(SizeT I) const {
480 assert(I < NumCases);
481 return Labels[I];
482 }
483 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
484 virtual NodeList getTerminatorEdges() const;
485 virtual void dump(const Cfg *Func) const;
486 static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; }
487
488private:
489 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
490 InstSwitch(const InstSwitch &) LLVM_DELETED_FUNCTION;
491 InstSwitch &operator=(const InstSwitch &) LLVM_DELETED_FUNCTION;
492 virtual void destroy(Cfg *Func) {
493 Func->deallocateArrayOf<uint64_t>(Values);
494 Func->deallocateArrayOf<CfgNode *>(Labels);
495 Inst::destroy(Func);
496 }
497 virtual ~InstSwitch() {}
498
499 CfgNode *LabelDefault;
500 SizeT NumCases; // not including the default case
501 uint64_t *Values; // size is NumCases
502 CfgNode **Labels; // size is NumCases
503};
504
505// Unreachable instruction. This is a terminator instruction with no
506// operands.
507class InstUnreachable : public Inst {
508public:
509 static InstUnreachable *create(Cfg *Func) {
510 return new (Func->allocateInst<InstUnreachable>()) InstUnreachable(Func);
511 }
512 virtual NodeList getTerminatorEdges() const { return NodeList(); }
513 virtual void dump(const Cfg *Func) const;
514 static bool classof(const Inst *Inst) {
515 return Inst->getKind() == Unreachable;
516 }
517
518private:
519 InstUnreachable(Cfg *Func);
520 InstUnreachable(const InstUnreachable &) LLVM_DELETED_FUNCTION;
521 InstUnreachable &operator=(const InstUnreachable &) LLVM_DELETED_FUNCTION;
522 virtual ~InstUnreachable() {}
523};
524
525} // end of namespace Ice
526
527#endif // SUBZERO_SRC_ICEINST_H