This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| Loop-linked Function Calls Submitted by

I'm not claiming to be the first to invent this, however it isn't something I've seen covered in any depth elsewhere. Also I don't know how applicable this is to other chip architectures; this is all done in ARM code.
I've recently found that I'm often ending a simple loop with a function call like this:

    (pseudocode)
    .loop
    [code]
    branch with link to function
    loop test
    conditional branch to loop

where the function is large or unwieldy or is used in a lot of places.
in ARM code this might be:

    MOV counter,#cycles
    .loop
    [code]
    BL function              ;branch with link
    SUBS counter,counter,#1  ;decrement loop counter
    BGT loop                 ;repeat loop (while counter +ve)

    ...
    .function
    [more code]
    MOV PC,R14               ;return - r14 is link register

However, this means that each loop cycle you are branching twice in quick succession - the return from the function call and then back to the start of the loop. This is bad because each branch causes a pipeline flush. This can be avoided by setting up the return address before the loop:

    (pseudocode)
    set up link register to point to loop
    .loop
    do loop checking
    [code]
    branch to function
    .end of loop

or in ARM code:

    ADR R14,loop             ;get the address of loop in R14
    MOV counter,#cycles
    .loop
    SUBS counter,counter,#1
    BLT loop_finish          ;finish when counter becomes negative
    B function               ;branch to function (without link)
    .loop_finish

So the function returns directly to the start of the loop. Note that the function itself is unchanged.
Of course this means that you can't use R14 for anything else, ie you couldn't call other subroutines. However if the final function in your loop is always called in this manner you can use another register for your link register. There are other possibilities, such as sharing functions called by branch-tables, etc.
As I said, I'm not claiming this is big or clever, but it is slightly faster than the naive code.

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.