Android/ARM codegen
Joakim via digitalmars-d-ldc
digitalmars-d-ldc at puremagic.com
Thu Jul 16 04:41:18 PDT 2015
Alright, I've been stepping through some failing tests: one that
seems to be bad codegen is that many calls to
std.algorithm.iteration.map seem to fail, for example, when
running the tests for std.zip. One of the std.zip tests calls
std.random.uniform, which then gets its second parameter stomped
by map from rndGen(). I've tracked it down to this function in
the llvm IR:
define weak_odr void
@_D3std9algorithm9iteration47__T3mapS363std6random6rndGenFNcNdNfZ9__lambda4Z42__T3mapTS3std5range13__T6RepeatTiZ6RepeatZ3mapMFNaNbNiNfS3std5range13__T6RepeatTiZ6RepeatZS3std9algorithm9iteration87__T9MapResultS363std6random6rndGenFNcNdNfZ9__lambda4TS3std5range13__T6RepeatTiZ6RepeatZ9MapResult(%"std.random.rndGen.MapResult!(__lambda4, Repeat!int).MapResult"* noalias nocapture sret %.sret_arg, i8* %.nest_arg, %"std.range.Repeat!int.Repeat"* byval nocapture readonly %r_arg) #1
{
%.structliteral = alloca
%"std.random.rndGen.MapResult!(__lambda4, Repeat!int).MapResult",
align 4 ; [#uses = 3 type =
%"std.random.rndGen.MapResult!(__lambda4, Repeat!int).MapResult"*]
%1 = getelementptr inbounds
%"std.random.rndGen.MapResult!(__lambda4, Repeat!int).MapResult"*
%.structliteral, i32 0, i32 0, i32 0 ; [#uses = 1 type = i32*]
store i32 0, i32* %1, align 4
%2 = getelementptr %"std.random.rndGen.MapResult!(__lambda4,
Repeat!int).MapResult"* %.structliteral, i32 0, i32 1 ; [#uses =
1 type = i8**]
store i8* %.nest_arg, i8** %2, align 4
%tmp = call %"std.random.rndGen.MapResult!(__lambda4,
Repeat!int).MapResult"*
@_D3std9algorithm9iteration87__T9MapResultS363std6random6rndGenFNcNdNfZ9__lambda4TS3std5range13__T6RepeatTiZ6RepeatZ9MapResult6__ctorMFNaNbNcNiNfS3std5range13__T6RepeatTiZ6RepeatZS3std9algorithm9iteration87__T9MapResultS363std6random6rndGenFNcNdNfZ9__lambda4TS3std5range13__T6RepeatTiZ6RepeatZ9MapResult(%"std.random.rndGen.MapResult!(__lambda4, Repeat!int).MapResult"* returned %.structliteral, %"std.range.Repeat!int.Repeat"* byval %r_arg) ; [#uses = 1 type = %"std.random.rndGen.MapResult!(__lambda4, Repeat!int).MapResult"*]
%3 = bitcast %"std.random.rndGen.MapResult!(__lambda4,
Repeat!int).MapResult"* %tmp to i64* ; [#uses = 1 type = i64*]
%4 = bitcast %"std.random.rndGen.MapResult!(__lambda4,
Repeat!int).MapResult"* %.sret_arg to i64* ; [#uses = 1 type =
i64*]
%5 = load i64* %3, align 1 ; [#uses = 1
type = i64]
store i64 %5, i64* %4, align 4
ret void
}
which gets translated to the following ARM assembly:
_D3std9algorithm9iteration47__T3mapS363std6random6rndGenFNcNdNfZ9__lambda4Z42__T3mapTS3std5range13__T6RepeatTiZ6RepeatZ3mapMFNaNbNiNfS3std5range13__T6RepeatTiZ6RepeatZS3std9algorithm9iteration87__T9MapResultS363std6random6rndGenFNcNdNfZ9__lambda4TS3std5range13__T6RepeatTiZ6RepeatZ9MapResult:
.fnstart
.Leh_func_begin94:
.pad #8
sub sp, sp, #8
.save {r4, lr}
push {r4, lr}
.pad #8
sub sp, sp, #8
mov r4, r0
mov r0, #0
str r2, [sp, #20]
stmib sp, {r0, r1}
add r0, sp, #4
ldr r1, [sp, #20]
bl
_D3std9algorithm9iteration87__T9MapResultS363std6random6rndGenFNcNdNfZ9__lambda4TS3std5range13__T6RepeatTiZ6RepeatZ9MapResult6__ctorMFNaNbNcNiNfS3std5range13__T6RepeatTiZ6RepeatZS3std9algorithm9iteration87__T9MapResultS363std6random6rndGenFNcNdNfZ9__lambda4TS3std5range13__T6RepeatTiZ6RepeatZ9MapResult(PLT)
ldmib sp, {r0, r1}
stm r4, {r0, r1}
add sp, sp, #8
pop {r4, lr}
add sp, sp, #8
bx lr
The problem appears to be that even though r4 is saved at the
beginning of the function, it is overwritten by r1 in the stmib
instruction afterwards. Obviously there's no point in pushing r4
and popping it at the end of the function, if you've lost it by
overwriting in between. Specifically, "sub sp, sp, #8" advances
the stack pointer by 8, then stmib increments it 4 _before_
storing r0 then r1, overwriting the contents of r4 saved at the
beginning of the function. Other calls to map also seem to fail
in other instances of the same template function, but
interestingly in different ways, ie no uses of stmib there. I
haven't tracked down exactly why those other instances fail.
I'm not sure how to reduce this further and if I need to file a
bug for llvm: any pointers?
More information about the digitalmars-d-ldc
mailing list