OLD | NEW |
1 //===- subzero/src/IceGlobalContext.cpp - Global context defs ---*- C++ -*-===// | 1 //===- subzero/src/IceGlobalContext.cpp - Global context defs ---*- C++ -*-===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file defines aspects of the compilation that persist across | 10 // This file defines aspects of the compilation that persist across |
11 // multiple functions. | 11 // multiple functions. |
12 // | 12 // |
13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
14 | 14 |
15 #include <ctype.h> // isdigit(), isupper() | 15 #include <ctype.h> // isdigit(), isupper() |
16 #include <locale> // locale | 16 #include <locale> // locale |
17 | 17 |
18 #include "IceDefs.h" | 18 #include "IceDefs.h" |
19 #include "IceTypes.h" | 19 #include "IceTypes.h" |
20 #include "IceCfg.h" | 20 #include "IceCfg.h" |
21 #include "IceClFlags.h" | 21 #include "IceClFlags.h" |
22 #include "IceGlobalContext.h" | 22 #include "IceGlobalContext.h" |
23 #include "IceOperand.h" | 23 #include "IceOperand.h" |
24 #include "IceTargetLowering.h" | 24 #include "IceTargetLowering.h" |
25 | 25 |
26 namespace Ice { | 26 namespace Ice { |
27 | 27 |
| 28 namespace { |
| 29 |
| 30 template <class MapTy, class ListTy> |
| 31 ListTy makeListOfValues(const MapTy &Pool) { |
| 32 ListTy Values; |
| 33 Values.reserve(Pool.size()); |
| 34 // TODO: replace the loop with std::transform + lambdas. |
| 35 for (typename MapTy::const_iterator I = Pool.begin(), E = Pool.end(); I != E; |
| 36 ++I) { |
| 37 Values.push_back(I->second); |
| 38 } |
| 39 return Values; |
| 40 } |
| 41 |
| 42 } // end of anonymous namespace |
| 43 |
28 // TypePool maps constants of type KeyType (e.g. float) to pointers to | 44 // TypePool maps constants of type KeyType (e.g. float) to pointers to |
29 // type ValueType (e.g. ConstantFloat). KeyType values are compared | 45 // type ValueType (e.g. ConstantFloat). KeyType values are compared |
30 // using memcmp() because of potential NaN values in KeyType values. | 46 // using memcmp() because of potential NaN values in KeyType values. |
31 // KeyTypeHasFP indicates whether KeyType is a floating-point type | 47 // KeyTypeHasFP indicates whether KeyType is a floating-point type |
32 // whose values need to be compared using memcmp() for NaN | 48 // whose values need to be compared using memcmp() for NaN |
33 // correctness. TODO: use std::is_floating_point<KeyType> instead of | 49 // correctness. TODO: use std::is_floating_point<KeyType> instead of |
34 // KeyTypeHasFP with C++11. | 50 // KeyTypeHasFP with C++11. |
35 template <typename KeyType, typename ValueType, bool KeyTypeHasFP = false> | 51 template <typename KeyType, typename ValueType, bool KeyTypeHasFP = false> |
36 class TypePool { | 52 class TypePool { |
37 TypePool(const TypePool &) LLVM_DELETED_FUNCTION; | 53 TypePool(const TypePool &) LLVM_DELETED_FUNCTION; |
38 TypePool &operator=(const TypePool &) LLVM_DELETED_FUNCTION; | 54 TypePool &operator=(const TypePool &) LLVM_DELETED_FUNCTION; |
39 | 55 |
40 public: | 56 public: |
41 TypePool() : NextPoolID(0) {} | 57 TypePool() : NextPoolID(0) {} |
42 ValueType *getOrAdd(GlobalContext *Ctx, Type Ty, KeyType Key) { | 58 ValueType *getOrAdd(GlobalContext *Ctx, Type Ty, KeyType Key) { |
43 TupleType TupleKey = std::make_pair(Ty, Key); | 59 TupleType TupleKey = std::make_pair(Ty, Key); |
44 typename ContainerType::const_iterator Iter = Pool.find(TupleKey); | 60 typename ContainerType::const_iterator Iter = Pool.find(TupleKey); |
45 if (Iter != Pool.end()) | 61 if (Iter != Pool.end()) |
46 return Iter->second; | 62 return Iter->second; |
47 ValueType *Result = ValueType::create(Ctx, Ty, Key, NextPoolID++); | 63 ValueType *Result = ValueType::create(Ctx, Ty, Key, NextPoolID++); |
48 Pool[TupleKey] = Result; | 64 Pool[TupleKey] = Result; |
49 return Result; | 65 return Result; |
50 } | 66 } |
51 ConstantList getConstantPool() const { | 67 ConstantList getConstantPool() const { |
52 ConstantList Constants; | 68 return makeListOfValues<ContainerType, ConstantList>(Pool); |
53 Constants.reserve(Pool.size()); | |
54 // TODO: replace the loop with std::transform + lambdas. | |
55 for (typename ContainerType::const_iterator I = Pool.begin(), | |
56 E = Pool.end(); | |
57 I != E; ++I) { | |
58 Constants.push_back(I->second); | |
59 } | |
60 return Constants; | |
61 } | 69 } |
62 | 70 |
63 private: | 71 private: |
64 typedef std::pair<Type, KeyType> TupleType; | 72 typedef std::pair<Type, KeyType> TupleType; |
65 struct TupleCompare { | 73 struct TupleCompare { |
66 bool operator()(const TupleType &A, const TupleType &B) const { | 74 bool operator()(const TupleType &A, const TupleType &B) const { |
67 if (A.first != B.first) | 75 if (A.first != B.first) |
68 return A.first < B.first; | 76 return A.first < B.first; |
69 if (KeyTypeHasFP) | 77 if (KeyTypeHasFP) |
70 return memcmp(&A.second, &B.second, sizeof(KeyType)) < 0; | 78 return memcmp(&A.second, &B.second, sizeof(KeyType)) < 0; |
71 return A.second < B.second; | 79 return A.second < B.second; |
72 } | 80 } |
73 }; | 81 }; |
74 typedef std::map<const TupleType, ValueType *, TupleCompare> ContainerType; | 82 typedef std::map<const TupleType, ValueType *, TupleCompare> ContainerType; |
75 ContainerType Pool; | 83 ContainerType Pool; |
76 uint32_t NextPoolID; | 84 uint32_t NextPoolID; |
77 }; | 85 }; |
78 | 86 |
| 87 // ImmediatePool is used for pooling constants that are typically used |
| 88 // as immediate operands but have been pooled for code randomization |
| 89 // purposes. The pool maps strings to constants of any type. The |
| 90 // string is a unique label for a given immediate. |
| 91 class ImmediatePool { |
| 92 ImmediatePool(const ImmediatePool &) LLVM_DELETED_FUNCTION; |
| 93 ImmediatePool &operator=(const ImmediatePool &) LLVM_DELETED_FUNCTION; |
| 94 |
| 95 public: |
| 96 ImmediatePool() {} |
| 97 |
| 98 void add(const IceString &Name, Constant *Value) { Pool[Name] = Value; } |
| 99 ConstantList getConstantPool() const { |
| 100 return makeListOfValues<ContainerType, ConstantList>(Pool); |
| 101 } |
| 102 |
| 103 private: |
| 104 typedef std::map<IceString, Constant *> ContainerType; |
| 105 ContainerType Pool; |
| 106 }; |
| 107 |
79 // UndefPool maps ICE types to the corresponding ConstantUndef values. | 108 // UndefPool maps ICE types to the corresponding ConstantUndef values. |
80 class UndefPool { | 109 class UndefPool { |
81 UndefPool(const UndefPool &) LLVM_DELETED_FUNCTION; | 110 UndefPool(const UndefPool &) LLVM_DELETED_FUNCTION; |
82 UndefPool &operator=(const UndefPool &) LLVM_DELETED_FUNCTION; | 111 UndefPool &operator=(const UndefPool &) LLVM_DELETED_FUNCTION; |
83 | 112 |
84 public: | 113 public: |
85 UndefPool() : NextPoolID(0) {} | 114 UndefPool() : NextPoolID(0) {} |
86 | 115 |
87 ConstantUndef *getOrAdd(GlobalContext *Ctx, Type Ty) { | 116 ConstantUndef *getOrAdd(GlobalContext *Ctx, Type Ty) { |
88 ContainerType::iterator I = Pool.find(Ty); | 117 ContainerType::iterator I = Pool.find(Ty); |
(...skipping 15 matching lines...) Expand all Loading... |
104 class ConstantPool { | 133 class ConstantPool { |
105 ConstantPool(const ConstantPool &) LLVM_DELETED_FUNCTION; | 134 ConstantPool(const ConstantPool &) LLVM_DELETED_FUNCTION; |
106 ConstantPool &operator=(const ConstantPool &) LLVM_DELETED_FUNCTION; | 135 ConstantPool &operator=(const ConstantPool &) LLVM_DELETED_FUNCTION; |
107 | 136 |
108 public: | 137 public: |
109 ConstantPool() {} | 138 ConstantPool() {} |
110 TypePool<float, ConstantFloat, true> Floats; | 139 TypePool<float, ConstantFloat, true> Floats; |
111 TypePool<double, ConstantDouble, true> Doubles; | 140 TypePool<double, ConstantDouble, true> Doubles; |
112 TypePool<uint64_t, ConstantInteger> Integers; | 141 TypePool<uint64_t, ConstantInteger> Integers; |
113 TypePool<RelocatableTuple, ConstantRelocatable> Relocatables; | 142 TypePool<RelocatableTuple, ConstantRelocatable> Relocatables; |
| 143 ImmediatePool Immediates; |
114 UndefPool Undefs; | 144 UndefPool Undefs; |
115 }; | 145 }; |
116 | 146 |
117 GlobalContext::GlobalContext(llvm::raw_ostream *OsDump, | 147 GlobalContext::GlobalContext(llvm::raw_ostream *OsDump, |
118 llvm::raw_ostream *OsEmit, VerboseMask Mask, | 148 llvm::raw_ostream *OsEmit, VerboseMask Mask, |
119 TargetArch Arch, OptLevel Opt, | 149 TargetArch Arch, OptLevel Opt, |
120 IceString TestPrefix, const ClFlags &Flags) | 150 IceString TestPrefix, const ClFlags &Flags) |
121 : StrDump(OsDump), StrEmit(OsEmit), VMask(Mask), | 151 : StrDump(OsDump), StrEmit(OsEmit), VMask(Mask), |
122 ConstPool(new ConstantPool()), Arch(Arch), Opt(Opt), | 152 ConstPool(new ConstantPool()), Arch(Arch), Opt(Opt), |
123 TestPrefix(TestPrefix), Flags(Flags), HasEmittedFirstMethod(false), | 153 TestPrefix(TestPrefix), Flags(Flags), HasEmittedFirstMethod(false), |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 BaseOS << "Unsupported constant type: " << Ty; | 366 BaseOS << "Unsupported constant type: " << Ty; |
337 llvm_unreachable(BaseOS.str().c_str()); | 367 llvm_unreachable(BaseOS.str().c_str()); |
338 } break; | 368 } break; |
339 case IceType_void: | 369 case IceType_void: |
340 case IceType_NUM: | 370 case IceType_NUM: |
341 break; | 371 break; |
342 } | 372 } |
343 llvm_unreachable("Unknown type"); | 373 llvm_unreachable("Unknown type"); |
344 } | 374 } |
345 | 375 |
| 376 void GlobalContext::addConstantPooledImmediate(const IceString &Name, |
| 377 Constant *Immediate) { |
| 378 ConstPool->Immediates.add(Name, Immediate); |
| 379 } |
| 380 |
346 ConstantList GlobalContext::getConstantPool(Type Ty) const { | 381 ConstantList GlobalContext::getConstantPool(Type Ty) const { |
347 switch (Ty) { | 382 switch (Ty) { |
348 case IceType_i1: | 383 case IceType_i1: |
349 case IceType_i8: | 384 case IceType_i8: |
350 case IceType_i16: | 385 case IceType_i16: |
351 case IceType_i32: | 386 case IceType_i32: |
352 case IceType_i64: | 387 case IceType_i64: |
353 return ConstPool->Integers.getConstantPool(); | 388 return ConstPool->Integers.getConstantPool(); |
354 case IceType_f32: | 389 case IceType_f32: |
355 return ConstPool->Floats.getConstantPool(); | 390 return ConstPool->Floats.getConstantPool(); |
(...skipping 11 matching lines...) Expand all Loading... |
367 BaseOS << "Unsupported constant type: " << Ty; | 402 BaseOS << "Unsupported constant type: " << Ty; |
368 llvm_unreachable(BaseOS.str().c_str()); | 403 llvm_unreachable(BaseOS.str().c_str()); |
369 } break; | 404 } break; |
370 case IceType_void: | 405 case IceType_void: |
371 case IceType_NUM: | 406 case IceType_NUM: |
372 break; | 407 break; |
373 } | 408 } |
374 llvm_unreachable("Unknown type"); | 409 llvm_unreachable("Unknown type"); |
375 } | 410 } |
376 | 411 |
| 412 ConstantList GlobalContext::getImmediatePool() const { |
| 413 return ConstPool->Immediates.getConstantPool(); |
| 414 } |
| 415 |
377 void Timer::printElapsedUs(GlobalContext *Ctx, const IceString &Tag) const { | 416 void Timer::printElapsedUs(GlobalContext *Ctx, const IceString &Tag) const { |
378 if (Ctx->isVerbose(IceV_Timing)) { | 417 if (Ctx->isVerbose(IceV_Timing)) { |
379 // Prefixing with '#' allows timing strings to be included | 418 // Prefixing with '#' allows timing strings to be included |
380 // without error in textual assembly output. | 419 // without error in textual assembly output. |
381 Ctx->getStrDump() << "# " << getElapsedUs() << " usec " << Tag << "\n"; | 420 Ctx->getStrDump() << "# " << getElapsedUs() << " usec " << Tag << "\n"; |
382 } | 421 } |
383 } | 422 } |
384 | 423 |
385 } // end of namespace Ice | 424 } // end of namespace Ice |
OLD | NEW |