blob: fdb56423476bf54cf5d308900e44a121c453a46e [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 Stichnoth5bc2b1d2014-05-22 13:38:48 -070026#include "IceTargetLowering.h"
Jim Stichnothc4554d72014-09-30 16:49:38 -070027#include "IceTimerTree.h"
Karl Schimpf20070e82016-03-17 13:30:13 -070028#include "IceTypes.def"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070029#include "IceTypes.h"
Jim Stichnoth98da9662015-06-27 06:38:08 -070030
Jim Stichnothb0051df2016-01-13 11:39:15 -080031#ifdef __clang__
Jim Stichnoth98da9662015-06-27 06:38:08 -070032#pragma clang diagnostic push
33#pragma clang diagnostic ignored "-Wunused-parameter"
Jim Stichnothb0051df2016-01-13 11:39:15 -080034#endif // __clang__
35
John Porto67f8de92015-06-25 10:14:17 -070036#include "llvm/Support/Timer.h"
Jim Stichnothb0051df2016-01-13 11:39:15 -080037
38#ifdef __clang__
Jim Stichnoth98da9662015-06-27 06:38:08 -070039#pragma clang diagnostic pop
Jim Stichnothb0051df2016-01-13 11:39:15 -080040#endif // __clang__
John Porto67f8de92015-06-25 10:14:17 -070041
Qining Lu7cd53512015-06-26 09:36:00 -070042#include <algorithm> // max()
John Porto67f8de92015-06-25 10:14:17 -070043
Jim Stichnothdddaf9c2014-12-04 14:09:21 -080044namespace std {
45template <> struct hash<Ice::RelocatableTuple> {
46 size_t operator()(const Ice::RelocatableTuple &Key) const {
Jim Stichnoth467ffe52016-03-29 15:01:06 -070047 // Use the relocatable's name, plus the hash of a combination of the number
48 // of OffsetExprs and the known, fixed offset for the reloc. We left shift
49 // the known relocatable by 5 trying to minimize the interaction between the
50 // bits in OffsetExpr.size() and Key.Offset.
51 return hash<Ice::SizeT>()(Key.Name.getID()) +
John Portoe82b5602016-02-24 15:58:55 -080052 hash<std::size_t>()(Key.OffsetExpr.size() + (Key.Offset << 5));
Jim Stichnothd2cb4362014-11-20 11:24:42 -080053 }
54};
Jim Stichnothdddaf9c2014-12-04 14:09:21 -080055} // end of namespace std
Jim Stichnothd2cb4362014-11-20 11:24:42 -080056
Jim Stichnothf7c9a142014-04-29 10:52:43 -070057namespace Ice {
58
Jim Stichnoth5bfe2152015-03-19 13:51:56 -070059namespace {
60
Andrew Scull57e12682015-09-16 11:30:19 -070061// Define the key comparison function for the constant pool's unordered_map,
62// but only for key types of interest: integer types, floating point types, and
63// the special RelocatableTuple.
Jim Stichnoth5bfe2152015-03-19 13:51:56 -070064template <typename KeyType, class Enable = void> struct KeyCompare {};
65
66template <typename KeyType>
67struct KeyCompare<KeyType,
68 typename std::enable_if<
69 std::is_integral<KeyType>::value ||
70 std::is_same<KeyType, RelocatableTuple>::value>::type> {
71 bool operator()(const KeyType &Value1, const KeyType &Value2) const {
72 return Value1 == Value2;
73 }
74};
75template <typename KeyType>
76struct KeyCompare<KeyType, typename std::enable_if<
77 std::is_floating_point<KeyType>::value>::type> {
78 bool operator()(const KeyType &Value1, const KeyType &Value2) const {
79 return !memcmp(&Value1, &Value2, sizeof(KeyType));
80 }
81};
82
Andrew Scull57e12682015-09-16 11:30:19 -070083// Define a key comparison function for sorting the constant pool's values
84// after they are dumped to a vector. This covers integer types, floating point
85// types, and ConstantRelocatable values.
Jim Stichnoth6e293c82015-04-09 09:11:18 -070086template <typename ValueType, class Enable = void> struct KeyCompareLess {};
87
88template <typename ValueType>
89struct KeyCompareLess<ValueType,
90 typename std::enable_if<std::is_floating_point<
91 typename ValueType::PrimType>::value>::type> {
92 bool operator()(const Constant *Const1, const Constant *Const2) const {
Andrew Scull8072bae2015-09-14 16:01:26 -070093 using CompareType = uint64_t;
Jim Stichnoth6e293c82015-04-09 09:11:18 -070094 static_assert(sizeof(typename ValueType::PrimType) <= sizeof(CompareType),
95 "Expected floating-point type of width 64-bit or less");
96 typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue();
97 typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue();
98 // We avoid "V1<V2" because of NaN.
99 // We avoid "memcmp(&V1,&V2,sizeof(V1))<0" which depends on the
100 // endian-ness of the host system running Subzero.
101 // Instead, compare the result of bit_cast to uint64_t.
102 uint64_t I1 = 0, I2 = 0;
103 memcpy(&I1, &V1, sizeof(V1));
104 memcpy(&I2, &V2, sizeof(V2));
105 return I1 < I2;
106 }
107};
108template <typename ValueType>
109struct KeyCompareLess<ValueType,
110 typename std::enable_if<std::is_integral<
111 typename ValueType::PrimType>::value>::type> {
112 bool operator()(const Constant *Const1, const Constant *Const2) const {
113 typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue();
114 typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue();
115 return V1 < V2;
116 }
117};
118template <typename ValueType>
119struct KeyCompareLess<
120 ValueType, typename std::enable_if<
121 std::is_same<ValueType, ConstantRelocatable>::value>::type> {
122 bool operator()(const Constant *Const1, const Constant *Const2) const {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700123 auto *V1 = llvm::cast<ValueType>(Const1);
124 auto *V2 = llvm::cast<ValueType>(Const2);
Jim Stichnoth6e293c82015-04-09 09:11:18 -0700125 if (V1->getName() == V2->getName())
126 return V1->getOffset() < V2->getOffset();
127 return V1->getName() < V2->getName();
128 }
129};
130
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700131// TypePool maps constants of type KeyType (e.g. float) to pointers to
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800132// type ValueType (e.g. ConstantFloat).
133template <Type Ty, typename KeyType, typename ValueType> class TypePool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700134 TypePool(const TypePool &) = delete;
135 TypePool &operator=(const TypePool &) = delete;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700136
137public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700138 TypePool() = default;
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800139 ValueType *getOrAdd(GlobalContext *Ctx, KeyType Key) {
140 auto Iter = Pool.find(Key);
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800141 if (Iter != Pool.end()) {
142 Iter->second->updateLookupCount();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700143 return Iter->second;
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800144 }
Jim Stichnoth54f3d512015-12-11 09:53:00 -0800145 auto *Result = ValueType::create(Ctx, Ty, Key);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800146 Pool[Key] = Result;
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800147 Result->updateLookupCount();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700148 return Result;
149 }
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700150 ConstantList getConstantPool() const {
151 ConstantList Constants;
152 Constants.reserve(Pool.size());
Jim Stichnothf44f3712014-10-01 14:05:51 -0700153 for (auto &I : Pool)
154 Constants.push_back(I.second);
Andrew Scull8072bae2015-09-14 16:01:26 -0700155 // The sort (and its KeyCompareLess machinery) is not strictly necessary,
156 // but is desirable for producing output that is deterministic across
157 // unordered_map::iterator implementations.
Jim Stichnoth6e293c82015-04-09 09:11:18 -0700158 std::sort(Constants.begin(), Constants.end(), KeyCompareLess<ValueType>());
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700159 return Constants;
160 }
Jim Stichnoth3d5e08d2016-03-01 12:22:29 -0800161 size_t size() const { return Pool.size(); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700162
163private:
Andrew Scull8072bae2015-09-14 16:01:26 -0700164 // Use the default hash function, and a custom key comparison function. The
165 // key comparison function for floating point variables can't use the default
166 // == based implementation because of special C++ semantics regarding +0.0,
167 // -0.0, and NaN comparison. However, it's OK to use the default hash for
168 // floating point values because KeyCompare is the final source of truth - in
169 // the worst case a "false" collision must be resolved.
170 using ContainerType =
171 std::unordered_map<KeyType, ValueType *, std::hash<KeyType>,
172 KeyCompare<KeyType>>;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700173 ContainerType Pool;
174};
175
Matt Walad8f4a7d2014-06-18 09:55:03 -0700176// UndefPool maps ICE types to the corresponding ConstantUndef values.
177class UndefPool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700178 UndefPool(const UndefPool &) = delete;
179 UndefPool &operator=(const UndefPool &) = delete;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700180
181public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700182 UndefPool() : Pool(IceType_NUM) {}
Matt Walad8f4a7d2014-06-18 09:55:03 -0700183
184 ConstantUndef *getOrAdd(GlobalContext *Ctx, Type Ty) {
Jim Stichnothae953202014-12-20 06:17:49 -0800185 if (Pool[Ty] == nullptr)
Jim Stichnothb36757e2015-10-05 13:55:11 -0700186 Pool[Ty] = ConstantUndef::create(Ctx, Ty);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800187 return Pool[Ty];
Matt Walad8f4a7d2014-06-18 09:55:03 -0700188 }
189
190private:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800191 std::vector<ConstantUndef *> Pool;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700192};
193
Jim Stichnoth5bfe2152015-03-19 13:51:56 -0700194} // end of anonymous namespace
195
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700196// The global constant pool bundles individual pools of each type of
197// interest.
198class ConstantPool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700199 ConstantPool(const ConstantPool &) = delete;
200 ConstantPool &operator=(const ConstantPool &) = delete;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700201
202public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700203 ConstantPool() = default;
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800204 TypePool<IceType_f32, float, ConstantFloat> Floats;
205 TypePool<IceType_f64, double, ConstantDouble> Doubles;
206 TypePool<IceType_i1, int8_t, ConstantInteger32> Integers1;
207 TypePool<IceType_i8, int8_t, ConstantInteger32> Integers8;
208 TypePool<IceType_i16, int16_t, ConstantInteger32> Integers16;
209 TypePool<IceType_i32, int32_t, ConstantInteger32> Integers32;
210 TypePool<IceType_i64, int64_t, ConstantInteger64> Integers64;
211 TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable> Relocatables;
Jan Voung261cae32015-02-01 10:31:03 -0800212 TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable>
213 ExternRelocatables;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700214 UndefPool Undefs;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700215};
216
Karl Schimpfe8457a22016-03-31 10:20:23 -0700217void GlobalContext::waitForWorkerThreads() {
218 if (WaitForWorkerThreadsCalled.exchange(true))
219 return;
220 optQueueNotifyEnd();
221 for (std::thread &Worker : TranslationThreads) {
222 Worker.join();
223 }
224 TranslationThreads.clear();
225
226 // Only notify the emit queue to end after all the translation threads have
227 // ended.
228 emitQueueNotifyEnd();
229 for (std::thread &Worker : EmitterThreads) {
230 Worker.join();
231 }
232 EmitterThreads.clear();
233
234 if (BuildDefs::timers()) {
235 auto Timers = getTimers();
236 for (ThreadContext *TLS : AllThreadContexts)
237 Timers->mergeFrom(TLS->Timers);
238 }
239 if (BuildDefs::dump()) {
240 // Do a separate loop over AllThreadContexts to avoid holding two locks at
241 // once.
242 auto Stats = getStatsCumulative();
243 for (ThreadContext *TLS : AllThreadContexts)
244 Stats->add(TLS->StatsCumulative);
245 }
246}
247
Jim Stichnothb5eee3d2016-03-31 11:05:39 -0700248void GlobalContext::CodeStats::dump(const Cfg *Func, GlobalContext *Ctx) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700249 if (!BuildDefs::dump())
Jim Stichnoth639c9212014-12-11 10:04:32 -0800250 return;
Jim Stichnoth3d5e08d2016-03-01 12:22:29 -0800251 OstreamLocker _(Ctx);
252 Ostream &Str = Ctx->getStrDump();
Jim Stichnothb5eee3d2016-03-31 11:05:39 -0700253 const std::string Name =
254 (Func == nullptr ? "_FINAL_" : Func->getFunctionNameAndSize());
Jim Stichnotha1dd3cc2015-01-31 10:48:11 -0800255#define X(str, tag) \
256 Str << "|" << Name << "|" str "|" << Stats[CS_##tag] << "\n";
257 CODESTATS_TABLE
258#undef X
259 Str << "|" << Name << "|Spills+Fills|"
260 << Stats[CS_NumSpills] + Stats[CS_NumFills] << "\n";
John Portoa3984a12016-04-01 11:14:30 -0700261 Str << "|" << Name << "|Memory Usage |";
262 if (const auto MemUsed = static_cast<size_t>(
263 llvm::TimeRecord::getCurrentTime(false).getMemUsed())) {
264 static constexpr size_t _1MB = 1024 * 1024;
265 Str << (MemUsed / _1MB) << " MB";
266 } else {
Jim Stichnoth639c9212014-12-11 10:04:32 -0800267 Str << "(requires '-track-memory')";
John Portoa3984a12016-04-01 11:14:30 -0700268 }
Jim Stichnoth639c9212014-12-11 10:04:32 -0800269 Str << "\n";
Jim Stichnoth3d5e08d2016-03-01 12:22:29 -0800270 Str << "|" << Name << "|CPool Sizes ";
271 {
272 auto Pool = Ctx->getConstPool();
273 Str << "|f32=" << Pool->Floats.size();
274 Str << "|f64=" << Pool->Doubles.size();
275 Str << "|i1=" << Pool->Integers1.size();
276 Str << "|i8=" << Pool->Integers8.size();
277 Str << "|i16=" << Pool->Integers16.size();
278 Str << "|i32=" << Pool->Integers32.size();
279 Str << "|i64=" << Pool->Integers64.size();
280 Str << "|Rel=" << Pool->Relocatables.size();
281 Str << "|ExtRel=" << Pool->ExternRelocatables.size();
282 }
283 Str << "\n";
Jim Stichnothb5eee3d2016-03-31 11:05:39 -0700284 if (Func != nullptr) {
John Portoa3984a12016-04-01 11:14:30 -0700285 Str << "|" << Name << "|Cfg Memory |" << Func->getTotalMemoryMB()
286 << " MB\n";
287 Str << "|" << Name << "|Liveness Memory |" << Func->getLivenessMemoryMB()
Jim Stichnothb5eee3d2016-03-31 11:05:39 -0700288 << " MB\n";
289 }
Jim Stichnoth639c9212014-12-11 10:04:32 -0800290}
291
Karl Schimpf3018cf22016-04-11 14:49:01 -0700292namespace {
293
294// By default, wake up the main parser thread when the OptQ gets half empty.
295static constexpr size_t DefaultOptQWakeupSize = GlobalContext::MaxOptQSize >> 1;
296
297} // end of anonymous namespace
298
Karl Schimpf2f67b922015-04-22 15:20:16 -0700299GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError,
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800300 ELFStreamer *ELFStr)
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700301 : Strings(new StringPool()), ConstPool(new ConstantPool()), ErrorStatus(),
302 StrDump(OsDump), StrEmit(OsEmit), StrError(OsError), IntrinsicsInfo(this),
Karl Schimpf3018cf22016-04-11 14:49:01 -0700303 ObjectWriter(),
304 OptQWakeupSize(std::max(DefaultOptQWakeupSize,
305 size_t(getFlags().getNumTranslationThreads()))),
306 OptQ(/*Sequential=*/getFlags().isSequential(),
307 /*MaxSize=*/
308 getFlags().isParseParallel()
309 ? MaxOptQSize
310 : getFlags().getNumTranslationThreads()),
Jim Stichnothbbca7542015-02-11 16:08:31 -0800311 // EmitQ is allowed unlimited size.
Karl Schimpfd4699942016-04-02 09:55:31 -0700312 EmitQ(/*Sequential=*/getFlags().isSequential()),
John Porto1bec8bc2015-06-22 10:51:13 -0700313 DataLowering(TargetDataLowering::createLowering(this)) {
Karl Schimpf2f67b922015-04-22 15:20:16 -0700314 assert(OsDump && "OsDump is not defined for GlobalContext");
315 assert(OsEmit && "OsEmit is not defined for GlobalContext");
316 assert(OsError && "OsError is not defined for GlobalContext");
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800317 // Make sure thread_local fields are properly initialized before any
318 // accesses are made. Do this here instead of at the start of
319 // main() so that all clients (e.g. unit tests) can benefit for
320 // free.
321 GlobalContext::TlsInit();
322 Cfg::TlsInit();
John Porto7bb9cab2016-04-01 05:43:09 -0700323 Liveness::TlsInit();
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800324 // Create a new ThreadContext for the current thread. No need to
325 // lock AllThreadContexts at this point since no other threads have
326 // access yet to this GlobalContext object.
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800327 ThreadContext *MyTLS = new ThreadContext();
328 AllThreadContexts.push_back(MyTLS);
329 ICE_TLS_SET_FIELD(TLS, MyTLS);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700330 // Pre-register built-in stack names.
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800331 if (BuildDefs::timers()) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800332 // TODO(stichnot): There needs to be a strong relationship between
333 // the newTimerStackID() return values and TSK_Default/TSK_Funcs.
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800334 newTimerStackID("Total across all functions");
335 newTimerStackID("Per-function summary");
336 }
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800337 Timers.initInto(MyTLS->Timers);
Karl Schimpfd4699942016-04-02 09:55:31 -0700338 switch (getFlags().getOutFileType()) {
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800339 case FT_Elf:
Jan Voung08c3bcd2014-12-01 17:55:16 -0800340 ObjectWriter.reset(new ELFObjectWriter(*this, *ELFStr));
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800341 break;
342 case FT_Asm:
343 case FT_Iasm:
344 break;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800345 }
Karl Schimpf20070e82016-03-17 13:30:13 -0700346// Cache up front common constants.
347#define X(tag, sizeLog2, align, elts, elty, str, rcstr) \
348 ConstZeroForType[IceType_##tag] = getConstantZeroInternal(IceType_##tag);
349 ICETYPE_TABLE;
350#undef X
351 ConstantTrue = getConstantInt1Internal(1);
352// Define runtime helper functions.
353#define X(Tag, Name) \
354 RuntimeHelperFunc[static_cast<size_t>(RuntimeHelper::H_##Tag)] = \
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700355 getConstantExternSym(getGlobalString(Name));
Karl Schimpf20070e82016-03-17 13:30:13 -0700356 RUNTIME_HELPER_FUNCTIONS_TABLE
357#undef X
John Porto1bec8bc2015-06-22 10:51:13 -0700358
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800359 TargetLowering::staticInit(this);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700360}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700361
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800362void GlobalContext::translateFunctions() {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800363 TimerMarker Timer(TimerStack::TT_translateFunctions, this);
Karl Schimpfe8457a22016-03-31 10:20:23 -0700364 while (std::unique_ptr<OptWorkItem> OptItem = optQueueBlockingPop()) {
365 auto Func = OptItem->getParsedCfg();
Jim Stichnoth8e928382015-02-02 17:03:08 -0800366 // Install Func in TLS for Cfg-specific container allocators.
John Portoe82b5602016-02-24 15:58:55 -0800367 CfgLocalAllocatorScope _(Func.get());
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800368 // Reset per-function stats being accumulated in TLS.
369 resetStats();
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800370 // Set verbose level to none if the current function does NOT
371 // match the -verbose-focus command-line option.
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800372 if (!matchSymbolName(Func->getFunctionName(),
373 getFlags().getVerboseFocusOn()))
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800374 Func->setVerbose(IceV_None);
375 // Disable translation if -notranslate is specified, or if the
376 // current function matches the -translate-only option. If
377 // translation is disabled, just dump the high-level IR and
378 // continue.
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800379 if (getFlags().getDisableTranslation() ||
380 !matchSymbolName(Func->getFunctionName(),
381 getFlags().getTranslateOnly())) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800382 Func->dump();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800383 continue; // Func goes out of scope and gets deleted
384 }
John Portof8b4cc82015-06-09 18:06:19 -0700385
Jim Stichnothbbca7542015-02-11 16:08:31 -0800386 Func->translate();
John Portobd2e2312016-03-15 11:06:25 -0700387 std::unique_ptr<EmitterWorkItem> Item;
Jim Stichnothbbca7542015-02-11 16:08:31 -0800388 if (Func->hasError()) {
389 getErrorStatus()->assign(EC_Translation);
390 OstreamLocker L(this);
Karl Schimpf2f67b922015-04-22 15:20:16 -0700391 getStrError() << "ICE translation error: " << Func->getFunctionName()
Jim Stichnothb40595a2016-01-29 06:14:31 -0800392 << ": " << Func->getError() << ": "
393 << Func->getFunctionNameAndSize() << "\n";
John Portobd2e2312016-03-15 11:06:25 -0700394 Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber());
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800395 } else {
Jim Stichnoth24824e72015-02-12 21:35:34 -0800396 Func->getAssembler<>()->setInternal(Func->getInternal());
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800397 switch (getFlags().getOutFileType()) {
398 case FT_Elf:
399 case FT_Iasm: {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800400 Func->emitIAS();
401 // The Cfg has already emitted into the assembly buffer, so
402 // stats have been fully collected into this thread's TLS.
403 // Dump them before TLS is reset for the next Cfg.
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700404 if (BuildDefs::dump())
Jim Stichnothb5eee3d2016-03-31 11:05:39 -0700405 dumpStats(Func.get());
John Portobd2e2312016-03-15 11:06:25 -0700406 auto Asm = Func->releaseAssembler();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800407 // Copy relevant fields into Asm before Func is deleted.
408 Asm->setFunctionName(Func->getFunctionName());
John Portobd2e2312016-03-15 11:06:25 -0700409 Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber(),
410 std::move(Asm));
John Portof8b4cc82015-06-09 18:06:19 -0700411 Item->setGlobalInits(Func->getGlobalInits());
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800412 } break;
413 case FT_Asm:
Jim Stichnothbbca7542015-02-11 16:08:31 -0800414 // The Cfg has not been emitted yet, so stats are not ready
415 // to be dumped.
John Portof8b4cc82015-06-09 18:06:19 -0700416 std::unique_ptr<VariableDeclarationList> GlobalInits =
417 Func->getGlobalInits();
John Portobd2e2312016-03-15 11:06:25 -0700418 Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber(),
419 std::move(Func));
John Portof8b4cc82015-06-09 18:06:19 -0700420 Item->setGlobalInits(std::move(GlobalInits));
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800421 break;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800422 }
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800423 }
John Portobd2e2312016-03-15 11:06:25 -0700424 assert(Item != nullptr);
425 emitQueueBlockingPush(std::move(Item));
Jim Stichnoth8e928382015-02-02 17:03:08 -0800426 // The Cfg now gets deleted as Func goes out of scope.
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800427 }
428}
429
Jim Stichnothbbca7542015-02-11 16:08:31 -0800430namespace {
431
Jim Stichnothbbca7542015-02-11 16:08:31 -0800432// Ensure Pending is large enough that Pending[Index] is valid.
John Portobd2e2312016-03-15 11:06:25 -0700433void resizePending(std::vector<std::unique_ptr<EmitterWorkItem>> *Pending,
434 uint32_t Index) {
435 if (Index >= Pending->size())
436 Utils::reserveAndResize(*Pending, Index + 1);
Jim Stichnothbbca7542015-02-11 16:08:31 -0800437}
438
439} // end of anonymous namespace
440
Jan Voungfb792842015-06-11 15:27:50 -0700441void GlobalContext::emitFileHeader() {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800442 TimerMarker T1(Ice::TimerStack::TT_emitAsm, this);
Jan Voungfb792842015-06-11 15:27:50 -0700443 if (getFlags().getOutFileType() == FT_Elf) {
444 getObjectWriter()->writeInitialELFHeader();
445 } else {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700446 if (!BuildDefs::dump()) {
Jim Stichnothc8799682015-06-22 13:04:10 -0700447 getStrError() << "emitFileHeader for non-ELF";
448 getErrorStatus()->assign(EC_Translation);
449 }
Jan Voungfb792842015-06-11 15:27:50 -0700450 TargetHeaderLowering::createLowering(this)->lower();
451 }
452}
453
Jim Stichnothcac003e2015-06-18 12:48:58 -0700454void GlobalContext::lowerConstants() { DataLowering->lowerConstants(); }
John Porto8b1a7052015-06-17 13:20:08 -0700455
Andrew Scull86df4e92015-07-30 13:54:44 -0700456void GlobalContext::lowerJumpTables() { DataLowering->lowerJumpTables(); }
457
John Portoa78e4ba2016-03-15 09:28:04 -0700458void GlobalContext::saveBlockInfoPtrs() {
459 for (VariableDeclaration *Global : Globals) {
John Porto844211e2016-02-04 08:42:48 -0800460 if (Cfg::isProfileGlobal(*Global)) {
John Portoa78e4ba2016-03-15 09:28:04 -0700461 ProfileBlockInfos.push_back(Global);
John Porto844211e2016-02-04 08:42:48 -0800462 }
463 }
464}
465
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700466void GlobalContext::lowerGlobals(const std::string &SectionSuffix) {
John Porto8b1a7052015-06-17 13:20:08 -0700467 TimerMarker T(TimerStack::TT_emitGlobalInitializers, this);
Karl Schimpfd4699942016-04-02 09:55:31 -0700468 const bool DumpGlobalVariables =
469 BuildDefs::dump() && (getFlags().getVerbose() & IceV_GlobalInit) &&
470 getFlags().getVerboseFocusOn().empty();
John Porto8b1a7052015-06-17 13:20:08 -0700471 if (DumpGlobalVariables) {
472 OstreamLocker L(this);
473 Ostream &Stream = getStrDump();
474 for (const Ice::VariableDeclaration *Global : Globals) {
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800475 Global->dump(Stream);
John Porto8b1a7052015-06-17 13:20:08 -0700476 }
477 }
Karl Schimpfd4699942016-04-02 09:55:31 -0700478 if (getFlags().getDisableTranslation())
John Porto8b1a7052015-06-17 13:20:08 -0700479 return;
480
John Portoa78e4ba2016-03-15 09:28:04 -0700481 saveBlockInfoPtrs();
Qining Lu7cd53512015-06-26 09:36:00 -0700482 // If we need to shuffle the layout of global variables, shuffle them now.
John Portoc5bc5cb2016-03-21 11:18:02 -0700483 if (getFlags().getReorderGlobalVariables()) {
Qining Luaee5fa82015-08-20 14:59:03 -0700484 // Create a random number generator for global variable reordering.
485 RandomNumberGenerator RNG(getFlags().getRandomSeed(),
486 RPE_GlobalVariableReordering);
Qining Lu7cd53512015-06-26 09:36:00 -0700487 RandomShuffle(Globals.begin(), Globals.end(),
Qining Luaee5fa82015-08-20 14:59:03 -0700488 [&RNG](int N) { return (uint32_t)RNG.next(N); });
Qining Lu7cd53512015-06-26 09:36:00 -0700489 }
John Porto8b1a7052015-06-17 13:20:08 -0700490 DataLowering->lowerGlobals(Globals, SectionSuffix);
John Portoa78e4ba2016-03-15 09:28:04 -0700491 if (ProfileBlockInfos.empty() && DisposeGlobalVariablesAfterLowering) {
492 Globals.clearAndPurge();
493 } else {
494 Globals.clear();
John Porto1bec8bc2015-06-22 10:51:13 -0700495 }
John Porto8b1a7052015-06-17 13:20:08 -0700496}
497
498void GlobalContext::lowerProfileData() {
John Porto1bec8bc2015-06-22 10:51:13 -0700499 // ProfileBlockInfoVarDecl is initialized in the constructor, and will only
500 // ever be nullptr after this method completes. This assertion is a convoluted
501 // way of ensuring lowerProfileData is invoked a single time.
John Portoa78e4ba2016-03-15 09:28:04 -0700502 assert(ProfileBlockInfoVarDecl == nullptr);
503
504 auto GlobalVariablePool = getInitializerAllocator();
505 ProfileBlockInfoVarDecl =
506 VariableDeclaration::createExternal(GlobalVariablePool.get());
507 ProfileBlockInfoVarDecl->setAlignment(typeWidthInBytes(IceType_i64));
508 ProfileBlockInfoVarDecl->setIsConstant(true);
509
510 // Note: if you change this symbol, make sure to update
511 // runtime/szrt_profiler.c as well.
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700512 ProfileBlockInfoVarDecl->setName(this, "__Sz_block_profile_info");
John Portoa78e4ba2016-03-15 09:28:04 -0700513
514 for (const VariableDeclaration *PBI : ProfileBlockInfos) {
515 if (Cfg::isProfileGlobal(*PBI)) {
516 constexpr RelocOffsetT BlockExecutionCounterOffset = 0;
517 ProfileBlockInfoVarDecl->addInitializer(
518 VariableDeclaration::RelocInitializer::create(
519 GlobalVariablePool.get(), PBI,
520 {RelocOffset::create(this, BlockExecutionCounterOffset)}));
521 }
522 }
523
John Porto8b1a7052015-06-17 13:20:08 -0700524 // This adds a 64-bit sentinel entry to the end of our array. For 32-bit
525 // architectures this will waste 4 bytes.
526 const SizeT Sizeof64BitNullPtr = typeWidthInBytes(IceType_i64);
527 ProfileBlockInfoVarDecl->addInitializer(
John Portoa78e4ba2016-03-15 09:28:04 -0700528 VariableDeclaration::ZeroInitializer::create(GlobalVariablePool.get(),
529 Sizeof64BitNullPtr));
John Porto1bec8bc2015-06-22 10:51:13 -0700530 Globals.push_back(ProfileBlockInfoVarDecl);
John Porto8b1a7052015-06-17 13:20:08 -0700531 constexpr char ProfileDataSection[] = "$sz_profiler$";
532 lowerGlobals(ProfileDataSection);
533}
534
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700535bool GlobalContext::matchSymbolName(const GlobalString &SymbolName,
536 const std::string &Match) {
537 return Match.empty() || Match == SymbolName.toString();
538}
539
Jim Stichnothbbca7542015-02-11 16:08:31 -0800540void GlobalContext::emitItems() {
541 const bool Threaded = !getFlags().isSequential();
542 // Pending is a vector containing the reassembled, ordered list of
543 // work items. When we're ready for the next item, we first check
544 // whether it's in the Pending list. If not, we take an item from
545 // the work queue, and if it's not the item we're waiting for, we
546 // insert it into Pending and repeat. The work item is deleted
547 // after it is processed.
John Portobd2e2312016-03-15 11:06:25 -0700548 std::vector<std::unique_ptr<EmitterWorkItem>> Pending;
Jim Stichnothbbca7542015-02-11 16:08:31 -0800549 uint32_t DesiredSequenceNumber = getFirstSequenceNumber();
Qining Lu7cd53512015-06-26 09:36:00 -0700550 uint32_t ShuffleStartIndex = DesiredSequenceNumber;
551 uint32_t ShuffleEndIndex = DesiredSequenceNumber;
552 bool EmitQueueEmpty = false;
553 const uint32_t ShuffleWindowSize =
554 std::max(1u, getFlags().getReorderFunctionsWindowSize());
John Portoc5bc5cb2016-03-21 11:18:02 -0700555 bool Shuffle = Threaded && getFlags().getReorderFunctions();
Qining Luaee5fa82015-08-20 14:59:03 -0700556 // Create a random number generator for function reordering.
557 RandomNumberGenerator RNG(getFlags().getRandomSeed(), RPE_FunctionReordering);
558
Qining Lu7cd53512015-06-26 09:36:00 -0700559 while (!EmitQueueEmpty) {
John Portobd2e2312016-03-15 11:06:25 -0700560 resizePending(&Pending, DesiredSequenceNumber);
Jim Stichnothbbca7542015-02-11 16:08:31 -0800561 // See if Pending contains DesiredSequenceNumber.
John Portobd2e2312016-03-15 11:06:25 -0700562 if (Pending[DesiredSequenceNumber] == nullptr) {
Qining Lu7cd53512015-06-26 09:36:00 -0700563 // We need to fetch an EmitterWorkItem from the queue.
John Portobd2e2312016-03-15 11:06:25 -0700564 auto RawItem = emitQueueBlockingPop();
Qining Lu7cd53512015-06-26 09:36:00 -0700565 if (RawItem == nullptr) {
566 // This is the notifier for an empty queue.
567 EmitQueueEmpty = true;
568 } else {
569 // We get an EmitterWorkItem, we need to add it to Pending.
570 uint32_t ItemSeq = RawItem->getSequenceNumber();
571 if (Threaded && ItemSeq != DesiredSequenceNumber) {
572 // Not the desired one, add it to Pending but do not increase
573 // DesiredSequenceNumber. Continue the loop, do not emit the item.
John Portobd2e2312016-03-15 11:06:25 -0700574 resizePending(&Pending, ItemSeq);
575 Pending[ItemSeq] = std::move(RawItem);
Qining Lu7cd53512015-06-26 09:36:00 -0700576 continue;
577 }
578 // ItemSeq == DesiredSequenceNumber, we need to check if we should
579 // emit it or not. If !Threaded, we're OK with ItemSeq !=
580 // DesiredSequenceNumber.
John Portobd2e2312016-03-15 11:06:25 -0700581 Pending[DesiredSequenceNumber] = std::move(RawItem);
Jim Stichnothbbca7542015-02-11 16:08:31 -0800582 }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800583 }
John Portobd2e2312016-03-15 11:06:25 -0700584 const auto *CurrentWorkItem = Pending[DesiredSequenceNumber].get();
585
Qining Lu7cd53512015-06-26 09:36:00 -0700586 // We have the desired EmitterWorkItem or nullptr as the end notifier.
587 // If the emitter queue is not empty, increase DesiredSequenceNumber and
588 // ShuffleEndIndex.
589 if (!EmitQueueEmpty) {
590 DesiredSequenceNumber++;
591 ShuffleEndIndex++;
592 }
593
594 if (Shuffle) {
595 // Continue fetching EmitterWorkItem if function reordering is turned on,
596 // and emit queue is not empty, and the number of consecutive pending
597 // items is smaller than the window size, and RawItem is not a
598 // WI_GlobalInits kind. Emit WI_GlobalInits kind block first to avoid
599 // holding an arbitrarily large GlobalDeclarationList.
600 if (!EmitQueueEmpty &&
601 ShuffleEndIndex - ShuffleStartIndex < ShuffleWindowSize &&
John Portobd2e2312016-03-15 11:06:25 -0700602 CurrentWorkItem->getKind() != EmitterWorkItem::WI_GlobalInits)
Qining Lu7cd53512015-06-26 09:36:00 -0700603 continue;
604
605 // Emit the EmitterWorkItem between Pending[ShuffleStartIndex] to
606 // Pending[ShuffleEndIndex]. If function reordering turned on, shuffle the
607 // pending items from Pending[ShuffleStartIndex] to
608 // Pending[ShuffleEndIndex].
609 RandomShuffle(Pending.begin() + ShuffleStartIndex,
610 Pending.begin() + ShuffleEndIndex,
Qining Luaee5fa82015-08-20 14:59:03 -0700611 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
Qining Lu7cd53512015-06-26 09:36:00 -0700612 }
613
614 // Emit the item from ShuffleStartIndex to ShuffleEndIndex.
615 for (uint32_t I = ShuffleStartIndex; I < ShuffleEndIndex; I++) {
John Portobd2e2312016-03-15 11:06:25 -0700616 std::unique_ptr<EmitterWorkItem> Item = std::move(Pending[I]);
Qining Lu7cd53512015-06-26 09:36:00 -0700617
618 switch (Item->getKind()) {
619 case EmitterWorkItem::WI_Nop:
620 break;
621 case EmitterWorkItem::WI_GlobalInits: {
622 accumulateGlobals(Item->getGlobalInits());
623 } break;
624 case EmitterWorkItem::WI_Asm: {
625 lowerGlobalsIfNoCodeHasBeenSeen();
626 accumulateGlobals(Item->getGlobalInits());
627
628 std::unique_ptr<Assembler> Asm = Item->getAsm();
629 Asm->alignFunction();
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700630 GlobalString Name = Asm->getFunctionName();
Qining Lu7cd53512015-06-26 09:36:00 -0700631 switch (getFlags().getOutFileType()) {
632 case FT_Elf:
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800633 getObjectWriter()->writeFunctionCode(Name, Asm->getInternal(),
Qining Lu7cd53512015-06-26 09:36:00 -0700634 Asm.get());
635 break;
636 case FT_Iasm: {
637 OstreamLocker L(this);
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800638 Cfg::emitTextHeader(Name, this, Asm.get());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700639 Asm->emitIASBytes(this);
Qining Lu7cd53512015-06-26 09:36:00 -0700640 } break;
641 case FT_Asm:
642 llvm::report_fatal_error("Unexpected FT_Asm");
643 break;
644 }
645 } break;
646 case EmitterWorkItem::WI_Cfg: {
647 if (!BuildDefs::dump())
648 llvm::report_fatal_error("WI_Cfg work item created inappropriately");
649 lowerGlobalsIfNoCodeHasBeenSeen();
650 accumulateGlobals(Item->getGlobalInits());
651
652 assert(getFlags().getOutFileType() == FT_Asm);
653 std::unique_ptr<Cfg> Func = Item->getCfg();
654 // Unfortunately, we have to temporarily install the Cfg in TLS
655 // because Variable::asType() uses the allocator to create the
656 // differently-typed copy.
John Portoe82b5602016-02-24 15:58:55 -0800657 CfgLocalAllocatorScope _(Func.get());
Qining Lu7cd53512015-06-26 09:36:00 -0700658 Func->emit();
Jim Stichnothb5eee3d2016-03-31 11:05:39 -0700659 dumpStats(Func.get());
Qining Lu7cd53512015-06-26 09:36:00 -0700660 } break;
661 }
662 }
663 // Update the start index for next shuffling queue
664 ShuffleStartIndex = ShuffleEndIndex;
Jim Stichnothbbca7542015-02-11 16:08:31 -0800665 }
John Portof8b4cc82015-06-09 18:06:19 -0700666
John Porto8b1a7052015-06-17 13:20:08 -0700667 // In case there are no code to be generated, we invoke the conditional
668 // lowerGlobals again -- this is a no-op if code has been emitted.
669 lowerGlobalsIfNoCodeHasBeenSeen();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800670}
671
Karl Schimpf9d98d792014-10-13 15:01:08 -0700672GlobalContext::~GlobalContext() {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800673 llvm::DeleteContainerPointers(AllThreadContexts);
John Porto1bec8bc2015-06-22 10:51:13 -0700674 LockedPtr<DestructorArray> Dtors = getDestructors();
675 // Destructors are invoked in the opposite object construction order.
Andrew Scull00741a02015-09-16 19:04:09 -0700676 for (const auto &Dtor : reverse_range(*Dtors))
677 Dtor();
Karl Schimpf9d98d792014-10-13 15:01:08 -0700678}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700679
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700680void GlobalContext::dumpStrings() {
681 if (!getFlags().getDumpStrings())
682 return;
683 OstreamLocker _(this);
684 Ostream &Str = getStrDump();
685 Str << "GlobalContext strings:\n";
686 getStrings()->dump(Str);
687}
688
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800689void GlobalContext::dumpConstantLookupCounts() {
690 if (!BuildDefs::dump())
691 return;
Karl Schimpfd4699942016-04-02 09:55:31 -0700692 const bool DumpCounts = (getFlags().getVerbose() & IceV_ConstPoolStats) &&
693 getFlags().getVerboseFocusOn().empty();
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800694 if (!DumpCounts)
695 return;
696
697 OstreamLocker _(this);
698 Ostream &Str = getStrDump();
699 Str << "Constant pool use stats: count+value+type\n";
700#define X(WhichPool) \
701 for (auto *C : getConstPool()->WhichPool.getConstantPool()) { \
702 Str << C->getLookupCount() << " "; \
703 C->dump(Str); \
704 Str << " " << C->getType() << "\n"; \
705 }
706 X(Integers1);
707 X(Integers8);
708 X(Integers16);
709 X(Integers32);
710 X(Integers64);
711 X(Floats);
712 X(Doubles);
713 X(Relocatables);
714 X(ExternRelocatables);
715#undef X
716}
717
Andrew Scull57e12682015-09-16 11:30:19 -0700718// TODO(stichnot): Consider adding thread-local caches of constant pool entries
719// to reduce contention.
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800720
721// All locking is done by the getConstantInt[0-9]+() target function.
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800722Constant *GlobalContext::getConstantInt(Type Ty, int64_t Value) {
723 switch (Ty) {
724 case IceType_i1:
725 return getConstantInt1(Value);
726 case IceType_i8:
727 return getConstantInt8(Value);
728 case IceType_i16:
729 return getConstantInt16(Value);
730 case IceType_i32:
731 return getConstantInt32(Value);
732 case IceType_i64:
733 return getConstantInt64(Value);
734 default:
735 llvm_unreachable("Bad integer type for getConstant");
736 }
Jim Stichnothae953202014-12-20 06:17:49 -0800737 return nullptr;
Jan Voungbc004632014-09-16 15:09:10 -0700738}
739
Karl Schimpf20070e82016-03-17 13:30:13 -0700740Constant *GlobalContext::getConstantInt1Internal(int8_t ConstantInt1) {
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800741 ConstantInt1 &= INT8_C(1);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800742 return getConstPool()->Integers1.getOrAdd(this, ConstantInt1);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800743}
744
Karl Schimpf20070e82016-03-17 13:30:13 -0700745Constant *GlobalContext::getConstantInt8Internal(int8_t ConstantInt8) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800746 return getConstPool()->Integers8.getOrAdd(this, ConstantInt8);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800747}
748
Karl Schimpf20070e82016-03-17 13:30:13 -0700749Constant *GlobalContext::getConstantInt16Internal(int16_t ConstantInt16) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800750 return getConstPool()->Integers16.getOrAdd(this, ConstantInt16);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800751}
752
Karl Schimpf20070e82016-03-17 13:30:13 -0700753Constant *GlobalContext::getConstantInt32Internal(int32_t ConstantInt32) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800754 return getConstPool()->Integers32.getOrAdd(this, ConstantInt32);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800755}
756
Karl Schimpf20070e82016-03-17 13:30:13 -0700757Constant *GlobalContext::getConstantInt64Internal(int64_t ConstantInt64) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800758 return getConstPool()->Integers64.getOrAdd(this, ConstantInt64);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700759}
760
761Constant *GlobalContext::getConstantFloat(float ConstantFloat) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800762 return getConstPool()->Floats.getOrAdd(this, ConstantFloat);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700763}
764
765Constant *GlobalContext::getConstantDouble(double ConstantDouble) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800766 return getConstPool()->Doubles.getOrAdd(this, ConstantDouble);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700767}
768
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700769Constant *GlobalContext::getConstantSymWithEmitString(
770 const RelocOffsetT Offset, const RelocOffsetArray &OffsetExpr,
771 GlobalString Name, const std::string &EmitString) {
John Porto27fddcc2016-02-02 15:06:09 -0800772 return getConstPool()->Relocatables.getOrAdd(
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800773 this, RelocatableTuple(Offset, OffsetExpr, Name, EmitString));
John Porto27fddcc2016-02-02 15:06:09 -0800774}
775
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800776Constant *GlobalContext::getConstantSym(RelocOffsetT Offset,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700777 GlobalString Name) {
John Porto27fddcc2016-02-02 15:06:09 -0800778 constexpr char EmptyEmitString[] = "";
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700779 return getConstantSymWithEmitString(Offset, {}, Name, EmptyEmitString);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700780}
781
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700782Constant *GlobalContext::getConstantExternSym(GlobalString Name) {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700783 constexpr RelocOffsetT Offset = 0;
Jan Voung261cae32015-02-01 10:31:03 -0800784 return getConstPool()->ExternRelocatables.getOrAdd(
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800785 this, RelocatableTuple(Offset, {}, Name));
Jan Voung261cae32015-02-01 10:31:03 -0800786}
787
Matt Walad8f4a7d2014-06-18 09:55:03 -0700788Constant *GlobalContext::getConstantUndef(Type Ty) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800789 return getConstPool()->Undefs.getOrAdd(this, Ty);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700790}
791
792Constant *GlobalContext::getConstantZero(Type Ty) {
Karl Schimpf20070e82016-03-17 13:30:13 -0700793 Constant *Zero = ConstZeroForType[Ty];
794 if (Zero == nullptr)
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700795 llvm::report_fatal_error("Unsupported constant type: " + typeStdString(Ty));
Karl Schimpf20070e82016-03-17 13:30:13 -0700796 return Zero;
797}
798
799// All locking is done by the getConstant*() target function.
800Constant *GlobalContext::getConstantZeroInternal(Type Ty) {
Matt Walad8f4a7d2014-06-18 09:55:03 -0700801 switch (Ty) {
802 case IceType_i1:
Karl Schimpf20070e82016-03-17 13:30:13 -0700803 return getConstantInt1Internal(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700804 case IceType_i8:
Karl Schimpf20070e82016-03-17 13:30:13 -0700805 return getConstantInt8Internal(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700806 case IceType_i16:
Karl Schimpf20070e82016-03-17 13:30:13 -0700807 return getConstantInt16Internal(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700808 case IceType_i32:
Karl Schimpf20070e82016-03-17 13:30:13 -0700809 return getConstantInt32Internal(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700810 case IceType_i64:
Karl Schimpf20070e82016-03-17 13:30:13 -0700811 return getConstantInt64Internal(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700812 case IceType_f32:
813 return getConstantFloat(0);
814 case IceType_f64:
815 return getConstantDouble(0);
Karl Schimpf20070e82016-03-17 13:30:13 -0700816 default:
817 return nullptr;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700818 }
Matt Walad8f4a7d2014-06-18 09:55:03 -0700819}
820
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800821ConstantList GlobalContext::getConstantPool(Type Ty) {
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700822 switch (Ty) {
823 case IceType_i1:
824 case IceType_i8:
Qining Lu253dc8a2015-06-22 10:10:23 -0700825 return getConstPool()->Integers8.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700826 case IceType_i16:
Qining Lu253dc8a2015-06-22 10:10:23 -0700827 return getConstPool()->Integers16.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700828 case IceType_i32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800829 return getConstPool()->Integers32.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700830 case IceType_i64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800831 return getConstPool()->Integers64.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700832 case IceType_f32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800833 return getConstPool()->Floats.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700834 case IceType_f64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800835 return getConstPool()->Doubles.getConstantPool();
Matt Wala928f1292014-07-07 16:50:46 -0700836 case IceType_v4i1:
837 case IceType_v8i1:
838 case IceType_v16i1:
839 case IceType_v16i8:
840 case IceType_v8i16:
841 case IceType_v4i32:
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700842 case IceType_v4f32:
843 llvm::report_fatal_error("Unsupported constant type: " + typeStdString(Ty));
844 break;
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700845 case IceType_void:
846 case IceType_NUM:
847 break;
848 }
849 llvm_unreachable("Unknown type");
850}
851
Jan Voung261cae32015-02-01 10:31:03 -0800852ConstantList GlobalContext::getConstantExternSyms() {
853 return getConstPool()->ExternRelocatables.getConstantPool();
854}
855
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700856GlobalString GlobalContext::getGlobalString(const std::string &Name) {
857 return GlobalString::createWithString(this, Name);
858}
859
Andrew Scull1eda90a2015-08-04 17:03:19 -0700860JumpTableDataList GlobalContext::getJumpTables() {
861 JumpTableDataList JumpTables(*getJumpTableList());
Andrew Scull57e12682015-09-16 11:30:19 -0700862 // Make order deterministic by sorting into functions and then ID of the jump
863 // table within that function.
Qining Luaee5fa82015-08-20 14:59:03 -0700864 std::sort(JumpTables.begin(), JumpTables.end(),
865 [](const JumpTableData &A, const JumpTableData &B) {
866 if (A.getFunctionName() != B.getFunctionName())
867 return A.getFunctionName() < B.getFunctionName();
868 return A.getId() < B.getId();
869 });
870
John Portoc5bc5cb2016-03-21 11:18:02 -0700871 if (getFlags().getReorderPooledConstants()) {
Qining Luaee5fa82015-08-20 14:59:03 -0700872 // If reorder-pooled-constants option is set to true, we also shuffle the
873 // jump tables before emitting them.
874
875 // Create a random number generator for jump tables reordering, considering
876 // jump tables as pooled constants.
877 RandomNumberGenerator RNG(getFlags().getRandomSeed(),
878 RPE_PooledConstantReordering);
John Portoe0d9afa2015-08-05 10:13:44 -0700879 RandomShuffle(JumpTables.begin(), JumpTables.end(),
Qining Luaee5fa82015-08-20 14:59:03 -0700880 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
Andrew Scull1eda90a2015-08-04 17:03:19 -0700881 }
882 return JumpTables;
883}
884
John Porto03077212016-04-05 06:30:21 -0700885void GlobalContext::addJumpTableData(JumpTableData JumpTable) {
886 getJumpTableList()->emplace_back(std::move(JumpTable));
Andrew Scull86df4e92015-07-30 13:54:44 -0700887}
888
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700889TimerStackIdT GlobalContext::newTimerStackID(const std::string &Name) {
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800890 if (!BuildDefs::timers())
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800891 return 0;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800892 auto Timers = getTimers();
893 TimerStackIdT NewID = Timers->size();
894 Timers->push_back(TimerStack(Name));
Jim Stichnoth8363a062014-10-07 10:02:38 -0700895 return NewID;
896}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700897
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800898TimerIdT GlobalContext::getTimerID(TimerStackIdT StackID,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700899 const std::string &Name) {
Jim Stichnoth2b000fd2016-04-06 06:37:15 -0700900 auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800901 assert(StackID < Timers->size());
902 return Timers->at(StackID).getTimerID(Name);
903}
904
Jim Stichnoth8363a062014-10-07 10:02:38 -0700905void GlobalContext::pushTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnoth2b000fd2016-04-06 06:37:15 -0700906 auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800907 assert(StackID < Timers->size());
908 Timers->at(StackID).push(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700909}
910
911void GlobalContext::popTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnoth2b000fd2016-04-06 06:37:15 -0700912 auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800913 assert(StackID < Timers->size());
914 Timers->at(StackID).pop(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700915}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700916
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700917void GlobalContext::resetTimer(TimerStackIdT StackID) {
Jim Stichnoth2b000fd2016-04-06 06:37:15 -0700918 auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800919 assert(StackID < Timers->size());
920 Timers->at(StackID).reset();
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700921}
922
Jim Stichnoth2b000fd2016-04-06 06:37:15 -0700923std::string GlobalContext::getTimerName(TimerStackIdT StackID) {
924 auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
925 assert(StackID < Timers->size());
926 return Timers->at(StackID).getName();
927}
928
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700929void GlobalContext::setTimerName(TimerStackIdT StackID,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700930 const std::string &NewName) {
Jim Stichnoth2b000fd2016-04-06 06:37:15 -0700931 auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800932 assert(StackID < Timers->size());
933 Timers->at(StackID).setName(NewName);
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700934}
935
Andrew Scull57e12682015-09-16 11:30:19 -0700936// Note: optQueueBlockingPush and optQueueBlockingPop use unique_ptr at the
937// interface to take and transfer ownership, but they internally store the raw
938// Cfg pointer in the work queue. This allows e.g. future queue optimizations
939// such as the use of atomics to modify queue elements.
Karl Schimpfe8457a22016-03-31 10:20:23 -0700940void GlobalContext::optQueueBlockingPush(std::unique_ptr<OptWorkItem> Item) {
941 assert(Item);
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800942 {
943 TimerMarker _(TimerStack::TT_qTransPush, this);
Karl Schimpfe8457a22016-03-31 10:20:23 -0700944 OptQ.blockingPush(std::move(Item));
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800945 }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800946 if (getFlags().isSequential())
947 translateFunctions();
Jim Stichnoth8e928382015-02-02 17:03:08 -0800948}
949
Karl Schimpfe8457a22016-03-31 10:20:23 -0700950std::unique_ptr<OptWorkItem> GlobalContext::optQueueBlockingPop() {
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800951 TimerMarker _(TimerStack::TT_qTransPop, this);
Karl Schimpf3018cf22016-04-11 14:49:01 -0700952 return OptQ.blockingPop(OptQWakeupSize);
Jim Stichnothbbca7542015-02-11 16:08:31 -0800953}
954
John Portobd2e2312016-03-15 11:06:25 -0700955void GlobalContext::emitQueueBlockingPush(
956 std::unique_ptr<EmitterWorkItem> Item) {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800957 assert(Item);
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800958 {
959 TimerMarker _(TimerStack::TT_qEmitPush, this);
John Portobd2e2312016-03-15 11:06:25 -0700960 EmitQ.blockingPush(std::move(Item));
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800961 }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800962 if (getFlags().isSequential())
963 emitItems();
964}
965
John Portobd2e2312016-03-15 11:06:25 -0700966std::unique_ptr<EmitterWorkItem> GlobalContext::emitQueueBlockingPop() {
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800967 TimerMarker _(TimerStack::TT_qEmitPop, this);
Jim Stichnothbbca7542015-02-11 16:08:31 -0800968 return EmitQ.blockingPop();
Jim Stichnoth8e928382015-02-02 17:03:08 -0800969}
970
Jim Stichnothb5eee3d2016-03-31 11:05:39 -0700971void GlobalContext::dumpStats(const Cfg *Func) {
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800972 if (!getFlags().getDumpStats())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800973 return;
Jim Stichnothb5eee3d2016-03-31 11:05:39 -0700974 if (Func == nullptr) {
975 getStatsCumulative()->dump(Func, this);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800976 } else {
Jim Stichnothb5eee3d2016-03-31 11:05:39 -0700977 ICE_TLS_GET_FIELD(TLS)->StatsFunction.dump(Func, this);
Jim Stichnoth18735602014-09-16 19:59:35 -0700978 }
979}
980
Jim Stichnoth8363a062014-10-07 10:02:38 -0700981void GlobalContext::dumpTimers(TimerStackIdT StackID, bool DumpCumulative) {
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800982 if (!BuildDefs::timers())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800983 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800984 auto Timers = getTimers();
985 assert(Timers->size() > StackID);
986 OstreamLocker L(this);
987 Timers->at(StackID).dump(getStrDump(), DumpCumulative);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700988}
989
Jim Stichnoth2b000fd2016-04-06 06:37:15 -0700990void GlobalContext::dumpLocalTimers(const std::string &TimerNameOverride,
991 TimerStackIdT StackID,
992 bool DumpCumulative) {
993 if (!BuildDefs::timers())
994 return;
995 auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
996 assert(Timers->size() > StackID);
997 // Temporarily override the thread-local timer name with the given name.
998 // Don't do it permanently because the final timer merge at the end expects
999 // the thread-local timer names to be the same as the global timer name.
1000 auto OrigName = getTimerName(StackID);
1001 setTimerName(StackID, TimerNameOverride);
1002 {
1003 OstreamLocker _(this);
1004 Timers->at(StackID).dump(getStrDump(), DumpCumulative);
1005 }
1006 setTimerName(StackID, OrigName);
1007}
1008
Jim Stichnoth467ffe52016-03-29 15:01:06 -07001009LockedPtr<StringPool>
1010GlobalStringPoolTraits::getStrings(const GlobalContext *PoolOwner) {
1011 return PoolOwner->getStrings();
1012}
1013
Jim Stichnothb88d8c82016-03-11 15:33:00 -08001014TimerIdT TimerMarker::getTimerIdFromFuncName(GlobalContext *Ctx,
Jim Stichnoth467ffe52016-03-29 15:01:06 -07001015 const std::string &FuncName) {
Jim Stichnothb88d8c82016-03-11 15:33:00 -08001016 if (!BuildDefs::timers())
1017 return 0;
Karl Schimpfd4699942016-04-02 09:55:31 -07001018 if (!getFlags().getTimeEachFunction())
Jim Stichnothb88d8c82016-03-11 15:33:00 -08001019 return 0;
1020 return Ctx->getTimerID(GlobalContext::TSK_Funcs, FuncName);
1021}
1022
Jim Stichnoth380d7b92015-01-30 13:10:39 -08001023void TimerMarker::push() {
1024 switch (StackID) {
1025 case GlobalContext::TSK_Default:
Jim Stichnoth318c01b2016-04-03 21:58:03 -07001026 Active = getFlags().getSubzeroTimingEnabled() ||
1027 !getFlags().getTimingFocusOn().empty();
Jim Stichnoth380d7b92015-01-30 13:10:39 -08001028 break;
1029 case GlobalContext::TSK_Funcs:
Karl Schimpfd4699942016-04-02 09:55:31 -07001030 Active = getFlags().getTimeEachFunction();
Jim Stichnoth380d7b92015-01-30 13:10:39 -08001031 break;
1032 default:
1033 break;
Jim Stichnoth1c44d812014-12-08 14:57:52 -08001034 }
Jim Stichnoth380d7b92015-01-30 13:10:39 -08001035 if (Active)
1036 Ctx->pushTimer(ID, StackID);
1037}
1038
1039void TimerMarker::pushCfg(const Cfg *Func) {
1040 Ctx = Func->getContext();
Karl Schimpfd4699942016-04-02 09:55:31 -07001041 Active = Func->getFocusedTiming() || getFlags().getSubzeroTimingEnabled();
Jim Stichnoth380d7b92015-01-30 13:10:39 -08001042 if (Active)
1043 Ctx->pushTimer(ID, StackID);
Jim Stichnoth8363a062014-10-07 10:02:38 -07001044}
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001045
Jim Stichnotha5fe17a2015-01-26 11:10:03 -08001046ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS);
Jim Stichnothe4a8f402015-01-20 12:52:51 -08001047
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001048} // end of namespace Ice