Sometimes I get hung up on tiny little things. I feel like I could do better on this code or this. And I often think is this efficient enough? Does it performs good? And I really want to tweak things.

Currently I'm hung up on this little corner finding function:

NinePatchDrawable::orientation NinePatchDrawable::get_orientation(int xl, int yl, int wl, int hl) {

    orientation o;
    if(yl == 0) {
        if (xl == 0) {
            o = NW;
        } else if (xl == wl - 1) {
            o = NE;
        } else {
            o = N;
        }
    } else if (yl == hl - 1) {
        if(xl == 0) {
            o = SW;
        } else if (xl == wl - 1) {
            o = SE;
        } else {
            o = S;
        }
    } else if (xl == 0) {
        o = W;
    } else if(xl == (wl - 1)) {
        o = E;
    } else {
        o = CENTER;
    }
    return o;
}

Don't get me wrong it works. But all those IF/ELSEs gets me frustrated. So I was thinking OK... what is the compiler actually doing with this funny code?

You can either explore it in your IDE or in my case I'm using CLion and currently CLion does not support jumping into assembly. So I just went to: https://godbolt.org/

Without optimization its as you've might expected to be:

get_orientation(int, int, int, int):                # @get_orientation(int, int, int, int)
        push    rbp
        mov     rbp, rsp
        mov     dword ptr [rbp - 4], edi
        mov     dword ptr [rbp - 8], esi
        mov     dword ptr [rbp - 12], edx
        mov     dword ptr [rbp - 16], ecx
        cmp     dword ptr [rbp - 8], 0
        jne     .LBB0_8
        cmp     dword ptr [rbp - 4], 0
        jne     .LBB0_3
        mov     dword ptr [rbp - 20], 0
        jmp     .LBB0_7
.LBB0_3:
        mov     eax, dword ptr [rbp - 4]
        mov     ecx, dword ptr [rbp - 12]
        sub     ecx, 1
        cmp     eax, ecx
        jne     .LBB0_5
        mov     dword ptr [rbp - 20], 2
        jmp     .LBB0_6
.LBB0_5:
        mov     dword ptr [rbp - 20], 1
.LBB0_6:
        jmp     .LBB0_7
.LBB0_7:
        jmp     .LBB0_24
.LBB0_8:
        mov     eax, dword ptr [rbp - 8]
        mov     ecx, dword ptr [rbp - 16]
        sub     ecx, 1
        cmp     eax, ecx
        jne     .LBB0_16
        cmp     dword ptr [rbp - 4], 0
        jne     .LBB0_11
        mov     dword ptr [rbp - 20], 6
        jmp     .LBB0_15
.LBB0_11:
        mov     eax, dword ptr [rbp - 4]
        mov     ecx, dword ptr [rbp - 12]
        sub     ecx, 1
        cmp     eax, ecx
        jne     .LBB0_13
        mov     dword ptr [rbp - 20], 4
        jmp     .LBB0_14
.LBB0_13:
        mov     dword ptr [rbp - 20], 5
.LBB0_14:
        jmp     .LBB0_15
.LBB0_15:
        jmp     .LBB0_23
.LBB0_16:
        cmp     dword ptr [rbp - 4], 0
        jne     .LBB0_18
        mov     dword ptr [rbp - 20], 7
        jmp     .LBB0_22
.LBB0_18:
        mov     eax, dword ptr [rbp - 4]
        mov     ecx, dword ptr [rbp - 12]
        sub     ecx, 1
        cmp     eax, ecx
        jne     .LBB0_20
        mov     dword ptr [rbp - 20], 3
        jmp     .LBB0_21
.LBB0_20:
        mov     dword ptr [rbp - 20], 8
.LBB0_21:
        jmp     .LBB0_22
.LBB0_22:
        jmp     .LBB0_23
.LBB0_23:
        jmp     .LBB0_24
.LBB0_24:
        mov     eax, dword ptr [rbp - 20]
        pop     rbp
        ret

I mean look at those JMPs :D...  of course with -O3 it does not look that bad at all:

get_orientation(int, int, int, int):                # @get_orientation(int, int, int, int)
        test    esi, esi
        je      .LBB0_1
        add     ecx, -1
        cmp     ecx, esi
        jne     .LBB0_8
        test    edi, edi
        je      .LBB0_6
        add     edx, -1
        xor     eax, eax
        cmp     edx, edi
        sete    al
        xor     eax, 5
        ret
.LBB0_1:
        test    edi, edi
        je      .LBB0_2
        add     edx, -1
        xor     eax, eax
        cmp     edx, edi
        sete    al
        add     eax, 1
        ret
.LBB0_8:
        test    edi, edi
        je      .LBB0_9
        add     edx, -1
        xor     eax, eax
        cmp     edx, edi
        setne   al
        lea     eax, [rax + 4*rax]
        add     eax, 3
        ret
.LBB0_2:
        xor     eax, eax
        ret
.LBB0_6:
        mov     eax, 6
        ret
.LBB0_9:
        mov     eax, 7
        ret
        

we have some jumps, but not so much as before, and we only have forward jumps, thats good. Maybe this code is already really good, It does not look bad at all. I'm really impressed what compilers can do nowadays. But I thought, maybe we can do some arithmetic to find the corners and maybe this code will compile a little bit better.

You might think, ok why am I doing this? Well mostly because its fun to optimize those little code sections and to find code that performs a little better. It won't do any performance improvements to my game. I'm certain of it. But it's fun.

Conclusion

Now I'm certain that I'll just write code without overthinking it too hard. Let the compiler do the optimizing stuff and write code that you understand at a first glance. Without bit-fiddling or some really cool hacky things.