digitalmars.D.ldc - LDC, ARM (seems like x86 too) bug?
- Jack Applegame (12/65) Sep 19 2017 Everything looks good.
- Johan Engelen (11/27) Sep 19 2017 [snip]
- Jack Applegame (3/11) Sep 19 2017 Thank you for explanation.
- Johan (5/18) Sep 20 2017 Is it important for you to be able to alias external symbols?
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: cmp r0, r1 bne .LBB0_1 bx lrEverything 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: cmp r2, r0 bne .LBB1_1 bx lrFunction `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: cmp r1, r0 blo .LBB1_1 bx lrSee https://godbolt.org/g/t2arr7
Sep 19 2017
On Tuesday, 19 September 2017 at 09:52:12 UTC, Jack Applegame wrote:Code:[snip]// 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); }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.This is a question of spec details. We are assuming C semantics for extern variables: just like normal variables, they cannot alias. See also: https://stackoverflow.com/questions/5559281/c-externs-that-alias-the-same-address LLVM optimizes these cases more aggressively than GCC: https://godbolt.org/g/yJdp9P -Johan
Sep 19 2017
On Tuesday, 19 September 2017 at 21:21:41 UTC, Johan Engelen wrote:This is a question of spec details. We are assuming C semantics for extern variables: just like normal variables, they cannot alias. See also: https://stackoverflow.com/questions/5559281/c-externs-that-alias-the-same-address LLVM optimizes these cases more aggressively than GCC: https://godbolt.org/g/yJdp9P -JohanThank you for explanation.
Sep 19 2017
On Wednesday, 20 September 2017 at 06:57:19 UTC, Jack Applegame wrote:On Tuesday, 19 September 2017 at 21:21:41 UTC, Johan Engelen wrote:Is it important for you to be able to alias external symbols? (ARM's compiler and others have __attribute__((alias)) for it) -JohanThis is a question of spec details. We are assuming C semantics for extern variables: just like normal variables, they cannot alias. See also: https://stackoverflow.com/questions/5559281/c-externs-that-alias-the-same-address LLVM optimizes these cases more aggressively than GCC: https://godbolt.org/g/yJdp9P -JohanThank you for explanation.
Sep 20 2017