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

Side by Side Diff: src/IceInst.h

Issue 1341423002: Reflow comments to use the full width. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix spelling and rebase Created 5 years, 3 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 /// \file 10 /// \file
11 /// This file declares the Inst class and its target-independent 11 /// This file declares the Inst class and its target-independent
12 /// subclasses, which represent the high-level Vanilla ICE instructions 12 /// subclasses, which represent the high-level Vanilla ICE instructions
13 /// and map roughly 1:1 to LLVM instructions. 13 /// and map roughly 1:1 to LLVM instructions.
14 /// 14 ///
15 //===----------------------------------------------------------------------===// 15 //===----------------------------------------------------------------------===//
16 16
17 #ifndef SUBZERO_SRC_ICEINST_H 17 #ifndef SUBZERO_SRC_ICEINST_H
18 #define SUBZERO_SRC_ICEINST_H 18 #define SUBZERO_SRC_ICEINST_H
19 19
20 #include "IceCfg.h" 20 #include "IceCfg.h"
21 #include "IceDefs.h" 21 #include "IceDefs.h"
22 #include "IceInst.def" 22 #include "IceInst.def"
23 #include "IceIntrinsics.h" 23 #include "IceIntrinsics.h"
24 #include "IceTypes.h" 24 #include "IceTypes.h"
25 25
26 // TODO: The Cfg structure, and instructions in particular, need to be 26 // TODO: The Cfg structure, and instructions in particular, need to be
27 // validated for things like valid operand types, valid branch targets, proper 27 // validated for things like valid operand types, valid branch targets, proper
28 // ordering of Phi and non-Phi instructions, etc. Most of the validity 28 // ordering of Phi and non-Phi instructions, etc. Most of the validity checking
29 // checking will be done in the bitcode reader. We need a list of everything 29 // will be done in the bitcode reader. We need a list of everything that should
30 // that should be validated, and tests for each. 30 // be validated, and tests for each.
31 31
32 namespace Ice { 32 namespace Ice {
33 33
34 /// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and 34 /// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and
35 /// InstTarget. High-level ICE instructions inherit from InstHighLevel, and 35 /// InstTarget. High-level ICE instructions inherit from InstHighLevel, and
36 /// low-level (target-specific) ICE instructions inherit from InstTarget. 36 /// low-level (target-specific) ICE instructions inherit from InstTarget.
37 class Inst : public llvm::ilist_node<Inst> { 37 class Inst : public llvm::ilist_node<Inst> {
38 Inst() = delete; 38 Inst() = delete;
39 Inst(const Inst &) = delete; 39 Inst(const Inst &) = delete;
40 Inst &operator=(const Inst &) = delete; 40 Inst &operator=(const Inst &) = delete;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 /// duplicates. 111 /// duplicates.
112 virtual NodeList getTerminatorEdges() const { 112 virtual NodeList getTerminatorEdges() const {
113 // All valid terminator instructions override this method. For the default 113 // All valid terminator instructions override this method. For the default
114 // implementation, we assert in case some CfgNode is constructed without a 114 // implementation, we assert in case some CfgNode is constructed without a
115 // terminator instruction at the end. 115 // terminator instruction at the end.
116 llvm_unreachable( 116 llvm_unreachable(
117 "getTerminatorEdges() called on a non-terminator instruction"); 117 "getTerminatorEdges() called on a non-terminator instruction");
118 return NodeList(); 118 return NodeList();
119 } 119 }
120 virtual bool isUnconditionalBranch() const { return false; } 120 virtual bool isUnconditionalBranch() const { return false; }
121 /// If the instruction is a branch-type instruction with OldNode as a 121 /// If the instruction is a branch-type instruction with OldNode as a target,
122 /// target, repoint it to NewNode and return true, otherwise return 122 /// repoint it to NewNode and return true, otherwise return false. Repoint all
123 /// false. Repoint all instances of OldNode as a target. 123 /// instances of OldNode as a target.
124 virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) { 124 virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
125 (void)OldNode; 125 (void)OldNode;
126 (void)NewNode; 126 (void)NewNode;
127 return false; 127 return false;
128 } 128 }
129 129
130 virtual bool isSimpleAssign() const { return false; } 130 virtual bool isSimpleAssign() const { return false; }
131 131
132 void livenessLightweight(Cfg *Func, LivenessBV &Live); 132 void livenessLightweight(Cfg *Func, LivenessBV &Live);
133 // Calculates liveness for this instruction. Returns true if this 133 /// Calculates liveness for this instruction. Returns true if this instruction
134 /// instruction is (tentatively) still live and should be retained, and false 134 /// is (tentatively) still live and should be retained, and false if this
135 /// if this instruction is (tentatively) dead and should be deleted. The 135 /// instruction is (tentatively) dead and should be deleted. The decision is
136 /// decision is tentative until the liveness dataflow algorithm has converged, 136 /// tentative until the liveness dataflow algorithm has converged, and then a
137 /// and then a separate pass permanently deletes dead instructions. 137 /// separate pass permanently 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 ultimately 141 /// Get the number of native instructions that this instruction ultimately
142 /// emits. By default, high-level instructions don't result in any native 142 /// emits. By default, high-level instructions don't result in any native
143 /// instructions, and a target-specific instruction results in a single native 143 /// instructions, and a target-specific instruction results in a single native
144 /// instruction. 144 /// 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 issue is
147 // issue is fixed. llvm::ilist<Ice::Inst> doesn't work under g++ 147 // fixed. llvm::ilist<Ice::Inst> doesn't work under g++ because the
148 // because the resize(size_t, Ice::Inst) method is incorrectly 148 // resize(size_t, Ice::Inst) method is incorrectly declared and thus doesn't
149 // declared and thus doesn't allow the abstract class Ice::Inst. 149 // allow the abstract class Ice::Inst. The method should be declared
150 // The method should be declared resize(size_t, const Ice::Inst &). 150 // resize(size_t, const Ice::Inst &). virtual void emit(const Cfg *Func)
151 // virtual void emit(const Cfg *Func) const = 0; 151 // const = 0; virtual void emitIAS(const Cfg *Func) const = 0;
152 // virtual void emitIAS(const Cfg *Func) const = 0;
153 virtual void emit(const Cfg *) const { 152 virtual void emit(const Cfg *) const {
154 llvm_unreachable("emit on abstract class"); 153 llvm_unreachable("emit on abstract class");
155 } 154 }
156 virtual void emitIAS(const Cfg *Func) const { emit(Func); } 155 virtual void emitIAS(const Cfg *Func) const { emit(Func); }
157 virtual void dump(const Cfg *Func) const; 156 virtual void dump(const Cfg *Func) const;
158 virtual void dumpExtras(const Cfg *Func) const; 157 virtual void dumpExtras(const Cfg *Func) const;
159 void dumpDecorated(const Cfg *Func) const; 158 void dumpDecorated(const Cfg *Func) const;
160 void emitSources(const Cfg *Func) const; 159 void emitSources(const Cfg *Func) const;
161 void dumpSources(const Cfg *Func) const; 160 void dumpSources(const Cfg *Func) const;
162 void dumpDest(const Cfg *Func) const; 161 void dumpDest(const Cfg *Func) const;
163 virtual bool isRedundantAssign() const { return false; } 162 virtual bool isRedundantAssign() const { return false; }
164 163
165 // TODO(jpp): Insts should not have non-trivial destructors, but they 164 // TODO(jpp): Insts should not have non-trivial destructors, but they
166 // currently do. This dtor is marked final as a multi-step refactor that 165 // currently do. This dtor is marked final as a multi-step refactor that
167 // will eventually fix this problem. 166 // will eventually fix this problem.
168 virtual ~Inst() = default; 167 virtual ~Inst() = default;
169 168
170 protected: 169 protected:
171 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest); 170 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
172 void addSource(Operand *Src) { 171 void addSource(Operand *Src) {
173 assert(Src); 172 assert(Src);
174 assert(NumSrcs < MaxSrcs); 173 assert(NumSrcs < MaxSrcs);
175 Srcs[NumSrcs++] = Src; 174 Srcs[NumSrcs++] = Src;
176 } 175 }
177 void setLastUse(SizeT VarIndex) { 176 void setLastUse(SizeT VarIndex) {
178 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded)) 177 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
179 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex); 178 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
180 } 179 }
181 void resetLastUses() { LiveRangesEnded = 0; } 180 void resetLastUses() { LiveRangesEnded = 0; }
182 /// The destroy() method lets the instruction cleanly release any 181 /// The destroy() method lets the instruction cleanly release any memory that
183 /// memory that was allocated via the Cfg's allocator. 182 /// was allocated via the Cfg's allocator.
184 virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); } 183 virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); }
185 184
186 const InstKind Kind; 185 const InstKind Kind;
187 /// Number is the instruction number for describing live ranges. 186 /// Number is the instruction number for describing live ranges.
188 InstNumberT Number; 187 InstNumberT Number;
189 /// Deleted means irrevocably deleted. 188 /// Deleted means irrevocably deleted.
190 bool Deleted = false; 189 bool Deleted = false;
191 /// Dead means one of two things depending on context: (1) pending 190 /// Dead means one of two things depending on context: (1) pending deletion
192 /// deletion after liveness analysis converges, or (2) marked for 191 /// after liveness analysis converges, or (2) marked for deletion during
193 /// deletion during lowering due to a folded bool operation. 192 /// lowering due to a folded bool operation.
194 bool Dead = false; 193 bool Dead = false;
195 /// HasSideEffects means the instruction is something like a function 194 /// HasSideEffects means the instruction is something like a function call or
196 /// call or a volatile load that can't be removed even if its Dest 195 /// a volatile load that can't be removed even if its Dest variable is not
197 /// variable is not live. 196 /// live.
198 bool HasSideEffects = false; 197 bool HasSideEffects = false;
199 /// IsDestNonKillable means that liveness analysis shouldn't consider 198 /// IsDestNonKillable means that liveness analysis shouldn't consider this
200 /// this instruction to kill the Dest variable. This is used when 199 /// instruction to kill the Dest variable. This is used when lowering produces
201 /// lowering produces two assignments to the same variable. 200 /// two assignments to the same variable.
202 bool IsDestNonKillable = false; 201 bool IsDestNonKillable = false;
203 202
204 Variable *Dest; 203 Variable *Dest;
205 const SizeT MaxSrcs; // only used for assert 204 const SizeT MaxSrcs; // only used for assert
206 SizeT NumSrcs = 0; 205 SizeT NumSrcs = 0;
207 Operand **Srcs; 206 Operand **Srcs;
208 207
209 /// LiveRangesEnded marks which Variables' live ranges end in this 208 /// LiveRangesEnded marks which Variables' live ranges end in this
210 /// instruction. An instruction can have an arbitrary number of 209 /// instruction. An instruction can have an arbitrary number of source
211 /// source operands (e.g. a call instruction), and each source 210 /// operands (e.g. a call instruction), and each source operand can contain 0
212 /// operand can contain 0 or 1 Variable (and target-specific operands 211 /// or 1 Variable (and target-specific operands could contain more than 1
213 /// could contain more than 1 Variable). All the variables in an 212 /// Variable). All the variables in an instruction are conceptually flattened
214 /// instruction are conceptually flattened and each variable is 213 /// and each variable is mapped to one bit position of the LiveRangesEnded bit
215 /// mapped to one bit position of the LiveRangesEnded bit vector. 214 /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are
216 /// Only the first CHAR_BIT * sizeof(LREndedBits) variables are
217 /// tracked this way. 215 /// tracked this way.
218 using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry 216 using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry
219 LREndedBits LiveRangesEnded; 217 LREndedBits LiveRangesEnded;
220 }; 218 };
221 219
222 class InstHighLevel : public Inst { 220 class InstHighLevel : public Inst {
223 InstHighLevel() = delete; 221 InstHighLevel() = delete;
224 InstHighLevel(const InstHighLevel &) = delete; 222 InstHighLevel(const InstHighLevel &) = delete;
225 InstHighLevel &operator=(const InstHighLevel &) = delete; 223 InstHighLevel &operator=(const InstHighLevel &) = delete;
226 224
227 protected: 225 protected:
228 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 226 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
229 : Inst(Func, Kind, MaxSrcs, Dest) {} 227 : Inst(Func, Kind, MaxSrcs, Dest) {}
230 void emit(const Cfg * /*Func*/) const override { 228 void emit(const Cfg * /*Func*/) const override {
231 llvm_unreachable("emit() called on a non-lowered instruction"); 229 llvm_unreachable("emit() called on a non-lowered instruction");
232 } 230 }
233 void emitIAS(const Cfg * /*Func*/) const override { 231 void emitIAS(const Cfg * /*Func*/) const override {
234 llvm_unreachable("emitIAS() called on a non-lowered instruction"); 232 llvm_unreachable("emitIAS() called on a non-lowered instruction");
235 } 233 }
236 }; 234 };
237 235
238 /// Alloca instruction. This captures the size in bytes as getSrc(0), 236 /// Alloca instruction. This captures the size in bytes as getSrc(0), and the
239 /// and the required alignment in bytes. The alignment must be either 237 /// required alignment in bytes. The alignment must be either 0 (no alignment
240 /// 0 (no alignment required) or a power of 2. 238 /// required) or a power of 2.
241 class InstAlloca : public InstHighLevel { 239 class InstAlloca : public InstHighLevel {
242 InstAlloca() = delete; 240 InstAlloca() = delete;
243 InstAlloca(const InstAlloca &) = delete; 241 InstAlloca(const InstAlloca &) = delete;
244 InstAlloca &operator=(const InstAlloca &) = delete; 242 InstAlloca &operator=(const InstAlloca &) = delete;
245 243
246 public: 244 public:
247 static InstAlloca *create(Cfg *Func, Operand *ByteCount, 245 static InstAlloca *create(Cfg *Func, Operand *ByteCount,
248 uint32_t AlignInBytes, Variable *Dest) { 246 uint32_t AlignInBytes, Variable *Dest) {
249 return new (Func->allocate<InstAlloca>()) 247 return new (Func->allocate<InstAlloca>())
250 InstAlloca(Func, ByteCount, AlignInBytes, Dest); 248 InstAlloca(Func, ByteCount, AlignInBytes, Dest);
251 } 249 }
252 uint32_t getAlignInBytes() const { return AlignInBytes; } 250 uint32_t getAlignInBytes() const { return AlignInBytes; }
253 Operand *getSizeInBytes() const { return getSrc(0); } 251 Operand *getSizeInBytes() const { return getSrc(0); }
254 void dump(const Cfg *Func) const override; 252 void dump(const Cfg *Func) const override;
255 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; } 253 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; }
256 254
257 private: 255 private:
258 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, 256 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
259 Variable *Dest); 257 Variable *Dest);
260 258
261 const uint32_t AlignInBytes; 259 const uint32_t AlignInBytes;
262 }; 260 };
263 261
264 /// Binary arithmetic instruction. The source operands are captured in 262 /// Binary arithmetic instruction. The source operands are captured in getSrc(0)
265 /// getSrc(0) and getSrc(1). 263 /// and getSrc(1).
266 class InstArithmetic : public InstHighLevel { 264 class InstArithmetic : public InstHighLevel {
267 InstArithmetic() = delete; 265 InstArithmetic() = delete;
268 InstArithmetic(const InstArithmetic &) = delete; 266 InstArithmetic(const InstArithmetic &) = delete;
269 InstArithmetic &operator=(const InstArithmetic &) = delete; 267 InstArithmetic &operator=(const InstArithmetic &) = delete;
270 268
271 public: 269 public:
272 enum OpKind { 270 enum OpKind {
273 #define X(tag, str, commutative) tag, 271 #define X(tag, str, commutative) tag,
274 ICEINSTARITHMETIC_TABLE 272 ICEINSTARITHMETIC_TABLE
275 #undef X 273 #undef X
(...skipping 13 matching lines...) Expand all
289 return Inst->getKind() == Arithmetic; 287 return Inst->getKind() == Arithmetic;
290 } 288 }
291 289
292 private: 290 private:
293 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, 291 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
294 Operand *Source2); 292 Operand *Source2);
295 293
296 const OpKind Op; 294 const OpKind Op;
297 }; 295 };
298 296
299 /// Assignment instruction. The source operand is captured in 297 /// Assignment instruction. The source operand is captured in getSrc(0). This is
300 /// getSrc(0). This is not part of the LLVM bitcode, but is a useful 298 /// not part of the LLVM bitcode, but is a useful abstraction for some of the
301 /// abstraction for some of the lowering. E.g., if Phi instruction 299 /// lowering. E.g., if Phi instruction lowering happens before target lowering,
302 /// lowering happens before target lowering, or for representing an 300 /// or for representing an Inttoptr instruction, or as an intermediate step for
303 /// Inttoptr instruction, or as an intermediate step for lowering a 301 /// lowering a Load instruction.
304 /// Load instruction.
305 class InstAssign : public InstHighLevel { 302 class InstAssign : public InstHighLevel {
306 InstAssign() = delete; 303 InstAssign() = delete;
307 InstAssign(const InstAssign &) = delete; 304 InstAssign(const InstAssign &) = delete;
308 InstAssign &operator=(const InstAssign &) = delete; 305 InstAssign &operator=(const InstAssign &) = delete;
309 306
310 public: 307 public:
311 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { 308 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
312 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); 309 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
313 } 310 }
314 bool isSimpleAssign() const override { return true; } 311 bool isSimpleAssign() const override { return true; }
315 void dump(const Cfg *Func) const override; 312 void dump(const Cfg *Func) const override;
316 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; } 313 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; }
317 314
318 private: 315 private:
319 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); 316 InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
320 }; 317 };
321 318
322 /// Branch instruction. This represents both conditional and 319 /// Branch instruction. This represents both conditional and unconditional
323 /// unconditional branches. 320 /// branches.
324 class InstBr : public InstHighLevel { 321 class InstBr : public InstHighLevel {
325 InstBr() = delete; 322 InstBr() = delete;
326 InstBr(const InstBr &) = delete; 323 InstBr(const InstBr &) = delete;
327 InstBr &operator=(const InstBr &) = delete; 324 InstBr &operator=(const InstBr &) = delete;
328 325
329 public: 326 public:
330 /// Create a conditional branch. If TargetTrue==TargetFalse, it is 327 /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized
331 /// optimized to an unconditional branch. 328 /// to an unconditional branch.
332 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue, 329 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
333 CfgNode *TargetFalse) { 330 CfgNode *TargetFalse) {
334 return new (Func->allocate<InstBr>()) 331 return new (Func->allocate<InstBr>())
335 InstBr(Func, Source, TargetTrue, TargetFalse); 332 InstBr(Func, Source, TargetTrue, TargetFalse);
336 } 333 }
337 /// Create an unconditional branch. 334 /// Create an unconditional branch.
338 static InstBr *create(Cfg *Func, CfgNode *Target) { 335 static InstBr *create(Cfg *Func, CfgNode *Target) {
339 return new (Func->allocate<InstBr>()) InstBr(Func, Target); 336 return new (Func->allocate<InstBr>()) InstBr(Func, Target);
340 } 337 }
341 bool isUnconditional() const { return getTargetTrue() == nullptr; } 338 bool isUnconditional() const { return getTargetTrue() == nullptr; }
(...skipping 16 matching lines...) Expand all
358 private: 355 private:
359 /// Conditional branch 356 /// Conditional branch
360 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); 357 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
361 /// Unconditional branch 358 /// Unconditional branch
362 InstBr(Cfg *Func, CfgNode *Target); 359 InstBr(Cfg *Func, CfgNode *Target);
363 360
364 CfgNode *TargetFalse; /// Doubles as unconditional branch target 361 CfgNode *TargetFalse; /// Doubles as unconditional branch target
365 CfgNode *TargetTrue; /// nullptr if unconditional branch 362 CfgNode *TargetTrue; /// nullptr if unconditional branch
366 }; 363 };
367 364
368 /// Call instruction. The call target is captured as getSrc(0), and 365 /// Call instruction. The call target is captured as getSrc(0), and arg I is
369 /// arg I is captured as getSrc(I+1). 366 /// captured as getSrc(I+1).
370 class InstCall : public InstHighLevel { 367 class InstCall : public InstHighLevel {
371 InstCall() = delete; 368 InstCall() = delete;
372 InstCall(const InstCall &) = delete; 369 InstCall(const InstCall &) = delete;
373 InstCall &operator=(const InstCall &) = delete; 370 InstCall &operator=(const InstCall &) = delete;
374 371
375 public: 372 public:
376 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 373 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
377 Operand *CallTarget, bool HasTailCall) { 374 Operand *CallTarget, bool HasTailCall) {
378 /// Set HasSideEffects to true so that the call instruction can't be 375 /// Set HasSideEffects to true so that the call instruction can't be
379 /// dead-code eliminated. IntrinsicCalls can override this if the 376 /// dead-code eliminated. IntrinsicCalls can override this if the particular
380 /// particular intrinsic is deletable and has no side-effects. 377 /// intrinsic is deletable and has no side-effects.
381 const bool HasSideEffects = true; 378 const bool HasSideEffects = true;
382 const InstKind Kind = Inst::Call; 379 const InstKind Kind = Inst::Call;
383 return new (Func->allocate<InstCall>()) InstCall( 380 return new (Func->allocate<InstCall>()) InstCall(
384 Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind); 381 Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind);
385 } 382 }
386 void addArg(Operand *Arg) { addSource(Arg); } 383 void addArg(Operand *Arg) { addSource(Arg); }
387 Operand *getCallTarget() const { return getSrc(0); } 384 Operand *getCallTarget() const { return getSrc(0); }
388 Operand *getArg(SizeT I) const { return getSrc(I + 1); } 385 Operand *getArg(SizeT I) const { return getSrc(I + 1); }
389 SizeT getNumArgs() const { return getSrcSize() - 1; } 386 SizeT getNumArgs() const { return getSrcSize() - 1; }
390 bool isTailcall() const { return HasTailCall; } 387 bool isTailcall() const { return HasTailCall; }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 void dump(const Cfg *Func) const override; 448 void dump(const Cfg *Func) const override;
452 static bool classof(const Inst *Inst) { 449 static bool classof(const Inst *Inst) {
453 return Inst->getKind() == ExtractElement; 450 return Inst->getKind() == ExtractElement;
454 } 451 }
455 452
456 private: 453 private:
457 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, 454 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
458 Operand *Source2); 455 Operand *Source2);
459 }; 456 };
460 457
461 /// Floating-point comparison instruction. The source operands are 458 /// Floating-point comparison instruction. The source operands are captured in
462 /// captured in getSrc(0) and getSrc(1). 459 /// getSrc(0) and getSrc(1).
463 class InstFcmp : public InstHighLevel { 460 class InstFcmp : public InstHighLevel {
464 InstFcmp() = delete; 461 InstFcmp() = delete;
465 InstFcmp(const InstFcmp &) = delete; 462 InstFcmp(const InstFcmp &) = delete;
466 InstFcmp &operator=(const InstFcmp &) = delete; 463 InstFcmp &operator=(const InstFcmp &) = delete;
467 464
468 public: 465 public:
469 enum FCond { 466 enum FCond {
470 #define X(tag, str) tag, 467 #define X(tag, str) tag,
471 ICEINSTFCMP_TABLE 468 ICEINSTFCMP_TABLE
472 #undef X 469 #undef X
473 _num 470 _num
474 }; 471 };
475 472
476 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, 473 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
477 Operand *Source1, Operand *Source2) { 474 Operand *Source1, Operand *Source2) {
478 return new (Func->allocate<InstFcmp>()) 475 return new (Func->allocate<InstFcmp>())
479 InstFcmp(Func, Condition, Dest, Source1, Source2); 476 InstFcmp(Func, Condition, Dest, Source1, Source2);
480 } 477 }
481 FCond getCondition() const { return Condition; } 478 FCond getCondition() const { return Condition; }
482 void dump(const Cfg *Func) const override; 479 void dump(const Cfg *Func) const override;
483 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; } 480 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; }
484 481
485 private: 482 private:
486 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, 483 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
487 Operand *Source2); 484 Operand *Source2);
488 485
489 const FCond Condition; 486 const FCond Condition;
490 }; 487 };
491 488
492 /// Integer comparison instruction. The source operands are captured 489 /// Integer comparison instruction. The source operands are captured in
493 /// in getSrc(0) and getSrc(1). 490 /// getSrc(0) and getSrc(1).
494 class InstIcmp : public InstHighLevel { 491 class InstIcmp : public InstHighLevel {
495 InstIcmp() = delete; 492 InstIcmp() = delete;
496 InstIcmp(const InstIcmp &) = delete; 493 InstIcmp(const InstIcmp &) = delete;
497 InstIcmp &operator=(const InstIcmp &) = delete; 494 InstIcmp &operator=(const InstIcmp &) = delete;
498 495
499 public: 496 public:
500 enum ICond { 497 enum ICond {
501 #define X(tag, str) tag, 498 #define X(tag, str) tag,
502 ICEINSTICMP_TABLE 499 ICEINSTICMP_TABLE
503 #undef X 500 #undef X
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 void dump(const Cfg *Func) const override; 533 void dump(const Cfg *Func) const override;
537 static bool classof(const Inst *Inst) { 534 static bool classof(const Inst *Inst) {
538 return Inst->getKind() == InsertElement; 535 return Inst->getKind() == InsertElement;
539 } 536 }
540 537
541 private: 538 private:
542 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, 539 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
543 Operand *Source2, Operand *Source3); 540 Operand *Source2, Operand *Source3);
544 }; 541 };
545 542
546 /// Call to an intrinsic function. The call target is captured as getSrc(0), 543 /// Call to an intrinsic function. The call target is captured as getSrc(0), and
547 /// and arg I is captured as getSrc(I+1). 544 /// arg I is captured as getSrc(I+1).
548 class InstIntrinsicCall : public InstCall { 545 class InstIntrinsicCall : public InstCall {
549 InstIntrinsicCall() = delete; 546 InstIntrinsicCall() = delete;
550 InstIntrinsicCall(const InstIntrinsicCall &) = delete; 547 InstIntrinsicCall(const InstIntrinsicCall &) = delete;
551 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; 548 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
552 549
553 public: 550 public:
554 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 551 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
555 Operand *CallTarget, 552 Operand *CallTarget,
556 const Intrinsics::IntrinsicInfo &Info) { 553 const Intrinsics::IntrinsicInfo &Info) {
557 return new (Func->allocate<InstIntrinsicCall>()) 554 return new (Func->allocate<InstIntrinsicCall>())
558 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); 555 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
559 } 556 }
560 static bool classof(const Inst *Inst) { 557 static bool classof(const Inst *Inst) {
561 return Inst->getKind() == IntrinsicCall; 558 return Inst->getKind() == IntrinsicCall;
562 } 559 }
563 560
564 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } 561 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
565 562
566 private: 563 private:
567 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, 564 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
568 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) 565 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
569 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects, 566 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects,
570 Inst::IntrinsicCall), 567 Inst::IntrinsicCall),
571 Info(Info) {} 568 Info(Info) {}
572 569
573 const Intrinsics::IntrinsicInfo Info; 570 const Intrinsics::IntrinsicInfo Info;
574 }; 571 };
575 572
576 /// Load instruction. The source address is captured in getSrc(0). 573 /// Load instruction. The source address is captured in getSrc(0).
577 class InstLoad : public InstHighLevel { 574 class InstLoad : public InstHighLevel {
578 InstLoad() = delete; 575 InstLoad() = delete;
579 InstLoad(const InstLoad &) = delete; 576 InstLoad(const InstLoad &) = delete;
580 InstLoad &operator=(const InstLoad &) = delete; 577 InstLoad &operator=(const InstLoad &) = delete;
581 578
582 public: 579 public:
583 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, 580 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
584 uint32_t Align = 1) { 581 uint32_t Align = 1) {
585 // TODO(kschimpf) Stop ignoring alignment specification. 582 // TODO(kschimpf) Stop ignoring alignment specification.
586 (void)Align; 583 (void)Align;
587 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); 584 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
588 } 585 }
589 Operand *getSourceAddress() const { return getSrc(0); } 586 Operand *getSourceAddress() const { return getSrc(0); }
590 void dump(const Cfg *Func) const override; 587 void dump(const Cfg *Func) const override;
591 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; } 588 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; }
592 589
593 private: 590 private:
594 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); 591 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
595 }; 592 };
596 593
597 /// Phi instruction. For incoming edge I, the node is Labels[I] and 594 /// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi
598 /// the Phi source operand is getSrc(I). 595 /// source operand is getSrc(I).
599 class InstPhi : public InstHighLevel { 596 class InstPhi : public InstHighLevel {
600 InstPhi() = delete; 597 InstPhi() = delete;
601 InstPhi(const InstPhi &) = delete; 598 InstPhi(const InstPhi &) = delete;
602 InstPhi &operator=(const InstPhi &) = delete; 599 InstPhi &operator=(const InstPhi &) = delete;
603 600
604 public: 601 public:
605 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { 602 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
606 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); 603 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
607 } 604 }
608 void addArgument(Operand *Source, CfgNode *Label); 605 void addArgument(Operand *Source, CfgNode *Label);
609 Operand *getOperandForTarget(CfgNode *Target) const; 606 Operand *getOperandForTarget(CfgNode *Target) const;
610 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } 607 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
611 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, 608 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
612 Liveness *Liveness); 609 Liveness *Liveness);
613 Inst *lower(Cfg *Func); 610 Inst *lower(Cfg *Func);
614 void dump(const Cfg *Func) const override; 611 void dump(const Cfg *Func) const override;
615 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; } 612 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; }
616 613
617 private: 614 private:
618 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); 615 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
619 void destroy(Cfg *Func) override { 616 void destroy(Cfg *Func) override {
620 Func->deallocateArrayOf<CfgNode *>(Labels); 617 Func->deallocateArrayOf<CfgNode *>(Labels);
621 Inst::destroy(Func); 618 Inst::destroy(Func);
622 } 619 }
623 620
624 /// Labels[] duplicates the InEdges[] information in the enclosing 621 /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode,
625 /// CfgNode, but the Phi instruction is created before InEdges[] 622 /// but the Phi instruction is created before InEdges[] is available, so it's
626 /// is available, so it's more complicated to share the list. 623 /// more complicated to share the list.
627 CfgNode **Labels; 624 CfgNode **Labels;
628 }; 625 };
629 626
630 /// Ret instruction. The return value is captured in getSrc(0), but if 627 /// Ret instruction. The return value is captured in getSrc(0), but if there is
631 /// there is no return value (void-type function), then 628 /// no return value (void-type function), then getSrcSize()==0 and
632 /// getSrcSize()==0 and hasRetValue()==false. 629 /// hasRetValue()==false.
633 class InstRet : public InstHighLevel { 630 class InstRet : public InstHighLevel {
634 InstRet() = delete; 631 InstRet() = delete;
635 InstRet(const InstRet &) = delete; 632 InstRet(const InstRet &) = delete;
636 InstRet &operator=(const InstRet &) = delete; 633 InstRet &operator=(const InstRet &) = delete;
637 634
638 public: 635 public:
639 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) { 636 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
640 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); 637 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
641 } 638 }
642 bool hasRetValue() const { return getSrcSize(); } 639 bool hasRetValue() const { return getSrcSize(); }
(...skipping 25 matching lines...) Expand all
668 Operand *getTrueOperand() const { return getSrc(1); } 665 Operand *getTrueOperand() const { return getSrc(1); }
669 Operand *getFalseOperand() const { return getSrc(2); } 666 Operand *getFalseOperand() const { return getSrc(2); }
670 void dump(const Cfg *Func) const override; 667 void dump(const Cfg *Func) const override;
671 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; } 668 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; }
672 669
673 private: 670 private:
674 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, 671 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
675 Operand *Source2); 672 Operand *Source2);
676 }; 673 };
677 674
678 /// Store instruction. The address operand is captured, along with the 675 /// Store instruction. The address operand is captured, along with the data
679 /// data operand to be stored into the address. 676 /// operand to be stored into the address.
680 class InstStore : public InstHighLevel { 677 class InstStore : public InstHighLevel {
681 InstStore() = delete; 678 InstStore() = delete;
682 InstStore(const InstStore &) = delete; 679 InstStore(const InstStore &) = delete;
683 InstStore &operator=(const InstStore &) = delete; 680 InstStore &operator=(const InstStore &) = delete;
684 681
685 public: 682 public:
686 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, 683 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
687 uint32_t Align = 1) { 684 uint32_t Align = 1) {
688 // TODO(kschimpf) Stop ignoring alignment specification. 685 // TODO(kschimpf) Stop ignoring alignment specification.
689 (void)Align; 686 (void)Align;
690 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); 687 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
691 } 688 }
692 Operand *getAddr() const { return getSrc(1); } 689 Operand *getAddr() const { return getSrc(1); }
693 Operand *getData() const { return getSrc(0); } 690 Operand *getData() const { return getSrc(0); }
694 Variable *getRmwBeacon() const; 691 Variable *getRmwBeacon() const;
695 void setRmwBeacon(Variable *Beacon); 692 void setRmwBeacon(Variable *Beacon);
696 void dump(const Cfg *Func) const override; 693 void dump(const Cfg *Func) const override;
697 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; } 694 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; }
698 695
699 private: 696 private:
700 InstStore(Cfg *Func, Operand *Data, Operand *Addr); 697 InstStore(Cfg *Func, Operand *Data, Operand *Addr);
701 }; 698 };
702 699
703 /// Switch instruction. The single source operand is captured as 700 /// Switch instruction. The single source operand is captured as getSrc(0).
704 /// getSrc(0).
705 class InstSwitch : public InstHighLevel { 701 class InstSwitch : public InstHighLevel {
706 InstSwitch() = delete; 702 InstSwitch() = delete;
707 InstSwitch(const InstSwitch &) = delete; 703 InstSwitch(const InstSwitch &) = delete;
708 InstSwitch &operator=(const InstSwitch &) = delete; 704 InstSwitch &operator=(const InstSwitch &) = delete;
709 705
710 public: 706 public:
711 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source, 707 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
712 CfgNode *LabelDefault) { 708 CfgNode *LabelDefault) {
713 return new (Func->allocate<InstSwitch>()) 709 return new (Func->allocate<InstSwitch>())
714 InstSwitch(Func, NumCases, Source, LabelDefault); 710 InstSwitch(Func, NumCases, Source, LabelDefault);
(...skipping 22 matching lines...) Expand all
737 Func->deallocateArrayOf<CfgNode *>(Labels); 733 Func->deallocateArrayOf<CfgNode *>(Labels);
738 Inst::destroy(Func); 734 Inst::destroy(Func);
739 } 735 }
740 736
741 CfgNode *LabelDefault; 737 CfgNode *LabelDefault;
742 SizeT NumCases; /// not including the default case 738 SizeT NumCases; /// not including the default case
743 uint64_t *Values; /// size is NumCases 739 uint64_t *Values; /// size is NumCases
744 CfgNode **Labels; /// size is NumCases 740 CfgNode **Labels; /// size is NumCases
745 }; 741 };
746 742
747 /// Unreachable instruction. This is a terminator instruction with no 743 /// Unreachable instruction. This is a terminator instruction with no operands.
748 /// operands.
749 class InstUnreachable : public InstHighLevel { 744 class InstUnreachable : public InstHighLevel {
750 InstUnreachable() = delete; 745 InstUnreachable() = delete;
751 InstUnreachable(const InstUnreachable &) = delete; 746 InstUnreachable(const InstUnreachable &) = delete;
752 InstUnreachable &operator=(const InstUnreachable &) = delete; 747 InstUnreachable &operator=(const InstUnreachable &) = delete;
753 748
754 public: 749 public:
755 static InstUnreachable *create(Cfg *Func) { 750 static InstUnreachable *create(Cfg *Func) {
756 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); 751 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
757 } 752 }
758 NodeList getTerminatorEdges() const override { return NodeList(); } 753 NodeList getTerminatorEdges() const override { return NodeList(); }
759 void dump(const Cfg *Func) const override; 754 void dump(const Cfg *Func) const override;
760 static bool classof(const Inst *Inst) { 755 static bool classof(const Inst *Inst) {
761 return Inst->getKind() == Unreachable; 756 return Inst->getKind() == Unreachable;
762 } 757 }
763 758
764 private: 759 private:
765 explicit InstUnreachable(Cfg *Func); 760 explicit InstUnreachable(Cfg *Func);
766 }; 761 };
767 762
768 /// BundleLock instruction. There are no operands. Contains an option 763 /// BundleLock instruction. There are no operands. Contains an option
769 /// indicating whether align_to_end is specified. 764 /// indicating whether align_to_end is specified.
770 class InstBundleLock : public InstHighLevel { 765 class InstBundleLock : public InstHighLevel {
771 InstBundleLock() = delete; 766 InstBundleLock() = delete;
772 InstBundleLock(const InstBundleLock &) = delete; 767 InstBundleLock(const InstBundleLock &) = delete;
773 InstBundleLock &operator=(const InstBundleLock &) = delete; 768 InstBundleLock &operator=(const InstBundleLock &) = delete;
774 769
775 public: 770 public:
776 enum Option { Opt_None, Opt_AlignToEnd }; 771 enum Option { Opt_None, Opt_AlignToEnd };
777 static InstBundleLock *create(Cfg *Func, Option BundleOption) { 772 static InstBundleLock *create(Cfg *Func, Option BundleOption) {
778 return new (Func->allocate<InstBundleLock>()) 773 return new (Func->allocate<InstBundleLock>())
779 InstBundleLock(Func, BundleOption); 774 InstBundleLock(Func, BundleOption);
780 } 775 }
781 void emit(const Cfg *Func) const override; 776 void emit(const Cfg *Func) const override;
782 void emitIAS(const Cfg * /* Func */) const override {} 777 void emitIAS(const Cfg * /* Func */) const override {}
783 void dump(const Cfg *Func) const override; 778 void dump(const Cfg *Func) const override;
784 Option getOption() const { return BundleOption; } 779 Option getOption() const { return BundleOption; }
785 static bool classof(const Inst *Inst) { 780 static bool classof(const Inst *Inst) {
786 return Inst->getKind() == BundleLock; 781 return Inst->getKind() == BundleLock;
787 } 782 }
788 783
789 private: 784 private:
790 Option BundleOption; 785 Option BundleOption;
791 InstBundleLock(Cfg *Func, Option BundleOption); 786 InstBundleLock(Cfg *Func, Option BundleOption);
792 }; 787 };
793 788
794 /// BundleUnlock instruction. There are no operands. 789 /// BundleUnlock instruction. There are no operands.
795 class InstBundleUnlock : public InstHighLevel { 790 class InstBundleUnlock : public InstHighLevel {
796 InstBundleUnlock() = delete; 791 InstBundleUnlock() = delete;
797 InstBundleUnlock(const InstBundleUnlock &) = delete; 792 InstBundleUnlock(const InstBundleUnlock &) = delete;
798 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete; 793 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
799 794
800 public: 795 public:
801 static InstBundleUnlock *create(Cfg *Func) { 796 static InstBundleUnlock *create(Cfg *Func) {
802 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func); 797 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
803 } 798 }
804 void emit(const Cfg *Func) const override; 799 void emit(const Cfg *Func) const override;
805 void emitIAS(const Cfg * /* Func */) const override {} 800 void emitIAS(const Cfg * /* Func */) const override {}
806 void dump(const Cfg *Func) const override; 801 void dump(const Cfg *Func) const override;
807 static bool classof(const Inst *Inst) { 802 static bool classof(const Inst *Inst) {
808 return Inst->getKind() == BundleUnlock; 803 return Inst->getKind() == BundleUnlock;
809 } 804 }
810 805
811 private: 806 private:
812 explicit InstBundleUnlock(Cfg *Func); 807 explicit InstBundleUnlock(Cfg *Func);
813 }; 808 };
814 809
815 /// FakeDef instruction. This creates a fake definition of a variable, 810 /// FakeDef instruction. This creates a fake definition of a variable, which is
816 /// which is how we represent the case when an instruction produces 811 /// how we represent the case when an instruction produces multiple results.
817 /// multiple results. This doesn't happen with high-level ICE 812 /// This doesn't happen with high-level ICE instructions, but might with lowered
818 /// instructions, but might with lowered instructions. For example, 813 /// instructions. For example, this would be a way to represent condition flags
819 /// this would be a way to represent condition flags being modified by 814 /// being modified by an instruction.
820 /// an instruction.
821 /// 815 ///
822 /// It's generally useful to set the optional source operand to be the 816 /// It's generally useful to set the optional source operand to be the dest
823 /// dest variable of the instruction that actually produces the FakeDef 817 /// variable of the instruction that actually produces the FakeDef dest.
824 /// dest. Otherwise, the original instruction could be dead-code 818 /// Otherwise, the original instruction could be dead-code eliminated if its
825 /// eliminated if its dest operand is unused, and therefore the FakeDef 819 /// dest operand is unused, and therefore the FakeDef dest wouldn't be properly
826 /// dest wouldn't be properly initialized. 820 /// initialized.
827 class InstFakeDef : public InstHighLevel { 821 class InstFakeDef : public InstHighLevel {
828 InstFakeDef() = delete; 822 InstFakeDef() = delete;
829 InstFakeDef(const InstFakeDef &) = delete; 823 InstFakeDef(const InstFakeDef &) = delete;
830 InstFakeDef &operator=(const InstFakeDef &) = delete; 824 InstFakeDef &operator=(const InstFakeDef &) = delete;
831 825
832 public: 826 public:
833 static InstFakeDef *create(Cfg *Func, Variable *Dest, 827 static InstFakeDef *create(Cfg *Func, Variable *Dest,
834 Variable *Src = nullptr) { 828 Variable *Src = nullptr) {
835 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); 829 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
836 } 830 }
837 void emit(const Cfg *Func) const override; 831 void emit(const Cfg *Func) const override;
838 void emitIAS(const Cfg * /* Func */) const override {} 832 void emitIAS(const Cfg * /* Func */) const override {}
839 void dump(const Cfg *Func) const override; 833 void dump(const Cfg *Func) const override;
840 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; } 834 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; }
841 835
842 private: 836 private:
843 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); 837 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
844 }; 838 };
845 839
846 /// FakeUse instruction. This creates a fake use of a variable, to 840 /// FakeUse instruction. This creates a fake use of a variable, to keep the
847 /// keep the instruction that produces that variable from being 841 /// instruction that produces that variable from being dead-code eliminated.
848 /// dead-code eliminated. This is useful in a variety of lowering 842 /// This is useful in a variety of lowering situations. The FakeUse instruction
849 /// situations. The FakeUse instruction has no dest, so it can itself 843 /// has no dest, so it can itself never be dead-code eliminated.
850 /// never be dead-code eliminated.
851 class InstFakeUse : public InstHighLevel { 844 class InstFakeUse : public InstHighLevel {
852 InstFakeUse() = delete; 845 InstFakeUse() = delete;
853 InstFakeUse(const InstFakeUse &) = delete; 846 InstFakeUse(const InstFakeUse &) = delete;
854 InstFakeUse &operator=(const InstFakeUse &) = delete; 847 InstFakeUse &operator=(const InstFakeUse &) = delete;
855 848
856 public: 849 public:
857 static InstFakeUse *create(Cfg *Func, Variable *Src) { 850 static InstFakeUse *create(Cfg *Func, Variable *Src) {
858 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src); 851 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src);
859 } 852 }
860 void emit(const Cfg *Func) const override; 853 void emit(const Cfg *Func) const override;
861 void emitIAS(const Cfg * /* Func */) const override {} 854 void emitIAS(const Cfg * /* Func */) const override {}
862 void dump(const Cfg *Func) const override; 855 void dump(const Cfg *Func) const override;
863 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; } 856 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; }
864 857
865 private: 858 private:
866 InstFakeUse(Cfg *Func, Variable *Src); 859 InstFakeUse(Cfg *Func, Variable *Src);
867 }; 860 };
868 861
869 /// FakeKill instruction. This "kills" a set of variables by modeling 862 /// FakeKill instruction. This "kills" a set of variables by modeling a trivial
870 /// a trivial live range at this instruction for each (implicit) 863 /// live range at this instruction for each (implicit) variable. The primary use
871 /// variable. The primary use is to indicate that scratch registers 864 /// is to indicate that scratch registers are killed after a call, so that the
872 /// are killed after a call, so that the register allocator won't 865 /// register allocator won't assign a scratch register to a variable whose live
873 /// assign a scratch register to a variable whose live range spans a 866 /// range spans a call.
874 /// call.
875 /// 867 ///
876 /// The FakeKill instruction also holds a pointer to the instruction 868 /// The FakeKill instruction also holds a pointer to the instruction that kills
877 /// that kills the set of variables, so that if that linked instruction 869 /// the set of variables, so that if that linked instruction gets dead-code
878 /// gets dead-code eliminated, the FakeKill instruction will as well. 870 /// eliminated, the FakeKill instruction will as well.
879 class InstFakeKill : public InstHighLevel { 871 class InstFakeKill : public InstHighLevel {
880 InstFakeKill() = delete; 872 InstFakeKill() = delete;
881 InstFakeKill(const InstFakeKill &) = delete; 873 InstFakeKill(const InstFakeKill &) = delete;
882 InstFakeKill &operator=(const InstFakeKill &) = delete; 874 InstFakeKill &operator=(const InstFakeKill &) = delete;
883 875
884 public: 876 public:
885 static InstFakeKill *create(Cfg *Func, const Inst *Linked) { 877 static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
886 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); 878 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
887 } 879 }
888 const Inst *getLinked() const { return Linked; } 880 const Inst *getLinked() const { return Linked; }
889 void emit(const Cfg *Func) const override; 881 void emit(const Cfg *Func) const override;
890 void emitIAS(const Cfg * /* Func */) const override {} 882 void emitIAS(const Cfg * /* Func */) const override {}
891 void dump(const Cfg *Func) const override; 883 void dump(const Cfg *Func) const override;
892 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; } 884 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; }
893 885
894 private: 886 private:
895 InstFakeKill(Cfg *Func, const Inst *Linked); 887 InstFakeKill(Cfg *Func, const Inst *Linked);
896 888
897 /// This instruction is ignored if Linked->isDeleted() is true. 889 /// This instruction is ignored if Linked->isDeleted() is true.
898 const Inst *Linked; 890 const Inst *Linked;
899 }; 891 };
900 892
901 /// JumpTable instruction. This represents a jump table that will be 893 /// JumpTable instruction. This represents a jump table that will be stored in
902 /// stored in the .rodata section. This is used to track and repoint 894 /// the .rodata section. This is used to track and repoint the target CfgNodes
903 /// the target CfgNodes which may change, for example due to 895 /// which may change, for example due to splitting for phi lowering.
904 /// splitting for phi lowering.
905 class InstJumpTable : public InstHighLevel { 896 class InstJumpTable : public InstHighLevel {
906 InstJumpTable() = delete; 897 InstJumpTable() = delete;
907 InstJumpTable(const InstJumpTable &) = delete; 898 InstJumpTable(const InstJumpTable &) = delete;
908 InstJumpTable &operator=(const InstJumpTable &) = delete; 899 InstJumpTable &operator=(const InstJumpTable &) = delete;
909 900
910 public: 901 public:
911 static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) { 902 static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) {
912 return new (Func->allocate<InstJumpTable>()) 903 return new (Func->allocate<InstJumpTable>())
913 InstJumpTable(Func, NumTargets, Default); 904 InstJumpTable(Func, NumTargets, Default);
914 } 905 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
961 assert(Kind <= Target_Max); 952 assert(Kind <= Target_Max);
962 } 953 }
963 }; 954 };
964 955
965 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source); 956 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
966 957
967 } // end of namespace Ice 958 } // end of namespace Ice
968 959
969 namespace llvm { 960 namespace llvm {
970 961
971 /// Override the default ilist traits so that Inst's private ctor and 962 /// Override the default ilist traits so that Inst's private ctor and deleted
972 /// deleted dtor aren't invoked. 963 /// dtor aren't invoked.
973 template <> 964 template <>
974 struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> { 965 struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
975 Ice::Inst *createSentinel() const { 966 Ice::Inst *createSentinel() const {
976 return static_cast<Ice::Inst *>(&Sentinel); 967 return static_cast<Ice::Inst *>(&Sentinel);
977 } 968 }
978 static void destroySentinel(Ice::Inst *) {} 969 static void destroySentinel(Ice::Inst *) {}
979 Ice::Inst *provideInitialHead() const { return createSentinel(); } 970 Ice::Inst *provideInitialHead() const { return createSentinel(); }
980 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); } 971 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
981 static void noteHead(Ice::Inst *, Ice::Inst *) {} 972 static void noteHead(Ice::Inst *, Ice::Inst *) {}
982 void deleteNode(Ice::Inst *) {} 973 void deleteNode(Ice::Inst *) {}
983 974
984 private: 975 private:
985 mutable ilist_half_node<Ice::Inst> Sentinel; 976 mutable ilist_half_node<Ice::Inst> Sentinel;
986 }; 977 };
987 978
988 } // end of namespace llvm 979 } // end of namespace llvm
989 980
990 #endif // SUBZERO_SRC_ICEINST_H 981 #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