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

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

Powered by Google App Engine
This is Rietveld 408576698