llvm::Expected<std::vector<CodeTemplate>> generateSelfAliasingCodeTemplates(const Instruction &Instr) { const AliasingConfigurations SelfAliasing(Instr, Instr); if (SelfAliasing.empty()) return llvm::make_error<SnippetGeneratorFailure>("empty self aliasing"); std::vector<CodeTemplate> Result; Result.emplace_back(); CodeTemplate &CT = Result.back(); InstructionTemplate IT(Instr); if (SelfAliasing.hasImplicitAliasing()) { CT.Info = "implicit Self cycles, picking random values."; } else { CT.Info = "explicit self cycles, selecting one aliasing Conf."; // This is a self aliasing instruction so defs and uses are from the same // instance, hence twice IT in the following call. setRandomAliasing(SelfAliasing, IT, IT); } CT.Instructions.push_back(std::move(IT)); return std::move(Result); }
static void appendCodeTemplates(const LLVMState &State, const Instruction &Instr, ExecutionMode ExecutionModeBit, llvm::StringRef ExecutionClassDescription, std::vector<CodeTemplate> &CodeTemplates) { assert(isEnumValue(ExecutionModeBit) && "Bit must be a power of two"); switch (ExecutionModeBit) { case ExecutionMode::ALWAYS_SERIAL_IMPLICIT_REGS_ALIAS: // Nothing to do, the instruction is always serial. LLVM_FALLTHROUGH; case ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS: { // Picking whatever value for the tied variable will make the instruction // serial. CodeTemplate CT; CT.Execution = ExecutionModeBit; CT.Info = ExecutionClassDescription; CT.Instructions.push_back(Instr); CodeTemplates.push_back(std::move(CT)); return; } case ExecutionMode::SERIAL_VIA_MEMORY_INSTR: { // Select back-to-back memory instruction. // TODO: Implement me. return; } case ExecutionMode::SERIAL_VIA_EXPLICIT_REGS: { // Making the execution of this instruction serial by selecting one def // register to alias with one use register. const AliasingConfigurations SelfAliasing(Instr, Instr); assert(!SelfAliasing.empty() && !SelfAliasing.hasImplicitAliasing() && "Instr must alias itself explicitly"); InstructionTemplate IT(Instr); // This is a self aliasing instruction so defs and uses are from the same // instance, hence twice IT in the following call. setRandomAliasing(SelfAliasing, IT, IT); CodeTemplate CT; CT.Execution = ExecutionModeBit; CT.Info = ExecutionClassDescription; CT.Instructions.push_back(std::move(IT)); CodeTemplates.push_back(std::move(CT)); return; } case ExecutionMode::SERIAL_VIA_NON_MEMORY_INSTR: { // Select back-to-back non-memory instruction. for (const auto OtherInstr : computeAliasingInstructions(State, Instr, kMaxAliasingInstructions)) { const AliasingConfigurations Forward(Instr, OtherInstr); const AliasingConfigurations Back(OtherInstr, Instr); InstructionTemplate ThisIT(Instr); InstructionTemplate OtherIT(OtherInstr); if (!Forward.hasImplicitAliasing()) setRandomAliasing(Forward, ThisIT, OtherIT); if (!Back.hasImplicitAliasing()) setRandomAliasing(Back, OtherIT, ThisIT); CodeTemplate CT; CT.Execution = ExecutionModeBit; CT.Info = ExecutionClassDescription; CT.Instructions.push_back(std::move(ThisIT)); CT.Instructions.push_back(std::move(OtherIT)); CodeTemplates.push_back(std::move(CT)); } return; } default: llvm_unreachable("Unhandled enum value"); } }