diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/optimizing/code_generator_mips.cc | 54 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_mips64.cc | 116 |
2 files changed, 133 insertions, 37 deletions
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index 6376f03b26..1f6b214f11 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -1941,6 +1941,7 @@ void LocationsBuilderMIPS::HandleBinaryOp(HBinaryOperation* instruction) { 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 @@ void LocationsBuilderMIPS::HandleBinaryOp(HBinaryOperation* instruction) { 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 LocationsBuilderMIPS::HandleBinaryOp(HBinaryOperation* instruction) { 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 @@ void InstructionCodeGeneratorMIPS::HandleBinaryOp(HBinaryOperation* instruction) __ 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; } diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc index 03a719f445..22989c8283 100644 --- a/compiler/optimizing/code_generator_mips64.cc +++ b/compiler/optimizing/code_generator_mips64.cc @@ -1793,11 +1793,19 @@ void LocationsBuilderMIPS64::HandleBinaryOp(HBinaryOperation* instruction) { int64_t imm = CodeGenerator::GetInt64ValueOf(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->IsAdd() || instruction->IsSub()); + bool single_use = right->GetUses().HasExactlyOneElement(); + if (instruction->IsSub()) { + if (!(type == DataType::Type::kInt32 && imm == INT32_MIN)) { + imm = -imm; + } + } + if (type == DataType::Type::kInt32) { + can_use_imm = IsInt<16>(imm) || (Low16Bits(imm) == 0) || single_use; + } else { + can_use_imm = IsInt<16>(imm) || (IsInt<32>(imm) && (Low16Bits(imm) == 0)) || single_use; + } } } if (can_use_imm) @@ -1855,30 +1863,90 @@ void InstructionCodeGeneratorMIPS64::HandleBinaryOp(HBinaryOperation* instructio __ Xori(dst, lhs, rhs_imm); else __ Xor(dst, lhs, rhs_reg); - } else if (instruction->IsAdd()) { - if (type == DataType::Type::kInt32) { - if (use_imm) - __ Addiu(dst, lhs, rhs_imm); - else - __ Addu(dst, lhs, rhs_reg); - } else { - if (use_imm) - __ Daddiu(dst, lhs, rhs_imm); - else - __ Daddu(dst, lhs, rhs_reg); + } else if (instruction->IsAdd() || instruction->IsSub()) { + if (instruction->IsSub()) { + rhs_imm = -rhs_imm; } - } else { - DCHECK(instruction->IsSub()); if (type == DataType::Type::kInt32) { - if (use_imm) - __ Addiu(dst, lhs, -rhs_imm); - else - __ Subu(dst, lhs, rhs_reg); + if (use_imm) { + if (IsInt<16>(rhs_imm)) { + __ Addiu(dst, lhs, rhs_imm); + } else { + 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); + } + } } else { - if (use_imm) - __ Daddiu(dst, lhs, -rhs_imm); - else + if (use_imm) { + if (IsInt<16>(rhs_imm)) { + __ Daddiu(dst, lhs, rhs_imm); + } else if (IsInt<32>(rhs_imm)) { + int16_t rhs_imm_high = High16Bits(rhs_imm); + int16_t rhs_imm_low = Low16Bits(rhs_imm); + bool overflow_hi16 = false; + if (rhs_imm_low < 0) { + rhs_imm_high += 1; + overflow_hi16 = (rhs_imm_high == -32768); + } + __ Daui(dst, lhs, rhs_imm_high); + if (rhs_imm_low != 0) { + __ Daddiu(dst, dst, rhs_imm_low); + } + if (overflow_hi16) { + __ Dahi(dst, 1); + } + } else { + int16_t rhs_imm_low = Low16Bits(Low32Bits(rhs_imm)); + if (rhs_imm_low < 0) { + rhs_imm += (INT64_C(1) << 16); + } + int16_t rhs_imm_upper = High16Bits(Low32Bits(rhs_imm)); + if (rhs_imm_upper < 0) { + rhs_imm += (INT64_C(1) << 32); + } + int16_t rhs_imm_high = Low16Bits(High32Bits(rhs_imm)); + if (rhs_imm_high < 0) { + rhs_imm += (INT64_C(1) << 48); + } + int16_t rhs_imm_top = High16Bits(High32Bits(rhs_imm)); + GpuRegister tmp = lhs; + if (rhs_imm_low != 0) { + __ Daddiu(dst, tmp, rhs_imm_low); + tmp = dst; + } + // Dahi and Dati must use the same input and output register, so we have to initialize + // the dst register using Daddiu or Daui, even when the intermediate value is zero: + // Daui(dst, lhs, 0). + if ((rhs_imm_upper != 0) || (rhs_imm_low == 0)) { + __ Daui(dst, tmp, rhs_imm_upper); + } + if (rhs_imm_high != 0) { + __ Dahi(dst, rhs_imm_high); + } + if (rhs_imm_top != 0) { + __ Dati(dst, rhs_imm_top); + } + } + } else if (instruction->IsAdd()) { + __ Daddu(dst, lhs, rhs_reg); + } else { + DCHECK(instruction->IsSub()); __ Dsubu(dst, lhs, rhs_reg); + } } } break; |