summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2024-06-18 13:11:19 +0000
committer VladimĂ­r Marko <vmarko@google.com> 2024-06-18 14:43:04 +0000
commite00748b45a3ed7aa68b7379e2adde1dc1a435c46 (patch)
treefb6426d4676c3de5719da8a69c8fa463534df4ea
parent4e8443e27655d8d23f7e27eed91de0a259c9912a (diff)
riscv64: Implement `LongCondCBranch`.
Test: m test-art-host-gtest Bug: 328561342 Change-Id: I84f643e6796369f461473661b561973ba7e7283a
-rw-r--r--compiler/utils/riscv64/assembler_riscv64.cc57
-rw-r--r--compiler/utils/riscv64/assembler_riscv64.h1
-rw-r--r--compiler/utils/riscv64/assembler_riscv64_test.cc24
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"),