MIPS: InstructionCodeGeneratorMIPS*::DivRemByPowerOfTwo()
Replace [d]sll+[d]srl with [d]ins on R2+.
Change-Id: I7587e46c47c8ce413d81a5c6c29d91e32a14d855
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 9f4c234..c4772ad 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -3774,8 +3774,12 @@
if (IsUint<16>(abs_imm - 1)) {
__ Andi(out, out, abs_imm - 1);
} else {
- __ Sll(out, out, 32 - ctz_imm);
- __ Srl(out, out, 32 - ctz_imm);
+ if (codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2()) {
+ __ Ins(out, ZERO, ctz_imm, 32 - ctz_imm);
+ } else {
+ __ Sll(out, out, 32 - ctz_imm);
+ __ Srl(out, out, 32 - ctz_imm);
+ }
}
__ Subu(out, out, TMP);
}
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index eb64f1b..c8891ed 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -3311,12 +3311,7 @@
__ Sra(TMP, dividend, 31);
__ Srl(TMP, TMP, 32 - ctz_imm);
__ Addu(out, dividend, TMP);
- if (IsUint<16>(abs_imm - 1)) {
- __ Andi(out, out, abs_imm - 1);
- } else {
- __ Sll(out, out, 32 - ctz_imm);
- __ Srl(out, out, 32 - ctz_imm);
- }
+ __ Ins(out, ZERO, ctz_imm, 32 - ctz_imm);
__ Subu(out, out, TMP);
}
} else {
@@ -3335,17 +3330,7 @@
__ Dsrl32(TMP, TMP, 32 - ctz_imm);
}
__ Daddu(out, dividend, TMP);
- if (IsUint<16>(abs_imm - 1)) {
- __ Andi(out, out, abs_imm - 1);
- } else {
- if (ctz_imm > 32) {
- __ Dsll(out, out, 64 - ctz_imm);
- __ Dsrl(out, out, 64 - ctz_imm);
- } else {
- __ Dsll32(out, out, 32 - ctz_imm);
- __ Dsrl32(out, out, 32 - ctz_imm);
- }
- }
+ __ DblIns(out, ZERO, ctz_imm, 64 - ctz_imm);
__ Dsubu(out, out, TMP);
}
}
diff --git a/compiler/utils/mips64/assembler_mips64.cc b/compiler/utils/mips64/assembler_mips64.cc
index bf56877..e1b0e75 100644
--- a/compiler/utils/mips64/assembler_mips64.cc
+++ b/compiler/utils/mips64/assembler_mips64.cc
@@ -430,6 +430,20 @@
EmitR(0x1f, rs, rt, static_cast<GpuRegister>(size - 1), pos, 0x3);
}
+void Mips64Assembler::Ins(GpuRegister rd, GpuRegister rt, int pos, int size) {
+ CHECK(IsUint<5>(pos)) << pos;
+ CHECK(IsUint<5>(size - 1)) << size;
+ CHECK(IsUint<5>(pos + size - 1)) << pos << " + " << size;
+ EmitR(0x1f, rt, rd, static_cast<GpuRegister>(pos + size - 1), pos, 0x04);
+}
+
+void Mips64Assembler::Dinsm(GpuRegister rt, GpuRegister rs, int pos, int size) {
+ CHECK(IsUint<5>(pos)) << pos;
+ CHECK(2 <= size && size <= 64) << size;
+ CHECK(IsUint<5>(pos + size - 33)) << pos << " + " << size;
+ EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 33), pos, 0x5);
+}
+
void Mips64Assembler::Dinsu(GpuRegister rt, GpuRegister rs, int pos, int size) {
CHECK(IsUint<5>(pos - 32)) << pos;
CHECK(IsUint<5>(size - 1)) << size;
@@ -437,6 +451,23 @@
EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 33), pos - 32, 0x6);
}
+void Mips64Assembler::Dins(GpuRegister rt, GpuRegister rs, int pos, int size) {
+ CHECK(IsUint<5>(pos)) << pos;
+ CHECK(IsUint<5>(size - 1)) << size;
+ CHECK(IsUint<5>(pos + size - 1)) << pos << " + " << size;
+ EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 1), pos, 0x7);
+}
+
+void Mips64Assembler::DblIns(GpuRegister rt, GpuRegister rs, int pos, int size) {
+ if (pos >= 32) {
+ Dinsu(rt, rs, pos, size);
+ } else if ((static_cast<int64_t>(pos) + size - 1) >= 32) {
+ Dinsm(rt, rs, pos, size);
+ } else {
+ Dins(rt, rs, pos, size);
+ }
+}
+
void Mips64Assembler::Lsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne) {
CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne;
int sa = saPlusOne - 1;
diff --git a/compiler/utils/mips64/assembler_mips64.h b/compiler/utils/mips64/assembler_mips64.h
index 9f5e6aa..7a61f39 100644
--- a/compiler/utils/mips64/assembler_mips64.h
+++ b/compiler/utils/mips64/assembler_mips64.h
@@ -478,7 +478,11 @@
void Dsbh(GpuRegister rd, GpuRegister rt); // MIPS64
void Dshd(GpuRegister rd, GpuRegister rt); // MIPS64
void Dext(GpuRegister rs, GpuRegister rt, int pos, int size); // MIPS64
+ void Ins(GpuRegister rt, GpuRegister rs, int pos, int size);
+ void Dins(GpuRegister rt, GpuRegister rs, int pos, int size); // MIPS64
+ void Dinsm(GpuRegister rt, GpuRegister rs, int pos, int size); // MIPS64
void Dinsu(GpuRegister rt, GpuRegister rs, int pos, int size); // MIPS64
+ void DblIns(GpuRegister rt, GpuRegister rs, int pos, int size); // MIPS64
void Lsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne);
void Dlsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne); // MIPS64
void Wsbh(GpuRegister rd, GpuRegister rt);
diff --git a/compiler/utils/mips64/assembler_mips64_test.cc b/compiler/utils/mips64/assembler_mips64_test.cc
index d89ca3d..b0e1d91 100644
--- a/compiler/utils/mips64/assembler_mips64_test.cc
+++ b/compiler/utils/mips64/assembler_mips64_test.cc
@@ -1353,23 +1353,42 @@
DriverStr(expected.str(), "Dext");
}
-TEST_F(AssemblerMIPS64Test, Dinsu) {
+TEST_F(AssemblerMIPS64Test, Ins) {
+ std::vector<mips64::GpuRegister*> regs = GetRegisters();
+ WarnOnCombinations(regs.size() * regs.size() * 33 * 16);
+ std::string expected;
+ for (mips64::GpuRegister* reg1 : regs) {
+ for (mips64::GpuRegister* reg2 : regs) {
+ for (int32_t pos = 0; pos < 32; pos++) {
+ for (int32_t size = 1; pos + size <= 32; size++) {
+ __ Ins(*reg1, *reg2, pos, size);
+ std::ostringstream instr;
+ instr << "ins $" << *reg1 << ", $" << *reg2 << ", " << pos << ", " << size << "\n";
+ expected += instr.str();
+ }
+ }
+ }
+ }
+ DriverStr(expected, "Ins");
+}
+
+TEST_F(AssemblerMIPS64Test, DblIns) {
std::vector<mips64::GpuRegister*> reg1_registers = GetRegisters();
std::vector<mips64::GpuRegister*> reg2_registers = GetRegisters();
- WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * 33 * 16);
+ WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * 65 * 32);
std::ostringstream expected;
for (mips64::GpuRegister* reg1 : reg1_registers) {
for (mips64::GpuRegister* reg2 : reg2_registers) {
- for (int32_t pos = 32; pos < 64; pos++) {
+ for (int32_t pos = 0; pos < 64; pos++) {
for (int32_t size = 1; pos + size <= 64; size++) {
- __ Dinsu(*reg1, *reg2, pos, size);
- expected << "dinsu $" << *reg1 << ", $" << *reg2 << ", " << pos << ", " << size << "\n";
+ __ DblIns(*reg1, *reg2, pos, size);
+ expected << "dins $" << *reg1 << ", $" << *reg2 << ", " << pos << ", " << size << "\n";
}
}
}
}
- DriverStr(expected.str(), "Dinsu");
+ DriverStr(expected.str(), "DblIns");
}
TEST_F(AssemblerMIPS64Test, Lsa) {