diff options
author | 2016-12-12 10:30:24 +0000 | |
---|---|---|
committer | 2016-12-12 10:30:24 +0000 | |
commit | c836b5a8a5ea00b0cd332d5e60c9ec10ae1e74fb (patch) | |
tree | eb5203121c5b8d1d6b33f39e1c8b2ff45ad26ca8 | |
parent | 726e5173059bb71dbd1b05c5de8f4a325c4a316f (diff) | |
parent | bffdc70d4b6dd994adf48b015e7818094f30938f (diff) |
Merge "Revert "Revert "ARM: VIXL32: Use DontCare for SetFlags + fix for GenerateFrameEntry."""
-rw-r--r-- | compiler/optimizing/code_generator_arm_vixl.cc | 24 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_arm_vixl.cc | 22 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_arm_vixl.h | 71 | ||||
-rw-r--r-- | test/538-checker-embed-constants/src/Main.java | 6 |
4 files changed, 115 insertions, 8 deletions
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index c8bdd0163d..3a3d2a9db1 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -1400,10 +1400,25 @@ void CodeGeneratorARMVIXL::GenerateFrameEntry() { GetAssembler()->cfi().AdjustCFAOffset(kArmWordSize * POPCOUNT(fpu_spill_mask_)); GetAssembler()->cfi().RelOffsetForMany(DWARFReg(s0), 0, fpu_spill_mask_, kArmWordSize); } + + if (GetGraph()->HasShouldDeoptimizeFlag()) { + UseScratchRegisterScope temps(GetVIXLAssembler()); + vixl32::Register temp = temps.Acquire(); + // Initialize should_deoptimize flag to 0. + __ Mov(temp, 0); + GetAssembler()->StoreToOffset(kStoreWord, temp, sp, -kShouldDeoptimizeFlagSize); + } + int adjust = GetFrameSize() - FrameEntrySpillSize(); __ Sub(sp, sp, adjust); GetAssembler()->cfi().AdjustCFAOffset(adjust); - GetAssembler()->StoreToOffset(kStoreWord, kMethodRegister, sp, 0); + + // Save the current method if we need it. Note that we do not + // do this in HCurrentMethod, as the instruction might have been removed + // in the SSA graph. + if (RequiresCurrentMethod()) { + GetAssembler()->StoreToOffset(kStoreWord, kMethodRegister, sp, 0); + } } void CodeGeneratorARMVIXL::GenerateFrameExit() { @@ -3606,8 +3621,7 @@ void InstructionCodeGeneratorARMVIXL::HandleLongRotate(HRor* ror) { __ And(shift_right, RegisterFrom(rhs), 0x1F); __ Lsrs(shift_left, RegisterFrom(rhs), 6); - // TODO(VIXL): Check that flags are kept after "vixl32::LeaveFlags" enabled. - __ Rsb(shift_left, shift_right, Operand::From(kArmBitsPerWord)); + __ Rsb(LeaveFlags, shift_left, shift_right, Operand::From(kArmBitsPerWord)); __ B(cc, &shift_by_32_plus_shift_right); // out_reg_hi = (reg_hi << shift_left) | (reg_lo >> shift_right). @@ -6758,9 +6772,9 @@ void InstructionCodeGeneratorARMVIXL::GenerateAddLongConst(Location out, return; } __ Adds(out_low, first_low, value_low); - if (GetAssembler()->ShifterOperandCanHold(ADC, value_high, kCcKeep)) { + if (GetAssembler()->ShifterOperandCanHold(ADC, value_high, kCcDontCare)) { __ Adc(out_high, first_high, value_high); - } else if (GetAssembler()->ShifterOperandCanHold(SBC, ~value_high, kCcKeep)) { + } else if (GetAssembler()->ShifterOperandCanHold(SBC, ~value_high, kCcDontCare)) { __ Sbc(out_high, first_high, ~value_high); } else { LOG(FATAL) << "Unexpected constant " << value_high; diff --git a/compiler/utils/arm/assembler_arm_vixl.cc b/compiler/utils/arm/assembler_arm_vixl.cc index c35c39328c..1614d04a95 100644 --- a/compiler/utils/arm/assembler_arm_vixl.cc +++ b/compiler/utils/arm/assembler_arm_vixl.cc @@ -455,5 +455,27 @@ void ArmVIXLMacroAssembler::CompareAndBranchIfNonZero(vixl32::Register rn, B(ne, label); } +void ArmVIXLMacroAssembler::B(vixl32::Label* label) { + if (!label->IsBound()) { + // Try to use 16-bit T2 encoding of B instruction. + DCHECK(OutsideITBlock()); + AssemblerAccurateScope ass(this, + kMaxInstructionSizeInBytes, + CodeBufferCheckScope::kMaximumSize); + b(al, Narrow, label); + AddBranchLabel(label); + return; + } + MacroAssembler::B(label); +} + +void ArmVIXLMacroAssembler::B(vixl32::Condition cond, vixl32::Label* label) { + // To further reduce the Bcc encoding size and use 16-bit T1 encoding, + // we can provide a hint to this function: i.e. far_target=false. + // By default this function uses 'EncodingSizeType::Best' which generates 32-bit T3 encoding. + MacroAssembler::B(cond, label); +} + + } // namespace arm } // namespace art diff --git a/compiler/utils/arm/assembler_arm_vixl.h b/compiler/utils/arm/assembler_arm_vixl.h index b4a4abc87e..17cf1064b0 100644 --- a/compiler/utils/arm/assembler_arm_vixl.h +++ b/compiler/utils/arm/assembler_arm_vixl.h @@ -54,6 +54,77 @@ class ArmVIXLMacroAssembler FINAL : public vixl32::MacroAssembler { void CompareAndBranchIfNonZero(vixl32::Register rn, vixl32::Label* label, bool is_far_target = true); + + // In T32 some of the instructions (add, mov, etc) outside an IT block + // have only 32-bit encodings. But there are 16-bit flag setting + // versions of these instructions (adds, movs, etc). In most of the + // cases in ART we don't care if the instructions keep flags or not; + // thus we can benefit from smaller code size. + // VIXL will never generate flag setting versions (for example, adds + // for Add macro instruction) unless vixl32::DontCare option is + // explicitly specified. That's why we introduce wrappers to use + // DontCare option by default. +#define WITH_FLAGS_DONT_CARE_RD_RN_OP(func_name) \ + void (func_name)(vixl32::Register rd, vixl32::Register rn, const vixl32::Operand& operand) { \ + MacroAssembler::func_name(vixl32::DontCare, rd, rn, operand); \ + } \ + using MacroAssembler::func_name + + WITH_FLAGS_DONT_CARE_RD_RN_OP(Adc); + WITH_FLAGS_DONT_CARE_RD_RN_OP(Sub); + WITH_FLAGS_DONT_CARE_RD_RN_OP(Sbc); + WITH_FLAGS_DONT_CARE_RD_RN_OP(Rsb); + WITH_FLAGS_DONT_CARE_RD_RN_OP(Rsc); + + WITH_FLAGS_DONT_CARE_RD_RN_OP(Eor); + WITH_FLAGS_DONT_CARE_RD_RN_OP(Orr); + WITH_FLAGS_DONT_CARE_RD_RN_OP(Orn); + WITH_FLAGS_DONT_CARE_RD_RN_OP(And); + WITH_FLAGS_DONT_CARE_RD_RN_OP(Bic); + + WITH_FLAGS_DONT_CARE_RD_RN_OP(Asr); + WITH_FLAGS_DONT_CARE_RD_RN_OP(Lsr); + WITH_FLAGS_DONT_CARE_RD_RN_OP(Lsl); + WITH_FLAGS_DONT_CARE_RD_RN_OP(Ror); + +#undef WITH_FLAGS_DONT_CARE_RD_RN_OP + +#define WITH_FLAGS_DONT_CARE_RD_OP(func_name) \ + void (func_name)(vixl32::Register rd, const vixl32::Operand& operand) { \ + MacroAssembler::func_name(vixl32::DontCare, rd, operand); \ + } \ + using MacroAssembler::func_name + + WITH_FLAGS_DONT_CARE_RD_OP(Mvn); + WITH_FLAGS_DONT_CARE_RD_OP(Mov); + +#undef WITH_FLAGS_DONT_CARE_RD_OP + + // The following two functions don't fall into above categories. Overload them separately. + void Rrx(vixl32::Register rd, vixl32::Register rn) { + MacroAssembler::Rrx(vixl32::DontCare, rd, rn); + } + using MacroAssembler::Rrx; + + void Mul(vixl32::Register rd, vixl32::Register rn, vixl32::Register rm) { + MacroAssembler::Mul(vixl32::DontCare, rd, rn, rm); + } + using MacroAssembler::Mul; + + // TODO: Remove when MacroAssembler::Add(FlagsUpdate, Condition, Register, Register, Operand) + // makes the right decision about 16-bit encodings. + void Add(vixl32::Register rd, vixl32::Register rn, const vixl32::Operand& operand) { + if (rd.Is(rn)) { + MacroAssembler::Add(rd, rn, operand); + } else { + MacroAssembler::Add(vixl32::DontCare, rd, rn, operand); + } + } + using MacroAssembler::Add; + + // These interfaces try to use 16-bit T2 encoding of B instruction. + void B(vixl32::Label* label); + void B(vixl32::Condition cond, vixl32::Label* label); }; class ArmVIXLAssembler FINAL : public Assembler { diff --git a/test/538-checker-embed-constants/src/Main.java b/test/538-checker-embed-constants/src/Main.java index 0329e63ffd..4f34ec90ea 100644 --- a/test/538-checker-embed-constants/src/Main.java +++ b/test/538-checker-embed-constants/src/Main.java @@ -308,7 +308,7 @@ public class Main { } /// CHECK-START-ARM: long Main.shl32(long) disassembly (after) - /// CHECK-DAG: mov {{r\d+}}, {{r\d+}} + /// CHECK-DAG: mov{{s?}} {{r\d+}}, {{r\d+}} /// CHECK-DAG: mov{{s?|\.w}} {{r\d+}}, #0 /// CHECK-START-ARM: long Main.shl32(long) disassembly (after) @@ -377,7 +377,7 @@ public class Main { /// CHECK-START-ARM: long Main.shr32(long) disassembly (after) /// CHECK-DAG: asr{{s?|\.w}} {{r\d+}}, <<high:r\d+>>, #31 - /// CHECK-DAG: mov {{r\d+}}, <<high>> + /// CHECK-DAG: mov{{s?}} {{r\d+}}, <<high>> /// CHECK-START-ARM: long Main.shr32(long) disassembly (after) /// CHECK-NOT: asr{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}} @@ -445,7 +445,7 @@ public class Main { } /// CHECK-START-ARM: long Main.ushr32(long) disassembly (after) - /// CHECK-DAG: mov {{r\d+}}, {{r\d+}} + /// CHECK-DAG: mov{{s?}} {{r\d+}}, {{r\d+}} /// CHECK-DAG: mov{{s?|\.w}} {{r\d+}}, #0 /// CHECK-START-ARM: long Main.ushr32(long) disassembly (after) |