ret vs. jr ra

2,142 views
Skip to first unread message

Urs Thuermann

unread,
Apr 29, 2021, 8:15:10 AM4/29/21
to RISC-V SW Dev
Why does GCC sometimes emit the return from a function as "ret" and
sometimes as "jr ra"? Both are the same so it's confusing that GCC
doesn't use always the same.

It seems "jr ra" is used if it's part of a function epilogue that
includes restoring of registers and/or stack cleanup, and "ret" if
it's the only instruction of that epilogue:

$ printf "foo(){} bar(){x();}" | riscv64-linux-gnu-gcc -w -O -S -xc - -o-
.file ""
.option pic
.text
.align 1
.globl foo
.type foo, @function
foo:
ret
.size foo, .-foo
.align 1
.globl bar
.type bar, @function
bar:
addi sp,sp,-16
sd ra,8(sp)
call x@plt
ld ra,8(sp)
addi sp,sp,16
jr ra
.size bar, .-bar
.ident "GCC: (Debian 8.3.0-2) 8.3.0"

But I wonder if that makes much sense.

urs

Andrew Waterman

unread,
Apr 29, 2021, 8:36:59 AM4/29/21
to Urs Thuermann, RISC-V SW Dev
GCC has the concept of a "simple" return, used by functions that don't need an epilogue.  In RISC-V, the idiomatic way of expressing that concept is "ret".

But, in the general case, GCC can use any register as the target for a procedure exit, hence the "jr xx".  Obviously, "xx" will almost always be "ra", except for indirect sibcalls.  So usually these things end up assembling to the same thing, even though they're expressed differently.

Clearly, we could add extra code to one path or the other to make them look the same, but IMO that's just extra baggage that serves no functional purpose.  I'm all for aesthetic improvements when they're Pareto-superior, but this isn't such a case.

--
You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+un...@groups.riscv.org.
To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/ygfa6phffty.fsf%40tehran.isnogud.escape.de.

Urs Thuermann

unread,
Apr 29, 2021, 9:35:06 AM4/29/21
to RISC-V SW Dev
Andrew Waterman <wate...@eecs.berkeley.edu> writes:

> GCC has the concept of a "simple" return, used by functions that don't need
> an epilogue. In RISC-V, the idiomatic way of expressing that concept is
> "ret".
>
> But, in the general case, GCC can use any register as the target for a
> procedure exit, hence the "jr xx". Obviously, "xx" will almost always be
> "ra", except for indirect sibcalls. So usually these things end up
> assembling to the same thing, even though they're expressed differently.

Thanks for clarifying. When I began reading GCC RISC-V code I was
surprised by that and I thought, my suggested change would be easier
for novices (which I'm also still are concerning some RISC-V stuff,
especially linker relaxations is a topic I still want to understand in
more detail).

> Clearly, we could add extra code to one path or the other to make them look
> the same, but IMO that's just extra baggage that serves no functional
> purpose. I'm all for aesthetic improvements when they're Pareto-superior,
> but this isn't such a case.

OK, I understand and that also makes sense.

urs
Reply all
Reply to author
Forward
0 new messages