summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp')
-rw-r--r--llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp67
1 files changed, 58 insertions, 9 deletions
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 063d72e2911..94b24732f6f 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -78,10 +78,11 @@ BenchmarkRunner::runOne(const BenchmarkConfiguration &Configuration,
// Repeat the snippet until there are at least NumInstructions in the
// resulting code. The snippet is always repeated at least once.
- const auto GenerateInstructions = [&Snippet](const int MinInstructions) {
- std::vector<llvm::MCInst> Code = Snippet;
+ const auto GenerateInstructions = [&Configuration](
+ const int MinInstructions) {
+ std::vector<llvm::MCInst> Code = Configuration.Snippet;
for (int I = 0; I < MinInstructions; ++I)
- Code.push_back(Snippet[I % Snippet.size()]);
+ Code.push_back(Configuration.Snippet[I % Configuration.Snippet.size()]);
return Code;
};
@@ -91,7 +92,8 @@ BenchmarkRunner::runOne(const BenchmarkConfiguration &Configuration,
constexpr const int kMinInstructionsForSnippet = 16;
{
auto ObjectFilePath =
- writeObjectFile(GenerateInstructions(kMinInstructionsForSnippet));
+ writeObjectFile(Configuration.SnippetSetup,
+ GenerateInstructions(kMinInstructionsForSnippet));
if (llvm::Error E = ObjectFilePath.takeError()) {
InstrBenchmark.Error = llvm::toString(std::move(E));
return InstrBenchmark;
@@ -105,7 +107,8 @@ BenchmarkRunner::runOne(const BenchmarkConfiguration &Configuration,
// Assemble NumRepetitions instructions repetitions of the snippet for
// measurements.
auto ObjectFilePath =
- writeObjectFile(GenerateInstructions(InstrBenchmark.NumRepetitions));
+ writeObjectFile(Configuration.SnippetSetup,
+ GenerateInstructions(InstrBenchmark.NumRepetitions));
if (llvm::Error E = ObjectFilePath.takeError()) {
InstrBenchmark.Error = llvm::toString(std::move(E));
return InstrBenchmark;
@@ -126,22 +129,68 @@ BenchmarkRunner::generateConfigurations(unsigned Opcode) const {
// TODO: Generate as many configurations as needed here.
BenchmarkConfiguration Configuration;
Configuration.Info = Prototype.Explanation;
- for (InstructionInstance &II : Prototype.Snippet)
- Configuration.Snippet.push_back(II.randomizeUnsetVariablesAndBuild());
+ for (InstructionInstance &II : Prototype.Snippet) {
+ II.randomizeUnsetVariables();
+ Configuration.Snippet.push_back(II.build());
+ }
+ Configuration.SnippetSetup.RegsToDef = computeRegsToDef(Prototype.Snippet);
return std::vector<BenchmarkConfiguration>{Configuration};
} else
return E.takeError();
}
+std::vector<unsigned> BenchmarkRunner::computeRegsToDef(
+ const std::vector<InstructionInstance> &Snippet) const {
+ // Collect all register uses and create an assignment for each of them.
+ // Loop invariant: DefinedRegs[i] is true iif it has been set at least once
+ // before the current instruction.
+ llvm::BitVector DefinedRegs = RATC.emptyRegisters();
+ std::vector<unsigned> RegsToDef;
+ for (const InstructionInstance &II : Snippet) {
+ // Returns the register that this Operand sets or uses, or 0 if this is not
+ // a register.
+ const auto GetOpReg = [&II](const Operand &Op) -> unsigned {
+ if (Op.ImplicitReg) {
+ return *Op.ImplicitReg;
+ } else if (Op.IsExplicit && II.getValueFor(Op).isReg()) {
+ return II.getValueFor(Op).getReg();
+ }
+ return 0;
+ };
+ // Collect used registers that have never been def'ed.
+ for (const Operand &Op : II.Instr.Operands) {
+ if (!Op.IsDef) {
+ const unsigned Reg = GetOpReg(Op);
+ if (Reg > 0 && !DefinedRegs.test(Reg)) {
+ RegsToDef.push_back(Reg);
+ DefinedRegs.set(Reg);
+ }
+ }
+ }
+ // Mark defs as having been def'ed.
+ for (const Operand &Op : II.Instr.Operands) {
+ if (Op.IsDef) {
+ const unsigned Reg = GetOpReg(Op);
+ if (Reg > 0) {
+ DefinedRegs.set(Reg);
+ }
+ }
+ }
+ }
+ return RegsToDef;
+}
+
llvm::Expected<std::string>
-BenchmarkRunner::writeObjectFile(llvm::ArrayRef<llvm::MCInst> Code) const {
+BenchmarkRunner::writeObjectFile(const BenchmarkConfiguration::Setup &Setup,
+ llvm::ArrayRef<llvm::MCInst> Code) const {
int ResultFD = 0;
llvm::SmallString<256> ResultPath;
if (llvm::Error E = llvm::errorCodeToError(llvm::sys::fs::createTemporaryFile(
"snippet", "o", ResultFD, ResultPath)))
return std::move(E);
llvm::raw_fd_ostream OFS(ResultFD, true /*ShouldClose*/);
- assembleToStream(State.createTargetMachine(), Code, OFS);
+ assembleToStream(State.getExegesisTarget(), State.createTargetMachine(),
+ Setup.RegsToDef, Code, OFS);
return ResultPath.str();
}
OpenPOWER on IntegriCloud