mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
[llvm-exegesis][mips] Expand loadImmediate()
Add support for loading 32-bit immediates and enable the use of GPR64 registers. Differential Revision: https://reviews.llvm.org/D71873
This commit is contained in:
parent
5554f90776
commit
7696c3e850
11
test/tools/llvm-exegesis/Mips/latency-GPR64.s
Normal file
11
test/tools/llvm-exegesis/Mips/latency-GPR64.s
Normal file
@ -0,0 +1,11 @@
|
||||
# RUN: llvm-exegesis -mode=latency -opcode-name=AND64 | FileCheck %s
|
||||
|
||||
CHECK: ---
|
||||
CHECK-NEXT: mode: latency
|
||||
CHECK-NEXT: key:
|
||||
CHECK-NEXT: instructions:
|
||||
CHECK-NEXT: AND64
|
||||
CHECK-NEXT: config: ''
|
||||
CHECK-NEXT: register_initial_values:
|
||||
CHECK-DAG: - '[[REG1:[A-Z0-9]+_64]]=0x0'
|
||||
CHECK-LAST: ...
|
@ -30,26 +30,75 @@ private:
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
// Generates instruction to load an immediate value into a register.
|
||||
static MCInst loadImmediate(unsigned Reg, unsigned RegBitWidth,
|
||||
const APInt &Value) {
|
||||
if (Value.getActiveBits() > 16)
|
||||
llvm_unreachable("Not implemented for Values wider than 16 bits");
|
||||
if (Value.getBitWidth() > RegBitWidth)
|
||||
llvm_unreachable("Value must fit in the Register");
|
||||
return MCInstBuilder(Mips::ORi)
|
||||
.addReg(Reg)
|
||||
.addReg(Mips::ZERO)
|
||||
.addImm(Value.getZExtValue());
|
||||
// Generates instructions to load an immediate value into a register.
|
||||
static std::vector<MCInst> loadImmediate(unsigned Reg, bool IsGPR32,
|
||||
const APInt &Value) {
|
||||
unsigned ZeroReg;
|
||||
unsigned ORi, LUi, SLL;
|
||||
if (IsGPR32) {
|
||||
ZeroReg = Mips::ZERO;
|
||||
ORi = Mips::ORi;
|
||||
SLL = Mips::SLL;
|
||||
LUi = Mips::LUi;
|
||||
} else {
|
||||
ZeroReg = Mips::ZERO_64;
|
||||
ORi = Mips::ORi64;
|
||||
SLL = Mips::SLL64_64;
|
||||
LUi = Mips::LUi64;
|
||||
}
|
||||
|
||||
if (Value.isIntN(16)) {
|
||||
return {MCInstBuilder(ORi)
|
||||
.addReg(Reg)
|
||||
.addReg(ZeroReg)
|
||||
.addImm(Value.getZExtValue())};
|
||||
}
|
||||
|
||||
std::vector<MCInst> Instructions;
|
||||
if (Value.isIntN(32)) {
|
||||
const uint16_t HiBits = Value.getHiBits(16).getZExtValue();
|
||||
if (!IsGPR32 && Value.getActiveBits() == 32) {
|
||||
// Expand to an ORi instead of a LUi to avoid sign-extending into the
|
||||
// upper 32 bits.
|
||||
Instructions.push_back(
|
||||
MCInstBuilder(ORi)
|
||||
.addReg(Reg)
|
||||
.addReg(ZeroReg)
|
||||
.addImm(HiBits));
|
||||
Instructions.push_back(
|
||||
MCInstBuilder(SLL)
|
||||
.addReg(Reg)
|
||||
.addReg(Reg)
|
||||
.addImm(16));
|
||||
} else {
|
||||
Instructions.push_back(
|
||||
MCInstBuilder(LUi)
|
||||
.addReg(Reg)
|
||||
.addImm(HiBits));
|
||||
}
|
||||
|
||||
const uint16_t LoBits = Value.getLoBits(16).getZExtValue();
|
||||
if (LoBits) {
|
||||
Instructions.push_back(
|
||||
MCInstBuilder(ORi)
|
||||
.addReg(Reg)
|
||||
.addReg(ZeroReg)
|
||||
.addImm(LoBits));
|
||||
}
|
||||
|
||||
return std::move(Instructions);
|
||||
}
|
||||
|
||||
llvm_unreachable("Not implemented for values wider than 32 bits");
|
||||
}
|
||||
|
||||
std::vector<MCInst> ExegesisMipsTarget::setRegTo(const MCSubtargetInfo &STI,
|
||||
unsigned Reg,
|
||||
const APInt &Value) const {
|
||||
if (Mips::GPR32RegClass.contains(Reg))
|
||||
return {loadImmediate(Reg, 32, Value)};
|
||||
return loadImmediate(Reg, true, Value);
|
||||
if (Mips::GPR64RegClass.contains(Reg))
|
||||
return {loadImmediate(Reg, 64, Value)};
|
||||
return loadImmediate(Reg, false, Value);
|
||||
errs() << "setRegTo is not implemented, results will be unreliable\n";
|
||||
return {};
|
||||
}
|
||||
|
@ -44,9 +44,22 @@ Matcher<MCInst> OpcodeIs(unsigned Opcode) {
|
||||
return Property(&MCInst::getOpcode, Eq(Opcode));
|
||||
}
|
||||
|
||||
Matcher<MCInst> IsLoadLowImm(int64_t Reg, int64_t Value) {
|
||||
return AllOf(OpcodeIs(Mips::ORi),
|
||||
ElementsAre(IsReg(Reg), IsReg(Mips::ZERO), IsImm(Value)));
|
||||
Matcher<MCInst> IsLoadLow16BitImm(unsigned Reg, int64_t Value, bool IsGPR32) {
|
||||
const unsigned ZeroReg = IsGPR32 ? Mips::ZERO : Mips::ZERO_64;
|
||||
const unsigned ORi = IsGPR32 ? Mips::ORi : Mips::ORi64;
|
||||
return AllOf(OpcodeIs(ORi),
|
||||
ElementsAre(IsReg(Reg), IsReg(ZeroReg), IsImm(Value)));
|
||||
}
|
||||
|
||||
Matcher<MCInst> IsLoadHigh16BitImm(unsigned Reg, int64_t Value, bool IsGPR32) {
|
||||
const unsigned LUi = IsGPR32 ? Mips::LUi : Mips::LUi64;
|
||||
return AllOf(OpcodeIs(LUi), ElementsAre(IsReg(Reg), IsImm(Value)));
|
||||
}
|
||||
|
||||
Matcher<MCInst> IsShift(unsigned Reg, uint16_t Amount, bool IsGPR32) {
|
||||
const unsigned SLL = IsGPR32 ? Mips::SLL : Mips::SLL64_64;
|
||||
return AllOf(OpcodeIs(SLL),
|
||||
ElementsAre(IsReg(Reg), IsReg(Reg), IsImm(Amount)));
|
||||
}
|
||||
|
||||
constexpr const char kTriple[] = "mips-unknown-linux";
|
||||
@ -70,11 +83,53 @@ protected:
|
||||
LLVMState State;
|
||||
};
|
||||
|
||||
TEST_F(MipsTargetTest, SetRegToConstant) {
|
||||
TEST_F(MipsTargetTest, SetGPR32RegTo16BitValue) {
|
||||
const uint16_t Value = 0xFFFFU;
|
||||
const unsigned Reg = Mips::T0;
|
||||
EXPECT_THAT(setRegTo(Reg, APInt(16, Value)),
|
||||
ElementsAre(IsLoadLowImm(Reg, Value)));
|
||||
ElementsAre(IsLoadLow16BitImm(Reg, Value, true)));
|
||||
}
|
||||
|
||||
TEST_F(MipsTargetTest, SetGPR64RegTo16BitValue) {
|
||||
const uint16_t Value = 0xFFFFU;
|
||||
const unsigned Reg = Mips::T0_64;
|
||||
EXPECT_THAT(setRegTo(Reg, APInt(16, Value)),
|
||||
ElementsAre(IsLoadLow16BitImm(Reg, Value, false)));
|
||||
}
|
||||
|
||||
TEST_F(MipsTargetTest, SetGPR32RegTo32BitValue) {
|
||||
const uint32_t Value0 = 0xFFFF0000UL;
|
||||
const unsigned Reg0 = Mips::T0;
|
||||
EXPECT_THAT(setRegTo(Reg0, APInt(32, Value0)),
|
||||
ElementsAre(IsLoadHigh16BitImm(Reg0, 0xFFFFU, true)));
|
||||
const uint32_t Value1 = 0xFFFFFFFFUL;
|
||||
const unsigned Reg1 = Mips::T1;
|
||||
EXPECT_THAT(setRegTo(Reg1, APInt(32, Value1)),
|
||||
ElementsAre(IsLoadHigh16BitImm(Reg1, 0xFFFFU, true),
|
||||
IsLoadLow16BitImm(Reg1, 0xFFFFU, true)));
|
||||
}
|
||||
|
||||
TEST_F(MipsTargetTest, SetGPR64RegTo32BitValue) {
|
||||
const uint32_t Value0 = 0x7FFF0000UL;
|
||||
const unsigned Reg0 = Mips::T0_64;
|
||||
EXPECT_THAT(setRegTo(Reg0, APInt(32, Value0)),
|
||||
ElementsAre(IsLoadHigh16BitImm(Reg0, 0x7FFFU, false)));
|
||||
const uint32_t Value1 = 0x7FFFFFFFUL;
|
||||
const unsigned Reg1 = Mips::T1_64;
|
||||
EXPECT_THAT(setRegTo(Reg1, APInt(32, Value1)),
|
||||
ElementsAre(IsLoadHigh16BitImm(Reg1, 0x7FFFU, false),
|
||||
IsLoadLow16BitImm(Reg1, 0xFFFFU, false)));
|
||||
const uint32_t Value2 = 0xFFFF0000UL;
|
||||
const unsigned Reg2 = Mips::T2_64;
|
||||
EXPECT_THAT(setRegTo(Reg2, APInt(32, Value2)),
|
||||
ElementsAre(IsLoadLow16BitImm(Reg2, 0xFFFFU, false),
|
||||
IsShift(Reg2, 16, false)));
|
||||
const uint32_t Value3 = 0xFFFFFFFFUL;
|
||||
const unsigned Reg3 = Mips::T3_64;
|
||||
EXPECT_THAT(setRegTo(Reg3, APInt(32, Value3)),
|
||||
ElementsAre(IsLoadLow16BitImm(Reg3, 0xFFFFU, false),
|
||||
IsShift(Reg3, 16, false),
|
||||
IsLoadLow16BitImm(Reg3, 0xFFFFU, false)));
|
||||
}
|
||||
|
||||
TEST_F(MipsTargetTest, DefaultPfmCounters) {
|
||||
|
Loading…
Reference in New Issue
Block a user