forked from OSchip/llvm-project
[llvm-exegesis] ExegisX86Target::setRegToConstant() should depend on the subtarget features.
Summary: This fixes PR38008. Reviewers: gchatelet, RKSimon Subscribers: tschuett, craig.topper, llvm-commits Differential Revision: https://reviews.llvm.org/D48820 llvm-svn: 336171
This commit is contained in:
parent
83e5f81d26
commit
e785169fce
|
@ -30,12 +30,13 @@ static constexpr const char FunctionID[] = "foo";
|
|||
|
||||
static std::vector<llvm::MCInst>
|
||||
generateSnippetSetupCode(const llvm::ArrayRef<unsigned> RegsToDef,
|
||||
const ExegesisTarget &ET, bool &IsComplete) {
|
||||
const ExegesisTarget &ET,
|
||||
const llvm::LLVMTargetMachine &TM, bool &IsComplete) {
|
||||
IsComplete = true;
|
||||
std::vector<llvm::MCInst> Result;
|
||||
for (const unsigned Reg : RegsToDef) {
|
||||
// Load a constant in the register.
|
||||
const auto Code = ET.setRegToConstant(Reg);
|
||||
const auto Code = ET.setRegToConstant(*TM.getMCSubtargetInfo(), Reg);
|
||||
if (Code.empty())
|
||||
IsComplete = false;
|
||||
Result.insert(Result.end(), Code.begin(), Code.end());
|
||||
|
@ -159,7 +160,7 @@ void assembleToStream(const ExegesisTarget &ET,
|
|||
Properties.reset(llvm::MachineFunctionProperties::Property::IsSSA);
|
||||
bool IsSnippetSetupComplete = false;
|
||||
std::vector<llvm::MCInst> SnippetWithSetup =
|
||||
generateSnippetSetupCode(RegsToDef, ET, IsSnippetSetupComplete);
|
||||
generateSnippetSetupCode(RegsToDef, ET, *TM, IsSnippetSetupComplete);
|
||||
if (!SnippetWithSetup.empty()) {
|
||||
SnippetWithSetup.insert(SnippetWithSetup.end(), Instructions.begin(),
|
||||
Instructions.end());
|
||||
|
|
|
@ -34,7 +34,8 @@ public:
|
|||
virtual void addTargetSpecificPasses(llvm::PassManagerBase &PM) const {}
|
||||
|
||||
// Generates code to move a constant into a the given register.
|
||||
virtual std::vector<llvm::MCInst> setRegToConstant(unsigned Reg) const {
|
||||
virtual std::vector<llvm::MCInst>
|
||||
setRegToConstant(const llvm::MCSubtargetInfo &STI, unsigned Reg) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "MCTargetDesc/X86MCTargetDesc.h"
|
||||
#include "X86.h"
|
||||
#include "X86RegisterInfo.h"
|
||||
#include "X86Subtarget.h"
|
||||
#include "llvm/MC/MCInstBuilder.h"
|
||||
|
||||
namespace exegesis {
|
||||
|
@ -130,8 +131,9 @@ class ExegesisX86Target : public ExegesisTarget {
|
|||
PM.add(llvm::createX86FloatingPointStackifierPass());
|
||||
}
|
||||
|
||||
std::vector<llvm::MCInst>
|
||||
setRegToConstant(unsigned Reg) const override {
|
||||
std::vector<llvm::MCInst> setRegToConstant(const llvm::MCSubtargetInfo &STI,
|
||||
unsigned Reg) const override {
|
||||
// GPR.
|
||||
if (llvm::X86::GR8RegClass.contains(Reg))
|
||||
return {llvm::MCInstBuilder(llvm::X86::MOV8ri).addReg(Reg).addImm(1)};
|
||||
if (llvm::X86::GR16RegClass.contains(Reg))
|
||||
|
@ -140,12 +142,25 @@ class ExegesisX86Target : public ExegesisTarget {
|
|||
return {llvm::MCInstBuilder(llvm::X86::MOV32ri).addReg(Reg).addImm(1)};
|
||||
if (llvm::X86::GR64RegClass.contains(Reg))
|
||||
return {llvm::MCInstBuilder(llvm::X86::MOV64ri32).addReg(Reg).addImm(1)};
|
||||
if (llvm::X86::VR128XRegClass.contains(Reg))
|
||||
return setVectorRegToConstant(Reg, 16, llvm::X86::VMOVDQUrm);
|
||||
if (llvm::X86::VR256XRegClass.contains(Reg))
|
||||
// MMX.
|
||||
if (llvm::X86::VR64RegClass.contains(Reg))
|
||||
return setVectorRegToConstant(Reg, 8, llvm::X86::MMX_MOVQ64rm);
|
||||
// {X,Y,Z}MM.
|
||||
if (llvm::X86::VR128XRegClass.contains(Reg)) {
|
||||
if (STI.getFeatureBits()[llvm::X86::FeatureAVX512])
|
||||
return setVectorRegToConstant(Reg, 16, llvm::X86::VMOVDQU32Z128rm);
|
||||
if (STI.getFeatureBits()[llvm::X86::FeatureAVX])
|
||||
return setVectorRegToConstant(Reg, 16, llvm::X86::VMOVDQUrm);
|
||||
return setVectorRegToConstant(Reg, 16, llvm::X86::MOVDQUrm);
|
||||
}
|
||||
if (llvm::X86::VR256XRegClass.contains(Reg)) {
|
||||
if (STI.getFeatureBits()[llvm::X86::FeatureAVX512])
|
||||
return setVectorRegToConstant(Reg, 32, llvm::X86::VMOVDQU32Z256rm);
|
||||
return setVectorRegToConstant(Reg, 32, llvm::X86::VMOVDQUYrm);
|
||||
}
|
||||
if (llvm::X86::VR512RegClass.contains(Reg))
|
||||
return setVectorRegToConstant(Reg, 64, llvm::X86::VMOVDQU64Zrm);
|
||||
return setVectorRegToConstant(Reg, 64, llvm::X86::VMOVDQU32Zrm);
|
||||
// X87.
|
||||
if (llvm::X86::RFP32RegClass.contains(Reg) ||
|
||||
llvm::X86::RFP64RegClass.contains(Reg) ||
|
||||
llvm::X86::RFP80RegClass.contains(Reg))
|
||||
|
@ -155,8 +170,7 @@ class ExegesisX86Target : public ExegesisTarget {
|
|||
|
||||
std::unique_ptr<BenchmarkRunner>
|
||||
createLatencyBenchmarkRunner(const LLVMState &State) const override {
|
||||
return llvm::make_unique<X86BenchmarkRunner<X86LatencyImpl>>(
|
||||
State);
|
||||
return llvm::make_unique<X86BenchmarkRunner<X86LatencyImpl>>(State);
|
||||
}
|
||||
|
||||
std::unique_ptr<BenchmarkRunner>
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include <memory>
|
||||
|
||||
#include "MCTargetDesc/X86MCTargetDesc.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
|
@ -17,27 +19,151 @@ using testing::Gt;
|
|||
using testing::NotNull;
|
||||
using testing::SizeIs;
|
||||
|
||||
constexpr const char kTriple[] = "x86_64-unknown-linux";
|
||||
|
||||
class X86TargetTest : public ::testing::Test {
|
||||
protected:
|
||||
X86TargetTest()
|
||||
: Target_(ExegesisTarget::lookup(llvm::Triple("x86_64-unknown-linux"))) {
|
||||
: ExegesisTarget_(ExegesisTarget::lookup(llvm::Triple(kTriple))) {
|
||||
EXPECT_THAT(ExegesisTarget_, NotNull());
|
||||
std::string error;
|
||||
Target_ = llvm::TargetRegistry::lookupTarget(kTriple, error);
|
||||
EXPECT_THAT(Target_, NotNull());
|
||||
}
|
||||
static void SetUpTestCase() { InitializeX86ExegesisTarget(); }
|
||||
static void SetUpTestCase() {
|
||||
LLVMInitializeX86TargetInfo();
|
||||
LLVMInitializeX86Target();
|
||||
LLVMInitializeX86TargetMC();
|
||||
InitializeX86ExegesisTarget();
|
||||
}
|
||||
|
||||
const ExegesisTarget *const Target_;
|
||||
const llvm::Target *Target_;
|
||||
const ExegesisTarget *const ExegesisTarget_;
|
||||
};
|
||||
|
||||
TEST_F(X86TargetTest, SetRegToConstantGPR) {
|
||||
const auto Insts = Target_->setRegToConstant(llvm::X86::EAX);
|
||||
const std::unique_ptr<llvm::MCSubtargetInfo> STI(
|
||||
Target_->createMCSubtargetInfo(kTriple, "core2", ""));
|
||||
const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::EAX);
|
||||
EXPECT_THAT(Insts, SizeIs(1));
|
||||
EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::MOV32ri);
|
||||
EXPECT_EQ(Insts[0].getOperand(0).getReg(), llvm::X86::EAX);
|
||||
}
|
||||
|
||||
TEST_F(X86TargetTest, SetRegToConstantXMM) {
|
||||
const auto Insts = Target_->setRegToConstant(llvm::X86::XMM1);
|
||||
EXPECT_THAT(Insts, SizeIs(Gt(0U)));
|
||||
TEST_F(X86TargetTest, SetRegToConstantXMM_SSE2) {
|
||||
const std::unique_ptr<llvm::MCSubtargetInfo> STI(
|
||||
Target_->createMCSubtargetInfo(kTriple, "core2", ""));
|
||||
const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::XMM1);
|
||||
EXPECT_THAT(Insts, SizeIs(7U));
|
||||
EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::SUB64ri8);
|
||||
EXPECT_EQ(Insts[1].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[2].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[3].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[4].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[5].getOpcode(), llvm::X86::MOVDQUrm);
|
||||
EXPECT_EQ(Insts[6].getOpcode(), llvm::X86::ADD64ri8);
|
||||
}
|
||||
|
||||
TEST_F(X86TargetTest, SetRegToConstantXMM_AVX) {
|
||||
const std::unique_ptr<llvm::MCSubtargetInfo> STI(
|
||||
Target_->createMCSubtargetInfo(kTriple, "core2", "+avx"));
|
||||
const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::XMM1);
|
||||
EXPECT_THAT(Insts, SizeIs(7U));
|
||||
EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::SUB64ri8);
|
||||
EXPECT_EQ(Insts[1].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[2].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[3].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[4].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[5].getOpcode(), llvm::X86::VMOVDQUrm);
|
||||
EXPECT_EQ(Insts[6].getOpcode(), llvm::X86::ADD64ri8);
|
||||
}
|
||||
|
||||
TEST_F(X86TargetTest, SetRegToConstantXMM_AVX512) {
|
||||
const std::unique_ptr<llvm::MCSubtargetInfo> STI(
|
||||
Target_->createMCSubtargetInfo(kTriple, "core2", "+avx512vl"));
|
||||
const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::XMM1);
|
||||
EXPECT_THAT(Insts, SizeIs(7U));
|
||||
EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::SUB64ri8);
|
||||
EXPECT_EQ(Insts[1].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[2].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[3].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[4].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[5].getOpcode(), llvm::X86::VMOVDQU32Z128rm);
|
||||
EXPECT_EQ(Insts[6].getOpcode(), llvm::X86::ADD64ri8);
|
||||
}
|
||||
|
||||
TEST_F(X86TargetTest, SetRegToConstantMMX) {
|
||||
const std::unique_ptr<llvm::MCSubtargetInfo> STI(
|
||||
Target_->createMCSubtargetInfo(kTriple, "core2", ""));
|
||||
const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::MM1);
|
||||
EXPECT_THAT(Insts, SizeIs(5U));
|
||||
EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::SUB64ri8);
|
||||
EXPECT_EQ(Insts[1].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[2].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[3].getOpcode(), llvm::X86::MMX_MOVQ64rm);
|
||||
EXPECT_EQ(Insts[4].getOpcode(), llvm::X86::ADD64ri8);
|
||||
}
|
||||
|
||||
TEST_F(X86TargetTest, SetRegToConstantYMM_AVX) {
|
||||
const std::unique_ptr<llvm::MCSubtargetInfo> STI(
|
||||
Target_->createMCSubtargetInfo(kTriple, "core2", "+avx"));
|
||||
const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::YMM1);
|
||||
EXPECT_THAT(Insts, SizeIs(11U));
|
||||
EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::SUB64ri8);
|
||||
EXPECT_EQ(Insts[1].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[2].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[3].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[4].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[5].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[6].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[7].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[8].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[9].getOpcode(), llvm::X86::VMOVDQUYrm);
|
||||
EXPECT_EQ(Insts[10].getOpcode(), llvm::X86::ADD64ri8);
|
||||
}
|
||||
|
||||
TEST_F(X86TargetTest, SetRegToConstantYMM_AVX512) {
|
||||
const std::unique_ptr<llvm::MCSubtargetInfo> STI(
|
||||
Target_->createMCSubtargetInfo(kTriple, "core2", "+avx512vl"));
|
||||
const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::YMM1);
|
||||
EXPECT_THAT(Insts, SizeIs(11U));
|
||||
EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::SUB64ri8);
|
||||
EXPECT_EQ(Insts[1].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[2].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[3].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[4].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[5].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[6].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[7].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[8].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[9].getOpcode(), llvm::X86::VMOVDQU32Z256rm);
|
||||
EXPECT_EQ(Insts[10].getOpcode(), llvm::X86::ADD64ri8);
|
||||
}
|
||||
|
||||
TEST_F(X86TargetTest, SetRegToConstantZMM_AVX512) {
|
||||
const std::unique_ptr<llvm::MCSubtargetInfo> STI(
|
||||
Target_->createMCSubtargetInfo(kTriple, "core2", "+avx512vl"));
|
||||
const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::ZMM1);
|
||||
EXPECT_THAT(Insts, SizeIs(19U));
|
||||
EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::SUB64ri8);
|
||||
EXPECT_EQ(Insts[1].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[2].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[3].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[4].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[5].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[6].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[7].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[8].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[9].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[10].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[11].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[12].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[13].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[14].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[15].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[16].getOpcode(), llvm::X86::MOV32mi);
|
||||
EXPECT_EQ(Insts[17].getOpcode(), llvm::X86::VMOVDQU32Zrm);
|
||||
EXPECT_EQ(Insts[18].getOpcode(), llvm::X86::ADD64ri8);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
Loading…
Reference in New Issue