Index: tools/llvm-exegesis/lib/X86/Target.cpp =================================================================== --- tools/llvm-exegesis/lib/X86/Target.cpp +++ tools/llvm-exegesis/lib/X86/Target.cpp @@ -182,12 +182,10 @@ return std::move(Instructions); } - std::vector - loadX87AndFinalize(unsigned Reg, unsigned RegBitWidth, unsigned Opcode) { - assert((RegBitWidth & 7) == 0 && - "RegBitWidth must be a multiple of 8 bits"); - initStack(RegBitWidth / 8); - add(llvm::MCInstBuilder(Opcode) + std::vector loadX87STAndFinalize(unsigned Reg) { + initStack(kF80Bytes); + add(llvm::MCInstBuilder(llvm::X86::LD_F80m) + // Address = ESP .addReg(llvm::X86::RSP) // BaseReg .addImm(1) // ScaleAmt .addReg(0) // IndexReg @@ -195,7 +193,21 @@ .addReg(0)); // Segment if (Reg != llvm::X86::ST0) add(llvm::MCInstBuilder(llvm::X86::ST_Frr).addReg(Reg)); - add(releaseStackSpace(RegBitWidth / 8)); + add(releaseStackSpace(kF80Bytes)); + return std::move(Instructions); + } + + std::vector loadX87FPAndFinalize(unsigned Reg) { + initStack(kF80Bytes); + add(llvm::MCInstBuilder(llvm::X86::LD_Fp80m) + .addReg(Reg) + // Address = ESP + .addReg(llvm::X86::RSP) // BaseReg + .addImm(1) // ScaleAmt + .addReg(0) // IndexReg + .addImm(0) // Disp + .addReg(0)); // Segment + add(releaseStackSpace(kF80Bytes)); return std::move(Instructions); } @@ -206,6 +218,8 @@ } private: + static constexpr const unsigned kF80Bytes = 10; // 80 bits. + ConstantInliner &add(const llvm::MCInst &Inst) { Instructions.push_back(Inst); return *this; @@ -318,12 +332,12 @@ if (STI.getFeatureBits()[llvm::X86::FeatureAVX512]) return CI.loadAndFinalize(Reg, 512, llvm::X86::VMOVDQU32Zrm); if (llvm::X86::RSTRegClass.contains(Reg)) { - if (Value.getBitWidth() == 32) - return CI.loadX87AndFinalize(Reg, 32, llvm::X86::LD_F32m); - if (Value.getBitWidth() == 64) - return CI.loadX87AndFinalize(Reg, 64, llvm::X86::LD_F64m); - if (Value.getBitWidth() == 80) - return CI.loadX87AndFinalize(Reg, 80, llvm::X86::LD_F80m); + return CI.loadX87STAndFinalize(Reg); + } + if (llvm::X86::RFP32RegClass.contains(Reg) || + llvm::X86::RFP64RegClass.contains(Reg) || + llvm::X86::RFP80RegClass.contains(Reg)) { + return CI.loadX87FPAndFinalize(Reg); } if (Reg == llvm::X86::EFLAGS) return CI.popFlagAndFinalize(); Index: unittests/tools/llvm-exegesis/X86/TargetTest.cpp =================================================================== --- unittests/tools/llvm-exegesis/X86/TargetTest.cpp +++ unittests/tools/llvm-exegesis/X86/TargetTest.cpp @@ -296,12 +296,17 @@ IsStackDeallocate(64)})); } +// Note: We always put 80 bits on the stack independently of the size of the +// value. This uses a bit more space but makes the code simpler. + TEST_F(Core2TargetTest, SetRegToST0_32Bits) { EXPECT_THAT( setRegTo(llvm::X86::ST0, APInt(32, 0x11112222ULL)), - ElementsAre(IsStackAllocate(4), + ElementsAre(IsStackAllocate(10), IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 0), - OpcodeIs(llvm::X86::LD_F32m), IsStackDeallocate(4))); + IsMovValueToStack(llvm::X86::MOV32mi, 0x00000000UL, 4), + IsMovValueToStack(llvm::X86::MOV16mi, 0x0000UL, 8), + OpcodeIs(llvm::X86::LD_F80m), IsStackDeallocate(10))); } TEST_F(Core2TargetTest, SetRegToST1_32Bits) { @@ -309,19 +314,22 @@ llvm::MCInstBuilder(llvm::X86::ST_Frr).addReg(llvm::X86::ST1); EXPECT_THAT( setRegTo(llvm::X86::ST1, APInt(32, 0x11112222ULL)), - ElementsAre(IsStackAllocate(4), + ElementsAre(IsStackAllocate(10), IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 0), - OpcodeIs(llvm::X86::LD_F32m), CopySt0ToSt1, - IsStackDeallocate(4))); + IsMovValueToStack(llvm::X86::MOV32mi, 0x00000000UL, 4), + IsMovValueToStack(llvm::X86::MOV16mi, 0x0000UL, 8), + OpcodeIs(llvm::X86::LD_F80m), CopySt0ToSt1, + IsStackDeallocate(10))); } TEST_F(Core2TargetTest, SetRegToST0_64Bits) { EXPECT_THAT( setRegTo(llvm::X86::ST0, APInt(64, 0x1111222233334444ULL)), - ElementsAre(IsStackAllocate(8), + ElementsAre(IsStackAllocate(10), IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 0), IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 4), - OpcodeIs(llvm::X86::LD_F64m), IsStackDeallocate(8))); + IsMovValueToStack(llvm::X86::MOV16mi, 0x0000UL, 8), + OpcodeIs(llvm::X86::LD_F80m), IsStackDeallocate(10))); } TEST_F(Core2TargetTest, SetRegToST0_80Bits) { @@ -334,5 +342,37 @@ OpcodeIs(llvm::X86::LD_F80m), IsStackDeallocate(10))); } +TEST_F(Core2TargetTest, SetRegToFP0_80Bits) { + EXPECT_THAT( + setRegTo(llvm::X86::FP0, APInt(80, "11112222333344445555", 16)), + ElementsAre(IsStackAllocate(10), + IsMovValueToStack(llvm::X86::MOV32mi, 0x44445555UL, 0), + IsMovValueToStack(llvm::X86::MOV32mi, 0x22223333UL, 4), + IsMovValueToStack(llvm::X86::MOV16mi, 0x1111UL, 8), + OpcodeIs(llvm::X86::LD_Fp80m), IsStackDeallocate(10))); +} + +TEST_F(Core2TargetTest, SetRegToFP1_32Bits) { + EXPECT_THAT( + setRegTo(llvm::X86::FP1, APInt(32, 0x11112222ULL)), + ElementsAre(IsStackAllocate(10), + IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 0), + IsMovValueToStack(llvm::X86::MOV32mi, 0x00000000UL, 4), + IsMovValueToStack(llvm::X86::MOV16mi, 0x0000UL, 8), + OpcodeIs(llvm::X86::LD_Fp80m), + IsStackDeallocate(10))); +} + +TEST_F(Core2TargetTest, SetRegToFP1_4Bits) { + EXPECT_THAT( + setRegTo(llvm::X86::FP1, APInt(4, 0x1ULL)), + ElementsAre(IsStackAllocate(10), + IsMovValueToStack(llvm::X86::MOV32mi, 0x00000001UL, 0), + IsMovValueToStack(llvm::X86::MOV32mi, 0x00000000UL, 4), + IsMovValueToStack(llvm::X86::MOV16mi, 0x0000UL, 8), + OpcodeIs(llvm::X86::LD_Fp80m), + IsStackDeallocate(10))); +} + } // namespace } // namespace exegesis