| //===- subzero/src/IceRNG.h - Random number generator -----------*- C++ -*-===// | 
 | // | 
 | //                        The Subzero Code Generator | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | /// | 
 | /// \file | 
 | /// \brief Declares a random number generator. | 
 | /// | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #ifndef SUBZERO_SRC_ICERNG_H | 
 | #define SUBZERO_SRC_ICERNG_H | 
 |  | 
 | #include "llvm/ADT/StringRef.h" | 
 | #include "llvm/Support/Compiler.h" | 
 | #include "IceDefs.h" | 
 |  | 
 | #include <cstdint> | 
 |  | 
 | namespace Ice { | 
 |  | 
 | class RandomNumberGenerator { | 
 |   RandomNumberGenerator() = delete; | 
 |   RandomNumberGenerator(const RandomNumberGenerator &) = delete; | 
 |   RandomNumberGenerator &operator=(const RandomNumberGenerator &) = delete; | 
 |  | 
 | public: | 
 |   explicit RandomNumberGenerator(uint64_t Seed, llvm::StringRef Salt = ""); | 
 |   /// Create a random number generator with: global seed, randomization pass ID | 
 |   /// and a salt uint64_t integer. | 
 |   /// @param Seed should be a global seed. | 
 |   /// @param RandomizationPassID should be one of RandomizationPassesEnum. | 
 |   /// @param Salt should be an additional integer input for generating unique | 
 |   /// RNG. | 
 |   /// The global seed is 64 bits; since it is likely to originate from the | 
 |   /// system time, the lower bits are more "valuable" than the upper bits. As | 
 |   /// such, we merge the randomization pass ID and the salt into the global seed | 
 |   /// by xor'ing them into high bit ranges. We expect the pass ID to fit within | 
 |   /// 4 bits, so it gets shifted by 60 to merge into the upper 4 bits. We expect | 
 |   /// the salt (usually the function sequence number) to fit within 12 bits, so | 
 |   /// it gets shifted by 48 before merging. | 
 |   explicit RandomNumberGenerator(uint64_t Seed, | 
 |                                  RandomizationPassesEnum RandomizationPassID, | 
 |                                  uint64_t Salt = 0); | 
 |   uint64_t next(uint64_t Max); | 
 |  | 
 | private: | 
 |   uint64_t State; | 
 | }; | 
 |  | 
 | /// This class adds additional random number generator utilities. The reason for | 
 | /// the wrapper class is that we want to keep the RandomNumberGenerator | 
 | /// interface identical to LLVM's. | 
 | class RandomNumberGeneratorWrapper { | 
 |   RandomNumberGeneratorWrapper() = delete; | 
 |   RandomNumberGeneratorWrapper(const RandomNumberGeneratorWrapper &) = delete; | 
 |   RandomNumberGeneratorWrapper & | 
 |   operator=(const RandomNumberGeneratorWrapper &) = delete; | 
 |  | 
 | public: | 
 |   uint64_t operator()(uint64_t Max) { return RNG.next(Max); } | 
 |   bool getTrueWithProbability(float Probability); | 
 |   explicit RandomNumberGeneratorWrapper(RandomNumberGenerator &RNG) | 
 |       : RNG(RNG) {} | 
 |  | 
 | private: | 
 |   RandomNumberGenerator &RNG; | 
 | }; | 
 |  | 
 | /// RandomShuffle is an implementation of std::random_shuffle() that doesn't | 
 | /// change across stdlib implementations. Adapted from a sample implementation | 
 | /// at cppreference.com. | 
 | template <class RandomIt, class RandomFunc> | 
 | void RandomShuffle(RandomIt First, RandomIt Last, RandomFunc &&RNG) { | 
 |   for (auto i = Last - First - 1; i > 0; --i) | 
 |     std::swap(First[i], First[RNG(i + 1)]); | 
 | } | 
 |  | 
 | } // end of namespace Ice | 
 |  | 
 | #endif // SUBZERO_SRC_ICERNG_H |