Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(596)

Side by Side Diff: src/IceInst.h

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

Powered by Google App Engine
This is Rietveld 408576698