MIPS: Improve HandleBinaryOp (Add/Sub) for constant inputs
Test: ./testrunner.py --optimizing --target
Change-Id: I35154a85f16b4f46d3b4d5827b130b1e20153461
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 6376f03..1f6b214 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -1941,6 +1941,7 @@
DCHECK_EQ(instruction->InputCount(), 2U);
LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
DataType::Type type = instruction->GetResultType();
+ bool isR6 = codegen_->GetInstructionSetFeatures().IsR6();
switch (type) {
case DataType::Type::kInt32: {
locations->SetInAt(0, Location::RequiresRegister());
@@ -1950,11 +1951,22 @@
int32_t imm = CodeGenerator::GetInt32ValueOf(right->AsConstant());
if (instruction->IsAnd() || instruction->IsOr() || instruction->IsXor()) {
can_use_imm = IsUint<16>(imm);
- } else if (instruction->IsAdd()) {
- can_use_imm = IsInt<16>(imm);
} else {
- DCHECK(instruction->IsSub());
- can_use_imm = IsInt<16>(-imm);
+ DCHECK(instruction->IsSub() || instruction->IsAdd());
+ if (instruction->IsSub()) {
+ imm = -imm;
+ }
+ if (isR6) {
+ bool single_use = right->GetUses().HasExactlyOneElement();
+ int16_t imm_high = High16Bits(imm);
+ int16_t imm_low = Low16Bits(imm);
+ if (imm_low < 0) {
+ imm_high += 1;
+ }
+ can_use_imm = !((imm_high != 0) && (imm_low != 0)) || single_use;
+ } else {
+ can_use_imm = IsInt<16>(imm);
+ }
}
}
if (can_use_imm)
@@ -1988,6 +2000,7 @@
void InstructionCodeGeneratorMIPS::HandleBinaryOp(HBinaryOperation* instruction) {
DataType::Type type = instruction->GetType();
LocationSummary* locations = instruction->GetLocations();
+ bool isR6 = codegen_->GetInstructionSetFeatures().IsR6();
switch (type) {
case DataType::Type::kInt32: {
@@ -2019,17 +2032,32 @@
__ Xori(dst, lhs, rhs_imm);
else
__ Xor(dst, lhs, rhs_reg);
- } else if (instruction->IsAdd()) {
- if (use_imm)
- __ Addiu(dst, lhs, rhs_imm);
- else
- __ Addu(dst, lhs, rhs_reg);
} else {
- DCHECK(instruction->IsSub());
- if (use_imm)
- __ Addiu(dst, lhs, -rhs_imm);
- else
+ DCHECK(instruction->IsAdd() || instruction->IsSub());
+ if (use_imm) {
+ if (instruction->IsSub()) {
+ rhs_imm = -rhs_imm;
+ }
+ if (IsInt<16>(rhs_imm)) {
+ __ Addiu(dst, lhs, rhs_imm);
+ } else {
+ DCHECK(isR6);
+ int16_t rhs_imm_high = High16Bits(rhs_imm);
+ int16_t rhs_imm_low = Low16Bits(rhs_imm);
+ if (rhs_imm_low < 0) {
+ rhs_imm_high += 1;
+ }
+ __ Aui(dst, lhs, rhs_imm_high);
+ if (rhs_imm_low != 0) {
+ __ Addiu(dst, dst, rhs_imm_low);
+ }
+ }
+ } else if (instruction->IsAdd()) {
+ __ Addu(dst, lhs, rhs_reg);
+ } else {
+ DCHECK(instruction->IsSub());
__ Subu(dst, lhs, rhs_reg);
+ }
}
break;
}