|  | //===- 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 |