Index: llvm/trunk/tools/llvm-exegesis/lib/CodeTemplate.h =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/CodeTemplate.h +++ llvm/trunk/tools/llvm-exegesis/lib/CodeTemplate.h @@ -66,25 +66,6 @@ unsigned ScratchSpacePointerInReg = 0; }; -// A global Random Number Generator to randomize configurations. -// FIXME: Move random number generation into an object and make it seedable for -// unit tests. -std::mt19937 &randomGenerator(); - -// Picks a random bit among the bits set in Vector and returns its index. -// Precondition: Vector must have at least one bit set. -size_t randomBit(const llvm::BitVector &Vector); - -// Picks a random configuration, then selects a random def and a random use from -// it and finally set the selected values in the provided InstructionInstances. -void setRandomAliasing(const AliasingConfigurations &AliasingConfigurations, - InstructionTemplate &DefIB, InstructionTemplate &UseIB); - -// Assigns a Random Value to all Variables in IT that are still Invalid. -// Do not use any of the registers in `ForbiddenRegs`. -void randomizeUnsetVariables(const llvm::BitVector &ForbiddenRegs, - InstructionTemplate &IT); - } // namespace exegesis #endif // LLVM_TOOLS_LLVM_EXEGESIS_CODETEMPLATE_H Index: llvm/trunk/tools/llvm-exegesis/lib/CodeTemplate.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/CodeTemplate.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/CodeTemplate.cpp @@ -52,11 +52,6 @@ return getValueFor(Instr.Variables[Op.VariableIndex]); } -// forward declaration. -static void randomize(const Instruction &Instr, const Variable &Var, - llvm::MCOperand &AssignedValue, - const llvm::BitVector &ForbiddenRegs); - bool InstructionTemplate::hasImmediateVariables() const { return llvm::any_of(Instr.Variables, [this](const Variable &Var) { assert(!Var.TiedOperands.empty()); @@ -76,89 +71,4 @@ return Result; } -std::mt19937 &randomGenerator() { - static std::random_device RandomDevice; - static std::mt19937 RandomGenerator(RandomDevice()); - return RandomGenerator; -} - -static size_t randomIndex(size_t Size) { - assert(Size > 0); - std::uniform_int_distribution<> Distribution(0, Size - 1); - return Distribution(randomGenerator()); -} - -template -static auto randomElement(const C &Container) -> decltype(Container[0]) { - return Container[randomIndex(Container.size())]; -} - -static void randomize(const Instruction &Instr, const Variable &Var, - llvm::MCOperand &AssignedValue, - const llvm::BitVector &ForbiddenRegs) { - assert(!Var.TiedOperands.empty()); - const Operand &Op = Instr.Operands[Var.TiedOperands.front()]; - assert(Op.Info != nullptr); - const auto &OpInfo = *Op.Info; - switch (OpInfo.OperandType) { - case llvm::MCOI::OperandType::OPERAND_IMMEDIATE: - // FIXME: explore immediate values too. - AssignedValue = llvm::MCOperand::createImm(1); - break; - case llvm::MCOI::OperandType::OPERAND_REGISTER: { - assert(Op.Tracker); - auto AllowedRegs = Op.Tracker->sourceBits(); - assert(AllowedRegs.size() == ForbiddenRegs.size()); - for (auto I : ForbiddenRegs.set_bits()) - AllowedRegs.reset(I); - AssignedValue = llvm::MCOperand::createReg(randomBit(AllowedRegs)); - break; - } - default: - break; - } -} - -static void setRegisterOperandValue(const RegisterOperandAssignment &ROV, - InstructionTemplate &IB) { - assert(ROV.Op); - if (ROV.Op->IsExplicit) { - auto &AssignedValue = IB.getValueFor(*ROV.Op); - if (AssignedValue.isValid()) { - assert(AssignedValue.isReg() && AssignedValue.getReg() == ROV.Reg); - return; - } - AssignedValue = llvm::MCOperand::createReg(ROV.Reg); - } else { - assert(ROV.Op->ImplicitReg != nullptr); - assert(ROV.Reg == *ROV.Op->ImplicitReg); - } -} - -size_t randomBit(const llvm::BitVector &Vector) { - assert(Vector.any()); - auto Itr = Vector.set_bits_begin(); - for (size_t I = randomIndex(Vector.count()); I != 0; --I) - ++Itr; - return *Itr; -} - -void setRandomAliasing(const AliasingConfigurations &AliasingConfigurations, - InstructionTemplate &DefIB, InstructionTemplate &UseIB) { - assert(!AliasingConfigurations.empty()); - assert(!AliasingConfigurations.hasImplicitAliasing()); - const auto &RandomConf = randomElement(AliasingConfigurations.Configurations); - setRegisterOperandValue(randomElement(RandomConf.Defs), DefIB); - setRegisterOperandValue(randomElement(RandomConf.Uses), UseIB); -} - -void randomizeUnsetVariables(const llvm::BitVector &ForbiddenRegs, - InstructionTemplate &IT) { - for (const Variable &Var : IT.Instr.Variables) { - llvm::MCOperand &AssignedValue = IT.getValueFor(Var); - if (!AssignedValue.isValid()) - randomize(IT.Instr, Var, AssignedValue, ForbiddenRegs); - } -} - } // namespace exegesis Index: llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.h =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.h +++ llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.h @@ -70,6 +70,25 @@ generateCodeTemplate(unsigned Opcode) const = 0; }; +// A global Random Number Generator to randomize configurations. +// FIXME: Move random number generation into an object and make it seedable for +// unit tests. +std::mt19937 &randomGenerator(); + +// Picks a random bit among the bits set in Vector and returns its index. +// Precondition: Vector must have at least one bit set. +size_t randomBit(const llvm::BitVector &Vector); + +// Picks a random configuration, then selects a random def and a random use from +// it and finally set the selected values in the provided InstructionInstances. +void setRandomAliasing(const AliasingConfigurations &AliasingConfigurations, + InstructionTemplate &DefIB, InstructionTemplate &UseIB); + +// Assigns a Random Value to all Variables in IT that are still Invalid. +// Do not use any of the registers in `ForbiddenRegs`. +void randomizeUnsetVariables(const llvm::BitVector &ForbiddenRegs, + InstructionTemplate &IT); + } // namespace exegesis #endif // LLVM_TOOLS_LLVM_EXEGESIS_SNIPPETGENERATOR_H Index: llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.cpp @@ -129,4 +129,89 @@ return std::move(CT); } +std::mt19937 &randomGenerator() { + static std::random_device RandomDevice; + static std::mt19937 RandomGenerator(RandomDevice()); + return RandomGenerator; +} + +static size_t randomIndex(size_t Size) { + assert(Size > 0); + std::uniform_int_distribution<> Distribution(0, Size - 1); + return Distribution(randomGenerator()); +} + +template +static auto randomElement(const C &Container) -> decltype(Container[0]) { + return Container[randomIndex(Container.size())]; +} + +static void randomize(const Instruction &Instr, const Variable &Var, + llvm::MCOperand &AssignedValue, + const llvm::BitVector &ForbiddenRegs) { + assert(!Var.TiedOperands.empty()); + const Operand &Op = Instr.Operands[Var.TiedOperands.front()]; + assert(Op.Info != nullptr); + const auto &OpInfo = *Op.Info; + switch (OpInfo.OperandType) { + case llvm::MCOI::OperandType::OPERAND_IMMEDIATE: + // FIXME: explore immediate values too. + AssignedValue = llvm::MCOperand::createImm(1); + break; + case llvm::MCOI::OperandType::OPERAND_REGISTER: { + assert(Op.Tracker); + auto AllowedRegs = Op.Tracker->sourceBits(); + assert(AllowedRegs.size() == ForbiddenRegs.size()); + for (auto I : ForbiddenRegs.set_bits()) + AllowedRegs.reset(I); + AssignedValue = llvm::MCOperand::createReg(randomBit(AllowedRegs)); + break; + } + default: + break; + } +} + +static void setRegisterOperandValue(const RegisterOperandAssignment &ROV, + InstructionTemplate &IB) { + assert(ROV.Op); + if (ROV.Op->IsExplicit) { + auto &AssignedValue = IB.getValueFor(*ROV.Op); + if (AssignedValue.isValid()) { + assert(AssignedValue.isReg() && AssignedValue.getReg() == ROV.Reg); + return; + } + AssignedValue = llvm::MCOperand::createReg(ROV.Reg); + } else { + assert(ROV.Op->ImplicitReg != nullptr); + assert(ROV.Reg == *ROV.Op->ImplicitReg); + } +} + +size_t randomBit(const llvm::BitVector &Vector) { + assert(Vector.any()); + auto Itr = Vector.set_bits_begin(); + for (size_t I = randomIndex(Vector.count()); I != 0; --I) + ++Itr; + return *Itr; +} + +void setRandomAliasing(const AliasingConfigurations &AliasingConfigurations, + InstructionTemplate &DefIB, InstructionTemplate &UseIB) { + assert(!AliasingConfigurations.empty()); + assert(!AliasingConfigurations.hasImplicitAliasing()); + const auto &RandomConf = randomElement(AliasingConfigurations.Configurations); + setRegisterOperandValue(randomElement(RandomConf.Defs), DefIB); + setRegisterOperandValue(randomElement(RandomConf.Uses), UseIB); +} + +void randomizeUnsetVariables(const llvm::BitVector &ForbiddenRegs, + InstructionTemplate &IT) { + for (const Variable &Var : IT.Instr.Variables) { + llvm::MCOperand &AssignedValue = IT.getValueFor(Var); + if (!AssignedValue.isValid()) + randomize(IT.Instr, Var, AssignedValue, ForbiddenRegs); + } +} + } // namespace exegesis