From: Clement Courbet Date: Tue, 3 Jul 2018 06:17:05 +0000 (+0000) Subject: [llvm-exegesis] ExegisX86Target::setRegToConstant() should depend on the subtarget... X-Git-Tag: llvmorg-7.0.0-rc1~2335 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e785169fcedb9a7ec001df295d5c019b1de51994;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/llvm/tools/llvm-exegesis/lib/Assembler.cpp b/llvm/tools/llvm-exegesis/lib/Assembler.cpp index c7fc6bd9ee91..d2be7f4829a7 100644 --- a/llvm/tools/llvm-exegesis/lib/Assembler.cpp +++ b/llvm/tools/llvm-exegesis/lib/Assembler.cpp @@ -30,12 +30,13 @@ static constexpr const char FunctionID[] = "foo"; static std::vector generateSnippetSetupCode(const llvm::ArrayRef RegsToDef, - const ExegesisTarget &ET, bool &IsComplete) { + const ExegesisTarget &ET, + const llvm::LLVMTargetMachine &TM, bool &IsComplete) { IsComplete = true; std::vector 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 SnippetWithSetup = - generateSnippetSetupCode(RegsToDef, ET, IsSnippetSetupComplete); + generateSnippetSetupCode(RegsToDef, ET, *TM, IsSnippetSetupComplete); if (!SnippetWithSetup.empty()) { SnippetWithSetup.insert(SnippetWithSetup.end(), Instructions.begin(), Instructions.end()); diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h index cb87e3a6d4bf..4f1f2869b749 100644 --- a/llvm/tools/llvm-exegesis/lib/Target.h +++ b/llvm/tools/llvm-exegesis/lib/Target.h @@ -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 setRegToConstant(unsigned Reg) const { + virtual std::vector + setRegToConstant(const llvm::MCSubtargetInfo &STI, unsigned Reg) const { return {}; } diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp index 594c48bbdba9..f0b411cd3c43 100644 --- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp @@ -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 - setRegToConstant(unsigned Reg) const override { + std::vector 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 createLatencyBenchmarkRunner(const LLVMState &State) const override { - return llvm::make_unique>( - State); + return llvm::make_unique>(State); } std::unique_ptr diff --git a/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp index c55edff9b7ea..0c2f3fbd9f9d 100644 --- a/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp @@ -4,6 +4,8 @@ #include #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 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 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 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 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 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 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 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 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