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

Side by Side Diff: src/IceOperand.h

Issue 300563003: Subzero: Initial O2 lowering (Closed) Base URL: https://gerrit.chromium.org/gerrit/p/native_client/pnacl-subzero.git@master
Patch Set: Created 6 years, 6 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/IceOperand.h - High-level operands -----------*- C++ -*-===// 1 //===- subzero/src/IceOperand.h - High-level operands -----------*- 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 Operand class and its target-independent 10 // This file declares the Operand class and its target-independent
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 private: 74 private:
75 Operand(const Operand &) LLVM_DELETED_FUNCTION; 75 Operand(const Operand &) LLVM_DELETED_FUNCTION;
76 Operand &operator=(const Operand &) LLVM_DELETED_FUNCTION; 76 Operand &operator=(const Operand &) LLVM_DELETED_FUNCTION;
77 }; 77 };
78 78
79 // Constant is the abstract base class for constants. All 79 // Constant is the abstract base class for constants. All
80 // constants are allocated from a global arena and are pooled. 80 // constants are allocated from a global arena and are pooled.
81 class Constant : public Operand { 81 class Constant : public Operand {
82 public: 82 public:
83 uint32_t getPoolEntryID() const { return PoolEntryID; } 83 uint32_t getPoolEntryID() const { return PoolEntryID; }
84 virtual void emit(const Cfg *Func) const = 0; 84 virtual void emit(const Cfg *Func) const { emit(Func->getContext()); }
85 virtual void dump(const Cfg *Func) const = 0; 85 virtual void dump(const Cfg *Func) const { dump(Func->getContext()); }
86 virtual void emit(GlobalContext *Ctx) const = 0;
87 virtual void dump(GlobalContext *Ctx) const = 0;
86 88
87 static bool classof(const Operand *Operand) { 89 static bool classof(const Operand *Operand) {
88 OperandKind Kind = Operand->getKind(); 90 OperandKind Kind = Operand->getKind();
89 return Kind >= kConst_Base && Kind <= kConst_Num; 91 return Kind >= kConst_Base && Kind <= kConst_Num;
90 } 92 }
91 93
92 protected: 94 protected:
93 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID) 95 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID)
94 : Operand(Kind, Ty), PoolEntryID(PoolEntryID) { 96 : Operand(Kind, Ty), PoolEntryID(PoolEntryID) {
95 Vars = NULL; 97 Vars = NULL;
(...skipping 13 matching lines...) Expand all
109 // ConstantPrimitive<> wraps a primitive type. 111 // ConstantPrimitive<> wraps a primitive type.
110 template <typename T, Operand::OperandKind K> 112 template <typename T, Operand::OperandKind K>
111 class ConstantPrimitive : public Constant { 113 class ConstantPrimitive : public Constant {
112 public: 114 public:
113 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, T Value, 115 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, T Value,
114 uint32_t PoolEntryID) { 116 uint32_t PoolEntryID) {
115 return new (Ctx->allocate<ConstantPrimitive>()) 117 return new (Ctx->allocate<ConstantPrimitive>())
116 ConstantPrimitive(Ty, Value, PoolEntryID); 118 ConstantPrimitive(Ty, Value, PoolEntryID);
117 } 119 }
118 T getValue() const { return Value; } 120 T getValue() const { return Value; }
119 virtual void emit(const Cfg *Func) const { 121 using Constant::emit;
120 Ostream &Str = Func->getContext()->getStrEmit(); 122 virtual void emit(GlobalContext *Ctx) const {
123 Ostream &Str = Ctx->getStrEmit();
121 Str << getValue(); 124 Str << getValue();
122 } 125 }
123 virtual void dump(const Cfg *Func) const { 126 using Constant::dump;
124 Ostream &Str = Func->getContext()->getStrDump(); 127 virtual void dump(GlobalContext *Ctx) const {
128 Ostream &Str = Ctx->getStrDump();
125 Str << getValue(); 129 Str << getValue();
126 } 130 }
127 131
128 static bool classof(const Operand *Operand) { 132 static bool classof(const Operand *Operand) {
129 return Operand->getKind() == K; 133 return Operand->getKind() == K;
130 } 134 }
131 135
132 private: 136 private:
133 ConstantPrimitive(Type Ty, T Value, uint32_t PoolEntryID) 137 ConstantPrimitive(Type Ty, T Value, uint32_t PoolEntryID)
134 : Constant(K, Ty, PoolEntryID), Value(Value) {} 138 : Constant(K, Ty, PoolEntryID), Value(Value) {}
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty, 175 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty,
172 const RelocatableTuple &Tuple, 176 const RelocatableTuple &Tuple,
173 uint32_t PoolEntryID) { 177 uint32_t PoolEntryID) {
174 return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable( 178 return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable(
175 Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID); 179 Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID);
176 } 180 }
177 int64_t getOffset() const { return Offset; } 181 int64_t getOffset() const { return Offset; }
178 IceString getName() const { return Name; } 182 IceString getName() const { return Name; }
179 void setSuppressMangling(bool Value) { SuppressMangling = Value; } 183 void setSuppressMangling(bool Value) { SuppressMangling = Value; }
180 bool getSuppressMangling() const { return SuppressMangling; } 184 bool getSuppressMangling() const { return SuppressMangling; }
181 virtual void emit(const Cfg *Func) const; 185 using Constant::emit;
182 virtual void dump(const Cfg *Func) const; 186 using Constant::dump;
187 virtual void emit(GlobalContext *Ctx) const;
188 virtual void dump(GlobalContext *Ctx) const;
183 189
184 static bool classof(const Operand *Operand) { 190 static bool classof(const Operand *Operand) {
185 OperandKind Kind = Operand->getKind(); 191 OperandKind Kind = Operand->getKind();
186 return Kind == kConstRelocatable; 192 return Kind == kConstRelocatable;
187 } 193 }
188 194
189 private: 195 private:
190 ConstantRelocatable(Type Ty, int64_t Offset, const IceString &Name, 196 ConstantRelocatable(Type Ty, int64_t Offset, const IceString &Name,
191 bool SuppressMangling, uint32_t PoolEntryID) 197 bool SuppressMangling, uint32_t PoolEntryID)
192 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset), 198 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset),
(...skipping 28 matching lines...) Expand all
221 bool isInf() const { return Weight == Inf; } 227 bool isInf() const { return Weight == Inf; }
222 228
223 private: 229 private:
224 uint32_t Weight; 230 uint32_t Weight;
225 }; 231 };
226 Ostream &operator<<(Ostream &Str, const RegWeight &W); 232 Ostream &operator<<(Ostream &Str, const RegWeight &W);
227 bool operator<(const RegWeight &A, const RegWeight &B); 233 bool operator<(const RegWeight &A, const RegWeight &B);
228 bool operator<=(const RegWeight &A, const RegWeight &B); 234 bool operator<=(const RegWeight &A, const RegWeight &B);
229 bool operator==(const RegWeight &A, const RegWeight &B); 235 bool operator==(const RegWeight &A, const RegWeight &B);
230 236
237 // LiveRange is a set of instruction number intervals representing
238 // a variable's live range. Generally there is one interval per basic
239 // block where the variable is live, but adjacent intervals get
240 // coalesced into a single interval. LiveRange also includes a
241 // weight, in case e.g. we want a live range to have higher weight
242 // inside a loop.
243 class LiveRange {
244 public:
245 LiveRange() : Weight(0) {}
246
247 void reset() {
248 Range.clear();
249 Weight.setWeight(0);
250 }
251 void addSegment(int32_t Start, int32_t End);
252
253 bool endsBefore(const LiveRange &Other) const;
254 bool overlaps(const LiveRange &Other) const;
255 bool containsValue(int32_t Value) const;
256 bool isEmpty() const { return Range.empty(); }
257 int32_t getStart() const { return Range.empty() ? -1 : Range.begin()->first; }
258
259 RegWeight getWeight() const { return Weight; }
260 void setWeight(const RegWeight &NewWeight) { Weight = NewWeight; }
261 void addWeight(uint32_t Delta) { Weight.addWeight(Delta); }
262 void dump(Ostream &Str) const;
263
264 // Defining USE_SET uses std::set to hold the segments instead of
265 // std::list. Using std::list will be slightly faster, but is more
266 // restrictive because new segments cannot be added in the middle.
267
268 //#define USE_SET
269
270 private:
271 typedef std::pair<int32_t, int32_t> RangeElementType;
272 #ifdef USE_SET
273 typedef std::set<RangeElementType> RangeType;
274 #else
275 typedef std::list<RangeElementType> RangeType;
276 #endif
277 RangeType Range;
278 RegWeight Weight;
279 };
280
281 Ostream &operator<<(Ostream &Str, const LiveRange &L);
282
231 // Variable represents an operand that is register-allocated or 283 // Variable represents an operand that is register-allocated or
232 // stack-allocated. If it is register-allocated, it will ultimately 284 // stack-allocated. If it is register-allocated, it will ultimately
233 // have a non-negative RegNum field. 285 // have a non-negative RegNum field.
234 class Variable : public Operand { 286 class Variable : public Operand {
235 public: 287 public:
236 static Variable *create(Cfg *Func, Type Ty, const CfgNode *Node, SizeT Index, 288 static Variable *create(Cfg *Func, Type Ty, const CfgNode *Node, SizeT Index,
237 const IceString &Name) { 289 const IceString &Name) {
238 return new (Func->allocate<Variable>()) Variable(Ty, Node, Index, Name); 290 return new (Func->allocate<Variable>()) Variable(Ty, Node, Index, Name);
239 } 291 }
240 292
(...skipping 15 matching lines...) Expand all
256 void setStackOffset(int32_t Offset) { StackOffset = Offset; } 308 void setStackOffset(int32_t Offset) { StackOffset = Offset; }
257 309
258 static const int32_t NoRegister = -1; 310 static const int32_t NoRegister = -1;
259 bool hasReg() const { return getRegNum() != NoRegister; } 311 bool hasReg() const { return getRegNum() != NoRegister; }
260 int32_t getRegNum() const { return RegNum; } 312 int32_t getRegNum() const { return RegNum; }
261 void setRegNum(int32_t NewRegNum) { 313 void setRegNum(int32_t NewRegNum) {
262 // Regnum shouldn't be set more than once. 314 // Regnum shouldn't be set more than once.
263 assert(!hasReg() || RegNum == NewRegNum); 315 assert(!hasReg() || RegNum == NewRegNum);
264 RegNum = NewRegNum; 316 RegNum = NewRegNum;
265 } 317 }
318 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; }
319 int32_t getRegNumTmp() const { return RegNumTmp; }
320 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; }
266 321
267 RegWeight getWeight() const { return Weight; } 322 RegWeight getWeight() const { return Weight; }
268 void setWeight(uint32_t NewWeight) { Weight = NewWeight; } 323 void setWeight(uint32_t NewWeight) { Weight = NewWeight; }
269 void setWeightInfinite() { Weight = RegWeight::Inf; } 324 void setWeightInfinite() { Weight = RegWeight::Inf; }
270 325
271 Variable *getPreferredRegister() const { return RegisterPreference; } 326 Variable *getPreferredRegister() const { return RegisterPreference; }
272 bool getRegisterOverlap() const { return AllowRegisterOverlap; } 327 bool getRegisterOverlap() const { return AllowRegisterOverlap; }
273 void setPreferredRegister(Variable *Prefer, bool Overlap) { 328 void setPreferredRegister(Variable *Prefer, bool Overlap) {
274 RegisterPreference = Prefer; 329 RegisterPreference = Prefer;
275 AllowRegisterOverlap = Overlap; 330 AllowRegisterOverlap = Overlap;
276 } 331 }
277 332
333 const LiveRange &getLiveRange() const { return Live; }
334 void setLiveRange(const LiveRange &Range) { Live = Range; }
335 void resetLiveRange() { Live.reset(); }
336 void addLiveRange(int32_t Start, int32_t End, uint32_t WeightDelta) {
337 assert(WeightDelta != RegWeight::Inf);
338 Live.addSegment(Start, End);
339 if (Weight.isInf())
340 Live.setWeight(RegWeight::Inf);
341 else
342 Live.addWeight(WeightDelta * Weight.getWeight());
343 }
344 void setLiveRangeInfiniteWeight() { Live.setWeight(RegWeight::Inf); }
345
278 Variable *getLo() const { return LoVar; } 346 Variable *getLo() const { return LoVar; }
279 Variable *getHi() const { return HiVar; } 347 Variable *getHi() const { return HiVar; }
280 void setLoHi(Variable *Lo, Variable *Hi) { 348 void setLoHi(Variable *Lo, Variable *Hi) {
281 assert(LoVar == NULL); 349 assert(LoVar == NULL);
282 assert(HiVar == NULL); 350 assert(HiVar == NULL);
283 LoVar = Lo; 351 LoVar = Lo;
284 HiVar = Hi; 352 HiVar = Hi;
285 } 353 }
286 // Creates a temporary copy of the variable with a different type. 354 // Creates a temporary copy of the variable with a different type.
287 // Used primarily for syntactic correctness of textual assembly 355 // Used primarily for syntactic correctness of textual assembly
288 // emission. Note that only basic information is copied, in 356 // emission. Note that only basic information is copied, in
289 // particular not DefInst, IsArgument, Weight, RegisterPreference, 357 // particular not DefInst, IsArgument, Weight, RegisterPreference,
290 // AllowRegisterOverlap, LoVar, HiVar, VarsReal. 358 // AllowRegisterOverlap, LoVar, HiVar, VarsReal.
291 Variable asType(Type Ty); 359 Variable asType(Type Ty);
292 360
293 virtual void emit(const Cfg *Func) const; 361 virtual void emit(const Cfg *Func) const;
294 virtual void dump(const Cfg *Func) const; 362 virtual void dump(const Cfg *Func) const;
295 363
296 static bool classof(const Operand *Operand) { 364 static bool classof(const Operand *Operand) {
297 return Operand->getKind() == kVariable; 365 return Operand->getKind() == kVariable;
298 } 366 }
299 367
300 // The destructor is public because of the asType() method. 368 // The destructor is public because of the asType() method.
301 virtual ~Variable() {} 369 virtual ~Variable() {}
302 370
303 private: 371 private:
304 Variable(Type Ty, const CfgNode *Node, SizeT Index, const IceString &Name) 372 Variable(Type Ty, const CfgNode *Node, SizeT Index, const IceString &Name)
305 : Operand(kVariable, Ty), Number(Index), Name(Name), DefInst(NULL), 373 : Operand(kVariable, Ty), Number(Index), Name(Name), DefInst(NULL),
306 DefNode(Node), IsArgument(false), StackOffset(0), RegNum(NoRegister), 374 DefNode(Node), IsArgument(false), StackOffset(0), RegNum(NoRegister),
307 Weight(1), RegisterPreference(NULL), AllowRegisterOverlap(false), 375 RegNumTmp(NoRegister), Weight(1), RegisterPreference(NULL),
308 LoVar(NULL), HiVar(NULL) { 376 AllowRegisterOverlap(false), LoVar(NULL), HiVar(NULL) {
309 Vars = VarsReal; 377 Vars = VarsReal;
310 Vars[0] = this; 378 Vars[0] = this;
311 NumVars = 1; 379 NumVars = 1;
312 } 380 }
313 Variable(const Variable &) LLVM_DELETED_FUNCTION; 381 Variable(const Variable &) LLVM_DELETED_FUNCTION;
314 Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION; 382 Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION;
315 // Number is unique across all variables, and is used as a 383 // Number is unique across all variables, and is used as a
316 // (bit)vector index for liveness analysis. 384 // (bit)vector index for liveness analysis.
317 const SizeT Number; 385 const SizeT Number;
318 // Name is optional. 386 // Name is optional.
319 const IceString Name; 387 const IceString Name;
320 // DefInst is the instruction that produces this variable as its 388 // DefInst is the instruction that produces this variable as its
321 // dest. 389 // dest.
322 Inst *DefInst; 390 Inst *DefInst;
323 // DefNode is the node where this variable was produced, and is 391 // DefNode is the node where this variable was produced, and is
324 // reset to NULL if it is used outside that node. This is used for 392 // reset to NULL if it is used outside that node. This is used for
325 // detecting isMultiblockLife(). TODO: Collapse this to a single 393 // detecting isMultiblockLife(). TODO: Collapse this to a single
326 // bit and use a separate pass to calculate the values across the 394 // bit and use a separate pass to calculate the values across the
327 // Cfg. This saves space in the Variable, and removes the fragility 395 // Cfg. This saves space in the Variable, and removes the fragility
328 // of incrementally computing and maintaining the information. 396 // of incrementally computing and maintaining the information.
329 const CfgNode *DefNode; 397 const CfgNode *DefNode;
330 bool IsArgument; 398 bool IsArgument;
331 // StackOffset is the canonical location on stack (only if 399 // StackOffset is the canonical location on stack (only if
332 // RegNum<0 || IsArgument). 400 // RegNum<0 || IsArgument).
333 int32_t StackOffset; 401 int32_t StackOffset;
334 // RegNum is the allocated register, or NoRegister if it isn't 402 // RegNum is the allocated register, or NoRegister if it isn't
335 // register-allocated. 403 // register-allocated.
336 int32_t RegNum; 404 int32_t RegNum;
405 // RegNumTmp is the tentative assignment during register allocation.
406 int32_t RegNumTmp;
337 RegWeight Weight; // Register allocation priority 407 RegWeight Weight; // Register allocation priority
338 // RegisterPreference says that if possible, the register allocator 408 // RegisterPreference says that if possible, the register allocator
339 // should prefer the register that was assigned to this linked 409 // should prefer the register that was assigned to this linked
340 // variable. It also allows a spill slot to share its stack 410 // variable. It also allows a spill slot to share its stack
341 // location with another variable, if that variable does not get 411 // location with another variable, if that variable does not get
342 // register-allocated and therefore has a stack location. 412 // register-allocated and therefore has a stack location.
343 Variable *RegisterPreference; 413 Variable *RegisterPreference;
344 // AllowRegisterOverlap says that it is OK to honor 414 // AllowRegisterOverlap says that it is OK to honor
345 // RegisterPreference and "share" a register even if the two live 415 // RegisterPreference and "share" a register even if the two live
346 // ranges overlap. 416 // ranges overlap.
347 bool AllowRegisterOverlap; 417 bool AllowRegisterOverlap;
418 LiveRange Live;
348 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When 419 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When
349 // lowering from I64 to I32 on a 32-bit architecture, we split the 420 // lowering from I64 to I32 on a 32-bit architecture, we split the
350 // variable into two machine-size pieces. LoVar is the low-order 421 // variable into two machine-size pieces. LoVar is the low-order
351 // machine-size portion, and HiVar is the remaining high-order 422 // machine-size portion, and HiVar is the remaining high-order
352 // portion. TODO: It's wasteful to penalize all variables on all 423 // portion. TODO: It's wasteful to penalize all variables on all
353 // targets this way; use a sparser representation. It's also 424 // targets this way; use a sparser representation. It's also
354 // wasteful for a 64-bit target. 425 // wasteful for a 64-bit target.
355 Variable *LoVar; 426 Variable *LoVar;
356 Variable *HiVar; 427 Variable *HiVar;
357 // VarsReal (and Operand::Vars) are set up such that Vars[0] == 428 // VarsReal (and Operand::Vars) are set up such that Vars[0] ==
358 // this. 429 // this.
359 Variable *VarsReal[1]; 430 Variable *VarsReal[1];
360 }; 431 };
361 432
362 } // end of namespace Ice 433 } // end of namespace Ice
363 434
364 #endif // SUBZERO_SRC_ICEOPERAND_H 435 #endif // SUBZERO_SRC_ICEOPERAND_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698