summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/test/tools/llvm-exegesis/Mips/latency-GPR64.s11
-rw-r--r--llvm/tools/llvm-exegesis/lib/Mips/Target.cpp75
-rw-r--r--llvm/unittests/tools/llvm-exegesis/Mips/TargetTest.cpp65
3 files changed, 133 insertions, 18 deletions
diff --git a/llvm/test/tools/llvm-exegesis/Mips/latency-GPR64.s b/llvm/test/tools/llvm-exegesis/Mips/latency-GPR64.s
new file mode 100644
index 00000000000..3be96581f96
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/Mips/latency-GPR64.s
@@ -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: ...
diff --git a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
index abf033d1e6e..d37034c043b 100644
--- a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
@@ -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 {};
}
diff --git a/llvm/unittests/tools/llvm-exegesis/Mips/TargetTest.cpp b/llvm/unittests/tools/llvm-exegesis/Mips/TargetTest.cpp
index 16c8e5fda27..2509beb26d7 100644
--- a/llvm/unittests/tools/llvm-exegesis/Mips/TargetTest.cpp
+++ b/llvm/unittests/tools/llvm-exegesis/Mips/TargetTest.cpp
@@ -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) {
OpenPOWER on IntegriCloud