blob: 3a21b3ae9ba81b46065dfd127d061772ca3c9f52 [file] [log] [blame]
Jim Stichnothc4554d72014-09-30 16:49:38 -07001//===- subzero/src/IceGlobalContext.cpp - Global context defs -------------===//
Jim Stichnothf7c9a142014-04-29 10:52:43 -07002//
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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Defines aspects of the compilation that persist across multiple
Andrew Scull57e12682015-09-16 11:30:19 -070012/// functions.
Andrew Scull9612d322015-07-06 14:53:25 -070013///
Jim Stichnothf7c9a142014-04-29 10:52:43 -070014//===----------------------------------------------------------------------===//
15
John Porto67f8de92015-06-25 10:14:17 -070016#include "IceGlobalContext.h"
Jim Stichnoth639c9212014-12-11 10:04:32 -080017
Jim Stichnothf7c9a142014-04-29 10:52:43 -070018#include "IceCfg.h"
John Portof8b4cc82015-06-09 18:06:19 -070019#include "IceCfgNode.h"
Jim Stichnoth989a7032014-08-08 10:13:44 -070020#include "IceClFlags.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070021#include "IceDefs.h"
Jan Voungec270732015-01-12 17:00:22 -080022#include "IceELFObjectWriter.h"
Karl Schimpf9d98d792014-10-13 15:01:08 -070023#include "IceGlobalInits.h"
John Porto7bb9cab2016-04-01 05:43:09 -070024#include "IceLiveness.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070025#include "IceOperand.h"
Jim Stichnoth54cf1a22016-08-08 14:15:00 -070026#include "IceRevision.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070027#include "IceTargetLowering.h"
Jim Stichnothc4554d72014-09-30 16:49:38 -070028#include "IceTimerTree.h"
Karl Schimpf20070e82016-03-17 13:30:13 -070029#include "IceTypes.def"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070030#include "IceTypes.h"
Jim Stichnoth98da9662015-06-27 06:38:08 -070031
Jim Stichnothb0051df2016-01-13 11:39:15 -080032#ifdef __clang__
Jim Stichnoth98da9662015-06-27 06:38:08 -070033#pragma clang diagnostic push
34#pragma clang diagnostic ignored "-Wunused-parameter"
Jim Stichnothb0051df2016-01-13 11:39:15 -080035#endif // __clang__
36
John Porto67f8de92015-06-25 10:14:17 -070037#include "llvm/Support/Timer.h"
Jim Stichnothb0051df2016-01-13 11:39:15 -080038
39#ifdef __clang__
Jim Stichnoth98da9662015-06-27 06:38:08 -070040#pragma clang diagnostic pop
Jim Stichnothb0051df2016-01-13 11:39:15 -080041#endif // __clang__
John Porto67f8de92015-06-25 10:14:17 -070042
Qining Lu7cd53512015-06-26 09:36:00 -070043#include <algorithm> // max()
John Porto67f8de92015-06-25 10:14:17 -070044
Jim Stichnothdddaf9c2014-12-04 14:09:21 -080045namespace std {
46template <> struct hash<Ice::RelocatableTuple> {
47 size_t operator()(const Ice::RelocatableTuple &Key) const {
Jim Stichnoth467ffe52016-03-29 15:01:06 -070048 // Use the relocatable's name, plus the hash of a combination of the number
49 // of OffsetExprs and the known, fixed offset for the reloc. We left shift
50 // the known relocatable by 5 trying to minimize the interaction between the
51 // bits in OffsetExpr.size() and Key.Offset.
52 return hash<Ice::SizeT>()(Key.Name.getID()) +
John Portoe82b5602016-02-24 15:58:55 -080053 hash<std::size_t>()(Key.OffsetExpr.size() + (Key.Offset << 5));
Jim Stichnothd2cb4362014-11-20 11:24:42 -080054 }
55};
Jim Stichnothdddaf9c2014-12-04 14:09:21 -080056} // end of namespace std
Jim Stichnothd2cb4362014-11-20 11:24:42 -080057
Jim Stichnothf7c9a142014-04-29 10:52:43 -070058namespace Ice {
59
Jim Stichnoth5bfe2152015-03-19 13:51:56 -070060namespace {
61
Andrew Scull57e12682015-09-16 11:30:19 -070062// Define the key comparison function for the constant pool's unordered_map,
63// but only for key types of interest: integer types, floating point types, and
64// the special RelocatableTuple.
Jim Stichnoth5bfe2152015-03-19 13:51:56 -070065template <typename KeyType, class Enable = void> struct KeyCompare {};
66
67template <typename KeyType>
68struct KeyCompare<KeyType,
69 typename std::enable_if<
70 std::is_integral<KeyType>::value ||
71 std::is_same<KeyType, RelocatableTuple>::value>::type> {
72 bool operator()(const KeyType &Value1, const KeyType &Value2) const {
73 return Value1 == Value2;
74 }
75};
76template <typename KeyType>
77struct KeyCompare<KeyType, typename std::enable_if<
78 std::is_floating_point<KeyType>::value>::type> {
79 bool operator()(const KeyType &Value1, const KeyType &Value2) const {
80 return !memcmp(&Value1, &Value2, sizeof(KeyType));
81 }
82};
83
Andrew Scull57e12682015-09-16 11:30:19 -070084// Define a key comparison function for sorting the constant pool's values
85// after they are dumped to a vector. This covers integer types, floating point
86// types, and ConstantRelocatable values.
Jim Stichnoth6e293c82015-04-09 09:11:18 -070087template <typename ValueType, class Enable = void> struct KeyCompareLess {};
88
89template <typename ValueType>
90struct KeyCompareLess<ValueType,
91 typename std::enable_if<std::is_floating_point<
92 typename ValueType::PrimType>::value>::type> {
93 bool operator()(const Constant *Const1, const Constant *Const2) const {
Andrew Scull8072bae2015-09-14 16:01:26 -070094 using CompareType = uint64_t;
Jim Stichnoth6e293c82015-04-09 09:11:18 -070095 static_assert(sizeof(typename ValueType::PrimType) <= sizeof(CompareType),
96 "Expected floating-point type of width 64-bit or less");
97 typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue();
98 typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue();
99 // We avoid "V1<V2" because of NaN.
100 // We avoid "memcmp(&V1,&V2,sizeof(V1))<0" which depends on the
101 // endian-ness of the host system running Subzero.
102 // Instead, compare the result of bit_cast to uint64_t.
103 uint64_t I1 = 0, I2 = 0;
104 memcpy(&I1, &V1, sizeof(V1));
105 memcpy(&I2, &V2, sizeof(V2));
106 return I1 < I2;
107 }
108};
109template <typename ValueType>
110struct KeyCompareLess<ValueType,
111 typename std::enable_if<std::is_integral<
112 typename ValueType::PrimType>::value>::type> {
113 bool operator()(const Constant *Const1, const Constant *Const2) const {
114 typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue();
115 typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue();
116 return V1 < V2;
117 }
118};
119template <typename ValueType>
120struct KeyCompareLess<
121 ValueType, typename std::enable_if<
122 std::is_same<ValueType, ConstantRelocatable>::value>::type> {
123 bool operator()(const Constant *Const1, const Constant *Const2) const {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700124 auto *V1 = llvm::cast<ValueType>(Const1);
125 auto *V2 = llvm::cast<ValueType>(Const2);
Jim Stichnoth6e293c82015-04-09 09:11:18 -0700126 if (V1->getName() == V2->getName())
127 return V1->getOffset() < V2->getOffset();
128 return V1->getName() < V2->getName();
129 }
130};
131
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700132// TypePool maps constants of type KeyType (e.g. float) to pointers to
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800133// type ValueType (e.g. ConstantFloat).
134template <Type Ty, typename KeyType, typename ValueType> class TypePool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700135 TypePool(const TypePool &) = delete;
136 TypePool &operator=(const TypePool &) = delete;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700137
138public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700139 TypePool() = default;
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800140 ValueType *getOrAdd(GlobalContext *Ctx, KeyType Key) {
141 auto Iter = Pool.find(Key);
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800142 if (Iter != Pool.end()) {
143 Iter->second->updateLookupCount();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700144 return Iter->second;
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800145 }
Jim Stichnoth54f3d512015-12-11 09:53:00 -0800146 auto *Result = ValueType::create(Ctx, Ty, Key);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800147 Pool[Key] = Result;
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800148 Result->updateLookupCount();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700149 return Result;
150 }
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700151 ConstantList getConstantPool() const {
152 ConstantList Constants;
153 Constants.reserve(Pool.size());
Jim Stichnothf44f3712014-10-01 14:05:51 -0700154 for (auto &I : Pool)
155 Constants.push_back(I.second);
Andrew Scull8072bae2015-09-14 16:01:26 -0700156 // The sort (and its KeyCompareLess machinery) is not strictly necessary,
157 // but is desirable for producing output that is deterministic across
158 // unordered_map::iterator implementations.
Jim Stichnoth6e293c82015-04-09 09:11:18 -0700159 std::sort(Constants.begin(), Constants.end(), KeyCompareLess<ValueType>());
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700160 return Constants;
161 }
Jim Stichnoth3d5e08d2016-03-01 12:22:29 -0800162 size_t size() const { return Pool.size(); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700163
164private:
Andrew Scull8072bae2015-09-14 16:01:26 -0700165 // Use the default hash function, and a custom key comparison function. The
166 // key comparison function for floating point variables can't use the default
167 // == based implementation because of special C++ semantics regarding +0.0,
168 // -0.0, and NaN comparison. However, it's OK to use the default hash for
169 // floating point values because KeyCompare is the final source of truth - in
170 // the worst case a "false" collision must be resolved.
171 using ContainerType =
172 std::unordered_map<KeyType, ValueType *, std::hash<KeyType>,
173 KeyCompare<KeyType>>;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700174 ContainerType Pool;
175};
176
Matt Walad8f4a7d2014-06-18 09:55:03 -0700177// UndefPool maps ICE types to the corresponding ConstantUndef values.
178class UndefPool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700179 UndefPool(const UndefPool &) = delete;
180 UndefPool &operator=(const UndefPool &) = delete;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700181
182public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700183 UndefPool() : Pool(IceType_NUM) {}
Matt Walad8f4a7d2014-06-18 09:55:03 -0700184
185 ConstantUndef *getOrAdd(GlobalContext *Ctx, Type Ty) {
Jim Stichnothae953202014-12-20 06:17:49 -0800186 if (Pool[Ty] == nullptr)
Jim Stichnothb36757e2015-10-05 13:55:11 -0700187 Pool[Ty] = ConstantUndef::create(Ctx, Ty);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800188 return Pool[Ty];
Matt Walad8f4a7d2014-06-18 09:55:03 -0700189 }
190
191private:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800192 std::vector<ConstantUndef *> Pool;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700193};
194
Jim Stichnoth5bfe2152015-03-19 13:51:56 -0700195} // end of anonymous namespace
196
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700197// The global constant pool bundles individual pools of each type of
198// interest.
199class ConstantPool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700200 ConstantPool(const ConstantPool &) = delete;
201 ConstantPool &operator=(const ConstantPool &) = delete;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700202
203public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700204 ConstantPool() = default;
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800205 TypePool<IceType_f32, float, ConstantFloat> Floats;
206 TypePool<IceType_f64, double, ConstantDouble> Doubles;
207 TypePool<IceType_i1, int8_t, ConstantInteger32> Integers1;
208 TypePool<IceType_i8, int8_t, ConstantInteger32> Integers8;
209 TypePool<IceType_i16, int16_t, ConstantInteger32> Integers16;
210 TypePool<IceType_i32, int32_t, ConstantInteger32> Integers32;
211 TypePool<IceType_i64, int64_t, ConstantInteger64> Integers64;
212 TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable> Relocatables;
Jan Voung261cae32015-02-01 10:31:03 -0800213 TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable>
214 ExternRelocatables;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700215 UndefPool Undefs;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700216};
217
Karl Schimpfe8457a22016-03-31 10:20:23 -0700218void GlobalContext::waitForWorkerThreads() {
219 if (WaitForWorkerThreadsCalled.exchange(true))
220 return;
221 optQueueNotifyEnd();
222 for (std::thread &Worker : TranslationThreads) {
223 Worker.join();
224 }
225 TranslationThreads.clear();
226
227 // Only notify the emit queue to end after all the translation threads have
228 // ended.
229 emitQueueNotifyEnd();
230 for (std::thread &Worker : EmitterThreads) {
231 Worker.join();
232 }
233 EmitterThreads.clear();
234
235 if (BuildDefs::timers()) {
236 auto Timers = getTimers();
237 for (ThreadContext *TLS : AllThreadContexts)
238 Timers->mergeFrom(TLS->Timers);
239 }
240 if (BuildDefs::dump()) {
241 // Do a separate loop over AllThreadContexts to avoid holding two locks at
242 // once.
243 auto Stats = getStatsCumulative();
244 for (ThreadContext *TLS : AllThreadContexts)
245 Stats->add(TLS->StatsCumulative);
246 }
247}
248
Jim Stichnothb5eee3d2016-03-31 11:05:39 -0700249void GlobalContext::CodeStats::dump(const Cfg *Func, GlobalContext *Ctx) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700250 if (!BuildDefs::dump())
Jim Stichnoth639c9212014-12-11 10:04:32 -0800251 return;
Jim Stichnoth3d5e08d2016-03-01 12:22:29 -0800252 OstreamLocker _(Ctx);
253 Ostream &Str = Ctx->getStrDump();
Jim Stichnothb5eee3d2016-03-31 11:05:39 -0700254 const std::string Name =
255 (Func == nullptr ? "_FINAL_" : Func->getFunctionNameAndSize());
Jim Stichnotha1dd3cc2015-01-31 10:48:11 -0800256#define X(str, tag) \
257 Str << "|" << Name << "|" str "|" << Stats[CS_##tag] << "\n";
258 CODESTATS_TABLE
259#undef X
260 Str << "|" << Name << "|Spills+Fills|"
261 << Stats[CS_NumSpills] + Stats[CS_NumFills] << "\n";
John Portoa3984a12016-04-01 11:14:30 -0700262 Str << "|" << Name << "|Memory Usage |";
263 if (const auto MemUsed = static_cast<size_t>(
264 llvm::TimeRecord::getCurrentTime(false).getMemUsed())) {
265 static constexpr size_t _1MB = 1024 * 1024;
266 Str << (MemUsed / _1MB) << " MB";
267 } else {
Jim Stichnoth639c9212014-12-11 10:04:32 -0800268 Str << "(requires '-track-memory')";
John Portoa3984a12016-04-01 11:14:30 -0700269 }
Jim Stichnoth639c9212014-12-11 10:04:32 -0800270 Str << "\n";
Jim Stichnoth3d5e08d2016-03-01 12:22:29 -0800271 Str << "|" << Name << "|CPool Sizes ";
272 {
273 auto Pool = Ctx->getConstPool();
274 Str << "|f32=" << Pool->Floats.size();
275 Str << "|f64=" << Pool->Doubles.size();
276 Str << "|i1=" << Pool->Integers1.size();
277 Str << "|i8=" << Pool->Integers8.size();
278 Str << "|i16=" << Pool->Integers16.size();
279 Str << "|i32=" << Pool->Integers32.size();
280 Str << "|i64=" << Pool->Integers64.size();
281 Str << "|Rel=" << Pool->Relocatables.size();
282 Str << "|ExtRel=" << Pool->ExternRelocatables.size();
283 }
284 Str << "\n";
Jim Stichnothb5eee3d2016-03-31 11:05:39 -0700285 if (Func != nullptr) {
John Portoa3984a12016-04-01 11:14:30 -0700286 Str << "|" << Name << "|Cfg Memory |" << Func->getTotalMemoryMB()
287 << " MB\n";
288 Str << "|" << Name << "|Liveness Memory |" << Func->getLivenessMemoryMB()
Jim Stichnothb5eee3d2016-03-31 11:05:39 -0700289 << " MB\n";
290 }
Jim Stichnoth639c9212014-12-11 10:04:32 -0800291}
292
Karl Schimpf3018cf22016-04-11 14:49:01 -0700293namespace {
294
295// By default, wake up the main parser thread when the OptQ gets half empty.
296static constexpr size_t DefaultOptQWakeupSize = GlobalContext::MaxOptQSize >> 1;
297
298} // end of anonymous namespace
299
Karl Schimpf2f67b922015-04-22 15:20:16 -0700300GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError,
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800301 ELFStreamer *ELFStr)
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700302 : Strings(new StringPool()), ConstPool(new ConstantPool()), ErrorStatus(),
303 StrDump(OsDump), StrEmit(OsEmit), StrError(OsError), IntrinsicsInfo(this),
Karl Schimpf3018cf22016-04-11 14:49:01 -0700304 ObjectWriter(),
305 OptQWakeupSize(std::max(DefaultOptQWakeupSize,
306 size_t(getFlags().getNumTranslationThreads()))),
307 OptQ(/*Sequential=*/getFlags().isSequential(),
308 /*MaxSize=*/
309 getFlags().isParseParallel()
310 ? MaxOptQSize
311 : getFlags().getNumTranslationThreads()),
Jim Stichnothbbca7542015-02-11 16:08:31 -0800312 // EmitQ is allowed unlimited size.
Karl Schimpfd4699942016-04-02 09:55:31 -0700313 EmitQ(/*Sequential=*/getFlags().isSequential()),
John Porto1bec8bc2015-06-22 10:51:13 -0700314 DataLowering(TargetDataLowering::createLowering(this)) {
Karl Schimpf2f67b922015-04-22 15:20:16 -0700315 assert(OsDump && "OsDump is not defined for GlobalContext");
316 assert(OsEmit && "OsEmit is not defined for GlobalContext");
317 assert(OsError && "OsError is not defined for GlobalContext");
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800318 // Make sure thread_local fields are properly initialized before any
319 // accesses are made. Do this here instead of at the start of
320 // main() so that all clients (e.g. unit tests) can benefit for
321 // free.
322 GlobalContext::TlsInit();
323 Cfg::TlsInit();
John Porto7bb9cab2016-04-01 05:43:09 -0700324 Liveness::TlsInit();
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800325 // Create a new ThreadContext for the current thread. No need to
326 // lock AllThreadContexts at this point since no other threads have
327 // access yet to this GlobalContext object.
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800328 ThreadContext *MyTLS = new ThreadContext();
329 AllThreadContexts.push_back(MyTLS);
330 ICE_TLS_SET_FIELD(TLS, MyTLS);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700331 // Pre-register built-in stack names.
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800332 if (BuildDefs::timers()) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800333 // TODO(stichnot): There needs to be a strong relationship between
334 // the newTimerStackID() return values and TSK_Default/TSK_Funcs.
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800335 newTimerStackID("Total across all functions");
336 newTimerStackID("Per-function summary");
337 }
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800338 Timers.initInto(MyTLS->Timers);
Karl Schimpfd4699942016-04-02 09:55:31 -0700339 switch (getFlags().getOutFileType()) {
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800340 case FT_Elf:
Jan Voung08c3bcd2014-12-01 17:55:16 -0800341 ObjectWriter.reset(new ELFObjectWriter(*this, *ELFStr));
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800342 break;
343 case FT_Asm:
344 case FT_Iasm:
345 break;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800346 }
Karl Schimpf20070e82016-03-17 13:30:13 -0700347// Cache up front common constants.
348#define X(tag, sizeLog2, align, elts, elty, str, rcstr) \
349 ConstZeroForType[IceType_##tag] = getConstantZeroInternal(IceType_##tag);
350 ICETYPE_TABLE;
351#undef X
352 ConstantTrue = getConstantInt1Internal(1);
353// Define runtime helper functions.
354#define X(Tag, Name) \
355 RuntimeHelperFunc[static_cast<size_t>(RuntimeHelper::H_##Tag)] = \
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700356 getConstantExternSym(getGlobalString(Name));
Karl Schimpf20070e82016-03-17 13:30:13 -0700357 RUNTIME_HELPER_FUNCTIONS_TABLE
358#undef X
John Porto1bec8bc2015-06-22 10:51:13 -0700359
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800360 TargetLowering::staticInit(this);
Jim Stichnoth54cf1a22016-08-08 14:15:00 -0700361
362 if (getFlags().getEmitRevision()) {
363 // Embed the Subzero revision into the compiled binary by creating a special
364 // global variable initialized with the revision string.
365 auto *Revision = VariableDeclaration::create(&Globals, true);
366 Revision->setName(this, "__Sz_revision");
367 Revision->setIsConstant(true);
368 const char *RevisionString = getSubzeroRevision();
369 Revision->addInitializer(VariableDeclaration::DataInitializer::create(
370 &Globals, RevisionString, 1 + strlen(RevisionString)));
371 Globals.push_back(Revision);
372 }
Jim Stichnoth8363a062014-10-07 10:02:38 -0700373}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700374
Lei Zhang04e9b1c2017-05-23 15:08:59 -0700375void GlobalContext::translateFunctionsWrapper(ThreadContext *MyTLS) {
376 ICE_TLS_SET_FIELD(TLS, MyTLS);
377 translateFunctions();
378}
379
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800380void GlobalContext::translateFunctions() {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800381 TimerMarker Timer(TimerStack::TT_translateFunctions, this);
Karl Schimpfe8457a22016-03-31 10:20:23 -0700382 while (std::unique_ptr<OptWorkItem> OptItem = optQueueBlockingPop()) {
Jim Stichnoth5f55d402016-06-27 07:30:56 -0700383 std::unique_ptr<EmitterWorkItem> Item;
Karl Schimpfe8457a22016-03-31 10:20:23 -0700384 auto Func = OptItem->getParsedCfg();
Jim Stichnoth8e928382015-02-02 17:03:08 -0800385 // Install Func in TLS for Cfg-specific container allocators.
John Portoe82b5602016-02-24 15:58:55 -0800386 CfgLocalAllocatorScope _(Func.get());
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800387 // Reset per-function stats being accumulated in TLS.
388 resetStats();
Jim Stichnothdd6dcfa2016-04-18 12:52:09 -0700389 // Set verbose level to none if the current function does NOT match the
390 // -verbose-focus command-line option.
391 if (!getFlags().matchVerboseFocusOn(Func->getFunctionName(),
392 Func->getSequenceNumber()))
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800393 Func->setVerbose(IceV_None);
Jim Stichnothdd6dcfa2016-04-18 12:52:09 -0700394 // Disable translation if -notranslate is specified, or if the current
395 // function matches the -translate-only option. If translation is disabled,
396 // just dump the high-level IR and continue.
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800397 if (getFlags().getDisableTranslation() ||
Jim Stichnothdd6dcfa2016-04-18 12:52:09 -0700398 !getFlags().matchTranslateOnly(Func->getFunctionName(),
399 Func->getSequenceNumber())) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800400 Func->dump();
Jim Stichnoth5f55d402016-06-27 07:30:56 -0700401 // Add a dummy work item as a placeholder. This maintains sequence
402 // numbers so that the emitter thread will emit subsequent functions.
403 Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber());
404 emitQueueBlockingPush(std::move(Item));
Jim Stichnothbbca7542015-02-11 16:08:31 -0800405 continue; // Func goes out of scope and gets deleted
406 }
John Portof8b4cc82015-06-09 18:06:19 -0700407
Jim Stichnothbbca7542015-02-11 16:08:31 -0800408 Func->translate();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800409 if (Func->hasError()) {
410 getErrorStatus()->assign(EC_Translation);
411 OstreamLocker L(this);
Karl Schimpf2f67b922015-04-22 15:20:16 -0700412 getStrError() << "ICE translation error: " << Func->getFunctionName()
Jim Stichnothb40595a2016-01-29 06:14:31 -0800413 << ": " << Func->getError() << ": "
414 << Func->getFunctionNameAndSize() << "\n";
John Portobd2e2312016-03-15 11:06:25 -0700415 Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber());
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800416 } else {
Jim Stichnoth24824e72015-02-12 21:35:34 -0800417 Func->getAssembler<>()->setInternal(Func->getInternal());
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800418 switch (getFlags().getOutFileType()) {
419 case FT_Elf:
420 case FT_Iasm: {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800421 Func->emitIAS();
422 // The Cfg has already emitted into the assembly buffer, so
423 // stats have been fully collected into this thread's TLS.
424 // Dump them before TLS is reset for the next Cfg.
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700425 if (BuildDefs::dump())
Jim Stichnothb5eee3d2016-03-31 11:05:39 -0700426 dumpStats(Func.get());
John Portobd2e2312016-03-15 11:06:25 -0700427 auto Asm = Func->releaseAssembler();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800428 // Copy relevant fields into Asm before Func is deleted.
429 Asm->setFunctionName(Func->getFunctionName());
John Portobd2e2312016-03-15 11:06:25 -0700430 Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber(),
431 std::move(Asm));
John Portof8b4cc82015-06-09 18:06:19 -0700432 Item->setGlobalInits(Func->getGlobalInits());
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800433 } break;
434 case FT_Asm:
Jim Stichnothbbca7542015-02-11 16:08:31 -0800435 // The Cfg has not been emitted yet, so stats are not ready
436 // to be dumped.
John Portof8b4cc82015-06-09 18:06:19 -0700437 std::unique_ptr<VariableDeclarationList> GlobalInits =
438 Func->getGlobalInits();
John Portobd2e2312016-03-15 11:06:25 -0700439 Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber(),
440 std::move(Func));
John Portof8b4cc82015-06-09 18:06:19 -0700441 Item->setGlobalInits(std::move(GlobalInits));
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800442 break;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800443 }
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800444 }
John Portobd2e2312016-03-15 11:06:25 -0700445 assert(Item != nullptr);
446 emitQueueBlockingPush(std::move(Item));
Jim Stichnoth8e928382015-02-02 17:03:08 -0800447 // The Cfg now gets deleted as Func goes out of scope.
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800448 }
449}
450
Jim Stichnothbbca7542015-02-11 16:08:31 -0800451namespace {
452
Jim Stichnothbbca7542015-02-11 16:08:31 -0800453// Ensure Pending is large enough that Pending[Index] is valid.
John Portobd2e2312016-03-15 11:06:25 -0700454void resizePending(std::vector<std::unique_ptr<EmitterWorkItem>> *Pending,
455 uint32_t Index) {
456 if (Index >= Pending->size())
457 Utils::reserveAndResize(*Pending, Index + 1);
Jim Stichnothbbca7542015-02-11 16:08:31 -0800458}
459
460} // end of anonymous namespace
461
Lei Zhang04e9b1c2017-05-23 15:08:59 -0700462// static
463void GlobalContext::TlsInit() { ICE_TLS_INIT_FIELD(TLS); }
464
Jan Voungfb792842015-06-11 15:27:50 -0700465void GlobalContext::emitFileHeader() {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800466 TimerMarker T1(Ice::TimerStack::TT_emitAsm, this);
Jan Voungfb792842015-06-11 15:27:50 -0700467 if (getFlags().getOutFileType() == FT_Elf) {
468 getObjectWriter()->writeInitialELFHeader();
469 } else {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700470 if (!BuildDefs::dump()) {
Jim Stichnothc8799682015-06-22 13:04:10 -0700471 getStrError() << "emitFileHeader for non-ELF";
472 getErrorStatus()->assign(EC_Translation);
473 }
Jan Voungfb792842015-06-11 15:27:50 -0700474 TargetHeaderLowering::createLowering(this)->lower();
475 }
476}
477
Jim Stichnothcac003e2015-06-18 12:48:58 -0700478void GlobalContext::lowerConstants() { DataLowering->lowerConstants(); }
John Porto8b1a7052015-06-17 13:20:08 -0700479
Andrew Scull86df4e92015-07-30 13:54:44 -0700480void GlobalContext::lowerJumpTables() { DataLowering->lowerJumpTables(); }
481
Jaydeep Patil3da9f652016-11-03 22:54:06 -0700482void GlobalContext::emitTargetRODataSections() {
483 DataLowering->emitTargetRODataSections();
484}
485
John Portoa78e4ba2016-03-15 09:28:04 -0700486void GlobalContext::saveBlockInfoPtrs() {
487 for (VariableDeclaration *Global : Globals) {
John Porto844211e2016-02-04 08:42:48 -0800488 if (Cfg::isProfileGlobal(*Global)) {
John Portoa78e4ba2016-03-15 09:28:04 -0700489 ProfileBlockInfos.push_back(Global);
John Porto844211e2016-02-04 08:42:48 -0800490 }
491 }
492}
493
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700494void GlobalContext::lowerGlobals(const std::string &SectionSuffix) {
John Porto8b1a7052015-06-17 13:20:08 -0700495 TimerMarker T(TimerStack::TT_emitGlobalInitializers, this);
Karl Schimpfd4699942016-04-02 09:55:31 -0700496 const bool DumpGlobalVariables =
497 BuildDefs::dump() && (getFlags().getVerbose() & IceV_GlobalInit) &&
Jim Stichnothdd6dcfa2016-04-18 12:52:09 -0700498 getFlags().matchVerboseFocusOn("", 0);
John Porto8b1a7052015-06-17 13:20:08 -0700499 if (DumpGlobalVariables) {
500 OstreamLocker L(this);
501 Ostream &Stream = getStrDump();
502 for (const Ice::VariableDeclaration *Global : Globals) {
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800503 Global->dump(Stream);
John Porto8b1a7052015-06-17 13:20:08 -0700504 }
505 }
Karl Schimpfd4699942016-04-02 09:55:31 -0700506 if (getFlags().getDisableTranslation())
John Porto8b1a7052015-06-17 13:20:08 -0700507 return;
508
John Portoa78e4ba2016-03-15 09:28:04 -0700509 saveBlockInfoPtrs();
Qining Lu7cd53512015-06-26 09:36:00 -0700510 // If we need to shuffle the layout of global variables, shuffle them now.
John Portoc5bc5cb2016-03-21 11:18:02 -0700511 if (getFlags().getReorderGlobalVariables()) {
Qining Luaee5fa82015-08-20 14:59:03 -0700512 // Create a random number generator for global variable reordering.
513 RandomNumberGenerator RNG(getFlags().getRandomSeed(),
514 RPE_GlobalVariableReordering);
Qining Lu7cd53512015-06-26 09:36:00 -0700515 RandomShuffle(Globals.begin(), Globals.end(),
Qining Luaee5fa82015-08-20 14:59:03 -0700516 [&RNG](int N) { return (uint32_t)RNG.next(N); });
Qining Lu7cd53512015-06-26 09:36:00 -0700517 }
Thomas Livelyaab70992016-06-07 13:54:59 -0700518
519 if (!BuildDefs::minimal() && Instrumentor)
Thomas Lively3f5cb6f2016-06-13 11:23:29 -0700520 Instrumentor->instrumentGlobals(Globals);
Thomas Livelyaab70992016-06-07 13:54:59 -0700521
John Porto8b1a7052015-06-17 13:20:08 -0700522 DataLowering->lowerGlobals(Globals, SectionSuffix);
John Portoa78e4ba2016-03-15 09:28:04 -0700523 if (ProfileBlockInfos.empty() && DisposeGlobalVariablesAfterLowering) {
524 Globals.clearAndPurge();
525 } else {
526 Globals.clear();
John Porto1bec8bc2015-06-22 10:51:13 -0700527 }
John Porto8b1a7052015-06-17 13:20:08 -0700528}
529
530void GlobalContext::lowerProfileData() {
John Porto1bec8bc2015-06-22 10:51:13 -0700531 // ProfileBlockInfoVarDecl is initialized in the constructor, and will only
532 // ever be nullptr after this method completes. This assertion is a convoluted
533 // way of ensuring lowerProfileData is invoked a single time.
John Portoa78e4ba2016-03-15 09:28:04 -0700534 assert(ProfileBlockInfoVarDecl == nullptr);
535
536 auto GlobalVariablePool = getInitializerAllocator();
537 ProfileBlockInfoVarDecl =
538 VariableDeclaration::createExternal(GlobalVariablePool.get());
539 ProfileBlockInfoVarDecl->setAlignment(typeWidthInBytes(IceType_i64));
540 ProfileBlockInfoVarDecl->setIsConstant(true);
541
542 // Note: if you change this symbol, make sure to update
543 // runtime/szrt_profiler.c as well.
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700544 ProfileBlockInfoVarDecl->setName(this, "__Sz_block_profile_info");
John Portoa78e4ba2016-03-15 09:28:04 -0700545
546 for (const VariableDeclaration *PBI : ProfileBlockInfos) {
547 if (Cfg::isProfileGlobal(*PBI)) {
548 constexpr RelocOffsetT BlockExecutionCounterOffset = 0;
549 ProfileBlockInfoVarDecl->addInitializer(
550 VariableDeclaration::RelocInitializer::create(
551 GlobalVariablePool.get(), PBI,
552 {RelocOffset::create(this, BlockExecutionCounterOffset)}));
553 }
554 }
555
John Porto8b1a7052015-06-17 13:20:08 -0700556 // This adds a 64-bit sentinel entry to the end of our array. For 32-bit
557 // architectures this will waste 4 bytes.
558 const SizeT Sizeof64BitNullPtr = typeWidthInBytes(IceType_i64);
559 ProfileBlockInfoVarDecl->addInitializer(
John Portoa78e4ba2016-03-15 09:28:04 -0700560 VariableDeclaration::ZeroInitializer::create(GlobalVariablePool.get(),
561 Sizeof64BitNullPtr));
John Porto1bec8bc2015-06-22 10:51:13 -0700562 Globals.push_back(ProfileBlockInfoVarDecl);
John Porto8b1a7052015-06-17 13:20:08 -0700563 constexpr char ProfileDataSection[] = "$sz_profiler$";
564 lowerGlobals(ProfileDataSection);
565}
566
Lei Zhang04e9b1c2017-05-23 15:08:59 -0700567void GlobalContext::emitterWrapper(ThreadContext *MyTLS) {
568 ICE_TLS_SET_FIELD(TLS, MyTLS);
569 emitItems();
570}
571
Jim Stichnothbbca7542015-02-11 16:08:31 -0800572void GlobalContext::emitItems() {
573 const bool Threaded = !getFlags().isSequential();
574 // Pending is a vector containing the reassembled, ordered list of
575 // work items. When we're ready for the next item, we first check
576 // whether it's in the Pending list. If not, we take an item from
577 // the work queue, and if it's not the item we're waiting for, we
578 // insert it into Pending and repeat. The work item is deleted
579 // after it is processed.
John Portobd2e2312016-03-15 11:06:25 -0700580 std::vector<std::unique_ptr<EmitterWorkItem>> Pending;
Jim Stichnothbbca7542015-02-11 16:08:31 -0800581 uint32_t DesiredSequenceNumber = getFirstSequenceNumber();
Qining Lu7cd53512015-06-26 09:36:00 -0700582 uint32_t ShuffleStartIndex = DesiredSequenceNumber;
583 uint32_t ShuffleEndIndex = DesiredSequenceNumber;
584 bool EmitQueueEmpty = false;
585 const uint32_t ShuffleWindowSize =
586 std::max(1u, getFlags().getReorderFunctionsWindowSize());
John Portoc5bc5cb2016-03-21 11:18:02 -0700587 bool Shuffle = Threaded && getFlags().getReorderFunctions();
Qining Luaee5fa82015-08-20 14:59:03 -0700588 // Create a random number generator for function reordering.
589 RandomNumberGenerator RNG(getFlags().getRandomSeed(), RPE_FunctionReordering);
590
Qining Lu7cd53512015-06-26 09:36:00 -0700591 while (!EmitQueueEmpty) {
John Portobd2e2312016-03-15 11:06:25 -0700592 resizePending(&Pending, DesiredSequenceNumber);
Jim Stichnothbbca7542015-02-11 16:08:31 -0800593 // See if Pending contains DesiredSequenceNumber.
John Portobd2e2312016-03-15 11:06:25 -0700594 if (Pending[DesiredSequenceNumber] == nullptr) {
Qining Lu7cd53512015-06-26 09:36:00 -0700595 // We need to fetch an EmitterWorkItem from the queue.
John Portobd2e2312016-03-15 11:06:25 -0700596 auto RawItem = emitQueueBlockingPop();
Qining Lu7cd53512015-06-26 09:36:00 -0700597 if (RawItem == nullptr) {
598 // This is the notifier for an empty queue.
599 EmitQueueEmpty = true;
600 } else {
601 // We get an EmitterWorkItem, we need to add it to Pending.
602 uint32_t ItemSeq = RawItem->getSequenceNumber();
603 if (Threaded && ItemSeq != DesiredSequenceNumber) {
604 // Not the desired one, add it to Pending but do not increase
605 // DesiredSequenceNumber. Continue the loop, do not emit the item.
John Portobd2e2312016-03-15 11:06:25 -0700606 resizePending(&Pending, ItemSeq);
607 Pending[ItemSeq] = std::move(RawItem);
Qining Lu7cd53512015-06-26 09:36:00 -0700608 continue;
609 }
610 // ItemSeq == DesiredSequenceNumber, we need to check if we should
611 // emit it or not. If !Threaded, we're OK with ItemSeq !=
612 // DesiredSequenceNumber.
John Portobd2e2312016-03-15 11:06:25 -0700613 Pending[DesiredSequenceNumber] = std::move(RawItem);
Jim Stichnothbbca7542015-02-11 16:08:31 -0800614 }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800615 }
John Portobd2e2312016-03-15 11:06:25 -0700616 const auto *CurrentWorkItem = Pending[DesiredSequenceNumber].get();
617
Qining Lu7cd53512015-06-26 09:36:00 -0700618 // We have the desired EmitterWorkItem or nullptr as the end notifier.
619 // If the emitter queue is not empty, increase DesiredSequenceNumber and
620 // ShuffleEndIndex.
621 if (!EmitQueueEmpty) {
622 DesiredSequenceNumber++;
623 ShuffleEndIndex++;
624 }
625
626 if (Shuffle) {
627 // Continue fetching EmitterWorkItem if function reordering is turned on,
628 // and emit queue is not empty, and the number of consecutive pending
629 // items is smaller than the window size, and RawItem is not a
630 // WI_GlobalInits kind. Emit WI_GlobalInits kind block first to avoid
631 // holding an arbitrarily large GlobalDeclarationList.
632 if (!EmitQueueEmpty &&
633 ShuffleEndIndex - ShuffleStartIndex < ShuffleWindowSize &&
John Portobd2e2312016-03-15 11:06:25 -0700634 CurrentWorkItem->getKind() != EmitterWorkItem::WI_GlobalInits)
Qining Lu7cd53512015-06-26 09:36:00 -0700635 continue;
636
637 // Emit the EmitterWorkItem between Pending[ShuffleStartIndex] to
638 // Pending[ShuffleEndIndex]. If function reordering turned on, shuffle the
639 // pending items from Pending[ShuffleStartIndex] to
640 // Pending[ShuffleEndIndex].
641 RandomShuffle(Pending.begin() + ShuffleStartIndex,
642 Pending.begin() + ShuffleEndIndex,
Qining Luaee5fa82015-08-20 14:59:03 -0700643 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
Qining Lu7cd53512015-06-26 09:36:00 -0700644 }
645
646 // Emit the item from ShuffleStartIndex to ShuffleEndIndex.
647 for (uint32_t I = ShuffleStartIndex; I < ShuffleEndIndex; I++) {
John Portobd2e2312016-03-15 11:06:25 -0700648 std::unique_ptr<EmitterWorkItem> Item = std::move(Pending[I]);
Qining Lu7cd53512015-06-26 09:36:00 -0700649
650 switch (Item->getKind()) {
651 case EmitterWorkItem::WI_Nop:
652 break;
653 case EmitterWorkItem::WI_GlobalInits: {
654 accumulateGlobals(Item->getGlobalInits());
655 } break;
656 case EmitterWorkItem::WI_Asm: {
657 lowerGlobalsIfNoCodeHasBeenSeen();
658 accumulateGlobals(Item->getGlobalInits());
659
660 std::unique_ptr<Assembler> Asm = Item->getAsm();
661 Asm->alignFunction();
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700662 GlobalString Name = Asm->getFunctionName();
Qining Lu7cd53512015-06-26 09:36:00 -0700663 switch (getFlags().getOutFileType()) {
664 case FT_Elf:
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800665 getObjectWriter()->writeFunctionCode(Name, Asm->getInternal(),
Qining Lu7cd53512015-06-26 09:36:00 -0700666 Asm.get());
667 break;
668 case FT_Iasm: {
669 OstreamLocker L(this);
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800670 Cfg::emitTextHeader(Name, this, Asm.get());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700671 Asm->emitIASBytes(this);
Qining Lu7cd53512015-06-26 09:36:00 -0700672 } break;
673 case FT_Asm:
674 llvm::report_fatal_error("Unexpected FT_Asm");
675 break;
676 }
677 } break;
678 case EmitterWorkItem::WI_Cfg: {
679 if (!BuildDefs::dump())
680 llvm::report_fatal_error("WI_Cfg work item created inappropriately");
681 lowerGlobalsIfNoCodeHasBeenSeen();
682 accumulateGlobals(Item->getGlobalInits());
683
684 assert(getFlags().getOutFileType() == FT_Asm);
685 std::unique_ptr<Cfg> Func = Item->getCfg();
686 // Unfortunately, we have to temporarily install the Cfg in TLS
687 // because Variable::asType() uses the allocator to create the
688 // differently-typed copy.
John Portoe82b5602016-02-24 15:58:55 -0800689 CfgLocalAllocatorScope _(Func.get());
Qining Lu7cd53512015-06-26 09:36:00 -0700690 Func->emit();
Jim Stichnothb5eee3d2016-03-31 11:05:39 -0700691 dumpStats(Func.get());
Qining Lu7cd53512015-06-26 09:36:00 -0700692 } break;
693 }
694 }
695 // Update the start index for next shuffling queue
696 ShuffleStartIndex = ShuffleEndIndex;
Jim Stichnothbbca7542015-02-11 16:08:31 -0800697 }
John Portof8b4cc82015-06-09 18:06:19 -0700698
John Porto8b1a7052015-06-17 13:20:08 -0700699 // In case there are no code to be generated, we invoke the conditional
700 // lowerGlobals again -- this is a no-op if code has been emitted.
701 lowerGlobalsIfNoCodeHasBeenSeen();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800702}
703
Karl Schimpf9d98d792014-10-13 15:01:08 -0700704GlobalContext::~GlobalContext() {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800705 llvm::DeleteContainerPointers(AllThreadContexts);
John Porto1bec8bc2015-06-22 10:51:13 -0700706 LockedPtr<DestructorArray> Dtors = getDestructors();
707 // Destructors are invoked in the opposite object construction order.
Andrew Scull00741a02015-09-16 19:04:09 -0700708 for (const auto &Dtor : reverse_range(*Dtors))
709 Dtor();
Karl Schimpf9d98d792014-10-13 15:01:08 -0700710}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700711
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700712void GlobalContext::dumpStrings() {
713 if (!getFlags().getDumpStrings())
714 return;
715 OstreamLocker _(this);
716 Ostream &Str = getStrDump();
717 Str << "GlobalContext strings:\n";
718 getStrings()->dump(Str);
719}
720
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800721void GlobalContext::dumpConstantLookupCounts() {
722 if (!BuildDefs::dump())
723 return;
Karl Schimpfd4699942016-04-02 09:55:31 -0700724 const bool DumpCounts = (getFlags().getVerbose() & IceV_ConstPoolStats) &&
Jim Stichnothdd6dcfa2016-04-18 12:52:09 -0700725 getFlags().matchVerboseFocusOn("", 0);
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800726 if (!DumpCounts)
727 return;
728
729 OstreamLocker _(this);
730 Ostream &Str = getStrDump();
731 Str << "Constant pool use stats: count+value+type\n";
732#define X(WhichPool) \
733 for (auto *C : getConstPool()->WhichPool.getConstantPool()) { \
734 Str << C->getLookupCount() << " "; \
735 C->dump(Str); \
736 Str << " " << C->getType() << "\n"; \
737 }
738 X(Integers1);
739 X(Integers8);
740 X(Integers16);
741 X(Integers32);
742 X(Integers64);
743 X(Floats);
744 X(Doubles);
745 X(Relocatables);
746 X(ExternRelocatables);
747#undef X
748}
749
Andrew Scull57e12682015-09-16 11:30:19 -0700750// TODO(stichnot): Consider adding thread-local caches of constant pool entries
751// to reduce contention.
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800752
753// All locking is done by the getConstantInt[0-9]+() target function.
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800754Constant *GlobalContext::getConstantInt(Type Ty, int64_t Value) {
755 switch (Ty) {
756 case IceType_i1:
757 return getConstantInt1(Value);
758 case IceType_i8:
759 return getConstantInt8(Value);
760 case IceType_i16:
761 return getConstantInt16(Value);
762 case IceType_i32:
763 return getConstantInt32(Value);
764 case IceType_i64:
765 return getConstantInt64(Value);
766 default:
767 llvm_unreachable("Bad integer type for getConstant");
768 }
Jim Stichnothae953202014-12-20 06:17:49 -0800769 return nullptr;
Jan Voungbc004632014-09-16 15:09:10 -0700770}
771
Karl Schimpf20070e82016-03-17 13:30:13 -0700772Constant *GlobalContext::getConstantInt1Internal(int8_t ConstantInt1) {
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800773 ConstantInt1 &= INT8_C(1);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800774 return getConstPool()->Integers1.getOrAdd(this, ConstantInt1);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800775}
776
Karl Schimpf20070e82016-03-17 13:30:13 -0700777Constant *GlobalContext::getConstantInt8Internal(int8_t ConstantInt8) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800778 return getConstPool()->Integers8.getOrAdd(this, ConstantInt8);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800779}
780
Karl Schimpf20070e82016-03-17 13:30:13 -0700781Constant *GlobalContext::getConstantInt16Internal(int16_t ConstantInt16) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800782 return getConstPool()->Integers16.getOrAdd(this, ConstantInt16);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800783}
784
Karl Schimpf20070e82016-03-17 13:30:13 -0700785Constant *GlobalContext::getConstantInt32Internal(int32_t ConstantInt32) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800786 return getConstPool()->Integers32.getOrAdd(this, ConstantInt32);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800787}
788
Karl Schimpf20070e82016-03-17 13:30:13 -0700789Constant *GlobalContext::getConstantInt64Internal(int64_t ConstantInt64) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800790 return getConstPool()->Integers64.getOrAdd(this, ConstantInt64);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700791}
792
793Constant *GlobalContext::getConstantFloat(float ConstantFloat) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800794 return getConstPool()->Floats.getOrAdd(this, ConstantFloat);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700795}
796
797Constant *GlobalContext::getConstantDouble(double ConstantDouble) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800798 return getConstPool()->Doubles.getOrAdd(this, ConstantDouble);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700799}
800
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700801Constant *GlobalContext::getConstantSymWithEmitString(
802 const RelocOffsetT Offset, const RelocOffsetArray &OffsetExpr,
803 GlobalString Name, const std::string &EmitString) {
John Porto27fddcc2016-02-02 15:06:09 -0800804 return getConstPool()->Relocatables.getOrAdd(
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800805 this, RelocatableTuple(Offset, OffsetExpr, Name, EmitString));
John Porto27fddcc2016-02-02 15:06:09 -0800806}
807
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800808Constant *GlobalContext::getConstantSym(RelocOffsetT Offset,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700809 GlobalString Name) {
John Porto27fddcc2016-02-02 15:06:09 -0800810 constexpr char EmptyEmitString[] = "";
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700811 return getConstantSymWithEmitString(Offset, {}, Name, EmptyEmitString);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700812}
813
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700814Constant *GlobalContext::getConstantExternSym(GlobalString Name) {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700815 constexpr RelocOffsetT Offset = 0;
Jan Voung261cae32015-02-01 10:31:03 -0800816 return getConstPool()->ExternRelocatables.getOrAdd(
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800817 this, RelocatableTuple(Offset, {}, Name));
Jan Voung261cae32015-02-01 10:31:03 -0800818}
819
Matt Walad8f4a7d2014-06-18 09:55:03 -0700820Constant *GlobalContext::getConstantUndef(Type Ty) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800821 return getConstPool()->Undefs.getOrAdd(this, Ty);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700822}
823
824Constant *GlobalContext::getConstantZero(Type Ty) {
Karl Schimpf20070e82016-03-17 13:30:13 -0700825 Constant *Zero = ConstZeroForType[Ty];
826 if (Zero == nullptr)
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700827 llvm::report_fatal_error("Unsupported constant type: " + typeStdString(Ty));
Karl Schimpf20070e82016-03-17 13:30:13 -0700828 return Zero;
829}
830
831// All locking is done by the getConstant*() target function.
832Constant *GlobalContext::getConstantZeroInternal(Type Ty) {
Matt Walad8f4a7d2014-06-18 09:55:03 -0700833 switch (Ty) {
834 case IceType_i1:
Karl Schimpf20070e82016-03-17 13:30:13 -0700835 return getConstantInt1Internal(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700836 case IceType_i8:
Karl Schimpf20070e82016-03-17 13:30:13 -0700837 return getConstantInt8Internal(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700838 case IceType_i16:
Karl Schimpf20070e82016-03-17 13:30:13 -0700839 return getConstantInt16Internal(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700840 case IceType_i32:
Karl Schimpf20070e82016-03-17 13:30:13 -0700841 return getConstantInt32Internal(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700842 case IceType_i64:
Karl Schimpf20070e82016-03-17 13:30:13 -0700843 return getConstantInt64Internal(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700844 case IceType_f32:
845 return getConstantFloat(0);
846 case IceType_f64:
847 return getConstantDouble(0);
Karl Schimpf20070e82016-03-17 13:30:13 -0700848 default:
849 return nullptr;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700850 }
Matt Walad8f4a7d2014-06-18 09:55:03 -0700851}
852
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800853ConstantList GlobalContext::getConstantPool(Type Ty) {
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700854 switch (Ty) {
855 case IceType_i1:
856 case IceType_i8:
Qining Lu253dc8a2015-06-22 10:10:23 -0700857 return getConstPool()->Integers8.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700858 case IceType_i16:
Qining Lu253dc8a2015-06-22 10:10:23 -0700859 return getConstPool()->Integers16.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700860 case IceType_i32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800861 return getConstPool()->Integers32.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700862 case IceType_i64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800863 return getConstPool()->Integers64.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700864 case IceType_f32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800865 return getConstPool()->Floats.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700866 case IceType_f64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800867 return getConstPool()->Doubles.getConstantPool();
Matt Wala928f1292014-07-07 16:50:46 -0700868 case IceType_v4i1:
869 case IceType_v8i1:
870 case IceType_v16i1:
871 case IceType_v16i8:
872 case IceType_v8i16:
873 case IceType_v4i32:
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700874 case IceType_v4f32:
875 llvm::report_fatal_error("Unsupported constant type: " + typeStdString(Ty));
876 break;
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700877 case IceType_void:
878 case IceType_NUM:
879 break;
880 }
881 llvm_unreachable("Unknown type");
882}
883
Jan Voung261cae32015-02-01 10:31:03 -0800884ConstantList GlobalContext::getConstantExternSyms() {
885 return getConstPool()->ExternRelocatables.getConstantPool();
886}
887
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700888GlobalString GlobalContext::getGlobalString(const std::string &Name) {
889 return GlobalString::createWithString(this, Name);
890}
891
Andrew Scull1eda90a2015-08-04 17:03:19 -0700892JumpTableDataList GlobalContext::getJumpTables() {
893 JumpTableDataList JumpTables(*getJumpTableList());
Andrew Scull57e12682015-09-16 11:30:19 -0700894 // Make order deterministic by sorting into functions and then ID of the jump
895 // table within that function.
Qining Luaee5fa82015-08-20 14:59:03 -0700896 std::sort(JumpTables.begin(), JumpTables.end(),
897 [](const JumpTableData &A, const JumpTableData &B) {
898 if (A.getFunctionName() != B.getFunctionName())
899 return A.getFunctionName() < B.getFunctionName();
900 return A.getId() < B.getId();
901 });
902
John Portoc5bc5cb2016-03-21 11:18:02 -0700903 if (getFlags().getReorderPooledConstants()) {
Qining Luaee5fa82015-08-20 14:59:03 -0700904 // If reorder-pooled-constants option is set to true, we also shuffle the
905 // jump tables before emitting them.
906
907 // Create a random number generator for jump tables reordering, considering
908 // jump tables as pooled constants.
909 RandomNumberGenerator RNG(getFlags().getRandomSeed(),
910 RPE_PooledConstantReordering);
John Portoe0d9afa2015-08-05 10:13:44 -0700911 RandomShuffle(JumpTables.begin(), JumpTables.end(),
Qining Luaee5fa82015-08-20 14:59:03 -0700912 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
Andrew Scull1eda90a2015-08-04 17:03:19 -0700913 }
914 return JumpTables;
915}
916
John Porto03077212016-04-05 06:30:21 -0700917void GlobalContext::addJumpTableData(JumpTableData JumpTable) {
918 getJumpTableList()->emplace_back(std::move(JumpTable));
Andrew Scull86df4e92015-07-30 13:54:44 -0700919}
920
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700921TimerStackIdT GlobalContext::newTimerStackID(const std::string &Name) {
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800922 if (!BuildDefs::timers())
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800923 return 0;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800924 auto Timers = getTimers();
925 TimerStackIdT NewID = Timers->size();
926 Timers->push_back(TimerStack(Name));
Jim Stichnoth8363a062014-10-07 10:02:38 -0700927 return NewID;
928}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700929
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800930TimerIdT GlobalContext::getTimerID(TimerStackIdT StackID,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700931 const std::string &Name) {
Jim Stichnoth2b000fd2016-04-06 06:37:15 -0700932 auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800933 assert(StackID < Timers->size());
934 return Timers->at(StackID).getTimerID(Name);
935}
936
Jim Stichnoth8363a062014-10-07 10:02:38 -0700937void GlobalContext::pushTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnoth2b000fd2016-04-06 06:37:15 -0700938 auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800939 assert(StackID < Timers->size());
940 Timers->at(StackID).push(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700941}
942
943void GlobalContext::popTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnoth2b000fd2016-04-06 06:37:15 -0700944 auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800945 assert(StackID < Timers->size());
946 Timers->at(StackID).pop(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700947}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700948
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700949void GlobalContext::resetTimer(TimerStackIdT StackID) {
Jim Stichnoth2b000fd2016-04-06 06:37:15 -0700950 auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800951 assert(StackID < Timers->size());
952 Timers->at(StackID).reset();
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700953}
954
Jim Stichnoth2b000fd2016-04-06 06:37:15 -0700955std::string GlobalContext::getTimerName(TimerStackIdT StackID) {
956 auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
957 assert(StackID < Timers->size());
958 return Timers->at(StackID).getName();
959}
960
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700961void GlobalContext::setTimerName(TimerStackIdT StackID,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700962 const std::string &NewName) {
Jim Stichnoth2b000fd2016-04-06 06:37:15 -0700963 auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800964 assert(StackID < Timers->size());
965 Timers->at(StackID).setName(NewName);
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700966}
967
Andrew Scull57e12682015-09-16 11:30:19 -0700968// Note: optQueueBlockingPush and optQueueBlockingPop use unique_ptr at the
969// interface to take and transfer ownership, but they internally store the raw
970// Cfg pointer in the work queue. This allows e.g. future queue optimizations
971// such as the use of atomics to modify queue elements.
Karl Schimpfe8457a22016-03-31 10:20:23 -0700972void GlobalContext::optQueueBlockingPush(std::unique_ptr<OptWorkItem> Item) {
973 assert(Item);
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800974 {
975 TimerMarker _(TimerStack::TT_qTransPush, this);
Karl Schimpfe8457a22016-03-31 10:20:23 -0700976 OptQ.blockingPush(std::move(Item));
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800977 }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800978 if (getFlags().isSequential())
979 translateFunctions();
Jim Stichnoth8e928382015-02-02 17:03:08 -0800980}
981
Karl Schimpfe8457a22016-03-31 10:20:23 -0700982std::unique_ptr<OptWorkItem> GlobalContext::optQueueBlockingPop() {
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800983 TimerMarker _(TimerStack::TT_qTransPop, this);
Karl Schimpf3018cf22016-04-11 14:49:01 -0700984 return OptQ.blockingPop(OptQWakeupSize);
Jim Stichnothbbca7542015-02-11 16:08:31 -0800985}
986
John Portobd2e2312016-03-15 11:06:25 -0700987void GlobalContext::emitQueueBlockingPush(
988 std::unique_ptr<EmitterWorkItem> Item) {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800989 assert(Item);
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800990 {
991 TimerMarker _(TimerStack::TT_qEmitPush, this);
John Portobd2e2312016-03-15 11:06:25 -0700992 EmitQ.blockingPush(std::move(Item));
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800993 }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800994 if (getFlags().isSequential())
995 emitItems();
996}
997
John Portobd2e2312016-03-15 11:06:25 -0700998std::unique_ptr<EmitterWorkItem> GlobalContext::emitQueueBlockingPop() {
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800999 TimerMarker _(TimerStack::TT_qEmitPop, this);
Jim Stichnothbbca7542015-02-11 16:08:31 -08001000 return EmitQ.blockingPop();
Jim Stichnoth8e928382015-02-02 17:03:08 -08001001}
1002
Lei Zhang04e9b1c2017-05-23 15:08:59 -07001003void GlobalContext::initParserThread() {
1004 ThreadContext *Tls = new ThreadContext();
1005 auto Timers = getTimers();
1006 Timers->initInto(Tls->Timers);
1007 AllThreadContexts.push_back(Tls);
1008 ICE_TLS_SET_FIELD(TLS, Tls);
1009}
1010
1011void GlobalContext::startWorkerThreads() {
1012 size_t NumWorkers = getFlags().getNumTranslationThreads();
1013 auto Timers = getTimers();
1014 for (size_t i = 0; i < NumWorkers; ++i) {
1015 ThreadContext *WorkerTLS = new ThreadContext();
1016 Timers->initInto(WorkerTLS->Timers);
1017 AllThreadContexts.push_back(WorkerTLS);
1018 TranslationThreads.push_back(std::thread(
1019 &GlobalContext::translateFunctionsWrapper, this, WorkerTLS));
1020 }
1021 if (NumWorkers) {
1022 ThreadContext *WorkerTLS = new ThreadContext();
1023 Timers->initInto(WorkerTLS->Timers);
1024 AllThreadContexts.push_back(WorkerTLS);
1025 EmitterThreads.push_back(
1026 std::thread(&GlobalContext::emitterWrapper, this, WorkerTLS));
1027 }
1028}
1029
1030void GlobalContext::resetStats() {
1031 if (BuildDefs::dump())
1032 ICE_TLS_GET_FIELD(TLS)->StatsFunction.reset();
1033}
1034
Jim Stichnothb5eee3d2016-03-31 11:05:39 -07001035void GlobalContext::dumpStats(const Cfg *Func) {
Karl Schimpfdf80eb82015-02-09 14:20:22 -08001036 if (!getFlags().getDumpStats())
Karl Schimpfb6c96af2014-11-17 10:58:39 -08001037 return;
Jim Stichnothb5eee3d2016-03-31 11:05:39 -07001038 if (Func == nullptr) {
1039 getStatsCumulative()->dump(Func, this);
Jim Stichnothe4a8f402015-01-20 12:52:51 -08001040 } else {
Jim Stichnothb5eee3d2016-03-31 11:05:39 -07001041 ICE_TLS_GET_FIELD(TLS)->StatsFunction.dump(Func, this);
Jim Stichnoth18735602014-09-16 19:59:35 -07001042 }
1043}
1044
Lei Zhang04e9b1c2017-05-23 15:08:59 -07001045void GlobalContext::statsUpdateEmitted(uint32_t InstCount) {
1046 if (!getFlags().getDumpStats())
1047 return;
1048 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
1049 Tls->StatsFunction.update(CodeStats::CS_InstCount, InstCount);
1050 Tls->StatsCumulative.update(CodeStats::CS_InstCount, InstCount);
1051}
1052
1053void GlobalContext::statsUpdateRegistersSaved(uint32_t Num) {
1054 if (!getFlags().getDumpStats())
1055 return;
1056 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
1057 Tls->StatsFunction.update(CodeStats::CS_RegsSaved, Num);
1058 Tls->StatsCumulative.update(CodeStats::CS_RegsSaved, Num);
1059}
1060
1061void GlobalContext::statsUpdateFrameBytes(uint32_t Bytes) {
1062 if (!getFlags().getDumpStats())
1063 return;
1064 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
1065 Tls->StatsFunction.update(CodeStats::CS_FrameByte, Bytes);
1066 Tls->StatsCumulative.update(CodeStats::CS_FrameByte, Bytes);
1067}
1068
1069void GlobalContext::statsUpdateSpills() {
1070 if (!getFlags().getDumpStats())
1071 return;
1072 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
1073 Tls->StatsFunction.update(CodeStats::CS_NumSpills);
1074 Tls->StatsCumulative.update(CodeStats::CS_NumSpills);
1075}
1076
1077void GlobalContext::statsUpdateFills() {
1078 if (!getFlags().getDumpStats())
1079 return;
1080 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
1081 Tls->StatsFunction.update(CodeStats::CS_NumFills);
1082 Tls->StatsCumulative.update(CodeStats::CS_NumFills);
1083}
1084
1085void GlobalContext::statsUpdateRPImms() {
1086 if (!getFlags().getDumpStats())
1087 return;
1088 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
1089 Tls->StatsFunction.update(CodeStats::CS_NumRPImms);
1090 Tls->StatsCumulative.update(CodeStats::CS_NumRPImms);
1091}
1092
Jim Stichnoth8363a062014-10-07 10:02:38 -07001093void GlobalContext::dumpTimers(TimerStackIdT StackID, bool DumpCumulative) {
Jim Stichnothb88d8c82016-03-11 15:33:00 -08001094 if (!BuildDefs::timers())
Karl Schimpfb6c96af2014-11-17 10:58:39 -08001095 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -08001096 auto Timers = getTimers();
1097 assert(Timers->size() > StackID);
1098 OstreamLocker L(this);
1099 Timers->at(StackID).dump(getStrDump(), DumpCumulative);
Jim Stichnoth8363a062014-10-07 10:02:38 -07001100}
1101
Jim Stichnoth2b000fd2016-04-06 06:37:15 -07001102void GlobalContext::dumpLocalTimers(const std::string &TimerNameOverride,
1103 TimerStackIdT StackID,
1104 bool DumpCumulative) {
1105 if (!BuildDefs::timers())
1106 return;
1107 auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
1108 assert(Timers->size() > StackID);
1109 // Temporarily override the thread-local timer name with the given name.
1110 // Don't do it permanently because the final timer merge at the end expects
1111 // the thread-local timer names to be the same as the global timer name.
1112 auto OrigName = getTimerName(StackID);
1113 setTimerName(StackID, TimerNameOverride);
1114 {
1115 OstreamLocker _(this);
1116 Timers->at(StackID).dump(getStrDump(), DumpCumulative);
1117 }
1118 setTimerName(StackID, OrigName);
1119}
1120
Jim Stichnoth467ffe52016-03-29 15:01:06 -07001121LockedPtr<StringPool>
1122GlobalStringPoolTraits::getStrings(const GlobalContext *PoolOwner) {
1123 return PoolOwner->getStrings();
1124}
1125
Jim Stichnothb88d8c82016-03-11 15:33:00 -08001126TimerIdT TimerMarker::getTimerIdFromFuncName(GlobalContext *Ctx,
Jim Stichnoth467ffe52016-03-29 15:01:06 -07001127 const std::string &FuncName) {
Jim Stichnothb88d8c82016-03-11 15:33:00 -08001128 if (!BuildDefs::timers())
1129 return 0;
Karl Schimpfd4699942016-04-02 09:55:31 -07001130 if (!getFlags().getTimeEachFunction())
Jim Stichnothb88d8c82016-03-11 15:33:00 -08001131 return 0;
1132 return Ctx->getTimerID(GlobalContext::TSK_Funcs, FuncName);
1133}
1134
Jim Stichnoth380d7b92015-01-30 13:10:39 -08001135void TimerMarker::push() {
1136 switch (StackID) {
1137 case GlobalContext::TSK_Default:
Jim Stichnoth318c01b2016-04-03 21:58:03 -07001138 Active = getFlags().getSubzeroTimingEnabled() ||
Jim Stichnothdd6dcfa2016-04-18 12:52:09 -07001139 !getFlags().getTimingFocusOnString().empty();
Jim Stichnoth380d7b92015-01-30 13:10:39 -08001140 break;
1141 case GlobalContext::TSK_Funcs:
Karl Schimpfd4699942016-04-02 09:55:31 -07001142 Active = getFlags().getTimeEachFunction();
Jim Stichnoth380d7b92015-01-30 13:10:39 -08001143 break;
1144 default:
1145 break;
Jim Stichnoth1c44d812014-12-08 14:57:52 -08001146 }
Jim Stichnoth380d7b92015-01-30 13:10:39 -08001147 if (Active)
1148 Ctx->pushTimer(ID, StackID);
1149}
1150
1151void TimerMarker::pushCfg(const Cfg *Func) {
1152 Ctx = Func->getContext();
Karl Schimpfd4699942016-04-02 09:55:31 -07001153 Active = Func->getFocusedTiming() || getFlags().getSubzeroTimingEnabled();
Jim Stichnoth380d7b92015-01-30 13:10:39 -08001154 if (Active)
1155 Ctx->pushTimer(ID, StackID);
Jim Stichnoth8363a062014-10-07 10:02:38 -07001156}
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001157
Jim Stichnotha5fe17a2015-01-26 11:10:03 -08001158ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS);
Jim Stichnothe4a8f402015-01-20 12:52:51 -08001159
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001160} // end of namespace Ice