summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Artemev <roman.artemev@syntacore.com>2024-04-18 13:40:13 +0300
committerVladimĂ­r Marko <vmarko@google.com>2024-04-18 14:55:03 +0000
commitb1eb2853b3e6349bac4f2cd5c2ee47458198399d (patch)
treeeb16c165abb4b9fe3de78f9c57d748c60159bc6d
parentc7bc9f58348dff223807c4828f99b6930b07ad3c (diff)
downloadart-b1eb2853b3e6349bac4f2cd5c2ee47458198399d.tar.gz
riscv64: Reorganize list of branches bound to the same label
Move next link from code buffer to branch object This change is required to properly support compressed branches Test: m test-art-host-gtest Test: run-gtests.sh Test: testrunner.py --target --optimizing Bug: 328561342 Change-Id: Icbf61e9ec758b0116358c29bf93d27878a9c7753
-rw-r--r--compiler/utils/riscv64/assembler_riscv64.cc36
-rw-r--r--compiler/utils/riscv64/assembler_riscv64.h10
2 files changed, 30 insertions, 16 deletions
diff --git a/compiler/utils/riscv64/assembler_riscv64.cc b/compiler/utils/riscv64/assembler_riscv64.cc
index a2df6d287d..9cd4a45f0c 100644
--- a/compiler/utils/riscv64/assembler_riscv64.cc
+++ b/compiler/utils/riscv64/assembler_riscv64.cc
@@ -6680,7 +6680,8 @@ Riscv64Assembler::Branch::Branch(uint32_t location, uint32_t target, XRegister r
lhs_reg_(rd),
rhs_reg_(Zero),
freg_(kNoFRegister),
- condition_(kUncond) {
+ condition_(kUncond),
+ next_branch_id_(0u) {
InitializeType(
(rd != Zero ? (is_bare ? kBareCall : kCall) : (is_bare ? kBareUncondBranch : kUncondBranch)));
}
@@ -6697,7 +6698,8 @@ Riscv64Assembler::Branch::Branch(uint32_t location,
lhs_reg_(lhs_reg),
rhs_reg_(rhs_reg),
freg_(kNoFRegister),
- condition_(condition) {
+ condition_(condition),
+ next_branch_id_(0u) {
DCHECK_NE(condition, kUncond);
DCHECK(!IsNop(condition, lhs_reg, rhs_reg));
DCHECK(!IsUncond(condition, lhs_reg, rhs_reg));
@@ -6714,7 +6716,8 @@ Riscv64Assembler::Branch::Branch(uint32_t location,
lhs_reg_(rd),
rhs_reg_(Zero),
freg_(kNoFRegister),
- condition_(kUncond) {
+ condition_(kUncond),
+ next_branch_id_(0u) {
CHECK_NE(rd , Zero);
InitializeType(label_or_literal_type);
}
@@ -6729,7 +6732,8 @@ Riscv64Assembler::Branch::Branch(uint32_t location,
lhs_reg_(Zero),
rhs_reg_(Zero),
freg_(rd),
- condition_(kUncond) {
+ condition_(kUncond),
+ next_branch_id_(0u) {
InitializeType(literal_type);
}
@@ -6790,6 +6794,8 @@ uint32_t Riscv64Assembler::Branch::GetOldEndLocation() const {
return GetOldLocation() + GetOldLength();
}
+uint32_t Riscv64Assembler::Branch::NextBranchId() const { return next_branch_id_; }
+
bool Riscv64Assembler::Branch::IsBare() const {
switch (type_) {
case kBareUncondBranch:
@@ -6904,6 +6910,10 @@ int32_t Riscv64Assembler::Branch::GetOffset() const {
return offset;
}
+void Riscv64Assembler::Branch::LinkToList(uint32_t next_branch_id) {
+ next_branch_id_ = next_branch_id;
+}
+
void Riscv64Assembler::EmitBcond(BranchCondition cond,
XRegister rs,
XRegister rt,
@@ -7023,16 +7033,16 @@ void Riscv64Assembler::EmitBranches() {
}
void Riscv64Assembler::FinalizeLabeledBranch(Riscv64Label* label) {
- DCHECK_ALIGNED(branches_.back().GetLength(), sizeof(uint32_t));
- uint32_t length = branches_.back().GetLength() / sizeof(uint32_t);
+ Branch& this_branch = branches_.back();
+ DCHECK_ALIGNED(this_branch.GetLength(), sizeof(uint32_t));
+ uint32_t length = this_branch.GetLength() / sizeof(uint32_t);
ScopedNoCInstructions no_compression(this);
if (!label->IsBound()) {
// Branch forward (to a following label), distance is unknown.
// The first branch forward will contain 0, serving as the terminator of
// the list of forward-reaching branches.
- Emit32(label->position_);
- length--;
+ this_branch.LinkToList(label->position_);
// Now make the label object point to this branch
// (this forms a linked list of branches preceding this label).
uint32_t branch_id = branches_.size() - 1;
@@ -7097,14 +7107,8 @@ void Riscv64Assembler::Bind(Riscv64Label* label) {
uint32_t branch_id = label->Position();
Branch* branch = GetBranch(branch_id);
branch->Resolve(bound_pc);
-
- uint32_t branch_location = branch->GetLocation();
- // Extract the location of the previous branch in the list (walking the list backwards;
- // the previous branch ID was stored in the space reserved for this branch).
- uint32_t prev = buffer_.Load<uint32_t>(branch_location);
-
- // On to the previous branch in the list...
- label->position_ = prev;
+ // On to the next branch in the list...
+ label->position_ = branch->NextBranchId();
}
// Now make the label object contain its own location (relative to the end of the preceding
diff --git a/compiler/utils/riscv64/assembler_riscv64.h b/compiler/utils/riscv64/assembler_riscv64.h
index fc5d3f0684..4f561dc1a6 100644
--- a/compiler/utils/riscv64/assembler_riscv64.h
+++ b/compiler/utils/riscv64/assembler_riscv64.h
@@ -2030,6 +2030,8 @@ class Riscv64Assembler final : public Assembler {
bool IsBare() const;
bool IsResolved() const;
+ uint32_t NextBranchId() const;
+
// Returns the bit size of the signed offset that the branch instruction can handle.
OffsetBits GetOffsetSize() const;
@@ -2057,6 +2059,9 @@ class Riscv64Assembler final : public Assembler {
// Calculates and returns the offset ready for encoding in the branch instruction(s).
int32_t GetOffset() const;
+ // Link with the next branch
+ void LinkToList(uint32_t next_branch_id);
+
private:
// Completes branch construction by determining and recording its type.
void InitializeType(Type initial_type);
@@ -2075,6 +2080,11 @@ class Riscv64Assembler final : public Assembler {
Type type_; // Current type of the branch.
Type old_type_; // Initial type of the branch.
+
+ // Id of the next branch bound to the same label in singly-linked zero-terminated list
+ // NOTE: encoded the same way as a position in a linked Label (id + sizeof(void*))
+ // Label itself is used to hold the 'head' of this list
+ uint32_t next_branch_id_;
};
// Branch and literal fixup.