Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backend: reserve registers not preserved across function calls in RISC-V #2853

Merged
merged 2 commits into from
Jul 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions tests/backend/riscv/test_preallocated.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from xdsl.backend.riscv.register_allocation import gather_allocated
from xdsl.builder import Builder
from xdsl.dialects import riscv, riscv_func
from xdsl.dialects.builtin import SymbolRefAttr


def test_gather_allocated():
Expand Down Expand Up @@ -56,3 +57,17 @@ def multiple_preallocated_body() -> None:
)

assert len(pa_regs) == 2

@Builder.implicit_region
def func_call_preallocated_body() -> None:
reg1 = riscv.IntRegisterType.unallocated()
v1 = riscv.GetRegisterOp(reg1).res
v2 = riscv.GetRegisterOp(riscv.Registers.S0).res
riscv_func.CallOp(SymbolRefAttr("hello"), (v1, v2), ())

pa_regs = gather_allocated(
riscv_func.FuncOp("foo", func_call_preallocated_body, ((), ()))
)

assert len(pa_regs) == 36
assert riscv.Registers.S0 in pa_regs
11 changes: 10 additions & 1 deletion xdsl/backend/riscv/register_allocation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from ordered_set import OrderedSet

from xdsl.backend.riscv.register_queue import RegisterQueue
from xdsl.dialects import riscv_func, riscv_scf, riscv_snitch
from xdsl.dialects import riscv, riscv_func, riscv_scf, riscv_snitch
from xdsl.dialects.riscv import (
FloatRegisterType,
IntRegisterType,
Expand All @@ -26,6 +26,15 @@ def gather_allocated(func: riscv_func.FuncOp) -> set[RISCVRegisterType]:
if not isinstance(op, RISCVAsmOperation):
continue

if isinstance(op, riscv_func.CallOp):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably worth putting a command here as to why this is done for whoever is going to implement call ABI to find and remove this.

# These registers are not guaranteed to hold the same values when the callee
# returns, according to the RISC-V calling convention.
# https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf
allocated.update(riscv.Registers.A)
allocated.update(riscv.Registers.T)
allocated.update(riscv.Registers.FA)
allocated.update(riscv.Registers.FT)

for param in chain(op.operands, op.results):
if isinstance(param.type, RISCVRegisterType) and param.type.is_allocated:
if not param.type.register_name.startswith("j"):
Expand Down
Loading