diff options
| author | 2024-06-18 13:11:19 +0000 | |
|---|---|---|
| committer | 2024-06-18 14:43:04 +0000 | |
| commit | e00748b45a3ed7aa68b7379e2adde1dc1a435c46 (patch) | |
| tree | fb6426d4676c3de5719da8a69c8fa463534df4ea | |
| parent | 4e8443e27655d8d23f7e27eed91de0a259c9912a (diff) | |
riscv64: Implement `LongCondCBranch`.
Test: m test-art-host-gtest
Bug: 328561342
Change-Id: I84f643e6796369f461473661b561973ba7e7283a
| -rw-r--r-- | compiler/utils/riscv64/assembler_riscv64.cc | 57 | ||||
| -rw-r--r-- | compiler/utils/riscv64/assembler_riscv64.h | 1 | ||||
| -rw-r--r-- | compiler/utils/riscv64/assembler_riscv64_test.cc | 24 |
3 files changed, 41 insertions, 41 deletions
diff --git a/compiler/utils/riscv64/assembler_riscv64.cc b/compiler/utils/riscv64/assembler_riscv64.cc index 9915030cf5..4309601d21 100644 --- a/compiler/utils/riscv64/assembler_riscv64.cc +++ b/compiler/utils/riscv64/assembler_riscv64.cc @@ -6574,6 +6574,7 @@ const Riscv64Assembler::Branch::BranchInfo Riscv64Assembler::Branch::branch_info {8, 4, Riscv64Assembler::Branch::kOffset21}, // kCondBranch21 // Long branches. + {10, 2, Riscv64Assembler::Branch::kOffset32}, // kLongCondCBranch {12, 4, Riscv64Assembler::Branch::kOffset32}, // kLongCondBranch {8, 0, Riscv64Assembler::Branch::kOffset32}, // kLongUncondBranch {8, 0, Riscv64Assembler::Branch::kOffset32}, // kLongCall @@ -6608,7 +6609,7 @@ void Riscv64Assembler::Branch::InitializeType(Type initial_type) { CHECK(IsCompressableCondition()); if (condition_ != kUncond) { InitShortOrLong( - offset_size_needed, {kCondCBranch, kCondBranch, kCondCBranch21, kLongCondBranch}); + offset_size_needed, {kCondCBranch, kCondBranch, kCondCBranch21, kLongCondCBranch}); break; } FALLTHROUGH_INTENDED; @@ -6707,6 +6708,7 @@ bool Riscv64Assembler::Branch::IsCompressed(Type type) { case kBareCondCBranch: case kBareUncondCBranch: case kCondCBranch21: + case kLongCondCBranch: return true; default: return false; @@ -6950,12 +6952,10 @@ uint32_t Riscv64Assembler::Branch::PromoteIfNeeded() { return 0u; } - Type cond21Type = old_type == kCondCBranch ? kCondCBranch21 : kCondBranch21; - if (compression_allowed_ && cond21Type == kCondBranch21 && IsCompressableCondition()) { - // If this branch was promoted from compressed one on initialization stage - // it could be promoted back to compressed if possible - cond21Type = kCondCBranch21; - } + Type cond21Type = + (compression_allowed_ && IsCompressableCondition()) ? kCondCBranch21 : kCondBranch21; + Type longCondType = + (compression_allowed_ && IsCompressableCondition()) ? kLongCondCBranch : kLongCondBranch; // The offset remains the same for `kCond[C]Branch21` for forward branches. DCHECK_EQ(branch_info_[cond21Type].length - branch_info_[cond21Type].pc_offset, @@ -6964,7 +6964,7 @@ uint32_t Riscv64Assembler::Branch::PromoteIfNeeded() { // Calculate the needed size for kCond[C]Branch21. needed_size = GetOffsetSizeNeeded(location_ + branch_info_[cond21Type].pc_offset, target_); } - type_ = (needed_size <= branch_info_[cond21Type].offset_size) ? cond21Type : kLongCondBranch; + type_ = (needed_size <= branch_info_[cond21Type].offset_size) ? cond21Type : longCondType; break; } case kUncondBranch: @@ -6979,10 +6979,15 @@ uint32_t Riscv64Assembler::Branch::PromoteIfNeeded() { } type_ = kLongCall; break; - // Medium branch (can be promoted to long). - case kCondCBranch21: - DCHECK(IsCompressableCondition()); - FALLTHROUGH_INTENDED; + // Medium branches (can be promoted to long). + case kCondCBranch21: { + OffsetBits needed_size = GetOffsetSizeNeeded(GetOffsetLocation(), target_); + if (needed_size <= GetOffsetSize()) { + return 0u; + } + type_ = kLongCondCBranch; + break; + } case kCondBranch21: { OffsetBits needed_size = GetOffsetSizeNeeded(GetOffsetLocation(), target_); if (needed_size <= GetOffsetSize()) { @@ -7063,6 +7068,18 @@ void Riscv64Assembler::EmitBranch(Riscv64Assembler::Branch* branch) { next(short_offset); }; + auto emit_cbcondz_opposite = [&]() { + DCHECK(branch->IsCompressableCondition()); + ScopedUseCInstructions use_compression(this); + if (condition == kCondNE) { + DCHECK_EQ(Branch::OppositeCondition(condition), kCondEQ); + CBeqz(branch->GetNonZeroRegister(), branch->GetLength()); + } else { + DCHECK_EQ(Branch::OppositeCondition(condition), kCondNE); + CBnez(branch->GetNonZeroRegister(), branch->GetLength()); + } + }; + switch (branch->GetType()) { // Compressed branches case Branch::kCondCBranch: @@ -7109,22 +7126,16 @@ void Riscv64Assembler::EmitBranch(Riscv64Assembler::Branch* branch) { J(offset); break; case Branch::kCondCBranch21: { - DCHECK(branch->IsCompressableCondition()); - { - ScopedUseCInstructions use_compression(this); - if (condition == kCondNE) { - DCHECK_EQ(Branch::OppositeCondition(condition), kCondEQ); - CBeqz(branch->GetNonZeroRegister(), branch->GetLength()); - } else { - DCHECK_EQ(Branch::OppositeCondition(condition), kCondNE); - CBnez(branch->GetNonZeroRegister(), branch->GetLength()); - } - } + emit_cbcondz_opposite(); CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); J(offset); break; } // Long branches. + case Branch::kLongCondCBranch: + emit_cbcondz_opposite(); + emit_auipc_and_next(TMP, [&](int32_t short_offset) { Jalr(Zero, TMP, short_offset); }); + break; case Branch::kLongCondBranch: EmitBcond(Branch::OppositeCondition(condition), lhs, rhs, branch->GetLength()); FALLTHROUGH_INTENDED; diff --git a/compiler/utils/riscv64/assembler_riscv64.h b/compiler/utils/riscv64/assembler_riscv64.h index 798141f674..c28764b64e 100644 --- a/compiler/utils/riscv64/assembler_riscv64.h +++ b/compiler/utils/riscv64/assembler_riscv64.h @@ -1965,6 +1965,7 @@ class Riscv64Assembler final : public Assembler { kCondBranch21, // Long branches. + kLongCondCBranch, kLongCondBranch, kLongUncondBranch, kLongCall, diff --git a/compiler/utils/riscv64/assembler_riscv64_test.cc b/compiler/utils/riscv64/assembler_riscv64_test.cc index c487a73577..3169f75e0f 100644 --- a/compiler/utils/riscv64/assembler_riscv64_test.cc +++ b/compiler/utils/riscv64/assembler_riscv64_test.cc @@ -8750,9 +8750,7 @@ TEST_F(AssemblerRISCV64Test, BcondBackward5KiB_WithoutC) { TestBcondBackward("BcondBackward5KiB_WithoutC", 5 * KB, "1", GetPrintBcondOppositeAndJ("2")); } -// Disabled: We do not implement `kLongCondCBranch` (c.b<cond>z + tail), -// so there is a mismatch with clang output. -TEST_F(AssemblerRISCV64Test, DISABLED_BcondForward2MiB) { +TEST_F(AssemblerRISCV64Test, BcondForward2MiB) { TestBcondForward("BcondForward2MiB", 2 * MB, "1", GetPrintBcondOppositeAndTail("2", "3")); } @@ -8762,9 +8760,7 @@ TEST_F(AssemblerRISCV64Test, BcondForward2MiB_WithoutC) { "BcondForward2MiB_WithoutC", 2 * MB, "1", GetPrintBcondOppositeAndTail("2", "3")); } -// Disabled: We do not implement `kLongCondCBranch` (c.b<cond>z + tail), -// so there is a mismatch with clang output. -TEST_F(AssemblerRISCV64Test, DISABLED_BcondBackward2MiB) { +TEST_F(AssemblerRISCV64Test, BcondBackward2MiB) { TestBcondBackward("BcondBackward2MiB", 2 * MB, "1", GetPrintBcondOppositeAndTail("2", "3")); } @@ -9202,9 +9198,7 @@ TEST_F(AssemblerRISCV64Test, BeqA0A1MaxOffset21Backward_WithoutC) { "1"); } -// Disabled: We do not implement `kLongCondCBranch` (c.b<cond>z + tail), -// so there is a mismatch with clang output. -TEST_F(AssemblerRISCV64Test, DISABLED_BeqA0ZeroOverMaxOffset21Forward) { +TEST_F(AssemblerRISCV64Test, BeqA0ZeroOverMaxOffset21Forward) { TestBeqzA0Forward("BeqA0ZeroOverMaxOffset21Forward", MaxOffset21ForwardDistance() - /*J*/ 4u + /*Exceed max*/ 2u, GetPrintBcondOppositeAndTail("2", "3"), @@ -9219,9 +9213,7 @@ TEST_F(AssemblerRISCV64Test, BeqA0ZeroOverMaxOffset21Forward_WithoutC) { "1"); } -// Disabled: We do not implement `kLongCondCBranch` (c.b<cond>z + tail), -// so there is a mismatch with clang output. -TEST_F(AssemblerRISCV64Test, DISABLED_BneA0ZeroOverMaxOffset21Forward) { +TEST_F(AssemblerRISCV64Test, BneA0ZeroOverMaxOffset21Forward) { TestBnezA0Forward("BneA0ZeroOverMaxOffset21Forward", MaxOffset21ForwardDistance() - /*J*/ 4u + /*Exceed max*/ 2u, GetPrintBcondOppositeAndTail("2", "3"), @@ -9251,9 +9243,7 @@ TEST_F(AssemblerRISCV64Test, BeqA0A1OverMaxOffset21Forward_WithoutC) { "1"); } -// Disabled: We do not implement `kLongCondCBranch` (c.b<cond>z + tail), -// so there is a mismatch with clang output. -TEST_F(AssemblerRISCV64Test, DISABLED_BeqA0ZeroOverMaxOffset21Backward) { +TEST_F(AssemblerRISCV64Test, BeqA0ZeroOverMaxOffset21Backward) { TestBeqzA0Backward("BeqA0ZeroOverMaxOffset21Backward", MaxOffset21BackwardDistance() - /*C.BNEZ*/ 2u + /*Exceed max*/ 2u, GetPrintBcondOppositeAndTail("2", "3"), @@ -9268,9 +9258,7 @@ TEST_F(AssemblerRISCV64Test, BeqA0ZeroOverMaxOffset21Backward_WithoutC) { "1"); } -// Disabled: We do not implement `kLongCondCBranch` (c.b<cond>z + tail), -// so there is a mismatch with clang output. -TEST_F(AssemblerRISCV64Test, DISABLED_BneA0ZeroOverMaxOffset21Backward) { +TEST_F(AssemblerRISCV64Test, BneA0ZeroOverMaxOffset21Backward) { TestBnezA0Backward("BneA0ZeroOverMaxOffset21Backward", MaxOffset21BackwardDistance() - /*C.BEQZ*/ 2u + /*Exceed max*/ 2u, GetPrintBcondOppositeAndTail("2", "3"), |