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

Side by Side Diff: src/IceInst.h

Issue 1216963007: Doxygenize the documentation comments (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Rebase to master Created 5 years, 5 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
« no previous file with comments | « src/IceGlobalInits.cpp ('k') | src/IceInst.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===// 1 //===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 ///
10 // This file declares the Inst class and its target-independent 10 /// \file
11 // subclasses, which represent the high-level Vanilla ICE instructions 11 /// This file declares the Inst class and its target-independent
12 // and map roughly 1:1 to LLVM instructions. 12 /// subclasses, which represent the high-level Vanilla ICE instructions
13 // 13 /// and map roughly 1:1 to LLVM instructions.
14 ///
14 //===----------------------------------------------------------------------===// 15 //===----------------------------------------------------------------------===//
15 16
16 #ifndef SUBZERO_SRC_ICEINST_H 17 #ifndef SUBZERO_SRC_ICEINST_H
17 #define SUBZERO_SRC_ICEINST_H 18 #define SUBZERO_SRC_ICEINST_H
18 19
19 #include "IceCfg.h" 20 #include "IceCfg.h"
20 #include "IceDefs.h" 21 #include "IceDefs.h"
21 #include "IceInst.def" 22 #include "IceInst.def"
22 #include "IceIntrinsics.h" 23 #include "IceIntrinsics.h"
23 #include "IceTypes.h" 24 #include "IceTypes.h"
24 25
25 // TODO: The Cfg structure, and instructions in particular, need to be 26 // TODO: The Cfg structure, and instructions in particular, need to be
26 // validated for things like valid operand types, valid branch 27 // validated for things like valid operand types, valid branch
27 // targets, proper ordering of Phi and non-Phi instructions, etc. 28 // targets, proper ordering of Phi and non-Phi instructions, etc.
28 // Most of the validity checking will be done in the bitcode reader. 29 // Most of the validity checking will be done in the bitcode reader.
29 // We need a list of everything that should be validated, and tests 30 // We need a list of everything that should be validated, and tests
30 // for each. 31 // for each.
31 32
32 namespace Ice { 33 namespace Ice {
33 34
34 // Base instruction class for ICE. Inst has two subclasses: 35 /// Base instruction class for ICE. Inst has two subclasses:
35 // InstHighLevel and InstTarget. High-level ICE instructions inherit 36 /// InstHighLevel and InstTarget. High-level ICE instructions inherit
36 // from InstHighLevel, and low-level (target-specific) ICE 37 /// from InstHighLevel, and low-level (target-specific) ICE
37 // instructions inherit from InstTarget. 38 /// instructions inherit from InstTarget.
38 class Inst : public llvm::ilist_node<Inst> { 39 class Inst : public llvm::ilist_node<Inst> {
39 Inst() = delete; 40 Inst() = delete;
40 Inst(const Inst &) = delete; 41 Inst(const Inst &) = delete;
41 Inst &operator=(const Inst &) = delete; 42 Inst &operator=(const Inst &) = delete;
42 43
43 public: 44 public:
44 enum InstKind { 45 enum InstKind {
45 // Arbitrary (alphabetical) order, except put Unreachable first. 46 // Arbitrary (alphabetical) order, except put Unreachable first.
46 Unreachable, 47 Unreachable,
47 Alloca, 48 Alloca,
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 99
99 SizeT getSrcSize() const { return NumSrcs; } 100 SizeT getSrcSize() const { return NumSrcs; }
100 Operand *getSrc(SizeT I) const { 101 Operand *getSrc(SizeT I) const {
101 assert(I < getSrcSize()); 102 assert(I < getSrcSize());
102 return Srcs[I]; 103 return Srcs[I];
103 } 104 }
104 105
105 bool isLastUse(const Operand *Src) const; 106 bool isLastUse(const Operand *Src) const;
106 void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn); 107 void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn);
107 108
108 // Returns a list of out-edges corresponding to a terminator 109 /// Returns a list of out-edges corresponding to a terminator
109 // instruction, which is the last instruction of the block. 110 /// instruction, which is the last instruction of the block.
110 virtual NodeList getTerminatorEdges() const { 111 virtual NodeList getTerminatorEdges() const {
111 // All valid terminator instructions override this method. For 112 // All valid terminator instructions override this method. For
112 // the default implementation, we assert in case some CfgNode 113 // the default implementation, we assert in case some CfgNode
113 // is constructed without a terminator instruction at the end. 114 // is constructed without a terminator instruction at the end.
114 llvm_unreachable( 115 llvm_unreachable(
115 "getTerminatorEdges() called on a non-terminator instruction"); 116 "getTerminatorEdges() called on a non-terminator instruction");
116 return NodeList(); 117 return NodeList();
117 } 118 }
118 virtual bool isUnconditionalBranch() const { return false; } 119 virtual bool isUnconditionalBranch() const { return false; }
119 // If the instruction is a branch-type instruction with OldNode as a 120 /// If the instruction is a branch-type instruction with OldNode as a
120 // target, repoint it to NewNode and return true, otherwise return 121 /// target, repoint it to NewNode and return true, otherwise return
121 // false. Only repoint one instance, even if the instruction has 122 /// false. Only repoint one instance, even if the instruction has
122 // multiple instances of OldNode as a target. 123 /// multiple instances of OldNode as a target.
123 virtual bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) { 124 virtual bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) {
124 (void)OldNode; 125 (void)OldNode;
125 (void)NewNode; 126 (void)NewNode;
126 return false; 127 return false;
127 } 128 }
128 129
129 virtual bool isSimpleAssign() const { return false; } 130 virtual bool isSimpleAssign() const { return false; }
130 131
131 void livenessLightweight(Cfg *Func, LivenessBV &Live); 132 void livenessLightweight(Cfg *Func, LivenessBV &Live);
132 // Calculates liveness for this instruction. Returns true if this 133 /// Calculates liveness for this instruction. Returns true if this
133 // instruction is (tentatively) still live and should be retained, 134 /// instruction is (tentatively) still live and should be retained,
134 // and false if this instruction is (tentatively) dead and should be 135 /// and false if this instruction is (tentatively) dead and should be
135 // deleted. The decision is tentative until the liveness dataflow 136 /// deleted. The decision is tentative until the liveness dataflow
136 // algorithm has converged, and then a separate pass permanently 137 /// algorithm has converged, and then a separate pass permanently
137 // deletes dead instructions. 138 /// deletes dead instructions.
138 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness, 139 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
139 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd); 140 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
140 141
141 // Get the number of native instructions that this instruction 142 /// Get the number of native instructions that this instruction
142 // ultimately emits. By default, high-level instructions don't 143 /// ultimately emits. By default, high-level instructions don't
143 // result in any native instructions, and a target-specific 144 /// result in any native instructions, and a target-specific
144 // instruction results in a single native instruction. 145 /// instruction results in a single native instruction.
145 virtual uint32_t getEmitInstCount() const { return 0; } 146 virtual uint32_t getEmitInstCount() const { return 0; }
146 // TODO(stichnot): Change Inst back to abstract once the g++ build 147 // TODO(stichnot): Change Inst back to abstract once the g++ build
147 // issue is fixed. llvm::ilist<Ice::Inst> doesn't work under g++ 148 // issue is fixed. llvm::ilist<Ice::Inst> doesn't work under g++
148 // because the resize(size_t, Ice::Inst) method is incorrectly 149 // because the resize(size_t, Ice::Inst) method is incorrectly
149 // declared and thus doesn't allow the abstract class Ice::Inst. 150 // declared and thus doesn't allow the abstract class Ice::Inst.
150 // The method should be declared resize(size_t, const Ice::Inst &). 151 // The method should be declared resize(size_t, const Ice::Inst &).
151 // virtual void emit(const Cfg *Func) const = 0; 152 // virtual void emit(const Cfg *Func) const = 0;
152 // virtual void emitIAS(const Cfg *Func) const = 0; 153 // virtual void emitIAS(const Cfg *Func) const = 0;
153 virtual void emit(const Cfg *) const { 154 virtual void emit(const Cfg *) const {
154 llvm_unreachable("emit on abstract class"); 155 llvm_unreachable("emit on abstract class");
(...skipping 17 matching lines...) Expand all
172 void addSource(Operand *Src) { 173 void addSource(Operand *Src) {
173 assert(Src); 174 assert(Src);
174 assert(NumSrcs < MaxSrcs); 175 assert(NumSrcs < MaxSrcs);
175 Srcs[NumSrcs++] = Src; 176 Srcs[NumSrcs++] = Src;
176 } 177 }
177 void setLastUse(SizeT VarIndex) { 178 void setLastUse(SizeT VarIndex) {
178 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded)) 179 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
179 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex); 180 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
180 } 181 }
181 void resetLastUses() { LiveRangesEnded = 0; } 182 void resetLastUses() { LiveRangesEnded = 0; }
182 // The destroy() method lets the instruction cleanly release any 183 /// The destroy() method lets the instruction cleanly release any
183 // memory that was allocated via the Cfg's allocator. 184 /// memory that was allocated via the Cfg's allocator.
184 virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); } 185 virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); }
185 186
186 const InstKind Kind; 187 const InstKind Kind;
187 // Number is the instruction number for describing live ranges. 188 /// Number is the instruction number for describing live ranges.
188 InstNumberT Number; 189 InstNumberT Number;
189 // Deleted means irrevocably deleted. 190 /// Deleted means irrevocably deleted.
190 bool Deleted = false; 191 bool Deleted = false;
191 // Dead means one of two things depending on context: (1) pending 192 /// Dead means one of two things depending on context: (1) pending
192 // deletion after liveness analysis converges, or (2) marked for 193 /// deletion after liveness analysis converges, or (2) marked for
193 // deletion during lowering due to a folded bool operation. 194 /// deletion during lowering due to a folded bool operation.
194 bool Dead = false; 195 bool Dead = false;
195 // HasSideEffects means the instruction is something like a function 196 /// HasSideEffects means the instruction is something like a function
196 // call or a volatile load that can't be removed even if its Dest 197 /// call or a volatile load that can't be removed even if its Dest
197 // variable is not live. 198 /// variable is not live.
198 bool HasSideEffects = false; 199 bool HasSideEffects = false;
199 // IsDestNonKillable means that liveness analysis shouldn't consider 200 /// IsDestNonKillable means that liveness analysis shouldn't consider
200 // this instruction to kill the Dest variable. This is used when 201 /// this instruction to kill the Dest variable. This is used when
201 // lowering produces two assignments to the same variable. 202 /// lowering produces two assignments to the same variable.
202 bool IsDestNonKillable = false; 203 bool IsDestNonKillable = false;
203 204
204 Variable *Dest; 205 Variable *Dest;
205 const SizeT MaxSrcs; // only used for assert 206 const SizeT MaxSrcs; // only used for assert
206 SizeT NumSrcs = 0; 207 SizeT NumSrcs = 0;
207 Operand **Srcs; 208 Operand **Srcs;
208 209
209 // LiveRangesEnded marks which Variables' live ranges end in this 210 /// LiveRangesEnded marks which Variables' live ranges end in this
210 // instruction. An instruction can have an arbitrary number of 211 /// instruction. An instruction can have an arbitrary number of
211 // source operands (e.g. a call instruction), and each source 212 /// source operands (e.g. a call instruction), and each source
212 // operand can contain 0 or 1 Variable (and target-specific operands 213 /// operand can contain 0 or 1 Variable (and target-specific operands
213 // could contain more than 1 Variable). All the variables in an 214 /// could contain more than 1 Variable). All the variables in an
214 // instruction are conceptually flattened and each variable is 215 /// instruction are conceptually flattened and each variable is
215 // mapped to one bit position of the LiveRangesEnded bit vector. 216 /// mapped to one bit position of the LiveRangesEnded bit vector.
216 // Only the first CHAR_BIT * sizeof(LREndedBits) variables are 217 /// Only the first CHAR_BIT * sizeof(LREndedBits) variables are
217 // tracked this way. 218 /// tracked this way.
218 typedef uint32_t LREndedBits; // only first 32 src operands tracked, sorry 219 typedef uint32_t LREndedBits; // only first 32 src operands tracked, sorry
219 LREndedBits LiveRangesEnded; 220 LREndedBits LiveRangesEnded;
220 }; 221 };
221 222
222 class InstHighLevel : public Inst { 223 class InstHighLevel : public Inst {
223 InstHighLevel() = delete; 224 InstHighLevel() = delete;
224 InstHighLevel(const InstHighLevel &) = delete; 225 InstHighLevel(const InstHighLevel &) = delete;
225 InstHighLevel &operator=(const InstHighLevel &) = delete; 226 InstHighLevel &operator=(const InstHighLevel &) = delete;
226 227
227 protected: 228 protected:
228 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 229 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
229 : Inst(Func, Kind, MaxSrcs, Dest) {} 230 : Inst(Func, Kind, MaxSrcs, Dest) {}
230 void emit(const Cfg * /*Func*/) const override { 231 void emit(const Cfg * /*Func*/) const override {
231 llvm_unreachable("emit() called on a non-lowered instruction"); 232 llvm_unreachable("emit() called on a non-lowered instruction");
232 } 233 }
233 void emitIAS(const Cfg * /*Func*/) const override { 234 void emitIAS(const Cfg * /*Func*/) const override {
234 llvm_unreachable("emitIAS() called on a non-lowered instruction"); 235 llvm_unreachable("emitIAS() called on a non-lowered instruction");
235 } 236 }
236 }; 237 };
237 238
238 // Alloca instruction. This captures the size in bytes as getSrc(0), 239 /// Alloca instruction. This captures the size in bytes as getSrc(0),
239 // and the required alignment in bytes. The alignment must be either 240 /// and the required alignment in bytes. The alignment must be either
240 // 0 (no alignment required) or a power of 2. 241 /// 0 (no alignment required) or a power of 2.
241 class InstAlloca : public InstHighLevel { 242 class InstAlloca : public InstHighLevel {
242 InstAlloca() = delete; 243 InstAlloca() = delete;
243 InstAlloca(const InstAlloca &) = delete; 244 InstAlloca(const InstAlloca &) = delete;
244 InstAlloca &operator=(const InstAlloca &) = delete; 245 InstAlloca &operator=(const InstAlloca &) = delete;
245 246
246 public: 247 public:
247 static InstAlloca *create(Cfg *Func, Operand *ByteCount, 248 static InstAlloca *create(Cfg *Func, Operand *ByteCount,
248 uint32_t AlignInBytes, Variable *Dest) { 249 uint32_t AlignInBytes, Variable *Dest) {
249 return new (Func->allocate<InstAlloca>()) 250 return new (Func->allocate<InstAlloca>())
250 InstAlloca(Func, ByteCount, AlignInBytes, Dest); 251 InstAlloca(Func, ByteCount, AlignInBytes, Dest);
251 } 252 }
252 uint32_t getAlignInBytes() const { return AlignInBytes; } 253 uint32_t getAlignInBytes() const { return AlignInBytes; }
253 Operand *getSizeInBytes() const { return getSrc(0); } 254 Operand *getSizeInBytes() const { return getSrc(0); }
254 void dump(const Cfg *Func) const override; 255 void dump(const Cfg *Func) const override;
255 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; } 256 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; }
256 257
257 private: 258 private:
258 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, 259 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
259 Variable *Dest); 260 Variable *Dest);
260 261
261 const uint32_t AlignInBytes; 262 const uint32_t AlignInBytes;
262 }; 263 };
263 264
264 // Binary arithmetic instruction. The source operands are captured in 265 /// Binary arithmetic instruction. The source operands are captured in
265 // getSrc(0) and getSrc(1). 266 /// getSrc(0) and getSrc(1).
266 class InstArithmetic : public InstHighLevel { 267 class InstArithmetic : public InstHighLevel {
267 InstArithmetic() = delete; 268 InstArithmetic() = delete;
268 InstArithmetic(const InstArithmetic &) = delete; 269 InstArithmetic(const InstArithmetic &) = delete;
269 InstArithmetic &operator=(const InstArithmetic &) = delete; 270 InstArithmetic &operator=(const InstArithmetic &) = delete;
270 271
271 public: 272 public:
272 enum OpKind { 273 enum OpKind {
273 #define X(tag, str, commutative) tag, 274 #define X(tag, str, commutative) tag,
274 ICEINSTARITHMETIC_TABLE 275 ICEINSTARITHMETIC_TABLE
275 #undef X 276 #undef X
(...skipping 13 matching lines...) Expand all
289 return Inst->getKind() == Arithmetic; 290 return Inst->getKind() == Arithmetic;
290 } 291 }
291 292
292 private: 293 private:
293 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, 294 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
294 Operand *Source2); 295 Operand *Source2);
295 296
296 const OpKind Op; 297 const OpKind Op;
297 }; 298 };
298 299
299 // Assignment instruction. The source operand is captured in 300 /// Assignment instruction. The source operand is captured in
300 // getSrc(0). This is not part of the LLVM bitcode, but is a useful 301 /// getSrc(0). This is not part of the LLVM bitcode, but is a useful
301 // abstraction for some of the lowering. E.g., if Phi instruction 302 /// abstraction for some of the lowering. E.g., if Phi instruction
302 // lowering happens before target lowering, or for representing an 303 /// lowering happens before target lowering, or for representing an
303 // Inttoptr instruction, or as an intermediate step for lowering a 304 /// Inttoptr instruction, or as an intermediate step for lowering a
304 // Load instruction. 305 /// Load instruction.
305 class InstAssign : public InstHighLevel { 306 class InstAssign : public InstHighLevel {
306 InstAssign() = delete; 307 InstAssign() = delete;
307 InstAssign(const InstAssign &) = delete; 308 InstAssign(const InstAssign &) = delete;
308 InstAssign &operator=(const InstAssign &) = delete; 309 InstAssign &operator=(const InstAssign &) = delete;
309 310
310 public: 311 public:
311 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { 312 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
312 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); 313 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
313 } 314 }
314 bool isSimpleAssign() const override { return true; } 315 bool isSimpleAssign() const override { return true; }
315 void dump(const Cfg *Func) const override; 316 void dump(const Cfg *Func) const override;
316 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; } 317 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; }
317 318
318 private: 319 private:
319 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); 320 InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
320 }; 321 };
321 322
322 // Branch instruction. This represents both conditional and 323 /// Branch instruction. This represents both conditional and
323 // unconditional branches. 324 /// unconditional branches.
324 class InstBr : public InstHighLevel { 325 class InstBr : public InstHighLevel {
325 InstBr() = delete; 326 InstBr() = delete;
326 InstBr(const InstBr &) = delete; 327 InstBr(const InstBr &) = delete;
327 InstBr &operator=(const InstBr &) = delete; 328 InstBr &operator=(const InstBr &) = delete;
328 329
329 public: 330 public:
330 // Create a conditional branch. If TargetTrue==TargetFalse, it is 331 /// Create a conditional branch. If TargetTrue==TargetFalse, it is
331 // optimized to an unconditional branch. 332 /// optimized to an unconditional branch.
332 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue, 333 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
333 CfgNode *TargetFalse) { 334 CfgNode *TargetFalse) {
334 return new (Func->allocate<InstBr>()) 335 return new (Func->allocate<InstBr>())
335 InstBr(Func, Source, TargetTrue, TargetFalse); 336 InstBr(Func, Source, TargetTrue, TargetFalse);
336 } 337 }
337 // Create an unconditional branch. 338 /// Create an unconditional branch.
338 static InstBr *create(Cfg *Func, CfgNode *Target) { 339 static InstBr *create(Cfg *Func, CfgNode *Target) {
339 return new (Func->allocate<InstBr>()) InstBr(Func, Target); 340 return new (Func->allocate<InstBr>()) InstBr(Func, Target);
340 } 341 }
341 bool isUnconditional() const { return getTargetTrue() == nullptr; } 342 bool isUnconditional() const { return getTargetTrue() == nullptr; }
342 Operand *getCondition() const { 343 Operand *getCondition() const {
343 assert(!isUnconditional()); 344 assert(!isUnconditional());
344 return getSrc(0); 345 return getSrc(0);
345 } 346 }
346 CfgNode *getTargetTrue() const { return TargetTrue; } 347 CfgNode *getTargetTrue() const { return TargetTrue; }
347 CfgNode *getTargetFalse() const { return TargetFalse; } 348 CfgNode *getTargetFalse() const { return TargetFalse; }
348 CfgNode *getTargetUnconditional() const { 349 CfgNode *getTargetUnconditional() const {
349 assert(isUnconditional()); 350 assert(isUnconditional());
350 return getTargetFalse(); 351 return getTargetFalse();
351 } 352 }
352 NodeList getTerminatorEdges() const override; 353 NodeList getTerminatorEdges() const override;
353 bool isUnconditionalBranch() const override { return isUnconditional(); } 354 bool isUnconditionalBranch() const override { return isUnconditional(); }
354 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override; 355 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override;
355 void dump(const Cfg *Func) const override; 356 void dump(const Cfg *Func) const override;
356 static bool classof(const Inst *Inst) { return Inst->getKind() == Br; } 357 static bool classof(const Inst *Inst) { return Inst->getKind() == Br; }
357 358
358 private: 359 private:
359 // Conditional branch 360 /// Conditional branch
360 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); 361 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
361 // Unconditional branch 362 /// Unconditional branch
362 InstBr(Cfg *Func, CfgNode *Target); 363 InstBr(Cfg *Func, CfgNode *Target);
363 364
364 CfgNode *TargetFalse; // Doubles as unconditional branch target 365 CfgNode *TargetFalse; /// Doubles as unconditional branch target
365 CfgNode *TargetTrue; // nullptr if unconditional branch 366 CfgNode *TargetTrue; /// nullptr if unconditional branch
366 }; 367 };
367 368
368 // Call instruction. The call target is captured as getSrc(0), and 369 /// Call instruction. The call target is captured as getSrc(0), and
369 // arg I is captured as getSrc(I+1). 370 /// arg I is captured as getSrc(I+1).
370 class InstCall : public InstHighLevel { 371 class InstCall : public InstHighLevel {
371 InstCall() = delete; 372 InstCall() = delete;
372 InstCall(const InstCall &) = delete; 373 InstCall(const InstCall &) = delete;
373 InstCall &operator=(const InstCall &) = delete; 374 InstCall &operator=(const InstCall &) = delete;
374 375
375 public: 376 public:
376 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 377 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
377 Operand *CallTarget, bool HasTailCall) { 378 Operand *CallTarget, bool HasTailCall) {
378 // Set HasSideEffects to true so that the call instruction can't be 379 /// Set HasSideEffects to true so that the call instruction can't be
379 // dead-code eliminated. IntrinsicCalls can override this if the 380 /// dead-code eliminated. IntrinsicCalls can override this if the
380 // particular intrinsic is deletable and has no side-effects. 381 /// particular intrinsic is deletable and has no side-effects.
381 const bool HasSideEffects = true; 382 const bool HasSideEffects = true;
382 const InstKind Kind = Inst::Call; 383 const InstKind Kind = Inst::Call;
383 return new (Func->allocate<InstCall>()) InstCall( 384 return new (Func->allocate<InstCall>()) InstCall(
384 Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind); 385 Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind);
385 } 386 }
386 void addArg(Operand *Arg) { addSource(Arg); } 387 void addArg(Operand *Arg) { addSource(Arg); }
387 Operand *getCallTarget() const { return getSrc(0); } 388 Operand *getCallTarget() const { return getSrc(0); }
388 Operand *getArg(SizeT I) const { return getSrc(I + 1); } 389 Operand *getArg(SizeT I) const { return getSrc(I + 1); }
389 SizeT getNumArgs() const { return getSrcSize() - 1; } 390 SizeT getNumArgs() const { return getSrcSize() - 1; }
390 bool isTailcall() const { return HasTailCall; } 391 bool isTailcall() const { return HasTailCall; }
391 void dump(const Cfg *Func) const override; 392 void dump(const Cfg *Func) const override;
392 static bool classof(const Inst *Inst) { return Inst->getKind() == Call; } 393 static bool classof(const Inst *Inst) { return Inst->getKind() == Call; }
393 Type getReturnType() const; 394 Type getReturnType() const;
394 395
395 protected: 396 protected:
396 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget, 397 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
397 bool HasTailCall, bool HasSideEff, InstKind Kind) 398 bool HasTailCall, bool HasSideEff, InstKind Kind)
398 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) { 399 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) {
399 HasSideEffects = HasSideEff; 400 HasSideEffects = HasSideEff;
400 addSource(CallTarget); 401 addSource(CallTarget);
401 } 402 }
402 403
403 private: 404 private:
404 bool HasTailCall; 405 bool HasTailCall;
405 }; 406 };
406 407
407 // Cast instruction (a.k.a. conversion operation). 408 /// Cast instruction (a.k.a. conversion operation).
408 class InstCast : public InstHighLevel { 409 class InstCast : public InstHighLevel {
409 InstCast() = delete; 410 InstCast() = delete;
410 InstCast(const InstCast &) = delete; 411 InstCast(const InstCast &) = delete;
411 InstCast &operator=(const InstCast &) = delete; 412 InstCast &operator=(const InstCast &) = delete;
412 413
413 public: 414 public:
414 enum OpKind { 415 enum OpKind {
415 #define X(tag, str) tag, 416 #define X(tag, str) tag,
416 ICEINSTCAST_TABLE 417 ICEINSTCAST_TABLE
417 #undef X 418 #undef X
(...skipping 10 matching lines...) Expand all
428 OpKind getCastKind() const { return CastKind; } 429 OpKind getCastKind() const { return CastKind; }
429 void dump(const Cfg *Func) const override; 430 void dump(const Cfg *Func) const override;
430 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; } 431 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; }
431 432
432 private: 433 private:
433 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); 434 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
434 435
435 const OpKind CastKind; 436 const OpKind CastKind;
436 }; 437 };
437 438
438 // ExtractElement instruction. 439 /// ExtractElement instruction.
439 class InstExtractElement : public InstHighLevel { 440 class InstExtractElement : public InstHighLevel {
440 InstExtractElement() = delete; 441 InstExtractElement() = delete;
441 InstExtractElement(const InstExtractElement &) = delete; 442 InstExtractElement(const InstExtractElement &) = delete;
442 InstExtractElement &operator=(const InstExtractElement &) = delete; 443 InstExtractElement &operator=(const InstExtractElement &) = delete;
443 444
444 public: 445 public:
445 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 446 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
446 Operand *Source2) { 447 Operand *Source2) {
447 return new (Func->allocate<InstExtractElement>()) 448 return new (Func->allocate<InstExtractElement>())
448 InstExtractElement(Func, Dest, Source1, Source2); 449 InstExtractElement(Func, Dest, Source1, Source2);
449 } 450 }
450 451
451 void dump(const Cfg *Func) const override; 452 void dump(const Cfg *Func) const override;
452 static bool classof(const Inst *Inst) { 453 static bool classof(const Inst *Inst) {
453 return Inst->getKind() == ExtractElement; 454 return Inst->getKind() == ExtractElement;
454 } 455 }
455 456
456 private: 457 private:
457 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, 458 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
458 Operand *Source2); 459 Operand *Source2);
459 }; 460 };
460 461
461 // Floating-point comparison instruction. The source operands are 462 /// Floating-point comparison instruction. The source operands are
462 // captured in getSrc(0) and getSrc(1). 463 /// captured in getSrc(0) and getSrc(1).
463 class InstFcmp : public InstHighLevel { 464 class InstFcmp : public InstHighLevel {
464 InstFcmp() = delete; 465 InstFcmp() = delete;
465 InstFcmp(const InstFcmp &) = delete; 466 InstFcmp(const InstFcmp &) = delete;
466 InstFcmp &operator=(const InstFcmp &) = delete; 467 InstFcmp &operator=(const InstFcmp &) = delete;
467 468
468 public: 469 public:
469 enum FCond { 470 enum FCond {
470 #define X(tag, str) tag, 471 #define X(tag, str) tag,
471 ICEINSTFCMP_TABLE 472 ICEINSTFCMP_TABLE
472 #undef X 473 #undef X
473 _num 474 _num
474 }; 475 };
475 476
476 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, 477 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
477 Operand *Source1, Operand *Source2) { 478 Operand *Source1, Operand *Source2) {
478 return new (Func->allocate<InstFcmp>()) 479 return new (Func->allocate<InstFcmp>())
479 InstFcmp(Func, Condition, Dest, Source1, Source2); 480 InstFcmp(Func, Condition, Dest, Source1, Source2);
480 } 481 }
481 FCond getCondition() const { return Condition; } 482 FCond getCondition() const { return Condition; }
482 void dump(const Cfg *Func) const override; 483 void dump(const Cfg *Func) const override;
483 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; } 484 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; }
484 485
485 private: 486 private:
486 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, 487 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
487 Operand *Source2); 488 Operand *Source2);
488 489
489 const FCond Condition; 490 const FCond Condition;
490 }; 491 };
491 492
492 // Integer comparison instruction. The source operands are captured 493 /// Integer comparison instruction. The source operands are captured
493 // in getSrc(0) and getSrc(1). 494 /// in getSrc(0) and getSrc(1).
494 class InstIcmp : public InstHighLevel { 495 class InstIcmp : public InstHighLevel {
495 InstIcmp() = delete; 496 InstIcmp() = delete;
496 InstIcmp(const InstIcmp &) = delete; 497 InstIcmp(const InstIcmp &) = delete;
497 InstIcmp &operator=(const InstIcmp &) = delete; 498 InstIcmp &operator=(const InstIcmp &) = delete;
498 499
499 public: 500 public:
500 enum ICond { 501 enum ICond {
501 #define X(tag, str) tag, 502 #define X(tag, str) tag,
502 ICEINSTICMP_TABLE 503 ICEINSTICMP_TABLE
503 #undef X 504 #undef X
504 _num 505 _num
505 }; 506 };
506 507
507 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, 508 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
508 Operand *Source1, Operand *Source2) { 509 Operand *Source1, Operand *Source2) {
509 return new (Func->allocate<InstIcmp>()) 510 return new (Func->allocate<InstIcmp>())
510 InstIcmp(Func, Condition, Dest, Source1, Source2); 511 InstIcmp(Func, Condition, Dest, Source1, Source2);
511 } 512 }
512 ICond getCondition() const { return Condition; } 513 ICond getCondition() const { return Condition; }
513 void dump(const Cfg *Func) const override; 514 void dump(const Cfg *Func) const override;
514 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; } 515 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; }
515 516
516 private: 517 private:
517 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, 518 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
518 Operand *Source2); 519 Operand *Source2);
519 520
520 const ICond Condition; 521 const ICond Condition;
521 }; 522 };
522 523
523 // InsertElement instruction. 524 /// InsertElement instruction.
524 class InstInsertElement : public InstHighLevel { 525 class InstInsertElement : public InstHighLevel {
525 InstInsertElement() = delete; 526 InstInsertElement() = delete;
526 InstInsertElement(const InstInsertElement &) = delete; 527 InstInsertElement(const InstInsertElement &) = delete;
527 InstInsertElement &operator=(const InstInsertElement &) = delete; 528 InstInsertElement &operator=(const InstInsertElement &) = delete;
528 529
529 public: 530 public:
530 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 531 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
531 Operand *Source2, Operand *Source3) { 532 Operand *Source2, Operand *Source3) {
532 return new (Func->allocate<InstInsertElement>()) 533 return new (Func->allocate<InstInsertElement>())
533 InstInsertElement(Func, Dest, Source1, Source2, Source3); 534 InstInsertElement(Func, Dest, Source1, Source2, Source3);
534 } 535 }
535 536
536 void dump(const Cfg *Func) const override; 537 void dump(const Cfg *Func) const override;
537 static bool classof(const Inst *Inst) { 538 static bool classof(const Inst *Inst) {
538 return Inst->getKind() == InsertElement; 539 return Inst->getKind() == InsertElement;
539 } 540 }
540 541
541 private: 542 private:
542 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, 543 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
543 Operand *Source2, Operand *Source3); 544 Operand *Source2, Operand *Source3);
544 }; 545 };
545 546
546 // Call to an intrinsic function. The call target is captured as getSrc(0), 547 /// Call to an intrinsic function. The call target is captured as getSrc(0),
547 // and arg I is captured as getSrc(I+1). 548 /// and arg I is captured as getSrc(I+1).
548 class InstIntrinsicCall : public InstCall { 549 class InstIntrinsicCall : public InstCall {
549 InstIntrinsicCall() = delete; 550 InstIntrinsicCall() = delete;
550 InstIntrinsicCall(const InstIntrinsicCall &) = delete; 551 InstIntrinsicCall(const InstIntrinsicCall &) = delete;
551 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; 552 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
552 553
553 public: 554 public:
554 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 555 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
555 Operand *CallTarget, 556 Operand *CallTarget,
556 const Intrinsics::IntrinsicInfo &Info) { 557 const Intrinsics::IntrinsicInfo &Info) {
557 return new (Func->allocate<InstIntrinsicCall>()) 558 return new (Func->allocate<InstIntrinsicCall>())
558 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); 559 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
559 } 560 }
560 static bool classof(const Inst *Inst) { 561 static bool classof(const Inst *Inst) {
561 return Inst->getKind() == IntrinsicCall; 562 return Inst->getKind() == IntrinsicCall;
562 } 563 }
563 564
564 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } 565 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
565 566
566 private: 567 private:
567 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, 568 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
568 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) 569 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
569 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects, 570 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects,
570 Inst::IntrinsicCall), 571 Inst::IntrinsicCall),
571 Info(Info) {} 572 Info(Info) {}
572 573
573 const Intrinsics::IntrinsicInfo Info; 574 const Intrinsics::IntrinsicInfo Info;
574 }; 575 };
575 576
576 // Load instruction. The source address is captured in getSrc(0). 577 /// Load instruction. The source address is captured in getSrc(0).
577 class InstLoad : public InstHighLevel { 578 class InstLoad : public InstHighLevel {
578 InstLoad() = delete; 579 InstLoad() = delete;
579 InstLoad(const InstLoad &) = delete; 580 InstLoad(const InstLoad &) = delete;
580 InstLoad &operator=(const InstLoad &) = delete; 581 InstLoad &operator=(const InstLoad &) = delete;
581 582
582 public: 583 public:
583 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, 584 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
584 uint32_t Align = 1) { 585 uint32_t Align = 1) {
585 // TODO(kschimpf) Stop ignoring alignment specification. 586 // TODO(kschimpf) Stop ignoring alignment specification.
586 (void)Align; 587 (void)Align;
587 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); 588 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
588 } 589 }
589 Operand *getSourceAddress() const { return getSrc(0); } 590 Operand *getSourceAddress() const { return getSrc(0); }
590 void dump(const Cfg *Func) const override; 591 void dump(const Cfg *Func) const override;
591 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; } 592 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; }
592 593
593 private: 594 private:
594 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); 595 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
595 }; 596 };
596 597
597 // Phi instruction. For incoming edge I, the node is Labels[I] and 598 /// Phi instruction. For incoming edge I, the node is Labels[I] and
598 // the Phi source operand is getSrc(I). 599 /// the Phi source operand is getSrc(I).
599 class InstPhi : public InstHighLevel { 600 class InstPhi : public InstHighLevel {
600 InstPhi() = delete; 601 InstPhi() = delete;
601 InstPhi(const InstPhi &) = delete; 602 InstPhi(const InstPhi &) = delete;
602 InstPhi &operator=(const InstPhi &) = delete; 603 InstPhi &operator=(const InstPhi &) = delete;
603 604
604 public: 605 public:
605 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { 606 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
606 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); 607 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
607 } 608 }
608 void addArgument(Operand *Source, CfgNode *Label); 609 void addArgument(Operand *Source, CfgNode *Label);
609 Operand *getOperandForTarget(CfgNode *Target) const; 610 Operand *getOperandForTarget(CfgNode *Target) const;
610 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } 611 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
611 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, 612 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
612 Liveness *Liveness); 613 Liveness *Liveness);
613 Inst *lower(Cfg *Func); 614 Inst *lower(Cfg *Func);
614 void dump(const Cfg *Func) const override; 615 void dump(const Cfg *Func) const override;
615 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; } 616 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; }
616 617
617 private: 618 private:
618 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); 619 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
619 void destroy(Cfg *Func) override { 620 void destroy(Cfg *Func) override {
620 Func->deallocateArrayOf<CfgNode *>(Labels); 621 Func->deallocateArrayOf<CfgNode *>(Labels);
621 Inst::destroy(Func); 622 Inst::destroy(Func);
622 } 623 }
623 624
624 // Labels[] duplicates the InEdges[] information in the enclosing 625 /// Labels[] duplicates the InEdges[] information in the enclosing
625 // CfgNode, but the Phi instruction is created before InEdges[] 626 /// CfgNode, but the Phi instruction is created before InEdges[]
626 // is available, so it's more complicated to share the list. 627 /// is available, so it's more complicated to share the list.
627 CfgNode **Labels; 628 CfgNode **Labels;
628 }; 629 };
629 630
630 // Ret instruction. The return value is captured in getSrc(0), but if 631 /// Ret instruction. The return value is captured in getSrc(0), but if
631 // there is no return value (void-type function), then 632 /// there is no return value (void-type function), then
632 // getSrcSize()==0 and hasRetValue()==false. 633 /// getSrcSize()==0 and hasRetValue()==false.
633 class InstRet : public InstHighLevel { 634 class InstRet : public InstHighLevel {
634 InstRet() = delete; 635 InstRet() = delete;
635 InstRet(const InstRet &) = delete; 636 InstRet(const InstRet &) = delete;
636 InstRet &operator=(const InstRet &) = delete; 637 InstRet &operator=(const InstRet &) = delete;
637 638
638 public: 639 public:
639 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) { 640 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
640 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); 641 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
641 } 642 }
642 bool hasRetValue() const { return getSrcSize(); } 643 bool hasRetValue() const { return getSrcSize(); }
643 Operand *getRetValue() const { 644 Operand *getRetValue() const {
644 assert(hasRetValue()); 645 assert(hasRetValue());
645 return getSrc(0); 646 return getSrc(0);
646 } 647 }
647 NodeList getTerminatorEdges() const override { return NodeList(); } 648 NodeList getTerminatorEdges() const override { return NodeList(); }
648 void dump(const Cfg *Func) const override; 649 void dump(const Cfg *Func) const override;
649 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; } 650 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; }
650 651
651 private: 652 private:
652 InstRet(Cfg *Func, Operand *RetValue); 653 InstRet(Cfg *Func, Operand *RetValue);
653 }; 654 };
654 655
655 // Select instruction. The condition, true, and false operands are captured. 656 /// Select instruction. The condition, true, and false operands are captured.
656 class InstSelect : public InstHighLevel { 657 class InstSelect : public InstHighLevel {
657 InstSelect() = delete; 658 InstSelect() = delete;
658 InstSelect(const InstSelect &) = delete; 659 InstSelect(const InstSelect &) = delete;
659 InstSelect &operator=(const InstSelect &) = delete; 660 InstSelect &operator=(const InstSelect &) = delete;
660 661
661 public: 662 public:
662 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, 663 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
663 Operand *SourceTrue, Operand *SourceFalse) { 664 Operand *SourceTrue, Operand *SourceFalse) {
664 return new (Func->allocate<InstSelect>()) 665 return new (Func->allocate<InstSelect>())
665 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); 666 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
666 } 667 }
667 Operand *getCondition() const { return getSrc(0); } 668 Operand *getCondition() const { return getSrc(0); }
668 Operand *getTrueOperand() const { return getSrc(1); } 669 Operand *getTrueOperand() const { return getSrc(1); }
669 Operand *getFalseOperand() const { return getSrc(2); } 670 Operand *getFalseOperand() const { return getSrc(2); }
670 void dump(const Cfg *Func) const override; 671 void dump(const Cfg *Func) const override;
671 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; } 672 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; }
672 673
673 private: 674 private:
674 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, 675 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
675 Operand *Source2); 676 Operand *Source2);
676 }; 677 };
677 678
678 // Store instruction. The address operand is captured, along with the 679 /// Store instruction. The address operand is captured, along with the
679 // data operand to be stored into the address. 680 /// data operand to be stored into the address.
680 class InstStore : public InstHighLevel { 681 class InstStore : public InstHighLevel {
681 InstStore() = delete; 682 InstStore() = delete;
682 InstStore(const InstStore &) = delete; 683 InstStore(const InstStore &) = delete;
683 InstStore &operator=(const InstStore &) = delete; 684 InstStore &operator=(const InstStore &) = delete;
684 685
685 public: 686 public:
686 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, 687 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
687 uint32_t Align = 1) { 688 uint32_t Align = 1) {
688 // TODO(kschimpf) Stop ignoring alignment specification. 689 // TODO(kschimpf) Stop ignoring alignment specification.
689 (void)Align; 690 (void)Align;
690 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); 691 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
691 } 692 }
692 Operand *getAddr() const { return getSrc(1); } 693 Operand *getAddr() const { return getSrc(1); }
693 Operand *getData() const { return getSrc(0); } 694 Operand *getData() const { return getSrc(0); }
694 Variable *getRmwBeacon() const { return llvm::dyn_cast<Variable>(getSrc(2)); } 695 Variable *getRmwBeacon() const { return llvm::dyn_cast<Variable>(getSrc(2)); }
695 void setRmwBeacon(Variable *Beacon); 696 void setRmwBeacon(Variable *Beacon);
696 void dump(const Cfg *Func) const override; 697 void dump(const Cfg *Func) const override;
697 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; } 698 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; }
698 699
699 private: 700 private:
700 InstStore(Cfg *Func, Operand *Data, Operand *Addr); 701 InstStore(Cfg *Func, Operand *Data, Operand *Addr);
701 }; 702 };
702 703
703 // Switch instruction. The single source operand is captured as 704 /// Switch instruction. The single source operand is captured as
704 // getSrc(0). 705 /// getSrc(0).
705 class InstSwitch : public InstHighLevel { 706 class InstSwitch : public InstHighLevel {
706 InstSwitch() = delete; 707 InstSwitch() = delete;
707 InstSwitch(const InstSwitch &) = delete; 708 InstSwitch(const InstSwitch &) = delete;
708 InstSwitch &operator=(const InstSwitch &) = delete; 709 InstSwitch &operator=(const InstSwitch &) = delete;
709 710
710 public: 711 public:
711 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source, 712 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
712 CfgNode *LabelDefault) { 713 CfgNode *LabelDefault) {
713 return new (Func->allocate<InstSwitch>()) 714 return new (Func->allocate<InstSwitch>())
714 InstSwitch(Func, NumCases, Source, LabelDefault); 715 InstSwitch(Func, NumCases, Source, LabelDefault);
(...skipping 17 matching lines...) Expand all
732 733
733 private: 734 private:
734 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); 735 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
735 void destroy(Cfg *Func) override { 736 void destroy(Cfg *Func) override {
736 Func->deallocateArrayOf<uint64_t>(Values); 737 Func->deallocateArrayOf<uint64_t>(Values);
737 Func->deallocateArrayOf<CfgNode *>(Labels); 738 Func->deallocateArrayOf<CfgNode *>(Labels);
738 Inst::destroy(Func); 739 Inst::destroy(Func);
739 } 740 }
740 741
741 CfgNode *LabelDefault; 742 CfgNode *LabelDefault;
742 SizeT NumCases; // not including the default case 743 SizeT NumCases; /// not including the default case
743 uint64_t *Values; // size is NumCases 744 uint64_t *Values; /// size is NumCases
744 CfgNode **Labels; // size is NumCases 745 CfgNode **Labels; /// size is NumCases
745 }; 746 };
746 747
747 // Unreachable instruction. This is a terminator instruction with no 748 /// Unreachable instruction. This is a terminator instruction with no
748 // operands. 749 /// operands.
749 class InstUnreachable : public InstHighLevel { 750 class InstUnreachable : public InstHighLevel {
750 InstUnreachable() = delete; 751 InstUnreachable() = delete;
751 InstUnreachable(const InstUnreachable &) = delete; 752 InstUnreachable(const InstUnreachable &) = delete;
752 InstUnreachable &operator=(const InstUnreachable &) = delete; 753 InstUnreachable &operator=(const InstUnreachable &) = delete;
753 754
754 public: 755 public:
755 static InstUnreachable *create(Cfg *Func) { 756 static InstUnreachable *create(Cfg *Func) {
756 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); 757 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
757 } 758 }
758 NodeList getTerminatorEdges() const override { return NodeList(); } 759 NodeList getTerminatorEdges() const override { return NodeList(); }
759 void dump(const Cfg *Func) const override; 760 void dump(const Cfg *Func) const override;
760 static bool classof(const Inst *Inst) { 761 static bool classof(const Inst *Inst) {
761 return Inst->getKind() == Unreachable; 762 return Inst->getKind() == Unreachable;
762 } 763 }
763 764
764 private: 765 private:
765 explicit InstUnreachable(Cfg *Func); 766 explicit InstUnreachable(Cfg *Func);
766 }; 767 };
767 768
768 // BundleLock instruction. There are no operands. Contains an option 769 /// BundleLock instruction. There are no operands. Contains an option
769 // indicating whether align_to_end is specified. 770 /// indicating whether align_to_end is specified.
770 class InstBundleLock : public InstHighLevel { 771 class InstBundleLock : public InstHighLevel {
771 InstBundleLock() = delete; 772 InstBundleLock() = delete;
772 InstBundleLock(const InstBundleLock &) = delete; 773 InstBundleLock(const InstBundleLock &) = delete;
773 InstBundleLock &operator=(const InstBundleLock &) = delete; 774 InstBundleLock &operator=(const InstBundleLock &) = delete;
774 775
775 public: 776 public:
776 enum Option { Opt_None, Opt_AlignToEnd }; 777 enum Option { Opt_None, Opt_AlignToEnd };
777 static InstBundleLock *create(Cfg *Func, Option BundleOption) { 778 static InstBundleLock *create(Cfg *Func, Option BundleOption) {
778 return new (Func->allocate<InstBundleLock>()) 779 return new (Func->allocate<InstBundleLock>())
779 InstBundleLock(Func, BundleOption); 780 InstBundleLock(Func, BundleOption);
780 } 781 }
781 void emit(const Cfg *Func) const override; 782 void emit(const Cfg *Func) const override;
782 void emitIAS(const Cfg * /* Func */) const override {} 783 void emitIAS(const Cfg * /* Func */) const override {}
783 void dump(const Cfg *Func) const override; 784 void dump(const Cfg *Func) const override;
784 Option getOption() const { return BundleOption; } 785 Option getOption() const { return BundleOption; }
785 static bool classof(const Inst *Inst) { 786 static bool classof(const Inst *Inst) {
786 return Inst->getKind() == BundleLock; 787 return Inst->getKind() == BundleLock;
787 } 788 }
788 789
789 private: 790 private:
790 Option BundleOption; 791 Option BundleOption;
791 InstBundleLock(Cfg *Func, Option BundleOption); 792 InstBundleLock(Cfg *Func, Option BundleOption);
792 }; 793 };
793 794
794 // BundleUnlock instruction. There are no operands. 795 /// BundleUnlock instruction. There are no operands.
795 class InstBundleUnlock : public InstHighLevel { 796 class InstBundleUnlock : public InstHighLevel {
796 InstBundleUnlock() = delete; 797 InstBundleUnlock() = delete;
797 InstBundleUnlock(const InstBundleUnlock &) = delete; 798 InstBundleUnlock(const InstBundleUnlock &) = delete;
798 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete; 799 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
799 800
800 public: 801 public:
801 static InstBundleUnlock *create(Cfg *Func) { 802 static InstBundleUnlock *create(Cfg *Func) {
802 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func); 803 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
803 } 804 }
804 void emit(const Cfg *Func) const override; 805 void emit(const Cfg *Func) const override;
805 void emitIAS(const Cfg * /* Func */) const override {} 806 void emitIAS(const Cfg * /* Func */) const override {}
806 void dump(const Cfg *Func) const override; 807 void dump(const Cfg *Func) const override;
807 static bool classof(const Inst *Inst) { 808 static bool classof(const Inst *Inst) {
808 return Inst->getKind() == BundleUnlock; 809 return Inst->getKind() == BundleUnlock;
809 } 810 }
810 811
811 private: 812 private:
812 explicit InstBundleUnlock(Cfg *Func); 813 explicit InstBundleUnlock(Cfg *Func);
813 }; 814 };
814 815
815 // FakeDef instruction. This creates a fake definition of a variable, 816 /// FakeDef instruction. This creates a fake definition of a variable,
816 // which is how we represent the case when an instruction produces 817 /// which is how we represent the case when an instruction produces
817 // multiple results. This doesn't happen with high-level ICE 818 /// multiple results. This doesn't happen with high-level ICE
818 // instructions, but might with lowered instructions. For example, 819 /// instructions, but might with lowered instructions. For example,
819 // this would be a way to represent condition flags being modified by 820 /// this would be a way to represent condition flags being modified by
820 // an instruction. 821 /// an instruction.
821 // 822 ///
822 // It's generally useful to set the optional source operand to be the 823 /// It's generally useful to set the optional source operand to be the
823 // dest variable of the instruction that actually produces the FakeDef 824 /// dest variable of the instruction that actually produces the FakeDef
824 // dest. Otherwise, the original instruction could be dead-code 825 /// dest. Otherwise, the original instruction could be dead-code
825 // eliminated if its dest operand is unused, and therefore the FakeDef 826 /// eliminated if its dest operand is unused, and therefore the FakeDef
826 // dest wouldn't be properly initialized. 827 /// dest wouldn't be properly initialized.
827 class InstFakeDef : public InstHighLevel { 828 class InstFakeDef : public InstHighLevel {
828 InstFakeDef() = delete; 829 InstFakeDef() = delete;
829 InstFakeDef(const InstFakeDef &) = delete; 830 InstFakeDef(const InstFakeDef &) = delete;
830 InstFakeDef &operator=(const InstFakeDef &) = delete; 831 InstFakeDef &operator=(const InstFakeDef &) = delete;
831 832
832 public: 833 public:
833 static InstFakeDef *create(Cfg *Func, Variable *Dest, 834 static InstFakeDef *create(Cfg *Func, Variable *Dest,
834 Variable *Src = nullptr) { 835 Variable *Src = nullptr) {
835 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); 836 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
836 } 837 }
837 void emit(const Cfg *Func) const override; 838 void emit(const Cfg *Func) const override;
838 void emitIAS(const Cfg * /* Func */) const override {} 839 void emitIAS(const Cfg * /* Func */) const override {}
839 void dump(const Cfg *Func) const override; 840 void dump(const Cfg *Func) const override;
840 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; } 841 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; }
841 842
842 private: 843 private:
843 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); 844 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
844 }; 845 };
845 846
846 // FakeUse instruction. This creates a fake use of a variable, to 847 /// FakeUse instruction. This creates a fake use of a variable, to
847 // keep the instruction that produces that variable from being 848 /// keep the instruction that produces that variable from being
848 // dead-code eliminated. This is useful in a variety of lowering 849 /// dead-code eliminated. This is useful in a variety of lowering
849 // situations. The FakeUse instruction has no dest, so it can itself 850 /// situations. The FakeUse instruction has no dest, so it can itself
850 // never be dead-code eliminated. 851 /// never be dead-code eliminated.
851 class InstFakeUse : public InstHighLevel { 852 class InstFakeUse : public InstHighLevel {
852 InstFakeUse() = delete; 853 InstFakeUse() = delete;
853 InstFakeUse(const InstFakeUse &) = delete; 854 InstFakeUse(const InstFakeUse &) = delete;
854 InstFakeUse &operator=(const InstFakeUse &) = delete; 855 InstFakeUse &operator=(const InstFakeUse &) = delete;
855 856
856 public: 857 public:
857 static InstFakeUse *create(Cfg *Func, Variable *Src) { 858 static InstFakeUse *create(Cfg *Func, Variable *Src) {
858 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src); 859 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src);
859 } 860 }
860 void emit(const Cfg *Func) const override; 861 void emit(const Cfg *Func) const override;
861 void emitIAS(const Cfg * /* Func */) const override {} 862 void emitIAS(const Cfg * /* Func */) const override {}
862 void dump(const Cfg *Func) const override; 863 void dump(const Cfg *Func) const override;
863 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; } 864 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; }
864 865
865 private: 866 private:
866 InstFakeUse(Cfg *Func, Variable *Src); 867 InstFakeUse(Cfg *Func, Variable *Src);
867 }; 868 };
868 869
869 // FakeKill instruction. This "kills" a set of variables by modeling 870 /// FakeKill instruction. This "kills" a set of variables by modeling
870 // a trivial live range at this instruction for each (implicit) 871 /// a trivial live range at this instruction for each (implicit)
871 // variable. The primary use is to indicate that scratch registers 872 /// variable. The primary use is to indicate that scratch registers
872 // are killed after a call, so that the register allocator won't 873 /// are killed after a call, so that the register allocator won't
873 // assign a scratch register to a variable whose live range spans a 874 /// assign a scratch register to a variable whose live range spans a
874 // call. 875 /// call.
875 // 876 ///
876 // The FakeKill instruction also holds a pointer to the instruction 877 /// The FakeKill instruction also holds a pointer to the instruction
877 // that kills the set of variables, so that if that linked instruction 878 /// that kills the set of variables, so that if that linked instruction
878 // gets dead-code eliminated, the FakeKill instruction will as well. 879 /// gets dead-code eliminated, the FakeKill instruction will as well.
879 class InstFakeKill : public InstHighLevel { 880 class InstFakeKill : public InstHighLevel {
880 InstFakeKill() = delete; 881 InstFakeKill() = delete;
881 InstFakeKill(const InstFakeKill &) = delete; 882 InstFakeKill(const InstFakeKill &) = delete;
882 InstFakeKill &operator=(const InstFakeKill &) = delete; 883 InstFakeKill &operator=(const InstFakeKill &) = delete;
883 884
884 public: 885 public:
885 static InstFakeKill *create(Cfg *Func, const Inst *Linked) { 886 static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
886 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); 887 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
887 } 888 }
888 const Inst *getLinked() const { return Linked; } 889 const Inst *getLinked() const { return Linked; }
889 void emit(const Cfg *Func) const override; 890 void emit(const Cfg *Func) const override;
890 void emitIAS(const Cfg * /* Func */) const override {} 891 void emitIAS(const Cfg * /* Func */) const override {}
891 void dump(const Cfg *Func) const override; 892 void dump(const Cfg *Func) const override;
892 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; } 893 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; }
893 894
894 private: 895 private:
895 InstFakeKill(Cfg *Func, const Inst *Linked); 896 InstFakeKill(Cfg *Func, const Inst *Linked);
896 897
897 // This instruction is ignored if Linked->isDeleted() is true. 898 /// This instruction is ignored if Linked->isDeleted() is true.
898 const Inst *Linked; 899 const Inst *Linked;
899 }; 900 };
900 901
901 // The Target instruction is the base class for all target-specific 902 /// The Target instruction is the base class for all target-specific
902 // instructions. 903 /// instructions.
903 class InstTarget : public Inst { 904 class InstTarget : public Inst {
904 InstTarget() = delete; 905 InstTarget() = delete;
905 InstTarget(const InstTarget &) = delete; 906 InstTarget(const InstTarget &) = delete;
906 InstTarget &operator=(const InstTarget &) = delete; 907 InstTarget &operator=(const InstTarget &) = delete;
907 908
908 public: 909 public:
909 uint32_t getEmitInstCount() const override { return 1; } 910 uint32_t getEmitInstCount() const override { return 1; }
910 void dump(const Cfg *Func) const override; 911 void dump(const Cfg *Func) const override;
911 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; } 912 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; }
912 913
913 protected: 914 protected:
914 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 915 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
915 : Inst(Func, Kind, MaxSrcs, Dest) { 916 : Inst(Func, Kind, MaxSrcs, Dest) {
916 assert(Kind >= Target); 917 assert(Kind >= Target);
917 } 918 }
918 }; 919 };
919 920
920 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source); 921 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
921 922
922 } // end of namespace Ice 923 } // end of namespace Ice
923 924
924 namespace llvm { 925 namespace llvm {
925 926
926 // Override the default ilist traits so that Inst's private ctor and 927 /// Override the default ilist traits so that Inst's private ctor and
927 // deleted dtor aren't invoked. 928 /// deleted dtor aren't invoked.
928 template <> 929 template <>
929 struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> { 930 struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
930 Ice::Inst *createSentinel() const { 931 Ice::Inst *createSentinel() const {
931 return static_cast<Ice::Inst *>(&Sentinel); 932 return static_cast<Ice::Inst *>(&Sentinel);
932 } 933 }
933 static void destroySentinel(Ice::Inst *) {} 934 static void destroySentinel(Ice::Inst *) {}
934 Ice::Inst *provideInitialHead() const { return createSentinel(); } 935 Ice::Inst *provideInitialHead() const { return createSentinel(); }
935 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); } 936 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
936 static void noteHead(Ice::Inst *, Ice::Inst *) {} 937 static void noteHead(Ice::Inst *, Ice::Inst *) {}
937 void deleteNode(Ice::Inst *) {} 938 void deleteNode(Ice::Inst *) {}
938 939
939 private: 940 private:
940 mutable ilist_half_node<Ice::Inst> Sentinel; 941 mutable ilist_half_node<Ice::Inst> Sentinel;
941 }; 942 };
942 943
943 } // end of namespace llvm 944 } // end of namespace llvm
944 945
945 #endif // SUBZERO_SRC_ICEINST_H 946 #endif // SUBZERO_SRC_ICEINST_H
OLDNEW
« no previous file with comments | « src/IceGlobalInits.cpp ('k') | src/IceInst.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698