[optimizing compiler] Add shifts
Added SHL, SHR, USHR for arm, x86, x86_64.
Change-Id: I971f594e270179457e6958acf1401ff7630df07e
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 3c53cea..917b7dd 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -2129,6 +2129,139 @@
}
}
+void LocationsBuilderX86::HandleShift(HBinaryOperation* op) {
+ DCHECK(op->IsShl() || op->IsShr() || op->IsUShr());
+
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(op, LocationSummary::kNoCall);
+
+ switch (op->GetResultType()) {
+ case Primitive::kPrimInt: {
+ locations->SetInAt(0, Location::RequiresRegister());
+ // The shift count needs to be in CL.
+ locations->SetInAt(1, Location::ByteRegisterOrConstant(ECX, op->InputAt(1)));
+ locations->SetOut(Location::SameAsFirstInput());
+ break;
+ }
+ case Primitive::kPrimLong: {
+ locations->SetInAt(0, Location::RequiresRegister());
+ // The shift count needs to be in CL.
+ locations->SetInAt(1, Location::RegisterLocation(ECX));
+ locations->SetOut(Location::SameAsFirstInput());
+ break;
+ }
+ default:
+ LOG(FATAL) << "Unexpected op type " << op->GetResultType();
+ }
+}
+
+void InstructionCodeGeneratorX86::HandleShift(HBinaryOperation* op) {
+ DCHECK(op->IsShl() || op->IsShr() || op->IsUShr());
+
+ LocationSummary* locations = op->GetLocations();
+ Location first = locations->InAt(0);
+ Location second = locations->InAt(1);
+ DCHECK(first.Equals(locations->Out()));
+
+ switch (op->GetResultType()) {
+ case Primitive::kPrimInt: {
+ Register first_reg = first.As<Register>();
+ if (second.IsRegister()) {
+ Register second_reg = second.As<Register>();
+ DCHECK_EQ(ECX, second_reg);
+ if (op->IsShl()) {
+ __ shll(first_reg, second_reg);
+ } else if (op->IsShr()) {
+ __ sarl(first_reg, second_reg);
+ } else {
+ __ shrl(first_reg, second_reg);
+ }
+ } else {
+ Immediate imm(second.GetConstant()->AsIntConstant()->GetValue());
+ if (op->IsShl()) {
+ __ shll(first_reg, imm);
+ } else if (op->IsShr()) {
+ __ sarl(first_reg, imm);
+ } else {
+ __ shrl(first_reg, imm);
+ }
+ }
+ break;
+ }
+ case Primitive::kPrimLong: {
+ Register second_reg = second.As<Register>();
+ DCHECK_EQ(ECX, second_reg);
+ if (op->IsShl()) {
+ GenerateShlLong(first, second_reg);
+ } else if (op->IsShr()) {
+ GenerateShrLong(first, second_reg);
+ } else {
+ GenerateUShrLong(first, second_reg);
+ }
+ break;
+ }
+ default:
+ LOG(FATAL) << "Unexpected op type " << op->GetResultType();
+ }
+}
+
+void InstructionCodeGeneratorX86::GenerateShlLong(const Location& loc, Register shifter) {
+ Label done;
+ __ shld(loc.AsRegisterPairHigh<Register>(), loc.AsRegisterPairLow<Register>(), shifter);
+ __ shll(loc.AsRegisterPairLow<Register>(), shifter);
+ __ testl(shifter, Immediate(32));
+ __ j(kEqual, &done);
+ __ movl(loc.AsRegisterPairHigh<Register>(), loc.AsRegisterPairLow<Register>());
+ __ movl(loc.AsRegisterPairLow<Register>(), Immediate(0));
+ __ Bind(&done);
+}
+
+void InstructionCodeGeneratorX86::GenerateShrLong(const Location& loc, Register shifter) {
+ Label done;
+ __ shrd(loc.AsRegisterPairLow<Register>(), loc.AsRegisterPairHigh<Register>(), shifter);
+ __ sarl(loc.AsRegisterPairHigh<Register>(), shifter);
+ __ testl(shifter, Immediate(32));
+ __ j(kEqual, &done);
+ __ movl(loc.AsRegisterPairLow<Register>(), loc.AsRegisterPairHigh<Register>());
+ __ sarl(loc.AsRegisterPairHigh<Register>(), Immediate(31));
+ __ Bind(&done);
+}
+
+void InstructionCodeGeneratorX86::GenerateUShrLong(const Location& loc, Register shifter) {
+ Label done;
+ __ shrd(loc.AsRegisterPairLow<Register>(), loc.AsRegisterPairHigh<Register>(), shifter);
+ __ shrl(loc.AsRegisterPairHigh<Register>(), shifter);
+ __ testl(shifter, Immediate(32));
+ __ j(kEqual, &done);
+ __ movl(loc.AsRegisterPairLow<Register>(), loc.AsRegisterPairHigh<Register>());
+ __ movl(loc.AsRegisterPairHigh<Register>(), Immediate(0));
+ __ Bind(&done);
+}
+
+void LocationsBuilderX86::VisitShl(HShl* shl) {
+ HandleShift(shl);
+}
+
+void InstructionCodeGeneratorX86::VisitShl(HShl* shl) {
+ HandleShift(shl);
+}
+
+void LocationsBuilderX86::VisitShr(HShr* shr) {
+ HandleShift(shr);
+}
+
+void InstructionCodeGeneratorX86::VisitShr(HShr* shr) {
+ HandleShift(shr);
+}
+
+void LocationsBuilderX86::VisitUShr(HUShr* ushr) {
+ HandleShift(ushr);
+}
+
+void InstructionCodeGeneratorX86::VisitUShr(HUShr* ushr) {
+ HandleShift(ushr);
+}
+
void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);