[optimizing compiler] Add division for floats and doubles
backends: x86, x86_64, arm.
Also:
- ordered instructions based on their name.
- add missing kNoOutputOverlap to add/sub/mul.
Change-Id: Ie47cde3b15ac74e7a1660c67a2eed1d7871f0ad0
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index cc9c6c1..f80ebdb 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -828,6 +828,16 @@
break;
}
+ case Instruction::DIV_FLOAT: {
+ Binop_23x<HDiv>(instruction, Primitive::kPrimFloat);
+ break;
+ }
+
+ case Instruction::DIV_DOUBLE: {
+ Binop_23x<HDiv>(instruction, Primitive::kPrimDouble);
+ break;
+ }
+
case Instruction::ADD_LONG_2ADDR: {
Binop_12x<HAdd>(instruction, Primitive::kPrimLong);
break;
@@ -883,6 +893,16 @@
break;
}
+ case Instruction::DIV_FLOAT_2ADDR: {
+ Binop_12x<HDiv>(instruction, Primitive::kPrimFloat);
+ break;
+ }
+
+ case Instruction::DIV_DOUBLE_2ADDR: {
+ Binop_12x<HDiv>(instruction, Primitive::kPrimDouble);
+ break;
+ }
+
case Instruction::ADD_INT_LIT16: {
Binop_22s<HAdd>(instruction, false);
break;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 7adf2cc..a5d4c43 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -1128,7 +1128,7 @@
case Primitive::kPrimDouble: {
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetInAt(1, Location::RequiresFpuRegister());
- locations->SetOut(Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
break;
}
@@ -1193,7 +1193,7 @@
case Primitive::kPrimDouble: {
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetInAt(1, Location::RequiresFpuRegister());
- locations->SetOut(Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
break;
}
default:
@@ -1262,7 +1262,7 @@
case Primitive::kPrimDouble: {
locations->SetInAt(0, Location::RequiresFpuRegister());
locations->SetInAt(1, Location::RequiresFpuRegister());
- locations->SetOut(Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
break;
}
@@ -1329,6 +1329,58 @@
}
}
+void LocationsBuilderARM::VisitDiv(HDiv* div) {
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall);
+ switch (div->GetResultType()) {
+ case Primitive::kPrimInt:
+ case Primitive::kPrimLong: {
+ LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+ break;
+ }
+ case Primitive::kPrimFloat:
+ case Primitive::kPrimDouble: {
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetInAt(1, Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+ }
+}
+
+void InstructionCodeGeneratorARM::VisitDiv(HDiv* div) {
+ LocationSummary* locations = div->GetLocations();
+ Location out = locations->Out();
+ Location first = locations->InAt(0);
+ Location second = locations->InAt(1);
+
+ switch (div->GetResultType()) {
+ case Primitive::kPrimInt:
+ case Primitive::kPrimLong: {
+ LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+ break;
+ }
+
+ case Primitive::kPrimFloat: {
+ __ vdivs(out.As<SRegister>(), first.As<SRegister>(), second.As<SRegister>());
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ __ vdivd(FromLowSToD(out.AsFpuRegisterPairLow<SRegister>()),
+ FromLowSToD(first.AsFpuRegisterPairLow<SRegister>()),
+ FromLowSToD(second.AsFpuRegisterPairLow<SRegister>()));
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+ }
+}
+
void LocationsBuilderARM::VisitNewInstance(HNewInstance* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 79528ac..f9aa44b 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -535,6 +535,7 @@
M(ArrayGet) \
M(ArraySet) \
M(DoubleConstant) \
+ M(Div) \
M(FloatConstant) \
M(Mul) \
M(Neg) \
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 99fa11d..495ff8b 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1293,6 +1293,56 @@
}
}
+void LocationsBuilderX86::VisitDiv(HDiv* div) {
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall);
+ switch (div->GetResultType()) {
+ case Primitive::kPrimInt:
+ case Primitive::kPrimLong: {
+ LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+ break;
+ }
+ case Primitive::kPrimFloat:
+ case Primitive::kPrimDouble: {
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetInAt(1, Location::RequiresFpuRegister());
+ locations->SetOut(Location::SameAsFirstInput());
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+ }
+}
+
+void InstructionCodeGeneratorX86::VisitDiv(HDiv* div) {
+ LocationSummary* locations = div->GetLocations();
+ Location first = locations->InAt(0);
+ Location second = locations->InAt(1);
+ DCHECK(first.Equals(locations->Out()));
+
+ switch (div->GetResultType()) {
+ case Primitive::kPrimInt:
+ case Primitive::kPrimLong: {
+ LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+ break;
+ }
+
+ case Primitive::kPrimFloat: {
+ __ divss(first.As<XmmRegister>(), second.As<XmmRegister>());
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ __ divsd(first.As<XmmRegister>(), second.As<XmmRegister>());
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+ }
+}
+
void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 163156a..4d11a24 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1218,6 +1218,56 @@
}
}
+void LocationsBuilderX86_64::VisitDiv(HDiv* div) {
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall);
+ switch (div->GetResultType()) {
+ case Primitive::kPrimInt:
+ case Primitive::kPrimLong: {
+ LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+ break;
+ }
+ case Primitive::kPrimFloat:
+ case Primitive::kPrimDouble: {
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetInAt(1, Location::RequiresFpuRegister());
+ locations->SetOut(Location::SameAsFirstInput());
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+ }
+}
+
+void InstructionCodeGeneratorX86_64::VisitDiv(HDiv* div) {
+ LocationSummary* locations = div->GetLocations();
+ Location first = locations->InAt(0);
+ Location second = locations->InAt(1);
+ DCHECK(first.Equals(locations->Out()));
+
+ switch (div->GetResultType()) {
+ case Primitive::kPrimInt:
+ case Primitive::kPrimLong: {
+ LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+ break;
+ }
+
+ case Primitive::kPrimFloat: {
+ __ divss(first.As<XmmRegister>(), second.As<XmmRegister>());
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ __ divsd(first.As<XmmRegister>(), second.As<XmmRegister>());
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+ }
+}
+
void LocationsBuilderX86_64::VisitNewInstance(HNewInstance* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 7adb840..f530708 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -468,46 +468,47 @@
#define FOR_EACH_CONCRETE_INSTRUCTION(M) \
M(Add, BinaryOperation) \
+ M(ArrayGet, Instruction) \
+ M(ArrayLength, Instruction) \
+ M(ArraySet, Instruction) \
+ M(BoundsCheck, Instruction) \
+ M(Compare, BinaryOperation) \
M(Condition, BinaryOperation) \
+ M(Div, BinaryOperation) \
+ M(DoubleConstant, Constant) \
M(Equal, Condition) \
- M(NotEqual, Condition) \
- M(LessThan, Condition) \
- M(LessThanOrEqual, Condition) \
+ M(Exit, Instruction) \
+ M(FloatConstant, Constant) \
+ M(Goto, Instruction) \
M(GreaterThan, Condition) \
M(GreaterThanOrEqual, Condition) \
- M(Exit, Instruction) \
- M(Goto, Instruction) \
M(If, Instruction) \
+ M(InstanceFieldGet, Instruction) \
+ M(InstanceFieldSet, Instruction) \
M(IntConstant, Constant) \
M(InvokeStatic, Invoke) \
M(InvokeVirtual, Invoke) \
+ M(LessThan, Condition) \
+ M(LessThanOrEqual, Condition) \
M(LoadLocal, Instruction) \
M(Local, Instruction) \
M(LongConstant, Constant) \
+ M(Mul, BinaryOperation) \
+ M(Neg, UnaryOperation) \
+ M(NewArray, Instruction) \
M(NewInstance, Instruction) \
M(Not, UnaryOperation) \
- M(ParameterValue, Instruction) \
+ M(NotEqual, Condition) \
+ M(NullCheck, Instruction) \
M(ParallelMove, Instruction) \
+ M(ParameterValue, Instruction) \
M(Phi, Instruction) \
M(Return, Instruction) \
M(ReturnVoid, Instruction) \
M(StoreLocal, Instruction) \
M(Sub, BinaryOperation) \
- M(Compare, BinaryOperation) \
- M(InstanceFieldGet, Instruction) \
- M(InstanceFieldSet, Instruction) \
- M(ArrayGet, Instruction) \
- M(ArraySet, Instruction) \
- M(ArrayLength, Instruction) \
- M(BoundsCheck, Instruction) \
- M(NullCheck, Instruction) \
- M(Temporary, Instruction) \
M(SuspendCheck, Instruction) \
- M(Mul, BinaryOperation) \
- M(Neg, UnaryOperation) \
- M(FloatConstant, Constant) \
- M(DoubleConstant, Constant) \
- M(NewArray, Instruction) \
+ M(Temporary, Instruction) \
#define FOR_EACH_INSTRUCTION(M) \
FOR_EACH_CONCRETE_INSTRUCTION(M) \
@@ -1658,8 +1659,6 @@
HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
: HBinaryOperation(result_type, left, right) {}
- virtual bool IsCommutative() { return false; }
-
virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
return x - y;
}
@@ -1689,6 +1688,20 @@
DISALLOW_COPY_AND_ASSIGN(HMul);
};
+class HDiv : public HBinaryOperation {
+ public:
+ HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right)
+ : HBinaryOperation(result_type, left, right) {}
+
+ virtual int32_t Evaluate(int32_t x, int32_t y) const { return x / y; }
+ virtual int64_t Evaluate(int64_t x, int64_t y) const { return x / y; }
+
+ DECLARE_INSTRUCTION(Div);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HDiv);
+};
+
// The value of a parameter in this method. Its location depends on
// the calling convention.
class HParameterValue : public HExpression<0> {