blob: 36aafe23249f3a198b52b3e903fb4f3f36b151da [file] [log] [blame]
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001//===- subzero/src/IceOperand.h - High-level operands -----------*- C++ -*-===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file declares the Operand class and its target-independent
11// subclasses. The main classes are Variable, which represents an
12// LLVM variable that is either register- or stack-allocated, and the
13// Constant hierarchy, which represents integer, floating-point,
14// and/or symbolic constants.
15//
16//===----------------------------------------------------------------------===//
17
18#ifndef SUBZERO_SRC_ICEOPERAND_H
19#define SUBZERO_SRC_ICEOPERAND_H
20
21#include "IceDefs.h"
22#include "IceTypes.h"
23
24namespace Ice {
25
26class Operand {
27public:
28 enum OperandKind {
29 kConst_Base,
30 kConstInteger,
31 kConstFloat,
32 kConstDouble,
33 kConstRelocatable,
Matt Walad8f4a7d2014-06-18 09:55:03 -070034 kConstUndef,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070035 kConst_Num,
36 kVariable,
37 // Target-specific operand classes use kTarget as the starting
38 // point for their Kind enum space.
39 kTarget
40 };
41 OperandKind getKind() const { return Kind; }
42 Type getType() const { return Ty; }
43
44 // Every Operand keeps an array of the Variables referenced in
45 // the operand. This is so that the liveness operations can get
46 // quick access to the variables of interest, without having to dig
47 // so far into the operand.
48 SizeT getNumVars() const { return NumVars; }
49 Variable *getVar(SizeT I) const {
50 assert(I < getNumVars());
51 return Vars[I];
52 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070053 virtual void emit(const Cfg *Func) const = 0;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070054 virtual void dump(const Cfg *Func) const = 0;
55
56 // Query whether this object was allocated in isolation, or added to
57 // some higher-level pool. This determines whether a containing
58 // object's destructor should delete this object. Generally,
59 // constants are pooled globally, variables are pooled per-CFG, and
60 // target-specific operands are not pooled.
61 virtual bool isPooled() const { return false; }
62
63 virtual ~Operand() {}
64
65protected:
66 Operand(OperandKind Kind, Type Ty)
67 : Ty(Ty), Kind(Kind), NumVars(0), Vars(NULL) {}
68
69 const Type Ty;
70 const OperandKind Kind;
71 // Vars and NumVars are initialized by the derived class.
72 SizeT NumVars;
73 Variable **Vars;
74
75private:
76 Operand(const Operand &) LLVM_DELETED_FUNCTION;
77 Operand &operator=(const Operand &) LLVM_DELETED_FUNCTION;
78};
79
80// Constant is the abstract base class for constants. All
81// constants are allocated from a global arena and are pooled.
82class Constant : public Operand {
83public:
Jim Stichnothf61d5b22014-05-23 13:31:24 -070084 uint32_t getPoolEntryID() const { return PoolEntryID; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -070085 virtual void emit(const Cfg *Func) const { emit(Func->getContext()); }
86 virtual void dump(const Cfg *Func) const { dump(Func->getContext()); }
87 virtual void emit(GlobalContext *Ctx) const = 0;
88 virtual void dump(GlobalContext *Ctx) const = 0;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070089
90 static bool classof(const Operand *Operand) {
91 OperandKind Kind = Operand->getKind();
92 return Kind >= kConst_Base && Kind <= kConst_Num;
93 }
94
95protected:
Jim Stichnothf61d5b22014-05-23 13:31:24 -070096 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID)
97 : Operand(Kind, Ty), PoolEntryID(PoolEntryID) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070098 Vars = NULL;
99 NumVars = 0;
100 }
101 virtual ~Constant() {}
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700102 // PoolEntryID is an integer that uniquely identifies the constant
103 // within its constant pool. It is used for building the constant
104 // pool in the object code and for referencing its entries.
105 const uint32_t PoolEntryID;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700106
107private:
108 Constant(const Constant &) LLVM_DELETED_FUNCTION;
109 Constant &operator=(const Constant &) LLVM_DELETED_FUNCTION;
110};
111
112// ConstantPrimitive<> wraps a primitive type.
113template <typename T, Operand::OperandKind K>
114class ConstantPrimitive : public Constant {
115public:
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700116 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, T Value,
117 uint32_t PoolEntryID) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700118 return new (Ctx->allocate<ConstantPrimitive>())
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700119 ConstantPrimitive(Ty, Value, PoolEntryID);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700120 }
121 T getValue() const { return Value; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700122 using Constant::emit;
Matt Wala928f1292014-07-07 16:50:46 -0700123 // The target needs to implement this for each ConstantPrimitive
124 // specialization.
125 virtual void emit(GlobalContext *Ctx) const;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700126 using Constant::dump;
127 virtual void dump(GlobalContext *Ctx) const {
128 Ostream &Str = Ctx->getStrDump();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700129 Str << getValue();
130 }
131
132 static bool classof(const Operand *Operand) {
133 return Operand->getKind() == K;
134 }
135
136private:
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700137 ConstantPrimitive(Type Ty, T Value, uint32_t PoolEntryID)
138 : Constant(K, Ty, PoolEntryID), Value(Value) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700139 ConstantPrimitive(const ConstantPrimitive &) LLVM_DELETED_FUNCTION;
140 ConstantPrimitive &operator=(const ConstantPrimitive &) LLVM_DELETED_FUNCTION;
141 virtual ~ConstantPrimitive() {}
142 const T Value;
143};
144
145typedef ConstantPrimitive<uint64_t, Operand::kConstInteger> ConstantInteger;
146typedef ConstantPrimitive<float, Operand::kConstFloat> ConstantFloat;
147typedef ConstantPrimitive<double, Operand::kConstDouble> ConstantDouble;
148
Jim Stichnothcabfa302014-09-03 15:19:12 -0700149template <> inline void ConstantInteger::dump(GlobalContext *Ctx) const {
150 Ostream &Str = Ctx->getStrDump();
151 if (getType() == IceType_i1)
152 Str << (getValue() ? "true" : "false");
153 else
154 Str << static_cast<int64_t>(getValue());
155}
156
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700157// RelocatableTuple bundles the parameters that are used to
158// construct an ConstantRelocatable. It is done this way so that
159// ConstantRelocatable can fit into the global constant pool
160// template mechanism.
161class RelocatableTuple {
162 RelocatableTuple &operator=(const RelocatableTuple &) LLVM_DELETED_FUNCTION;
163
164public:
165 RelocatableTuple(const int64_t Offset, const IceString &Name,
166 bool SuppressMangling)
167 : Offset(Offset), Name(Name), SuppressMangling(SuppressMangling) {}
168 RelocatableTuple(const RelocatableTuple &Other)
169 : Offset(Other.Offset), Name(Other.Name),
170 SuppressMangling(Other.SuppressMangling) {}
171
172 const int64_t Offset;
173 const IceString Name;
174 bool SuppressMangling;
175};
176
177bool operator<(const RelocatableTuple &A, const RelocatableTuple &B);
178
179// ConstantRelocatable represents a symbolic constant combined with
180// a fixed offset.
181class ConstantRelocatable : public Constant {
182public:
183 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty,
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700184 const RelocatableTuple &Tuple,
185 uint32_t PoolEntryID) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700186 return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable(
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700187 Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700188 }
189 int64_t getOffset() const { return Offset; }
190 IceString getName() const { return Name; }
191 void setSuppressMangling(bool Value) { SuppressMangling = Value; }
192 bool getSuppressMangling() const { return SuppressMangling; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700193 using Constant::emit;
194 using Constant::dump;
195 virtual void emit(GlobalContext *Ctx) const;
196 virtual void dump(GlobalContext *Ctx) const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700197
198 static bool classof(const Operand *Operand) {
199 OperandKind Kind = Operand->getKind();
200 return Kind == kConstRelocatable;
201 }
202
203private:
204 ConstantRelocatable(Type Ty, int64_t Offset, const IceString &Name,
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700205 bool SuppressMangling, uint32_t PoolEntryID)
206 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset),
207 Name(Name), SuppressMangling(SuppressMangling) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700208 ConstantRelocatable(const ConstantRelocatable &) LLVM_DELETED_FUNCTION;
209 ConstantRelocatable &
210 operator=(const ConstantRelocatable &) LLVM_DELETED_FUNCTION;
211 virtual ~ConstantRelocatable() {}
212 const int64_t Offset; // fixed offset to add
213 const IceString Name; // optional for debug/dump
214 bool SuppressMangling;
215};
216
Matt Walad8f4a7d2014-06-18 09:55:03 -0700217// ConstantUndef represents an unspecified bit pattern. Although it is
218// legal to lower ConstantUndef to any value, backends should try to
219// make code generation deterministic by lowering ConstantUndefs to 0.
220class ConstantUndef : public Constant {
221public:
222 static ConstantUndef *create(GlobalContext *Ctx, Type Ty,
223 uint32_t PoolEntryID) {
224 return new (Ctx->allocate<ConstantUndef>()) ConstantUndef(Ty, PoolEntryID);
225 }
226
227 using Constant::emit;
Matt Walae3777672014-07-31 09:06:17 -0700228 // The target needs to implement this.
229 virtual void emit(GlobalContext *Ctx) const;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700230
231 using Constant::dump;
232 virtual void dump(GlobalContext *Ctx) const {
233 Ostream &Str = Ctx->getStrEmit();
234 Str << "undef";
235 }
236
237 static bool classof(const Operand *Operand) {
238 return Operand->getKind() == kConstUndef;
239 }
240
241private:
242 ConstantUndef(Type Ty, uint32_t PoolEntryID)
243 : Constant(kConstUndef, Ty, PoolEntryID) {}
244 ConstantUndef(const ConstantUndef &) LLVM_DELETED_FUNCTION;
245 ConstantUndef &operator=(const ConstantUndef &) LLVM_DELETED_FUNCTION;
246 virtual ~ConstantUndef() {}
247};
248
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700249// RegWeight is a wrapper for a uint32_t weight value, with a
250// special value that represents infinite weight, and an addWeight()
251// method that ensures that W+infinity=infinity.
252class RegWeight {
253public:
254 RegWeight() : Weight(0) {}
255 RegWeight(uint32_t Weight) : Weight(Weight) {}
256 const static uint32_t Inf = ~0; // Force regalloc to give a register
257 const static uint32_t Zero = 0; // Force regalloc NOT to give a register
258 void addWeight(uint32_t Delta) {
259 if (Delta == Inf)
260 Weight = Inf;
261 else if (Weight != Inf)
262 Weight += Delta;
263 }
264 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); }
265 void setWeight(uint32_t Val) { Weight = Val; }
266 uint32_t getWeight() const { return Weight; }
267 bool isInf() const { return Weight == Inf; }
268
269private:
270 uint32_t Weight;
271};
272Ostream &operator<<(Ostream &Str, const RegWeight &W);
273bool operator<(const RegWeight &A, const RegWeight &B);
274bool operator<=(const RegWeight &A, const RegWeight &B);
275bool operator==(const RegWeight &A, const RegWeight &B);
276
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700277// LiveRange is a set of instruction number intervals representing
278// a variable's live range. Generally there is one interval per basic
279// block where the variable is live, but adjacent intervals get
280// coalesced into a single interval. LiveRange also includes a
281// weight, in case e.g. we want a live range to have higher weight
282// inside a loop.
283class LiveRange {
284public:
285 LiveRange() : Weight(0) {}
286
287 void reset() {
288 Range.clear();
289 Weight.setWeight(0);
290 }
291 void addSegment(InstNumberT Start, InstNumberT End);
292
293 bool endsBefore(const LiveRange &Other) const;
294 bool overlaps(const LiveRange &Other) const;
295 bool overlaps(InstNumberT OtherBegin) const;
296 bool containsValue(InstNumberT Value) const;
297 bool isEmpty() const { return Range.empty(); }
298 InstNumberT getStart() const {
299 return Range.empty() ? -1 : Range.begin()->first;
300 }
301
302 RegWeight getWeight() const { return Weight; }
303 void setWeight(const RegWeight &NewWeight) { Weight = NewWeight; }
304 void addWeight(uint32_t Delta) { Weight.addWeight(Delta); }
305 void dump(Ostream &Str) const;
306
307 // Defining USE_SET uses std::set to hold the segments instead of
308 // std::list. Using std::list will be slightly faster, but is more
309 // restrictive because new segments cannot be added in the middle.
310
311 //#define USE_SET
312
313private:
314 typedef std::pair<InstNumberT, InstNumberT> RangeElementType;
315#ifdef USE_SET
316 typedef std::set<RangeElementType> RangeType;
317#else
318 typedef std::list<RangeElementType> RangeType;
319#endif
320 RangeType Range;
321 RegWeight Weight;
322};
323
324Ostream &operator<<(Ostream &Str, const LiveRange &L);
325
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700326// Variable represents an operand that is register-allocated or
327// stack-allocated. If it is register-allocated, it will ultimately
328// have a non-negative RegNum field.
329class Variable : public Operand {
330public:
331 static Variable *create(Cfg *Func, Type Ty, const CfgNode *Node, SizeT Index,
332 const IceString &Name) {
333 return new (Func->allocate<Variable>()) Variable(Ty, Node, Index, Name);
334 }
335
336 SizeT getIndex() const { return Number; }
337 IceString getName() const;
Karl Schimpfc132b762014-09-11 09:43:47 -0700338 void setName(IceString &NewName) {
339 // Make sure that the name can only be set once.
340 assert(Name.empty());
341 Name = NewName;
342 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700343
344 Inst *getDefinition() const { return DefInst; }
345 void setDefinition(Inst *Inst, const CfgNode *Node);
346 void replaceDefinition(Inst *Inst, const CfgNode *Node);
347
348 const CfgNode *getLocalUseNode() const { return DefNode; }
349 bool isMultiblockLife() const { return (DefNode == NULL); }
350 void setUse(const Inst *Inst, const CfgNode *Node);
351
352 bool getIsArg() const { return IsArgument; }
Matt Wala45a06232014-07-09 16:33:22 -0700353 void setIsArg(Cfg *Func, bool IsArg = true);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700354
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700355 int32_t getStackOffset() const { return StackOffset; }
356 void setStackOffset(int32_t Offset) { StackOffset = Offset; }
357
358 static const int32_t NoRegister = -1;
359 bool hasReg() const { return getRegNum() != NoRegister; }
360 int32_t getRegNum() const { return RegNum; }
361 void setRegNum(int32_t NewRegNum) {
362 // Regnum shouldn't be set more than once.
363 assert(!hasReg() || RegNum == NewRegNum);
364 RegNum = NewRegNum;
365 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700366 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; }
367 int32_t getRegNumTmp() const { return RegNumTmp; }
368 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700369
370 RegWeight getWeight() const { return Weight; }
371 void setWeight(uint32_t NewWeight) { Weight = NewWeight; }
372 void setWeightInfinite() { Weight = RegWeight::Inf; }
373
374 Variable *getPreferredRegister() const { return RegisterPreference; }
375 bool getRegisterOverlap() const { return AllowRegisterOverlap; }
376 void setPreferredRegister(Variable *Prefer, bool Overlap) {
377 RegisterPreference = Prefer;
378 AllowRegisterOverlap = Overlap;
379 }
380
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700381 const LiveRange &getLiveRange() const { return Live; }
382 void setLiveRange(const LiveRange &Range) { Live = Range; }
383 void resetLiveRange() { Live.reset(); }
384 void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) {
385 assert(WeightDelta != RegWeight::Inf);
386 Live.addSegment(Start, End);
387 if (Weight.isInf())
388 Live.setWeight(RegWeight::Inf);
389 else
390 Live.addWeight(WeightDelta * Weight.getWeight());
391 }
392 void setLiveRangeInfiniteWeight() { Live.setWeight(RegWeight::Inf); }
393
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700394 Variable *getLo() const { return LoVar; }
395 Variable *getHi() const { return HiVar; }
396 void setLoHi(Variable *Lo, Variable *Hi) {
397 assert(LoVar == NULL);
398 assert(HiVar == NULL);
399 LoVar = Lo;
400 HiVar = Hi;
401 }
402 // Creates a temporary copy of the variable with a different type.
403 // Used primarily for syntactic correctness of textual assembly
404 // emission. Note that only basic information is copied, in
405 // particular not DefInst, IsArgument, Weight, RegisterPreference,
406 // AllowRegisterOverlap, LoVar, HiVar, VarsReal.
407 Variable asType(Type Ty);
408
409 virtual void emit(const Cfg *Func) const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700410 virtual void dump(const Cfg *Func) const;
411
412 static bool classof(const Operand *Operand) {
413 return Operand->getKind() == kVariable;
414 }
415
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700416 // The destructor is public because of the asType() method.
417 virtual ~Variable() {}
418
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700419private:
420 Variable(Type Ty, const CfgNode *Node, SizeT Index, const IceString &Name)
421 : Operand(kVariable, Ty), Number(Index), Name(Name), DefInst(NULL),
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700422 DefNode(Node), IsArgument(false), StackOffset(0), RegNum(NoRegister),
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700423 RegNumTmp(NoRegister), Weight(1), RegisterPreference(NULL),
424 AllowRegisterOverlap(false), LoVar(NULL), HiVar(NULL) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700425 Vars = VarsReal;
426 Vars[0] = this;
427 NumVars = 1;
428 }
429 Variable(const Variable &) LLVM_DELETED_FUNCTION;
430 Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700431 // Number is unique across all variables, and is used as a
432 // (bit)vector index for liveness analysis.
433 const SizeT Number;
434 // Name is optional.
Karl Schimpfc132b762014-09-11 09:43:47 -0700435 IceString Name;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700436 // DefInst is the instruction that produces this variable as its
437 // dest.
438 Inst *DefInst;
439 // DefNode is the node where this variable was produced, and is
440 // reset to NULL if it is used outside that node. This is used for
441 // detecting isMultiblockLife(). TODO: Collapse this to a single
442 // bit and use a separate pass to calculate the values across the
443 // Cfg. This saves space in the Variable, and removes the fragility
444 // of incrementally computing and maintaining the information.
445 const CfgNode *DefNode;
446 bool IsArgument;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700447 // StackOffset is the canonical location on stack (only if
448 // RegNum<0 || IsArgument).
449 int32_t StackOffset;
450 // RegNum is the allocated register, or NoRegister if it isn't
451 // register-allocated.
452 int32_t RegNum;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700453 // RegNumTmp is the tentative assignment during register allocation.
454 int32_t RegNumTmp;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700455 RegWeight Weight; // Register allocation priority
456 // RegisterPreference says that if possible, the register allocator
457 // should prefer the register that was assigned to this linked
458 // variable. It also allows a spill slot to share its stack
459 // location with another variable, if that variable does not get
460 // register-allocated and therefore has a stack location.
461 Variable *RegisterPreference;
462 // AllowRegisterOverlap says that it is OK to honor
463 // RegisterPreference and "share" a register even if the two live
464 // ranges overlap.
465 bool AllowRegisterOverlap;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700466 LiveRange Live;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700467 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When
468 // lowering from I64 to I32 on a 32-bit architecture, we split the
469 // variable into two machine-size pieces. LoVar is the low-order
470 // machine-size portion, and HiVar is the remaining high-order
471 // portion. TODO: It's wasteful to penalize all variables on all
472 // targets this way; use a sparser representation. It's also
473 // wasteful for a 64-bit target.
474 Variable *LoVar;
475 Variable *HiVar;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700476 // VarsReal (and Operand::Vars) are set up such that Vars[0] ==
477 // this.
478 Variable *VarsReal[1];
479};
480
481} // end of namespace Ice
482
483#endif // SUBZERO_SRC_ICEOPERAND_H