diff options
author | Calin Juravle <calin@google.com> | 2014-11-18 23:06:35 +0000 |
---|---|---|
committer | Calin Juravle <calin@google.com> | 2014-11-24 16:06:55 +0000 |
commit | 9aec02fc5df5518c16f1e5a9b6cb198a192db973 (patch) | |
tree | fe924b37f395af1bb50f55ee6c87c66b727f00af /compiler/utils | |
parent | 20032e512c003a8f42735c4e1eca19c1472bb95e (diff) | |
download | android_art-9aec02fc5df5518c16f1e5a9b6cb198a192db973.tar.gz android_art-9aec02fc5df5518c16f1e5a9b6cb198a192db973.tar.bz2 android_art-9aec02fc5df5518c16f1e5a9b6cb198a192db973.zip |
[optimizing compiler] Add shifts
Added SHL, SHR, USHR for arm, x86, x86_64.
Change-Id: I971f594e270179457e6958acf1401ff7630df07e
Diffstat (limited to 'compiler/utils')
-rw-r--r-- | compiler/utils/arm/assembler_arm32.cc | 8 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_thumb2.cc | 8 | ||||
-rw-r--r-- | compiler/utils/assembler_test.h | 4 | ||||
-rw-r--r-- | compiler/utils/x86/assembler_x86.cc | 12 | ||||
-rw-r--r-- | compiler/utils/x86/assembler_x86.h | 3 | ||||
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.cc | 40 | ||||
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.h | 7 | ||||
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64_test.cc | 76 |
8 files changed, 139 insertions, 19 deletions
diff --git a/compiler/utils/arm/assembler_arm32.cc b/compiler/utils/arm/assembler_arm32.cc index a1594b02ac..a541763881 100644 --- a/compiler/utils/arm/assembler_arm32.cc +++ b/compiler/utils/arm/assembler_arm32.cc @@ -1079,7 +1079,7 @@ void Arm32Assembler::EmitVFPds(Condition cond, int32_t opcode, void Arm32Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc, Condition cond) { - CHECK_NE(shift_imm, 0u); // Do not use Lsl if no shift is wanted. + CHECK_LE(shift_imm, 31u); if (setcc) { movs(rd, ShifterOperand(rm, LSL, shift_imm), cond); } else { @@ -1090,7 +1090,7 @@ void Arm32Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm, void Arm32Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc, Condition cond) { - CHECK_NE(shift_imm, 0u); // Do not use Lsr if no shift is wanted. + CHECK(1u <= shift_imm && shift_imm <= 32u); if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax. if (setcc) { movs(rd, ShifterOperand(rm, LSR, shift_imm), cond); @@ -1102,7 +1102,7 @@ void Arm32Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm, void Arm32Assembler::Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc, Condition cond) { - CHECK_NE(shift_imm, 0u); // Do not use Asr if no shift is wanted. + CHECK(1u <= shift_imm && shift_imm <= 32u); if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax. if (setcc) { movs(rd, ShifterOperand(rm, ASR, shift_imm), cond); @@ -1114,7 +1114,7 @@ void Arm32Assembler::Asr(Register rd, Register rm, uint32_t shift_imm, void Arm32Assembler::Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc, Condition cond) { - CHECK_NE(shift_imm, 0u); // Use Rrx instruction. + CHECK(1u <= shift_imm && shift_imm <= 31u); if (setcc) { movs(rd, ShifterOperand(rm, ROR, shift_imm), cond); } else { diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc index a34920999e..a377cb2892 100644 --- a/compiler/utils/arm/assembler_thumb2.cc +++ b/compiler/utils/arm/assembler_thumb2.cc @@ -2210,7 +2210,7 @@ void Thumb2Assembler::EmitBranches() { void Thumb2Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc, Condition cond) { - CHECK_NE(shift_imm, 0u); // Do not use Lsl if no shift is wanted. + CHECK_LE(shift_imm, 31u); CheckCondition(cond); EmitShift(rd, rm, LSL, shift_imm, setcc); } @@ -2218,7 +2218,7 @@ void Thumb2Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm, void Thumb2Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc, Condition cond) { - CHECK_NE(shift_imm, 0u); // Do not use Lsr if no shift is wanted. + CHECK(1u <= shift_imm && shift_imm <= 32u); if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax. CheckCondition(cond); EmitShift(rd, rm, LSR, shift_imm, setcc); @@ -2227,7 +2227,7 @@ void Thumb2Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm, void Thumb2Assembler::Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc, Condition cond) { - CHECK_NE(shift_imm, 0u); // Do not use Asr if no shift is wanted. + CHECK(1u <= shift_imm && shift_imm <= 32u); if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax. CheckCondition(cond); EmitShift(rd, rm, ASR, shift_imm, setcc); @@ -2236,7 +2236,7 @@ void Thumb2Assembler::Asr(Register rd, Register rm, uint32_t shift_imm, void Thumb2Assembler::Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc, Condition cond) { - CHECK_NE(shift_imm, 0u); // Use Rrx instruction. + CHECK(1u <= shift_imm && shift_imm <= 31u); CheckCondition(cond); EmitShift(rd, rm, ROR, shift_imm, setcc); } diff --git a/compiler/utils/assembler_test.h b/compiler/utils/assembler_test.h index 9d3fa01a9d..54c931dc93 100644 --- a/compiler/utils/assembler_test.h +++ b/compiler/utils/assembler_test.h @@ -223,6 +223,10 @@ class AssemblerTest : public testing::Test { UNREACHABLE(); } + std::string GetRegisterName(const Reg& reg) { + return GetRegName<RegisterView::kUsePrimaryName>(reg); + } + protected: explicit AssemblerTest() {} diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc index afa4a3b958..a297ea3b6e 100644 --- a/compiler/utils/x86/assembler_x86.cc +++ b/compiler/utils/x86/assembler_x86.cc @@ -1126,7 +1126,8 @@ void X86Assembler::sarl(Register operand, Register shifter) { } -void X86Assembler::shld(Register dst, Register src) { +void X86Assembler::shld(Register dst, Register src, Register shifter) { + DCHECK_EQ(ECX, shifter); AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitUint8(0x0F); EmitUint8(0xA5); @@ -1134,6 +1135,15 @@ void X86Assembler::shld(Register dst, Register src) { } +void X86Assembler::shrd(Register dst, Register src, Register shifter) { + DCHECK_EQ(ECX, shifter); + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitUint8(0x0F); + EmitUint8(0xAD); + EmitRegisterOperand(src, dst); +} + + void X86Assembler::negl(Register reg) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitUint8(0xF7); diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h index 8aed9348d6..6ea66a5fa7 100644 --- a/compiler/utils/x86/assembler_x86.h +++ b/compiler/utils/x86/assembler_x86.h @@ -405,7 +405,8 @@ class X86Assembler FINAL : public Assembler { void shrl(Register operand, Register shifter); void sarl(Register reg, const Immediate& imm); void sarl(Register operand, Register shifter); - void shld(Register dst, Register src); + void shld(Register dst, Register src, Register shifter); + void shrd(Register dst, Register src, Register shifter); void negl(Register reg); void notl(Register reg); diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc index 8c428f455e..dff3849076 100644 --- a/compiler/utils/x86_64/assembler_x86_64.cc +++ b/compiler/utils/x86_64/assembler_x86_64.cc @@ -1451,8 +1451,18 @@ void X86_64Assembler::shll(CpuRegister reg, const Immediate& imm) { } +void X86_64Assembler::shlq(CpuRegister reg, const Immediate& imm) { + EmitGenericShift(true, 4, reg, imm); +} + + void X86_64Assembler::shll(CpuRegister operand, CpuRegister shifter) { - EmitGenericShift(4, operand, shifter); + EmitGenericShift(false, 4, operand, shifter); +} + + +void X86_64Assembler::shlq(CpuRegister operand, CpuRegister shifter) { + EmitGenericShift(true, 4, operand, shifter); } @@ -1467,7 +1477,12 @@ void X86_64Assembler::shrq(CpuRegister reg, const Immediate& imm) { void X86_64Assembler::shrl(CpuRegister operand, CpuRegister shifter) { - EmitGenericShift(5, operand, shifter); + EmitGenericShift(false, 5, operand, shifter); +} + + +void X86_64Assembler::shrq(CpuRegister operand, CpuRegister shifter) { + EmitGenericShift(true, 5, operand, shifter); } @@ -1477,7 +1492,17 @@ void X86_64Assembler::sarl(CpuRegister reg, const Immediate& imm) { void X86_64Assembler::sarl(CpuRegister operand, CpuRegister shifter) { - EmitGenericShift(7, operand, shifter); + EmitGenericShift(false, 7, operand, shifter); +} + + +void X86_64Assembler::sarq(CpuRegister reg, const Immediate& imm) { + EmitGenericShift(true, 7, reg, imm); +} + + +void X86_64Assembler::sarq(CpuRegister operand, CpuRegister shifter) { + EmitGenericShift(true, 7, operand, shifter); } @@ -1826,12 +1851,17 @@ void X86_64Assembler::EmitGenericShift(bool wide, } -void X86_64Assembler::EmitGenericShift(int reg_or_opcode, +void X86_64Assembler::EmitGenericShift(bool wide, + int reg_or_opcode, CpuRegister operand, CpuRegister shifter) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); CHECK_EQ(shifter.AsRegister(), RCX); - EmitOptionalRex32(operand); + if (wide) { + EmitRex64(operand); + } else { + EmitOptionalRex32(operand); + } EmitUint8(0xD3); EmitOperand(reg_or_opcode, Operand(operand)); } diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h index 4dd70e27d7..ab1bc9e97d 100644 --- a/compiler/utils/x86_64/assembler_x86_64.h +++ b/compiler/utils/x86_64/assembler_x86_64.h @@ -460,7 +460,12 @@ class X86_64Assembler FINAL : public Assembler { void sarl(CpuRegister reg, const Immediate& imm); void sarl(CpuRegister operand, CpuRegister shifter); + void shlq(CpuRegister reg, const Immediate& imm); + void shlq(CpuRegister operand, CpuRegister shifter); void shrq(CpuRegister reg, const Immediate& imm); + void shrq(CpuRegister operand, CpuRegister shifter); + void sarq(CpuRegister reg, const Immediate& imm); + void sarq(CpuRegister operand, CpuRegister shifter); void negl(CpuRegister reg); void negq(CpuRegister reg); @@ -657,7 +662,7 @@ class X86_64Assembler FINAL : public Assembler { void EmitNearLabelLink(Label* label); void EmitGenericShift(bool wide, int rm, CpuRegister reg, const Immediate& imm); - void EmitGenericShift(int rm, CpuRegister operand, CpuRegister shifter); + void EmitGenericShift(bool wide, int rm, CpuRegister operand, CpuRegister shifter); // If any input is not false, output the necessary rex prefix. void EmitOptionalRex(bool force, bool w, bool r, bool x, bool b); diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc index af389e69ad..14a98b9359 100644 --- a/compiler/utils/x86_64/assembler_x86_64_test.cc +++ b/compiler/utils/x86_64/assembler_x86_64_test.cc @@ -296,7 +296,7 @@ TEST_F(AssemblerX86_64Test, SublImm) { DriverStr(Repeatri(&x86_64::X86_64Assembler::subl, 4U, "sub ${imm}, %{reg}"), "subli"); } -// Shll only allows CL as the shift register. +// Shll only allows CL as the shift count. std::string shll_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { std::ostringstream str; @@ -319,7 +319,31 @@ TEST_F(AssemblerX86_64Test, ShllImm) { DriverStr(Repeatri(&x86_64::X86_64Assembler::shll, 1U, "shll ${imm}, %{reg}"), "shlli"); } -// Shrl only allows CL as the shift register. +// Shlq only allows CL as the shift count. +std::string shlq_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { + std::ostringstream str; + + std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); + + x86_64::CpuRegister shifter(x86_64::RCX); + for (auto reg : registers) { + assembler->shlq(*reg, shifter); + str << "shlq %cl, %" << assembler_test->GetRegisterName(*reg) << "\n"; + } + printf("%s\n", str.str().c_str()); + + return str.str(); +} + +TEST_F(AssemblerX86_64Test, ShlqReg) { + DriverFn(&shlq_fn, "shlq"); +} + +TEST_F(AssemblerX86_64Test, ShlqImm) { + DriverStr(RepeatRI(&x86_64::X86_64Assembler::shlq, 1U, "shlq ${imm}, %{reg}"), "shlqi"); +} + +// Shrl only allows CL as the shift count. std::string shrl_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { std::ostringstream str; @@ -342,7 +366,30 @@ TEST_F(AssemblerX86_64Test, ShrlImm) { DriverStr(Repeatri(&x86_64::X86_64Assembler::shrl, 1U, "shrl ${imm}, %{reg}"), "shrli"); } -// Sarl only allows CL as the shift register. +// Shrq only allows CL as the shift count. +std::string shrq_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { + std::ostringstream str; + + std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); + + x86_64::CpuRegister shifter(x86_64::RCX); + for (auto reg : registers) { + assembler->shrq(*reg, shifter); + str << "shrq %cl, %" << assembler_test->GetRegisterName(*reg) << "\n"; + } + + return str.str(); +} + +TEST_F(AssemblerX86_64Test, ShrqReg) { + DriverFn(&shrq_fn, "shrq"); +} + +TEST_F(AssemblerX86_64Test, ShrqImm) { + DriverStr(RepeatRI(&x86_64::X86_64Assembler::shrq, 1U, "shrq ${imm}, %{reg}"), "shrqi"); +} + +// Sarl only allows CL as the shift count. std::string sarl_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { std::ostringstream str; @@ -365,6 +412,29 @@ TEST_F(AssemblerX86_64Test, SarlImm) { DriverStr(Repeatri(&x86_64::X86_64Assembler::sarl, 1U, "sarl ${imm}, %{reg}"), "sarli"); } +// Sarq only allows CL as the shift count. +std::string sarq_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { + std::ostringstream str; + + std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); + + x86_64::CpuRegister shifter(x86_64::RCX); + for (auto reg : registers) { + assembler->sarq(*reg, shifter); + str << "sarq %cl, %" << assembler_test->GetRegisterName(*reg) << "\n"; + } + + return str.str(); +} + +TEST_F(AssemblerX86_64Test, SarqReg) { + DriverFn(&sarq_fn, "sarq"); +} + +TEST_F(AssemblerX86_64Test, SarqImm) { + DriverStr(RepeatRI(&x86_64::X86_64Assembler::sarq, 1U, "sarq ${imm}, %{reg}"), "sarqi"); +} + TEST_F(AssemblerX86_64Test, CmpqRegs) { DriverStr(RepeatRR(&x86_64::X86_64Assembler::cmpq, "cmpq %{reg2}, %{reg1}"), "cmpq"); } |