Index: src/IceThreading.h |
diff --git a/src/IceUtils.h b/src/IceThreading.h |
similarity index 65% |
copy from src/IceUtils.h |
copy to src/IceThreading.h |
index dc3a5ff1d77ef160d2b321038f17db3ed64cdbde..9ae3b670328525aebef538fe24cf87511b03dd43 100644 |
--- a/src/IceUtils.h |
+++ b/src/IceThreading.h |
@@ -1,4 +1,4 @@ |
-//===- subzero/src/IceUtils.h - Utility functions ---------------*- C++ -*-===// |
+//===- subzero/src/IceThreading.h - Threading functions ---------*- C++ -*-===// |
// |
// The Subzero Code Generator |
// |
@@ -7,61 +7,19 @@ |
// |
//===----------------------------------------------------------------------===// |
// |
-// This file declares some utility functions. |
+// This file declares threading-related functions. |
// |
//===----------------------------------------------------------------------===// |
-#ifndef SUBZERO_SRC_ICEUTILS_H |
-#define SUBZERO_SRC_ICEUTILS_H |
+#ifndef SUBZERO_SRC_ICETHREADING_H |
+#define SUBZERO_SRC_ICETHREADING_H |
-#include <climits> |
#include <condition_variable> |
+#include <mutex> |
-namespace Ice { |
+#include "IceDefs.h" |
-// Similar to bit_cast, but allows copying from types of unrelated |
-// sizes. This method was introduced to enable the strict aliasing |
-// optimizations of GCC 4.4. Basically, GCC mindlessly relies on |
-// obscure details in the C++ standard that make reinterpret_cast |
-// virtually useless. |
-template <class D, class S> inline D bit_copy(const S &source) { |
- D destination; |
- // This use of memcpy is safe: source and destination cannot overlap. |
- memcpy(&destination, reinterpret_cast<const void *>(&source), |
- sizeof(destination)); |
- return destination; |
-} |
- |
-class Utils { |
-public: |
- // Check whether an N-bit two's-complement representation can hold value. |
- template <typename T> static inline bool IsInt(int N, T value) { |
- assert((0 < N) && |
- (static_cast<unsigned int>(N) < (CHAR_BIT * sizeof(value)))); |
- T limit = static_cast<T>(1) << (N - 1); |
- return (-limit <= value) && (value < limit); |
- } |
- |
- template <typename T> static inline bool IsUint(int N, T value) { |
- assert((0 < N) && |
- (static_cast<unsigned int>(N) < (CHAR_BIT * sizeof(value)))); |
- T limit = static_cast<T>(1) << N; |
- return (0 <= value) && (value < limit); |
- } |
- |
- template <typename T> static inline bool WouldOverflowAdd(T X, T Y) { |
- return ((X > 0 && Y > 0 && (X > std::numeric_limits<T>::max() - Y)) || |
- (X < 0 && Y < 0 && (X < std::numeric_limits<T>::min() - Y))); |
- } |
- |
- static inline uint64_t OffsetToAlignment(uint64_t Pos, uint64_t Align) { |
- assert(llvm::isPowerOf2_64(Align)); |
- uint64_t Mod = Pos & (Align - 1); |
- if (Mod == 0) |
- return 0; |
- return Align - Mod; |
- } |
-}; |
+namespace Ice { |
// BoundedProducerConsumerQueue is a work queue that allows multiple |
// producers and multiple consumers. A producer adds entries using |
@@ -96,7 +54,7 @@ class BoundedProducerConsumerQueue { |
operator=(const BoundedProducerConsumerQueue &) = delete; |
public: |
- BoundedProducerConsumerQueue(size_t MaxSize, bool Sequential) |
+ BoundedProducerConsumerQueue(bool Sequential, size_t MaxSize = MaxStaticSize) |
: Back(0), Front(0), MaxSize(std::min(MaxSize, MaxStaticSize)), |
Sequential(Sequential), IsEnded(false) {} |
void blockingPush(T *Item) { |
@@ -190,6 +148,60 @@ private: |
} |
}; |
+// EmitterWorkItem is a simple wrapper around a pointer that |
+// represents a work item to be emitted, i.e. a function or a set of |
+// global declarations and initializers, and it includes a sequence |
+// number so that work items can be emitted in a particular order for |
+// deterministic output. It acts like an interface class, but instead |
+// of making the classes of interest inherit from EmitterWorkItem, it |
+// wraps pointers to these classes. Some space is wasted compared to |
+// storing the pointers in a union, but not too much due to the work |
+// granularity. |
+class EmitterWorkItem { |
+ EmitterWorkItem() = delete; |
+ EmitterWorkItem(const EmitterWorkItem &) = delete; |
+ EmitterWorkItem &operator=(const EmitterWorkItem &) = delete; |
+ |
+public: |
+ // ItemKind can be one of the following: |
+ // |
+ // WI_Nop: No actual work. This is a placeholder to maintain |
+ // sequence numbers in case there is a translation error. |
+ // |
+ // WI_GlobalInits: A list of global declarations and initializers. |
+ // |
+ // WI_Asm: A function that has already had emitIAS() called on it. |
+ // The work is transferred via the Assembler buffer, and the |
+ // originating Cfg has been deleted (to recover lots of memory). |
+ // |
+ // WI_Cfg: A Cfg that has not yet had emit() or emitIAS() called on |
+ // it. This is only used as a debugging configuration when we want |
+ // to emit "readable" assembly code, possibly annotated with |
+ // liveness and other information only available in the Cfg and not |
+ // in the Assembler buffer. |
+ enum ItemKind { WI_Nop, WI_GlobalInits, WI_Asm, WI_Cfg }; |
+ // Constructor for a WI_Nop work item. |
+ explicit EmitterWorkItem(uint32_t Seq); |
+ // Constructor for a WI_GlobalInits work item. |
+ EmitterWorkItem(uint32_t Seq, VariableDeclarationList *D); |
+ // Constructor for a WI_Asm work item. |
+ EmitterWorkItem(uint32_t Seq, Assembler *A); |
+ // Constructor for a WI_Cfg work item. |
+ EmitterWorkItem(uint32_t Seq, Cfg *F); |
+ uint32_t getSequenceNumber() const { return Sequence; } |
+ ItemKind getKind() const { return Kind; } |
+ std::unique_ptr<VariableDeclarationList> getGlobalInits(); |
+ std::unique_ptr<Assembler> getAsm(); |
+ std::unique_ptr<Cfg> getCfg(); |
+ |
+private: |
+ const uint32_t Sequence; |
+ const ItemKind Kind; |
+ std::unique_ptr<VariableDeclarationList> GlobalInits; |
+ std::unique_ptr<Assembler> Function; |
+ std::unique_ptr<Cfg> RawFunc; |
+}; |
+ |
} // end of namespace Ice |
-#endif // SUBZERO_SRC_ICEUTILS_H |
+#endif // SUBZERO_SRC_ICETHREADING_H |