[Issue 4438] A missed function inlining

d-bugmail at puremagic.com d-bugmail at puremagic.com
Thu Apr 14 17:29:10 PDT 2011


http://d.puremagic.com/issues/show_bug.cgi?id=4438



--- Comment #4 from bearophile_hugs at eml.cc 2011-04-14 17:25:38 PDT ---
A different case of missed inlining. In the following code isValidMove() is not
inlined by DMD 2.052 (with -O -inline -release), despite this function contains
no loop and no throws. Removing the "ref" for the board array in the
isValidMove() signature changes nothing.

The runtime is 12.6 seconds, the alternative version of the knightsTour()
function with manually inlined isValidMove() (currently commented out below)
runs in 8.0 seconds. My tests show that GCC -O3 is able to inline similar code
written in C.



// Code adapted from:
// http://en.literateprograms.org/The_Knight's_Tour_(C)?oldid=14704
import core.stdc.stdio: printf;

template TypeTuple(T...) {
    alias T TypeTuple;
}

bool isValidMove(int N)(ref int[N][N] board, int xpos, int ypos, int nmove) {
    if (xpos < 0 || xpos >= N || ypos < 0 || ypos >= N ||
        (board[xpos][ypos] && board[xpos][ypos] < nmove))
        return false;
    return true;
}

// run time: 12.6 seconds
bool knightsTour(int N)(ref int[N][N] board, int xpos, int ypos, int nmove) {
    if (!isValidMove(board, xpos, ypos, nmove))
        return false;

    board[xpos][ypos] = nmove;

    if (nmove == N * N)
        return true;

    alias TypeTuple!(+1, -2, -2, -1, -1, +2, +2, +1) spx;
    alias TypeTuple!(+2, +1, -1, +2, -2, +1, -1, -2) spy;
    static assert(spx.length == spy.length);
    bool ok = true;
    foreach (i, sx; spx)
        ok = ok && !knightsTour(board, xpos + sx, ypos + spy[i], nmove + 1);
    if (ok) {
        board[xpos][ypos] = N * N;
        return false;
    }

    return true;
}

/*
// run time:  8.0 seconds
bool knightsTour(int N)(ref int[N][N] board, int xpos, int ypos, int nmove) {
    // if is not valid move
    if (xpos < 0 || xpos >= N || ypos < 0 || ypos >= N ||
        (board[xpos][ypos] && board[xpos][ypos] < nmove))
        return false;

    board[xpos][ypos] = nmove;

    if (nmove == N * N)
        return true;

    alias TypeTuple!(+1, -2, -2, -1, -1, +2, +2, +1) spx;
    alias TypeTuple!(+2, +1, -1, +2, -2, +1, -1, -2) spy;
    static assert(spx.length == spy.length);
    bool ok = true;
    foreach (i, sx; spx)
        ok = ok && !knightsTour(board, xpos + sx, ypos + spy[i], nmove + 1);
    if (ok) {
        board[xpos][ypos] = N * N;
        return false;
    }

    return true;
}
*/

void main() {
    enum int side = 8;
    enum int xpos = 0;
    enum int ypos = xpos;

    int[side][side] board;
    printf("Executing Knight's Tour...\n");

    if (knightsTour(board, xpos, ypos, 1)) {
        printf("Solution found:\n");
        foreach (ref row; board) {
            foreach (item; row)
                printf("%3d", item);
            printf("\n");
        }
    } else
        printf("No solution found.\n");
}


The first part of the assembly of knightsTour() shows the call to
isValidMove():

_D4test20__T11knightsTourVk8Z11knightsTourFKG8G8iiiiZb  comdat
    sub ESP,02Ch
    push EBX
    push EBP
    push ESI
    mov ESI,044h[ESP]
    push EDI
    mov 038h[ESP],EAX
    push ESI
    push dword ptr 048h[ESP]
    push dword ptr 048h[ESP]
    call near ptr _D4test20__T11isValidMoveVk8Z11isValidMoveFKG8G8iiiiZb
    xor AL,1
    je  L2D
    pop EDI
    ...

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list