diff options
author | 2017-05-10 12:46:57 +0100 | |
---|---|---|
committer | 2017-05-24 11:35:08 +0100 | |
commit | fd522533bf8cea5a8334f233922c39536b1a3d29 (patch) | |
tree | 8394d517d43c6b0a78b053ac7fe9f7bc61f387fa | |
parent | a4bf3c33e501758fa8e707ef30f9ee67ea20511e (diff) |
ARM: Specify if some branches go to far targets
Also avoids some branches to branches.
Test: m test-art-target
Change-Id: I839bcaa6ba5fba7aaa8474bee5532366ac0cc4ac
-rw-r--r-- | compiler/optimizing/code_generator_arm_vixl.cc | 38 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm_vixl.h | 3 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_arm.cc | 7 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_arm_vixl.cc | 9 |
4 files changed, 33 insertions, 24 deletions
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index 34821f83cd..1f8e1efd5e 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -2139,7 +2139,8 @@ static void GenerateEqualLong(HCondition* cond, CodeGeneratorARMVIXL* codegen) { static void GenerateLongComparesAndJumps(HCondition* cond, vixl32::Label* true_label, vixl32::Label* false_label, - CodeGeneratorARMVIXL* codegen) { + CodeGeneratorARMVIXL* codegen, + bool is_far_target = true) { LocationSummary* locations = cond->GetLocations(); Location left = locations->InAt(0); Location right = locations->InAt(1); @@ -2190,12 +2191,12 @@ static void GenerateLongComparesAndJumps(HCondition* cond, __ Cmp(left_high, val_high); if (if_cond == kCondNE) { - __ B(ARMCondition(true_high_cond), true_label); + __ B(ARMCondition(true_high_cond), true_label, is_far_target); } else if (if_cond == kCondEQ) { - __ B(ARMCondition(false_high_cond), false_label); + __ B(ARMCondition(false_high_cond), false_label, is_far_target); } else { - __ B(ARMCondition(true_high_cond), true_label); - __ B(ARMCondition(false_high_cond), false_label); + __ B(ARMCondition(true_high_cond), true_label, is_far_target); + __ B(ARMCondition(false_high_cond), false_label, is_far_target); } // Must be equal high, so compare the lows. __ Cmp(left_low, val_low); @@ -2205,19 +2206,19 @@ static void GenerateLongComparesAndJumps(HCondition* cond, __ Cmp(left_high, right_high); if (if_cond == kCondNE) { - __ B(ARMCondition(true_high_cond), true_label); + __ B(ARMCondition(true_high_cond), true_label, is_far_target); } else if (if_cond == kCondEQ) { - __ B(ARMCondition(false_high_cond), false_label); + __ B(ARMCondition(false_high_cond), false_label, is_far_target); } else { - __ B(ARMCondition(true_high_cond), true_label); - __ B(ARMCondition(false_high_cond), false_label); + __ B(ARMCondition(true_high_cond), true_label, is_far_target); + __ B(ARMCondition(false_high_cond), false_label, is_far_target); } // Must be equal high, so compare the lows. __ Cmp(left_low, right_low); } // The last comparison might be unsigned. // TODO: optimize cases where this is always true/false - __ B(final_condition, true_label); + __ B(final_condition, true_label, is_far_target); } static void GenerateConditionLong(HCondition* cond, CodeGeneratorARMVIXL* codegen) { @@ -2292,7 +2293,7 @@ static void GenerateConditionLong(HCondition* cond, CodeGeneratorARMVIXL* codege vixl32::Label* const final_label = codegen->GetFinalLabel(cond, &done_label); vixl32::Label true_label, false_label; - GenerateLongComparesAndJumps(cond, &true_label, &false_label, codegen); + GenerateLongComparesAndJumps(cond, &true_label, &false_label, codegen, /* is_far_target */ false); // False case: result = 0. __ Bind(&false_label); @@ -2957,7 +2958,8 @@ void InstructionCodeGeneratorARMVIXL::VisitExit(HExit* exit ATTRIBUTE_UNUSED) { void InstructionCodeGeneratorARMVIXL::GenerateCompareTestAndBranch(HCondition* condition, vixl32::Label* true_target_in, - vixl32::Label* false_target_in) { + vixl32::Label* false_target_in, + bool is_far_target) { if (CanGenerateTest(condition, codegen_->GetAssembler())) { vixl32::Label* non_fallthrough_target; bool invert; @@ -2973,7 +2975,7 @@ void InstructionCodeGeneratorARMVIXL::GenerateCompareTestAndBranch(HCondition* c const auto cond = GenerateTest(condition, invert, codegen_); - __ B(cond.first, non_fallthrough_target); + __ B(cond.first, non_fallthrough_target, is_far_target); if (false_target_in != nullptr && false_target_in != non_fallthrough_target) { __ B(false_target_in); @@ -2989,7 +2991,7 @@ void InstructionCodeGeneratorARMVIXL::GenerateCompareTestAndBranch(HCondition* c vixl32::Label* false_target = (false_target_in == nullptr) ? &fallthrough : false_target_in; DCHECK_EQ(condition->InputAt(0)->GetType(), Primitive::kPrimLong); - GenerateLongComparesAndJumps(condition, true_target, false_target, codegen_); + GenerateLongComparesAndJumps(condition, true_target, false_target, codegen_, is_far_target); if (false_target != &fallthrough) { __ B(false_target); @@ -3057,7 +3059,7 @@ void InstructionCodeGeneratorARMVIXL::GenerateTestAndBranch(HInstruction* instru // the HCondition, generate the comparison directly. Primitive::Type type = condition->InputAt(0)->GetType(); if (type == Primitive::kPrimLong || Primitive::IsFloatingPointType(type)) { - GenerateCompareTestAndBranch(condition, true_target, false_target); + GenerateCompareTestAndBranch(condition, true_target, false_target, far_target); return; } @@ -3076,14 +3078,14 @@ void InstructionCodeGeneratorARMVIXL::GenerateTestAndBranch(HInstruction* instru if (right.IsImmediate() && right.GetImmediate() == 0 && (arm_cond.Is(ne) || arm_cond.Is(eq))) { if (arm_cond.Is(eq)) { - __ CompareAndBranchIfZero(left, non_fallthrough_target); + __ CompareAndBranchIfZero(left, non_fallthrough_target, far_target); } else { DCHECK(arm_cond.Is(ne)); - __ CompareAndBranchIfNonZero(left, non_fallthrough_target); + __ CompareAndBranchIfNonZero(left, non_fallthrough_target, far_target); } } else { __ Cmp(left, right); - __ B(arm_cond, non_fallthrough_target); + __ B(arm_cond, non_fallthrough_target, far_target); } } diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h index 91f7524c8e..91e9a3edc4 100644 --- a/compiler/optimizing/code_generator_arm_vixl.h +++ b/compiler/optimizing/code_generator_arm_vixl.h @@ -400,7 +400,8 @@ class InstructionCodeGeneratorARMVIXL : public InstructionCodeGenerator { bool far_target = true); void GenerateCompareTestAndBranch(HCondition* condition, vixl::aarch32::Label* true_target, - vixl::aarch32::Label* false_target); + vixl::aarch32::Label* false_target, + bool is_far_target = true); void DivRemOneOrMinusOne(HBinaryOperation* instruction); void DivRemByPowerOfTwo(HBinaryOperation* instruction); void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction); diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc index e8a62aafae..9803c9a0e9 100644 --- a/compiler/optimizing/intrinsics_arm.cc +++ b/compiler/optimizing/intrinsics_arm.cc @@ -2758,12 +2758,15 @@ void IntrinsicCodeGeneratorARM::VisitThreadInterrupted(HInvoke* invoke) { int32_t offset = Thread::InterruptedOffset<kArmPointerSize>().Int32Value(); __ LoadFromOffset(kLoadWord, out, TR, offset); Label done; - __ CompareAndBranchIfZero(out, &done); + Label* const final_label = codegen_->GetFinalLabel(invoke, &done); + __ CompareAndBranchIfZero(out, final_label); __ dmb(ISH); __ LoadImmediate(IP, 0); __ StoreToOffset(kStoreWord, IP, TR, offset); __ dmb(ISH); - __ Bind(&done); + if (done.IsLinked()) { + __ Bind(&done); + } } UNIMPLEMENTED_INTRINSIC(ARM, MathMinDoubleDouble) diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc index ce3ba52b34..1a33b0ee01 100644 --- a/compiler/optimizing/intrinsics_arm_vixl.cc +++ b/compiler/optimizing/intrinsics_arm_vixl.cc @@ -3127,7 +3127,7 @@ void IntrinsicCodeGeneratorARMVIXL::VisitIntegerValueOf(HInvoke* invoke) { __ Add(out, in, -info.low); __ Cmp(out, info.high - info.low + 1); vixl32::Label allocate, done; - __ B(hs, &allocate); + __ B(hs, &allocate, /* is_far_target */ false); // If the value is within the bounds, load the j.l.Integer directly from the array. uint32_t data_offset = mirror::Array::DataOffset(kHeapReferenceSize).Uint32Value(); uint32_t address = dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(info.cache)); @@ -3164,12 +3164,15 @@ void IntrinsicCodeGeneratorARMVIXL::VisitThreadInterrupted(HInvoke* invoke) { UseScratchRegisterScope temps(assembler->GetVIXLAssembler()); vixl32::Register temp = temps.Acquire(); vixl32::Label done; - __ CompareAndBranchIfZero(out, &done, /* far_target */ false); + vixl32::Label* const final_label = codegen_->GetFinalLabel(invoke, &done); + __ CompareAndBranchIfZero(out, final_label, /* far_target */ false); __ Dmb(vixl32::ISH); __ Mov(temp, 0); assembler->StoreToOffset(kStoreWord, temp, tr, offset); __ Dmb(vixl32::ISH); - __ Bind(&done); + if (done.IsReferenced()) { + __ Bind(&done); + } } UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathRoundDouble) // Could be done by changing rounding mode, maybe? |