diff options
-rw-r--r-- | compiler/optimizing/code_generator_arm_vixl.cc | 81 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm_vixl.h | 1 | ||||
-rw-r--r-- | compiler/optimizing/scheduler_arm.cc | 6 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_arm_shared.h | 7 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_arm_test.h | 555 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_arm_vixl.cc | 6 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_arm_vixl.h | 4 | ||||
-rw-r--r-- | compiler/utils/arm/jni_macro_assembler_arm_vixl.cc | 4 |
8 files changed, 52 insertions, 612 deletions
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index 7f8353312f..7c6a5fde40 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -5597,42 +5597,13 @@ Location LocationsBuilderARMVIXL::ArmEncodableConstantOrRegister(HInstruction* c return Location::RequiresRegister(); } -bool LocationsBuilderARMVIXL::CanEncodeConstantAsImmediate(HConstant* input_cst, - Opcode opcode) { - uint64_t value = static_cast<uint64_t>(Int64FromConstant(input_cst)); - if (DataType::Is64BitType(input_cst->GetType())) { - Opcode high_opcode = opcode; - SetCc low_set_cc = kCcDontCare; - switch (opcode) { - case SUB: - // Flip the operation to an ADD. - value = -value; - opcode = ADD; - FALLTHROUGH_INTENDED; - case ADD: - if (Low32Bits(value) == 0u) { - return CanEncodeConstantAsImmediate(High32Bits(value), opcode, kCcDontCare); - } - high_opcode = ADC; - low_set_cc = kCcSet; - break; - default: - break; - } - return CanEncodeConstantAsImmediate(Low32Bits(value), opcode, low_set_cc) && - CanEncodeConstantAsImmediate(High32Bits(value), high_opcode, kCcDontCare); - } else { - return CanEncodeConstantAsImmediate(Low32Bits(value), opcode); - } -} - -// TODO(VIXL): Replace art::arm::SetCc` with `vixl32::FlagsUpdate after flags set optimization -// enabled. -bool LocationsBuilderARMVIXL::CanEncodeConstantAsImmediate(uint32_t value, - Opcode opcode, - SetCc set_cc) { - ArmVIXLAssembler* assembler = codegen_->GetAssembler(); - if (assembler->ShifterOperandCanHold(opcode, value, set_cc)) { +static bool CanEncode32BitConstantAsImmediate( + CodeGeneratorARMVIXL* codegen, + uint32_t value, + Opcode opcode, + vixl32::FlagsUpdate flags_update = vixl32::FlagsUpdate::DontCare) { + ArmVIXLAssembler* assembler = codegen->GetAssembler(); + if (assembler->ShifterOperandCanHold(opcode, value, flags_update)) { return true; } Opcode neg_opcode = kNoOperand; @@ -5649,13 +5620,41 @@ bool LocationsBuilderARMVIXL::CanEncodeConstantAsImmediate(uint32_t value, return false; } - if (assembler->ShifterOperandCanHold(neg_opcode, neg_value, set_cc)) { + if (assembler->ShifterOperandCanHold(neg_opcode, neg_value, flags_update)) { return true; } return opcode == AND && IsPowerOfTwo(value + 1); } +bool LocationsBuilderARMVIXL::CanEncodeConstantAsImmediate(HConstant* input_cst, Opcode opcode) { + uint64_t value = static_cast<uint64_t>(Int64FromConstant(input_cst)); + if (DataType::Is64BitType(input_cst->GetType())) { + Opcode high_opcode = opcode; + vixl32::FlagsUpdate low_flags_update = vixl32::FlagsUpdate::DontCare; + switch (opcode) { + case SUB: + // Flip the operation to an ADD. + value = -value; + opcode = ADD; + FALLTHROUGH_INTENDED; + case ADD: + if (Low32Bits(value) == 0u) { + return CanEncode32BitConstantAsImmediate(codegen_, High32Bits(value), opcode); + } + high_opcode = ADC; + low_flags_update = vixl32::FlagsUpdate::SetFlags; + break; + default: + break; + } + return CanEncode32BitConstantAsImmediate(codegen_, High32Bits(value), high_opcode) && + CanEncode32BitConstantAsImmediate(codegen_, Low32Bits(value), opcode, low_flags_update); + } else { + return CanEncode32BitConstantAsImmediate(codegen_, Low32Bits(value), opcode); + } +} + void InstructionCodeGeneratorARMVIXL::HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info) { DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet()); @@ -8131,13 +8130,11 @@ void InstructionCodeGeneratorARMVIXL::GenerateAddLongConst(Location out, return; } __ Adds(out_low, first_low, value_low); - if (GetAssembler()->ShifterOperandCanHold(ADC, value_high, kCcDontCare)) { + if (GetAssembler()->ShifterOperandCanHold(ADC, value_high)) { __ Adc(out_high, first_high, value_high); - } else if (GetAssembler()->ShifterOperandCanHold(SBC, ~value_high, kCcDontCare)) { - __ Sbc(out_high, first_high, ~value_high); } else { - LOG(FATAL) << "Unexpected constant " << value_high; - UNREACHABLE(); + DCHECK(GetAssembler()->ShifterOperandCanHold(SBC, ~value_high)); + __ Sbc(out_high, first_high, ~value_high); } } diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h index c46d17ccec..38570bb0fe 100644 --- a/compiler/optimizing/code_generator_arm_vixl.h +++ b/compiler/optimizing/code_generator_arm_vixl.h @@ -287,7 +287,6 @@ class LocationsBuilderARMVIXL : public HGraphVisitor { Location ArithmeticZeroOrFpuRegister(HInstruction* input); Location ArmEncodableConstantOrRegister(HInstruction* constant, Opcode opcode); bool CanEncodeConstantAsImmediate(HConstant* input_cst, Opcode opcode); - bool CanEncodeConstantAsImmediate(uint32_t value, Opcode opcode, SetCc set_cc = kCcDontCare); CodeGeneratorARMVIXL* const codegen_; InvokeDexCallingConventionVisitorARMVIXL parameter_visitor_; diff --git a/compiler/optimizing/scheduler_arm.cc b/compiler/optimizing/scheduler_arm.cc index b3c8f105d1..8dcadaad2e 100644 --- a/compiler/optimizing/scheduler_arm.cc +++ b/compiler/optimizing/scheduler_arm.cc @@ -330,10 +330,12 @@ bool SchedulingLatencyVisitorARM::CanGenerateTest(HCondition* condition) { } } else if (c == kCondLE || c == kCondGT) { if (value < std::numeric_limits<int64_t>::max() && - !codegen_->GetAssembler()->ShifterOperandCanHold(SBC, High32Bits(value + 1), kCcSet)) { + !codegen_->GetAssembler()->ShifterOperandCanHold( + SBC, High32Bits(value + 1), vixl32::FlagsUpdate::SetFlags)) { return false; } - } else if (!codegen_->GetAssembler()->ShifterOperandCanHold(SBC, High32Bits(value), kCcSet)) { + } else if (!codegen_->GetAssembler()->ShifterOperandCanHold( + SBC, High32Bits(value), vixl32::FlagsUpdate::SetFlags)) { return false; } } diff --git a/compiler/utils/arm/assembler_arm_shared.h b/compiler/utils/arm/assembler_arm_shared.h index 21f13eeab7..7464052d93 100644 --- a/compiler/utils/arm/assembler_arm_shared.h +++ b/compiler/utils/arm/assembler_arm_shared.h @@ -40,13 +40,6 @@ enum StoreOperandType { kStoreDWord }; -// Set condition codes request. -enum SetCc { - kCcDontCare, // Allows prioritizing 16-bit instructions on Thumb2 whether they set CCs or not. - kCcSet, - kCcKeep, -}; - } // namespace arm } // namespace art diff --git a/compiler/utils/arm/assembler_arm_test.h b/compiler/utils/arm/assembler_arm_test.h deleted file mode 100644 index 8c3a11f2cf..0000000000 --- a/compiler/utils/arm/assembler_arm_test.h +++ /dev/null @@ -1,555 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_TEST_H_ -#define ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_TEST_H_ - -#include "utils/assembler_test.h" - -namespace art { - -template<typename Ass, - typename Reg, - typename FPReg, - typename Imm, - typename SOp, - typename Cond, - typename SetCc> -class AssemblerArmTest : public AssemblerTest<Ass, Reg, FPReg, Imm> { - public: - typedef AssemblerTest<Ass, Reg, FPReg, Imm> Base; - - using Base::GetRegisters; - using Base::GetRegName; - using Base::CreateImmediate; - using Base::WarnOnCombinations; - - static constexpr int64_t kFullImmRangeThreshold = 32; - - virtual void FillImmediates(std::vector<Imm>& immediates, int64_t imm_min, int64_t imm_max) { - // Small range: do completely. - if (imm_max - imm_min <= kFullImmRangeThreshold) { - for (int64_t i = imm_min; i <= imm_max; ++i) { - immediates.push_back(CreateImmediate(i)); - } - } else { - immediates.push_back(CreateImmediate(imm_min)); - immediates.push_back(CreateImmediate(imm_max)); - if (imm_min < imm_max - 1) { - immediates.push_back(CreateImmediate(imm_min + 1)); - } - if (imm_min < imm_max - 2) { - immediates.push_back(CreateImmediate(imm_min + 2)); - } - if (imm_min < imm_max - 3) { - immediates.push_back(CreateImmediate(imm_max - 1)); - } - if (imm_min < imm_max - 4) { - immediates.push_back(CreateImmediate((imm_min + imm_max) / 2)); - } - } - } - - std::string RepeatRRIIC(void (Ass::*f)(Reg, Reg, Imm, Imm, Cond), - int64_t imm1_min, int64_t imm1_max, - int64_t imm2_min, int64_t imm2_max, - std::string fmt) { - return RepeatTemplatedRRIIC(f, GetRegisters(), GetRegisters(), - &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>, - &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>, - imm1_min, imm1_max, imm2_min, imm2_max, - fmt); - } - - template <typename Reg1, typename Reg2> - std::string RepeatTemplatedRRIIC(void (Ass::*f)(Reg1, Reg2, Imm, Imm, Cond), - const std::vector<Reg1*> reg1_registers, - const std::vector<Reg2*> reg2_registers, - std::string (AssemblerArmTest::*GetName1)(const Reg1&), - std::string (AssemblerArmTest::*GetName2)(const Reg2&), - int64_t imm1_min, int64_t imm1_max, - int64_t imm2_min, int64_t imm2_max, - std::string fmt) { - std::vector<Imm> immediates1; - FillImmediates(immediates1, imm1_min, imm1_max); - std::vector<Imm> immediates2; - FillImmediates(immediates2, imm2_min, imm2_max); - - std::vector<Cond>& cond = GetConditions(); - - WarnOnCombinations(cond.size() * immediates1.size() * immediates2.size() * - reg1_registers.size() * reg2_registers.size()); - - std::ostringstream oss; - bool first = true; - for (Cond& c : cond) { - std::string after_cond = fmt; - - size_t cond_index = after_cond.find(COND_TOKEN); - if (cond_index != std::string::npos) { - after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c)); - } - - for (Imm i : immediates1) { - std::string base = after_cond; - - size_t imm1_index = base.find(IMM1_TOKEN); - if (imm1_index != std::string::npos) { - std::ostringstream sreg; - sreg << i; - std::string imm_string = sreg.str(); - base.replace(imm1_index, ConstexprStrLen(IMM1_TOKEN), imm_string); - } - - for (Imm j : immediates2) { - std::string base2 = base; - - size_t imm2_index = base2.find(IMM2_TOKEN); - if (imm2_index != std::string::npos) { - std::ostringstream sreg; - sreg << j; - std::string imm_string = sreg.str(); - base2.replace(imm2_index, ConstexprStrLen(IMM2_TOKEN), imm_string); - } - - for (auto reg1 : reg1_registers) { - std::string base3 = base2; - - std::string reg1_string = (this->*GetName1)(*reg1); - size_t reg1_index; - while ((reg1_index = base3.find(Base::REG1_TOKEN)) != std::string::npos) { - base3.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string); - } - - for (auto reg2 : reg2_registers) { - std::string base4 = base3; - - std::string reg2_string = (this->*GetName2)(*reg2); - size_t reg2_index; - while ((reg2_index = base4.find(Base::REG2_TOKEN)) != std::string::npos) { - base4.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string); - } - - if (first) { - first = false; - } else { - oss << "\n"; - } - oss << base4; - - (Base::GetAssembler()->*f)(*reg1, *reg2, i, j, c); - } - } - } - } - } - // Add a newline at the end. - oss << "\n"; - - return oss.str(); - } - - std::string RepeatRRiiC(void (Ass::*f)(Reg, Reg, Imm, Imm, Cond), - std::vector<std::pair<Imm, Imm>>& immediates, - std::string fmt) { - return RepeatTemplatedRRiiC<Reg, Reg>(f, GetRegisters(), GetRegisters(), - &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>, - &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>, - immediates, fmt); - } - - template <typename Reg1, typename Reg2> - std::string RepeatTemplatedRRiiC(void (Ass::*f)(Reg1, Reg2, Imm, Imm, Cond), - const std::vector<Reg1*> reg1_registers, - const std::vector<Reg2*> reg2_registers, - std::string (AssemblerArmTest::*GetName1)(const Reg1&), - std::string (AssemblerArmTest::*GetName2)(const Reg2&), - std::vector<std::pair<Imm, Imm>>& immediates, - std::string fmt) { - std::vector<Cond>& cond = GetConditions(); - - WarnOnCombinations(cond.size() * immediates.size() * reg1_registers.size() * - reg2_registers.size()); - - std::ostringstream oss; - bool first = true; - for (Cond& c : cond) { - std::string after_cond = fmt; - - size_t cond_index = after_cond.find(COND_TOKEN); - if (cond_index != std::string::npos) { - after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c)); - } - - for (std::pair<Imm, Imm>& pair : immediates) { - Imm i = pair.first; - Imm j = pair.second; - std::string after_imm1 = after_cond; - - size_t imm1_index = after_imm1.find(IMM1_TOKEN); - if (imm1_index != std::string::npos) { - std::ostringstream sreg; - sreg << i; - std::string imm_string = sreg.str(); - after_imm1.replace(imm1_index, ConstexprStrLen(IMM1_TOKEN), imm_string); - } - - std::string after_imm2 = after_imm1; - - size_t imm2_index = after_imm2.find(IMM2_TOKEN); - if (imm2_index != std::string::npos) { - std::ostringstream sreg; - sreg << j; - std::string imm_string = sreg.str(); - after_imm2.replace(imm2_index, ConstexprStrLen(IMM2_TOKEN), imm_string); - } - - for (auto reg1 : reg1_registers) { - std::string after_reg1 = after_imm2; - - std::string reg1_string = (this->*GetName1)(*reg1); - size_t reg1_index; - while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) { - after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string); - } - - for (auto reg2 : reg2_registers) { - std::string after_reg2 = after_reg1; - - std::string reg2_string = (this->*GetName2)(*reg2); - size_t reg2_index; - while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) { - after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string); - } - - if (first) { - first = false; - } else { - oss << "\n"; - } - oss << after_reg2; - - (Base::GetAssembler()->*f)(*reg1, *reg2, i, j, c); - } - } - } - } - // Add a newline at the end. - oss << "\n"; - - return oss.str(); - } - - std::string RepeatRRC(void (Ass::*f)(Reg, Reg, Cond), std::string fmt) { - return RepeatTemplatedRRC(f, GetRegisters(), GetRegisters(), GetConditions(), - &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>, - &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>, - fmt); - } - - template <typename Reg1, typename Reg2> - std::string RepeatTemplatedRRC(void (Ass::*f)(Reg1, Reg2, Cond), - const std::vector<Reg1*>& reg1_registers, - const std::vector<Reg2*>& reg2_registers, - const std::vector<Cond>& cond, - std::string (AssemblerArmTest::*GetName1)(const Reg1&), - std::string (AssemblerArmTest::*GetName2)(const Reg2&), - std::string fmt) { - WarnOnCombinations(cond.size() * reg1_registers.size() * reg2_registers.size()); - - std::ostringstream oss; - bool first = true; - for (const Cond& c : cond) { - std::string after_cond = fmt; - - size_t cond_index = after_cond.find(COND_TOKEN); - if (cond_index != std::string::npos) { - after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c)); - } - - for (auto reg1 : reg1_registers) { - std::string after_reg1 = after_cond; - - std::string reg1_string = (this->*GetName1)(*reg1); - size_t reg1_index; - while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) { - after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string); - } - - for (auto reg2 : reg2_registers) { - std::string after_reg2 = after_reg1; - - std::string reg2_string = (this->*GetName2)(*reg2); - size_t reg2_index; - while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) { - after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string); - } - - if (first) { - first = false; - } else { - oss << "\n"; - } - oss << after_reg2; - - (Base::GetAssembler()->*f)(*reg1, *reg2, c); - } - } - } - // Add a newline at the end. - oss << "\n"; - - return oss.str(); - } - - std::string RepeatRRRC(void (Ass::*f)(Reg, Reg, Reg, Cond), std::string fmt) { - return RepeatTemplatedRRRC(f, GetRegisters(), GetRegisters(), GetRegisters(), GetConditions(), - &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>, - &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>, - &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>, - fmt); - } - - template <typename Reg1, typename Reg2, typename Reg3> - std::string RepeatTemplatedRRRC(void (Ass::*f)(Reg1, Reg2, Reg3, Cond), - const std::vector<Reg1*>& reg1_registers, - const std::vector<Reg2*>& reg2_registers, - const std::vector<Reg3*>& reg3_registers, - const std::vector<Cond>& cond, - std::string (AssemblerArmTest::*GetName1)(const Reg1&), - std::string (AssemblerArmTest::*GetName2)(const Reg2&), - std::string (AssemblerArmTest::*GetName3)(const Reg3&), - std::string fmt) { - WarnOnCombinations(cond.size() * reg1_registers.size() * reg2_registers.size() * - reg3_registers.size()); - - std::ostringstream oss; - bool first = true; - for (const Cond& c : cond) { - std::string after_cond = fmt; - - size_t cond_index = after_cond.find(COND_TOKEN); - if (cond_index != std::string::npos) { - after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c)); - } - - for (auto reg1 : reg1_registers) { - std::string after_reg1 = after_cond; - - std::string reg1_string = (this->*GetName1)(*reg1); - size_t reg1_index; - while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) { - after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string); - } - - for (auto reg2 : reg2_registers) { - std::string after_reg2 = after_reg1; - - std::string reg2_string = (this->*GetName2)(*reg2); - size_t reg2_index; - while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) { - after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string); - } - - for (auto reg3 : reg3_registers) { - std::string after_reg3 = after_reg2; - - std::string reg3_string = (this->*GetName3)(*reg3); - size_t reg3_index; - while ((reg3_index = after_reg3.find(REG3_TOKEN)) != std::string::npos) { - after_reg3.replace(reg3_index, ConstexprStrLen(REG3_TOKEN), reg3_string); - } - - if (first) { - first = false; - } else { - oss << "\n"; - } - oss << after_reg3; - - (Base::GetAssembler()->*f)(*reg1, *reg2, *reg3, c); - } - } - } - } - // Add a newline at the end. - oss << "\n"; - - return oss.str(); - } - - template <typename RegT> - std::string RepeatTemplatedRSC(void (Ass::*f)(RegT, SOp, Cond), - const std::vector<RegT*>& registers, - const std::vector<SOp>& shifts, - const std::vector<Cond>& cond, - std::string (AssemblerArmTest::*GetName)(const RegT&), - std::string fmt) { - WarnOnCombinations(cond.size() * registers.size() * shifts.size()); - - std::ostringstream oss; - bool first = true; - for (const Cond& c : cond) { - std::string after_cond = fmt; - - size_t cond_index = after_cond.find(COND_TOKEN); - if (cond_index != std::string::npos) { - after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c)); - } - - for (const SOp& shift : shifts) { - std::string after_shift = after_cond; - - std::string shift_string = GetShiftString(shift); - size_t shift_index; - while ((shift_index = after_shift.find(Base::SHIFT_TOKEN)) != std::string::npos) { - after_shift.replace(shift_index, ConstexprStrLen(Base::SHIFT_TOKEN), shift_string); - } - - for (auto reg : registers) { - std::string after_reg = after_shift; - - std::string reg_string = (this->*GetName)(*reg); - size_t reg_index; - while ((reg_index = after_reg.find(Base::REG_TOKEN)) != std::string::npos) { - after_reg.replace(reg_index, ConstexprStrLen(Base::REG_TOKEN), reg_string); - } - - if (first) { - first = false; - } else { - oss << "\n"; - } - oss << after_reg; - - (Base::GetAssembler()->*f)(*reg, shift, c); - } - } - } - // Add a newline at the end. - oss << "\n"; - - return oss.str(); - } - - template <typename Reg1, typename Reg2> - std::string RepeatTemplatedRRSC(void (Ass::*f)(Reg1, Reg2, const SOp&, Cond), - const std::vector<Reg1*>& reg1_registers, - const std::vector<Reg2*>& reg2_registers, - const std::vector<SOp>& shifts, - const std::vector<Cond>& cond, - std::string (AssemblerArmTest::*GetName1)(const Reg1&), - std::string (AssemblerArmTest::*GetName2)(const Reg2&), - std::string fmt) { - WarnOnCombinations(cond.size() * reg1_registers.size() * reg2_registers.size() * shifts.size()); - - std::ostringstream oss; - bool first = true; - for (const Cond& c : cond) { - std::string after_cond = fmt; - - size_t cond_index = after_cond.find(COND_TOKEN); - if (cond_index != std::string::npos) { - after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c)); - } - - for (const SOp& shift : shifts) { - std::string after_shift = after_cond; - - std::string shift_string = GetShiftString(shift); - size_t shift_index; - while ((shift_index = after_shift.find(SHIFT_TOKEN)) != std::string::npos) { - after_shift.replace(shift_index, ConstexprStrLen(SHIFT_TOKEN), shift_string); - } - - for (auto reg1 : reg1_registers) { - std::string after_reg1 = after_shift; - - std::string reg1_string = (this->*GetName1)(*reg1); - size_t reg1_index; - while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) { - after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string); - } - - for (auto reg2 : reg2_registers) { - std::string after_reg2 = after_reg1; - - std::string reg2_string = (this->*GetName2)(*reg2); - size_t reg2_index; - while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) { - after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string); - } - - if (first) { - first = false; - } else { - oss << "\n"; - } - oss << after_reg2; - - (Base::GetAssembler()->*f)(*reg1, *reg2, shift, c); - } - } - } - } - // Add a newline at the end. - oss << "\n"; - - return oss.str(); - } - - protected: - AssemblerArmTest() {} - - virtual std::vector<Cond>& GetConditions() = 0; - virtual std::string GetConditionString(Cond c) = 0; - - virtual std::vector<SetCc>& GetSetCcs() = 0; - virtual std::string GetSetCcString(SetCc s) = 0; - - virtual std::vector<SOp>& GetShiftOperands() = 0; - virtual std::string GetShiftString(SOp sop) = 0; - - virtual Reg GetPCRegister() = 0; - virtual std::vector<Reg*> GetRegistersWithoutPC() { - std::vector<Reg*> without_pc = GetRegisters(); - Reg pc_reg = GetPCRegister(); - - for (auto it = without_pc.begin(); it != without_pc.end(); ++it) { - if (**it == pc_reg) { - without_pc.erase(it); - break; - } - } - - return without_pc; - } - - static constexpr const char* IMM1_TOKEN = "{imm1}"; - static constexpr const char* IMM2_TOKEN = "{imm2}"; - static constexpr const char* REG3_TOKEN = "{reg3}"; - static constexpr const char* REG4_TOKEN = "{reg4}"; - static constexpr const char* COND_TOKEN = "{cond}"; - static constexpr const char* SET_CC_TOKEN = "{s}"; - static constexpr const char* SHIFT_TOKEN = "{shift}"; - - private: - DISALLOW_COPY_AND_ASSIGN(AssemblerArmTest); -}; - -} // namespace art - -#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_TEST_H_ diff --git a/compiler/utils/arm/assembler_arm_vixl.cc b/compiler/utils/arm/assembler_arm_vixl.cc index d6b24da407..05250a4157 100644 --- a/compiler/utils/arm/assembler_arm_vixl.cc +++ b/compiler/utils/arm/assembler_arm_vixl.cc @@ -112,12 +112,14 @@ bool ArmVIXLAssembler::ShifterOperandCanAlwaysHold(uint32_t immediate) { return vixl_masm_.IsModifiedImmediate(immediate); } -bool ArmVIXLAssembler::ShifterOperandCanHold(Opcode opcode, uint32_t immediate, SetCc set_cc) { +bool ArmVIXLAssembler::ShifterOperandCanHold(Opcode opcode, + uint32_t immediate, + vixl::aarch32::FlagsUpdate update_flags) { switch (opcode) { case ADD: case SUB: // Less than (or equal to) 12 bits can be done if we don't need to set condition codes. - if (IsUint<12>(immediate) && set_cc != kCcSet) { + if (IsUint<12>(immediate) && update_flags != vixl::aarch32::SetFlags) { return true; } return ShifterOperandCanAlwaysHold(immediate); diff --git a/compiler/utils/arm/assembler_arm_vixl.h b/compiler/utils/arm/assembler_arm_vixl.h index 1377e64073..b0310f2fb6 100644 --- a/compiler/utils/arm/assembler_arm_vixl.h +++ b/compiler/utils/arm/assembler_arm_vixl.h @@ -218,7 +218,9 @@ class ArmVIXLAssembler FINAL : public Assembler { void StoreRegisterList(RegList regs, size_t stack_offset); bool ShifterOperandCanAlwaysHold(uint32_t immediate); - bool ShifterOperandCanHold(Opcode opcode, uint32_t immediate, SetCc set_cc = kCcDontCare); + bool ShifterOperandCanHold(Opcode opcode, + uint32_t immediate, + vixl::aarch32::FlagsUpdate update_flags = vixl::aarch32::DontCare); bool CanSplitLoadStoreOffset(int32_t allowed_offset_bits, int32_t offset, /*out*/ int32_t* add_to_base, diff --git a/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc b/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc index 2b3e979606..065c3de23c 100644 --- a/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc +++ b/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc @@ -492,7 +492,7 @@ void ArmVIXLJNIMacroAssembler::CreateHandleScopeEntry(ManagedRegister mout_reg, temps.Exclude(in_reg.AsVIXLRegister()); ___ Cmp(in_reg.AsVIXLRegister(), 0); - if (asm_.ShifterOperandCanHold(ADD, handle_scope_offset.Int32Value(), kCcDontCare)) { + if (asm_.ShifterOperandCanHold(ADD, handle_scope_offset.Int32Value())) { if (!out_reg.Equals(in_reg)) { ExactAssemblyScope guard(asm_.GetVIXLAssembler(), 3 * vixl32::kMaxInstructionSizeInBytes, @@ -531,7 +531,7 @@ void ArmVIXLJNIMacroAssembler::CreateHandleScopeEntry(FrameOffset out_off, // e.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset) ___ Cmp(scratch.AsVIXLRegister(), 0); - if (asm_.ShifterOperandCanHold(ADD, handle_scope_offset.Int32Value(), kCcDontCare)) { + if (asm_.ShifterOperandCanHold(ADD, handle_scope_offset.Int32Value())) { ExactAssemblyScope guard(asm_.GetVIXLAssembler(), 2 * vixl32::kMaxInstructionSizeInBytes, CodeBufferCheckScope::kMaximumSize); |