[llvm] r336352 - [llvm-exegesis] Add uop computation for more X87 instruction classes.
Clement Courbet via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 5 06:54:51 PDT 2018
Author: courbet
Date: Thu Jul 5 06:54:51 2018
New Revision: 336352
URL: http://llvm.org/viewvc/llvm-project?rev=336352&view=rev
Log:
[llvm-exegesis] Add uop computation for more X87 instruction classes.
Summary:
This allows measuring comparisons (UCOM_FpIr32,UCOM_Fpr32,...),
conditional moves (CMOVBE_Fp32,...)
Reviewers: gchatelet
Subscribers: tschuett, llvm-commits
Differential Revision: https://reviews.llvm.org/D48713
Modified:
llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h
llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp
llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp
Modified: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp?rev=336352&r1=336351&r2=336352&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp Thu Jul 5 06:54:51 2018
@@ -196,8 +196,8 @@ BenchmarkRunner::writeObjectFile(const B
return ResultPath.str();
}
-llvm::Expected<SnippetPrototype> BenchmarkRunner::generateSelfAliasingPrototype(
- const Instruction &Instr) const {
+llvm::Expected<SnippetPrototype>
+BenchmarkRunner::generateSelfAliasingPrototype(const Instruction &Instr) const {
const AliasingConfigurations SelfAliasing(Instr, Instr);
if (SelfAliasing.empty()) {
return llvm::make_error<BenchmarkFailure>("empty self aliasing");
@@ -217,4 +217,13 @@ llvm::Expected<SnippetPrototype> Benchma
return std::move(Prototype);
}
+llvm::Expected<SnippetPrototype>
+BenchmarkRunner::generateUnconstrainedPrototype(const Instruction &Instr,
+ llvm::StringRef Msg) const {
+ SnippetPrototype Prototype;
+ Prototype.Explanation =
+ llvm::formatv("{0}, repeating an unconstrained assignment", Msg);
+ Prototype.Snippet.emplace_back(Instr);
+ return std::move(Prototype);
+}
} // namespace exegesis
Modified: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h?rev=336352&r1=336351&r2=336352&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h Thu Jul 5 06:54:51 2018
@@ -70,8 +70,13 @@ protected:
const LLVMState &State;
const RegisterAliasingTrackerCache RATC;
+ // Generates a single instruction prototype that has a self-dependency.
llvm::Expected<SnippetPrototype>
generateSelfAliasingPrototype(const Instruction &Instr) const;
+ // Generates a single instruction prototype without assignment constraints.
+ llvm::Expected<SnippetPrototype>
+ generateUnconstrainedPrototype(const Instruction &Instr,
+ llvm::StringRef Msg) const;
private:
// API to be implemented by subclasses.
Modified: llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp?rev=336352&r1=336351&r2=336352&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp Thu Jul 5 06:54:51 2018
@@ -139,16 +139,10 @@ UopsBenchmarkRunner::generatePrototype(u
const Instruction Instr(InstrDesc, RATC);
const AliasingConfigurations SelfAliasing(Instr, Instr);
if (SelfAliasing.empty()) {
- SnippetPrototype Prototype;
- Prototype.Explanation = "instruction is parallel, repeating a random one.";
- Prototype.Snippet.emplace_back(Instr);
- return std::move(Prototype);
+ return generateUnconstrainedPrototype(Instr, "instruction is parallel");
}
if (SelfAliasing.hasImplicitAliasing()) {
- SnippetPrototype Prototype;
- Prototype.Explanation = "instruction is serial, repeating a random one.";
- Prototype.Snippet.emplace_back(Instr);
- return std::move(Prototype);
+ return generateUnconstrainedPrototype(Instr, "instruction is serial");
}
const auto TiedVariables = getTiedVariables(Instr);
if (!TiedVariables.empty()) {
Modified: llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp?rev=336352&r1=336351&r2=336352&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp Thu Jul 5 06:54:51 2018
@@ -44,9 +44,9 @@ template <typename Impl> class X86Benchm
case llvm::X86II::NotFP:
break;
case llvm::X86II::ZeroArgFP:
- return Impl::handleZeroArgFP(Instr);
+ return llvm::make_error<BenchmarkFailure>("Unsupported x87 ZeroArgFP");
case llvm::X86II::OneArgFP:
- return Impl::handleOneArgFP(Instr); // fstp ST(0)
+ return llvm::make_error<BenchmarkFailure>("Unsupported x87 OneArgFP");
case llvm::X86II::OneArgFPRW:
case llvm::X86II::TwoArgFP: {
// These are instructions like
@@ -61,7 +61,7 @@ template <typename Impl> class X86Benchm
case llvm::X86II::CondMovFP:
return Impl::handleCondMovFP(Instr);
case llvm::X86II::SpecialFP:
- return Impl::handleSpecialFP(Instr);
+ return llvm::make_error<BenchmarkFailure>("Unsupported x87 SpecialFP");
default:
llvm_unreachable("Unknown FP Type!");
}
@@ -76,14 +76,6 @@ protected:
using Base = LatencyBenchmarkRunner;
using Base::Base;
llvm::Expected<SnippetPrototype>
- handleZeroArgFP(const Instruction &Instr) const {
- return llvm::make_error<BenchmarkFailure>("Unsupported x87 ZeroArgFP");
- }
- llvm::Expected<SnippetPrototype>
- handleOneArgFP(const Instruction &Instr) const {
- return llvm::make_error<BenchmarkFailure>("Unsupported x87 OneArgFP");
- }
- llvm::Expected<SnippetPrototype>
handleCompareFP(const Instruction &Instr) const {
return llvm::make_error<BenchmarkFailure>("Unsupported x87 CompareFP");
}
@@ -91,35 +83,23 @@ protected:
handleCondMovFP(const Instruction &Instr) const {
return llvm::make_error<BenchmarkFailure>("Unsupported x87 CondMovFP");
}
- llvm::Expected<SnippetPrototype>
- handleSpecialFP(const Instruction &Instr) const {
- return llvm::make_error<BenchmarkFailure>("Unsupported x87 SpecialFP");
- }
};
class X86UopsImpl : public UopsBenchmarkRunner {
protected:
using Base = UopsBenchmarkRunner;
using Base::Base;
- llvm::Expected<SnippetPrototype>
- handleZeroArgFP(const Instruction &Instr) const {
- return llvm::make_error<BenchmarkFailure>("Unsupported x87 ZeroArgFP");
- }
- llvm::Expected<SnippetPrototype>
- handleOneArgFP(const Instruction &Instr) const {
- return llvm::make_error<BenchmarkFailure>("Unsupported x87 OneArgFP");
- }
+ // We can compute uops for any FP instruction that does not grow or shrink the
+ // stack (either do not touch the stack or push as much as they pop).
llvm::Expected<SnippetPrototype>
handleCompareFP(const Instruction &Instr) const {
- return llvm::make_error<BenchmarkFailure>("Unsupported x87 CompareFP");
+ return generateUnconstrainedPrototype(
+ Instr, "instruction does not grow/shrink the FP stack");
}
llvm::Expected<SnippetPrototype>
handleCondMovFP(const Instruction &Instr) const {
- return llvm::make_error<BenchmarkFailure>("Unsupported x87 CondMovFP");
- }
- llvm::Expected<SnippetPrototype>
- handleSpecialFP(const Instruction &Instr) const {
- return llvm::make_error<BenchmarkFailure>("Unsupported x87 SpecialFP");
+ return generateUnconstrainedPrototype(
+ Instr, "instruction does not grow/shrink the FP stack");
}
};
@@ -163,6 +143,15 @@ class ExegesisX86Target : public Exegesi
llvm::X86::RFP64RegClass.contains(Reg) ||
llvm::X86::RFP80RegClass.contains(Reg))
return setVectorRegToConstant(Reg, 8, llvm::X86::LD_Fp64m);
+ if (Reg == llvm::X86::EFLAGS) {
+ // Set all flags to 0 but the bits that are "reserved and set to 1".
+ constexpr const uint32_t kImmValue = 0x00007002u;
+ std::vector<llvm::MCInst> Result;
+ Result.push_back(allocateStackSpace(8));
+ Result.push_back(fillStackSpace(llvm::X86::MOV64mi32, 0, kImmValue));
+ Result.push_back(llvm::MCInstBuilder(llvm::X86::POPF64)); // Also pops.
+ return Result;
+ }
return {};
}
@@ -193,41 +182,59 @@ private:
// value that has set bits for all byte values and is a normal float/
// double. 0x40404040 is ~32.5 when interpreted as a double and ~3.0f when
// interpreted as a float.
- constexpr const uint64_t kImmValue = 0x40404040ull;
+ constexpr const uint32_t kImmValue = 0x40404040u;
std::vector<llvm::MCInst> Result;
- // Allocate scratch memory on the stack.
- Result.push_back(llvm::MCInstBuilder(llvm::X86::SUB64ri8)
- .addReg(llvm::X86::RSP)
- .addReg(llvm::X86::RSP)
- .addImm(RegSizeBytes));
- // Fill scratch memory.
- for (unsigned Disp = 0; Disp < RegSizeBytes; Disp += 4) {
- Result.push_back(llvm::MCInstBuilder(llvm::X86::MOV32mi)
- // Address = ESP
- .addReg(llvm::X86::RSP) // BaseReg
- .addImm(1) // ScaleAmt
- .addReg(0) // IndexReg
- .addImm(Disp) // Disp
- .addReg(0) // Segment
- // Immediate.
- .addImm(kImmValue));
- }
- // Load Reg from scratch memory.
- Result.push_back(llvm::MCInstBuilder(RMOpcode)
- .addReg(Reg)
- // Address = ESP
- .addReg(llvm::X86::RSP) // BaseReg
- .addImm(1) // ScaleAmt
- .addReg(0) // IndexReg
- .addImm(0) // Disp
- .addReg(0)); // Segment
- // Release scratch memory.
- Result.push_back(llvm::MCInstBuilder(llvm::X86::ADD64ri8)
- .addReg(llvm::X86::RSP)
- .addReg(llvm::X86::RSP)
- .addImm(RegSizeBytes));
+ Result.push_back(allocateStackSpace(RegSizeBytes));
+ constexpr const unsigned kMov32NumBytes = 4;
+ for (unsigned Disp = 0; Disp < RegSizeBytes; Disp += kMov32NumBytes) {
+ Result.push_back(fillStackSpace(llvm::X86::MOV32mi, Disp, kImmValue));
+ }
+ Result.push_back(loadToReg(Reg, RMOpcode));
+ Result.push_back(releaseStackSpace(RegSizeBytes));
return Result;
}
+
+ // Allocates scratch memory on the stack.
+ static llvm::MCInst allocateStackSpace(unsigned Bytes) {
+ return llvm::MCInstBuilder(llvm::X86::SUB64ri8)
+ .addReg(llvm::X86::RSP)
+ .addReg(llvm::X86::RSP)
+ .addImm(Bytes);
+ }
+
+ // Fills scratch memory at offset `OffsetBytes` with value `Imm`.
+ static llvm::MCInst fillStackSpace(unsigned MovOpcode, unsigned OffsetBytes,
+ uint64_t Imm) {
+ return llvm::MCInstBuilder(MovOpcode)
+ // Address = ESP
+ .addReg(llvm::X86::RSP) // BaseReg
+ .addImm(1) // ScaleAmt
+ .addReg(0) // IndexReg
+ .addImm(OffsetBytes) // Disp
+ .addReg(0) // Segment
+ // Immediate.
+ .addImm(Imm);
+ }
+
+ // Loads scratch memory into register `Reg` using opcode `RMOpcode`.
+ static llvm::MCInst loadToReg(unsigned Reg, unsigned RMOpcode) {
+ return llvm::MCInstBuilder(RMOpcode)
+ .addReg(Reg)
+ // Address = ESP
+ .addReg(llvm::X86::RSP) // BaseReg
+ .addImm(1) // ScaleAmt
+ .addReg(0) // IndexReg
+ .addImm(0) // Disp
+ .addReg(0); // Segment
+ }
+
+ // Releases scratch memory.
+ static llvm::MCInst releaseStackSpace(unsigned Bytes) {
+ return llvm::MCInstBuilder(llvm::X86::ADD64ri8)
+ .addReg(llvm::X86::RSP)
+ .addReg(llvm::X86::RSP)
+ .addImm(Bytes);
+ }
};
} // namespace
More information about the llvm-commits
mailing list