OLD | NEW |
1 //===- subzero/src/IceGlobalContext.cpp - Global context defs -------------===// | 1 //===- subzero/src/IceGlobalContext.cpp - Global context defs -------------===// |
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 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 } | 57 } |
58 }; | 58 }; |
59 template <typename KeyType> | 59 template <typename KeyType> |
60 struct KeyCompare<KeyType, typename std::enable_if< | 60 struct KeyCompare<KeyType, typename std::enable_if< |
61 std::is_floating_point<KeyType>::value>::type> { | 61 std::is_floating_point<KeyType>::value>::type> { |
62 bool operator()(const KeyType &Value1, const KeyType &Value2) const { | 62 bool operator()(const KeyType &Value1, const KeyType &Value2) const { |
63 return !memcmp(&Value1, &Value2, sizeof(KeyType)); | 63 return !memcmp(&Value1, &Value2, sizeof(KeyType)); |
64 } | 64 } |
65 }; | 65 }; |
66 | 66 |
| 67 // Define a key comparison function for sorting the constant pool's |
| 68 // values after they are dumped to a vector. This covers integer |
| 69 // types, floating point types, and ConstantRelocatable values. |
| 70 template <typename ValueType, class Enable = void> struct KeyCompareLess {}; |
| 71 |
| 72 template <typename ValueType> |
| 73 struct KeyCompareLess<ValueType, |
| 74 typename std::enable_if<std::is_floating_point< |
| 75 typename ValueType::PrimType>::value>::type> { |
| 76 bool operator()(const Constant *Const1, const Constant *Const2) const { |
| 77 typedef uint64_t CompareType; |
| 78 static_assert(sizeof(typename ValueType::PrimType) <= sizeof(CompareType), |
| 79 "Expected floating-point type of width 64-bit or less"); |
| 80 typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue(); |
| 81 typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue(); |
| 82 // We avoid "V1<V2" because of NaN. |
| 83 // We avoid "memcmp(&V1,&V2,sizeof(V1))<0" which depends on the |
| 84 // endian-ness of the host system running Subzero. |
| 85 // Instead, compare the result of bit_cast to uint64_t. |
| 86 uint64_t I1 = 0, I2 = 0; |
| 87 memcpy(&I1, &V1, sizeof(V1)); |
| 88 memcpy(&I2, &V2, sizeof(V2)); |
| 89 return I1 < I2; |
| 90 } |
| 91 }; |
| 92 template <typename ValueType> |
| 93 struct KeyCompareLess<ValueType, |
| 94 typename std::enable_if<std::is_integral< |
| 95 typename ValueType::PrimType>::value>::type> { |
| 96 bool operator()(const Constant *Const1, const Constant *Const2) const { |
| 97 typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue(); |
| 98 typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue(); |
| 99 return V1 < V2; |
| 100 } |
| 101 }; |
| 102 template <typename ValueType> |
| 103 struct KeyCompareLess< |
| 104 ValueType, typename std::enable_if< |
| 105 std::is_same<ValueType, ConstantRelocatable>::value>::type> { |
| 106 bool operator()(const Constant *Const1, const Constant *Const2) const { |
| 107 auto V1 = llvm::cast<ValueType>(Const1); |
| 108 auto V2 = llvm::cast<ValueType>(Const2); |
| 109 if (V1->getName() == V2->getName()) |
| 110 return V1->getOffset() < V2->getOffset(); |
| 111 return V1->getName() < V2->getName(); |
| 112 } |
| 113 }; |
| 114 |
67 // TypePool maps constants of type KeyType (e.g. float) to pointers to | 115 // TypePool maps constants of type KeyType (e.g. float) to pointers to |
68 // type ValueType (e.g. ConstantFloat). | 116 // type ValueType (e.g. ConstantFloat). |
69 template <Type Ty, typename KeyType, typename ValueType> class TypePool { | 117 template <Type Ty, typename KeyType, typename ValueType> class TypePool { |
70 TypePool(const TypePool &) = delete; | 118 TypePool(const TypePool &) = delete; |
71 TypePool &operator=(const TypePool &) = delete; | 119 TypePool &operator=(const TypePool &) = delete; |
72 | 120 |
73 public: | 121 public: |
74 TypePool() : NextPoolID(0) {} | 122 TypePool() : NextPoolID(0) {} |
75 ValueType *getOrAdd(GlobalContext *Ctx, KeyType Key) { | 123 ValueType *getOrAdd(GlobalContext *Ctx, KeyType Key) { |
76 auto Iter = Pool.find(Key); | 124 auto Iter = Pool.find(Key); |
77 if (Iter != Pool.end()) | 125 if (Iter != Pool.end()) |
78 return Iter->second; | 126 return Iter->second; |
79 ValueType *Result = ValueType::create(Ctx, Ty, Key, NextPoolID++); | 127 ValueType *Result = ValueType::create(Ctx, Ty, Key, NextPoolID++); |
80 Pool[Key] = Result; | 128 Pool[Key] = Result; |
81 return Result; | 129 return Result; |
82 } | 130 } |
83 ConstantList getConstantPool() const { | 131 ConstantList getConstantPool() const { |
84 ConstantList Constants; | 132 ConstantList Constants; |
85 Constants.reserve(Pool.size()); | 133 Constants.reserve(Pool.size()); |
86 for (auto &I : Pool) | 134 for (auto &I : Pool) |
87 Constants.push_back(I.second); | 135 Constants.push_back(I.second); |
| 136 // The sort (and its KeyCompareLess machinery) is not strictly |
| 137 // necessary, but is desirable for producing output that is |
| 138 // deterministic across unordered_map::iterator implementations. |
| 139 std::sort(Constants.begin(), Constants.end(), KeyCompareLess<ValueType>()); |
88 return Constants; | 140 return Constants; |
89 } | 141 } |
90 | 142 |
91 private: | 143 private: |
92 // Use the default hash function, and a custom key comparison | 144 // Use the default hash function, and a custom key comparison |
93 // function. The key comparison function for floating point | 145 // function. The key comparison function for floating point |
94 // variables can't use the default == based implementation because | 146 // variables can't use the default == based implementation because |
95 // of special C++ semantics regarding +0.0, -0.0, and NaN | 147 // of special C++ semantics regarding +0.0, -0.0, and NaN |
96 // comparison. However, it's OK to use the default hash for | 148 // comparison. However, it's OK to use the default hash for |
97 // floating point values because KeyCompare is the final source of | 149 // floating point values because KeyCompare is the final source of |
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 Ctx = Func->getContext(); | 825 Ctx = Func->getContext(); |
774 Active = | 826 Active = |
775 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); | 827 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); |
776 if (Active) | 828 if (Active) |
777 Ctx->pushTimer(ID, StackID); | 829 Ctx->pushTimer(ID, StackID); |
778 } | 830 } |
779 | 831 |
780 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); | 832 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); |
781 | 833 |
782 } // end of namespace Ice | 834 } // end of namespace Ice |
OLD | NEW |