LDC, ARM (seems like x86 too) bug?
Jack Applegame
japplegame at gmail.com
Tue Sep 19 09:52:12 UTC 2017
Code:
> // values from linker script
> extern(C) extern __gshared {
> uint src_beg; // source begin uint trg_beg; // target begin
> uint trg_end; // target end }
>
> void copy(uint* ss, uint* ts, const uint* te) {
> while(ts != te) *ts++ = *ss++;
> }
>
> void foo() {
> copy(&src_beg, &trg_beg, &trg_end);
> }
Function `copy` dump:
> void example.copy(uint*, uint*, const(uint*)):
> cmp r1, r0
> it eq
> bxeq lr
> .LBB0_1:
> ldr r3, [r2], #4
> str r3, [r1], #4
> cmp r0, r1
> bne .LBB0_1
> bx lr
Everything looks good.
Function `foo` dump:
> void example.foo():
> movw r0, :lower16:trg_beg
> movw r1, :lower16:src_beg
> movw r2, :lower16:trg_end
> movt r0, :upper16:trg_beg
> movt r1, :upper16:src_beg
> movt r2, :upper16:trg_end
> .LBB1_1:
> ldr r3, [r1], #4
> str r3, [r0], #4
> cmp r2, r0
> bne .LBB1_1
> bx lr
Function `copy` is inlined - very good, but the loop condition
check must be before the loop body.
See https://godbolt.org/g/NtjvQM
Apparently, LDC believes that addresses of `trg_beg` and
`trg_end` can not be initially equal and moves check to the end.
But this is not always the case.
Changing condition to `<` fixes issue:
> void example.foo():
> movw r0, :lower16:trg_end
> movw r1, :lower16:trg_beg
> movt r0, :upper16:trg_end
> movt r1, :upper16:trg_beg
> cmp r1, r0
> it hs
> bxhs lr
> movw r1, :lower16:trg_beg
> movw r2, :lower16:src_beg
> movt r1, :upper16:trg_beg
> movt r2, :upper16:src_beg
> .LBB1_1:
> ldr r3, [r2], #4
> str r3, [r1], #4
> cmp r1, r0
> blo .LBB1_1
> bx lr
See https://godbolt.org/g/t2arr7
More information about the digitalmars-d-ldc
mailing list