Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 1 | //===- subzero/src/IceGlobalContext.h - Global context defs -----*- 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 aspects of the compilation that persist across |
| 11 | // multiple functions. |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
| 15 | #ifndef SUBZERO_SRC_ICEGLOBALCONTEXT_H |
| 16 | #define SUBZERO_SRC_ICEGLOBALCONTEXT_H |
| 17 | |
Jim Stichnoth | a18cc9c | 2014-09-30 19:10:22 -0700 | [diff] [blame] | 18 | #include <memory> |
| 19 | |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 20 | #include "llvm/Support/Allocator.h" |
| 21 | #include "llvm/Support/raw_ostream.h" |
| 22 | |
| 23 | #include "IceDefs.h" |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 24 | #include "IceIntrinsics.h" |
Matt Wala | 1bd2fce | 2014-08-08 14:02:09 -0700 | [diff] [blame] | 25 | #include "IceRNG.h" |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 26 | #include "IceTypes.h" |
| 27 | |
| 28 | namespace Ice { |
| 29 | |
Jim Stichnoth | 989a703 | 2014-08-08 10:13:44 -0700 | [diff] [blame] | 30 | class ClFlags; |
| 31 | |
Jim Stichnoth | 1873560 | 2014-09-16 19:59:35 -0700 | [diff] [blame] | 32 | // This class collects rudimentary statistics during translation. |
| 33 | class CodeStats { |
| 34 | public: |
| 35 | CodeStats() |
| 36 | : InstructionsEmitted(0), RegistersSaved(0), FrameBytes(0), Spills(0), |
| 37 | Fills(0) {} |
| 38 | void reset() { *this = CodeStats(); } |
| 39 | void updateEmitted(uint32_t InstCount) { InstructionsEmitted += InstCount; } |
| 40 | void updateRegistersSaved(uint32_t Num) { RegistersSaved += Num; } |
| 41 | void updateFrameBytes(uint32_t Bytes) { FrameBytes += Bytes; } |
| 42 | void updateSpills() { ++Spills; } |
| 43 | void updateFills() { ++Fills; } |
| 44 | void dump(const IceString &Name, Ostream &Str) { |
| 45 | Str << "|" << Name << "|Inst Count |" << InstructionsEmitted << "\n"; |
| 46 | Str << "|" << Name << "|Regs Saved |" << RegistersSaved << "\n"; |
| 47 | Str << "|" << Name << "|Frame Bytes |" << FrameBytes << "\n"; |
| 48 | Str << "|" << Name << "|Spills |" << Spills << "\n"; |
| 49 | Str << "|" << Name << "|Fills |" << Fills << "\n"; |
| 50 | Str << "|" << Name << "|Spills+Fills|" << Spills + Fills << "\n"; |
| 51 | } |
| 52 | |
| 53 | private: |
| 54 | uint32_t InstructionsEmitted; |
| 55 | uint32_t RegistersSaved; |
| 56 | uint32_t FrameBytes; |
| 57 | uint32_t Spills; |
| 58 | uint32_t Fills; |
| 59 | }; |
| 60 | |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 61 | // TODO: Accesses to all non-const fields of GlobalContext need to |
| 62 | // be synchronized, especially the constant pool, the allocator, and |
| 63 | // the output streams. |
| 64 | class GlobalContext { |
| 65 | public: |
| 66 | GlobalContext(llvm::raw_ostream *OsDump, llvm::raw_ostream *OsEmit, |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 67 | VerboseMask Mask, TargetArch Arch, OptLevel Opt, |
Jim Stichnoth | 989a703 | 2014-08-08 10:13:44 -0700 | [diff] [blame] | 68 | IceString TestPrefix, const ClFlags &Flags); |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 69 | ~GlobalContext(); |
| 70 | |
| 71 | // Returns true if any of the specified options in the verbose mask |
| 72 | // are set. If the argument is omitted, it checks if any verbose |
Jim Stichnoth | c4554d7 | 2014-09-30 16:49:38 -0700 | [diff] [blame] | 73 | // options at all are set. |
| 74 | bool isVerbose(VerboseMask Mask = IceV_All) const { return VMask & Mask; } |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 75 | void setVerbose(VerboseMask Mask) { VMask = Mask; } |
| 76 | void addVerbose(VerboseMask Mask) { VMask |= Mask; } |
| 77 | void subVerbose(VerboseMask Mask) { VMask &= ~Mask; } |
| 78 | |
Jim Stichnoth | 78282f6 | 2014-07-27 23:14:00 -0700 | [diff] [blame] | 79 | Ostream &getStrDump() { return *StrDump; } |
| 80 | Ostream &getStrEmit() { return *StrEmit; } |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 81 | |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 82 | TargetArch getTargetArch() const { return Arch; } |
| 83 | OptLevel getOptLevel() const { return Opt; } |
| 84 | |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 85 | // When emitting assembly, we allow a string to be prepended to |
| 86 | // names of translated functions. This makes it easier to create an |
| 87 | // execution test against a reference translator like llc, with both |
| 88 | // translators using the same bitcode as input. |
| 89 | IceString getTestPrefix() const { return TestPrefix; } |
| 90 | IceString mangleName(const IceString &Name) const; |
| 91 | |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 92 | // The purpose of HasEmitted is to add a header comment at the |
| 93 | // beginning of assembly code emission, doing it once per file |
| 94 | // rather than once per function. |
| 95 | bool testAndSetHasEmittedFirstMethod() { |
| 96 | bool HasEmitted = HasEmittedFirstMethod; |
| 97 | HasEmittedFirstMethod = true; |
| 98 | return HasEmitted; |
| 99 | } |
| 100 | |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 101 | // Manage Constants. |
| 102 | // getConstant*() functions are not const because they might add |
| 103 | // something to the constant pool. |
Jan Voung | bc00463 | 2014-09-16 15:09:10 -0700 | [diff] [blame] | 104 | Constant *getConstantInt32(Type Ty, uint32_t ConstantInt32); |
| 105 | Constant *getConstantInt64(Type Ty, uint64_t ConstantInt64); |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 106 | Constant *getConstantFloat(float Value); |
| 107 | Constant *getConstantDouble(double Value); |
| 108 | // Returns a symbolic constant. |
| 109 | Constant *getConstantSym(Type Ty, int64_t Offset, const IceString &Name = "", |
| 110 | bool SuppressMangling = false); |
Matt Wala | d8f4a7d | 2014-06-18 09:55:03 -0700 | [diff] [blame] | 111 | // Returns an undef. |
| 112 | Constant *getConstantUndef(Type Ty); |
| 113 | // Returns a zero value. |
| 114 | Constant *getConstantZero(Type Ty); |
Jim Stichnoth | f61d5b2 | 2014-05-23 13:31:24 -0700 | [diff] [blame] | 115 | // getConstantPool() returns a copy of the constant pool for |
| 116 | // constants of a given type. |
| 117 | ConstantList getConstantPool(Type Ty) const; |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 118 | |
Jim Stichnoth | 989a703 | 2014-08-08 10:13:44 -0700 | [diff] [blame] | 119 | const ClFlags &getFlags() const { return Flags; } |
| 120 | |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 121 | // Allocate data of type T using the global allocator. |
| 122 | template <typename T> T *allocate() { return Allocator.Allocate<T>(); } |
| 123 | |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 124 | const Intrinsics &getIntrinsicsInfo() const { return IntrinsicsInfo; } |
| 125 | |
Matt Wala | 1bd2fce | 2014-08-08 14:02:09 -0700 | [diff] [blame] | 126 | // TODO(wala,stichnot): Make the RNG play nicely with multithreaded |
| 127 | // translation. |
| 128 | RandomNumberGenerator &getRNG() { return RNG; } |
| 129 | |
Jim Stichnoth | 1873560 | 2014-09-16 19:59:35 -0700 | [diff] [blame] | 130 | // Reset stats at the beginning of a function. |
| 131 | void resetStats() { StatsFunction.reset(); } |
Jim Stichnoth | ff9c706 | 2014-09-18 04:50:49 -0700 | [diff] [blame] | 132 | void dumpStats(const IceString &Name, bool Final = false); |
Jim Stichnoth | 1873560 | 2014-09-16 19:59:35 -0700 | [diff] [blame] | 133 | void statsUpdateEmitted(uint32_t InstCount) { |
| 134 | StatsFunction.updateEmitted(InstCount); |
| 135 | StatsCumulative.updateEmitted(InstCount); |
| 136 | } |
| 137 | void statsUpdateRegistersSaved(uint32_t Num) { |
| 138 | StatsFunction.updateRegistersSaved(Num); |
| 139 | StatsCumulative.updateRegistersSaved(Num); |
| 140 | } |
| 141 | void statsUpdateFrameBytes(uint32_t Bytes) { |
| 142 | StatsFunction.updateFrameBytes(Bytes); |
| 143 | StatsCumulative.updateFrameBytes(Bytes); |
| 144 | } |
| 145 | void statsUpdateSpills() { |
| 146 | StatsFunction.updateSpills(); |
| 147 | StatsCumulative.updateSpills(); |
| 148 | } |
| 149 | void statsUpdateFills() { |
| 150 | StatsFunction.updateFills(); |
| 151 | StatsCumulative.updateFills(); |
| 152 | } |
| 153 | |
Jim Stichnoth | c4554d7 | 2014-09-30 16:49:38 -0700 | [diff] [blame] | 154 | static TimerIdT getTimerID(const IceString &Name); |
| 155 | void pushTimer(TimerIdT ID); |
| 156 | void popTimer(TimerIdT ID); |
| 157 | void dumpTimers(); |
| 158 | |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 159 | private: |
Jim Stichnoth | 78282f6 | 2014-07-27 23:14:00 -0700 | [diff] [blame] | 160 | Ostream *StrDump; // Stream for dumping / diagnostics |
| 161 | Ostream *StrEmit; // Stream for code emission |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 162 | |
| 163 | llvm::BumpPtrAllocator Allocator; |
| 164 | VerboseMask VMask; |
Jim Stichnoth | a18cc9c | 2014-09-30 19:10:22 -0700 | [diff] [blame] | 165 | std::unique_ptr<class ConstantPool> ConstPool; |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 166 | Intrinsics IntrinsicsInfo; |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 167 | const TargetArch Arch; |
| 168 | const OptLevel Opt; |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 169 | const IceString TestPrefix; |
Jim Stichnoth | 989a703 | 2014-08-08 10:13:44 -0700 | [diff] [blame] | 170 | const ClFlags &Flags; |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 171 | bool HasEmittedFirstMethod; |
Matt Wala | 1bd2fce | 2014-08-08 14:02:09 -0700 | [diff] [blame] | 172 | RandomNumberGenerator RNG; |
Jim Stichnoth | 1873560 | 2014-09-16 19:59:35 -0700 | [diff] [blame] | 173 | CodeStats StatsFunction; |
| 174 | CodeStats StatsCumulative; |
Jim Stichnoth | a18cc9c | 2014-09-30 19:10:22 -0700 | [diff] [blame] | 175 | std::unique_ptr<class TimerStack> Timers; |
Jim Stichnoth | 0795ba0 | 2014-10-01 14:23:01 -0700 | [diff] [blame^] | 176 | GlobalContext(const GlobalContext &) = delete; |
| 177 | GlobalContext &operator=(const GlobalContext &) = delete; |
Jim Stichnoth | 217dc08 | 2014-07-11 14:06:55 -0700 | [diff] [blame] | 178 | |
| 179 | // Private helpers for mangleName() |
| 180 | typedef llvm::SmallVector<char, 32> ManglerVector; |
| 181 | void incrementSubstitutions(ManglerVector &OldName) const; |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 182 | }; |
| 183 | |
Jim Stichnoth | c4554d7 | 2014-09-30 16:49:38 -0700 | [diff] [blame] | 184 | // Helper class to push and pop a timer marker. The constructor |
| 185 | // pushes a marker, and the destructor pops it. This is for |
| 186 | // convenient timing of regions of code. |
| 187 | class TimerMarker { |
Jim Stichnoth | 0795ba0 | 2014-10-01 14:23:01 -0700 | [diff] [blame^] | 188 | TimerMarker(const TimerMarker &) = delete; |
| 189 | TimerMarker &operator=(const TimerMarker &) = delete; |
Jim Stichnoth | c4554d7 | 2014-09-30 16:49:38 -0700 | [diff] [blame] | 190 | |
| 191 | public: |
| 192 | TimerMarker(TimerIdT ID, GlobalContext *Ctx) |
| 193 | : ID(ID), Ctx(Ctx), Active(Ctx->getFlags().SubzeroTimingEnabled) { |
| 194 | if (Active) |
| 195 | Ctx->pushTimer(ID); |
| 196 | } |
| 197 | ~TimerMarker() { |
| 198 | if (Active) |
| 199 | Ctx->popTimer(ID); |
| 200 | } |
| 201 | |
| 202 | private: |
| 203 | TimerIdT ID; |
| 204 | GlobalContext *const Ctx; |
| 205 | const bool Active; |
| 206 | }; |
| 207 | |
Jim Stichnoth | f7c9a14 | 2014-04-29 10:52:43 -0700 | [diff] [blame] | 208 | } // end of namespace Ice |
| 209 | |
| 210 | #endif // SUBZERO_SRC_ICEGLOBALCONTEXT_H |