Hi,
I'm compiling lldiv.c from the NetBSD standard library. It works on ARM,
Mips,
Microblaze,ppc, ppc64, and x86_64. On i386 a very strange thing happens.
Here's the source:
#include <stdlib.h>
#define __weak_alias(sym) __attribute__ ((weak, alias (#sym)))
lldiv_t lldiv(long long int num, long long int denom) __weak_alias(_lldiv);
lldiv_t _lldiv(long long num, long long denom)
{
lldiv_t r;
r.quot = num / denom;
r.rem = num % denom;
if (num >= 0 && r.rem < 0) {
r.quot++;
r.rem -= denom;
}
return (r);
}
I get the following code emitted for the return if the alias line is present:
LBB0_3: # %if.end
movl 64(%esp), %eax
movsd 24(%esp), %xmm0
movsd 32(%esp), %xmm1
movsd %xmm1, 8(%eax)
movsd %xmm0, (%eax)
addl $56, %esp
popl %esi
ret
.Ltmp0:
.size _lldiv, .Ltmp0-_lldiv
.weak lldiv
lldiv = _lldiv
And this if it isn't:
LBB0_3: # %if.end
movl 64(%esp), %eax
movsd 24(%esp), %xmm0
movsd 32(%esp), %xmm1
movsd %xmm1, 8(%eax)
movsd %xmm0, (%eax)
addl $56, %esp
popl %esi
ret $4
.Ltmp0:
.size _lldiv, .Ltmp0-_lldiv
Other than the $4 on the return address, the code is otherwise identical. The
alias version crashes, of course. Is there supposed to be an implicit pop of
the return structure pointer? What could cause an alias to mess this up?
-Rich
On Fri, Jan 13, 2012 at 2:53 PM, Richard Pennington <rich at pennware.com> wrote:> Hi, > > I'm compiling lldiv.c from the NetBSD standard library. It works on ARM, Mips, > Microblaze,ppc, ppc64, and x86_64. On i386 a very strange thing happens. > Here's the source: > > #include <stdlib.h> > #define __weak_alias(sym) __attribute__ ((weak, alias (#sym))) > > lldiv_t lldiv(long long int num, long long int denom) __weak_alias(_lldiv); > > lldiv_t _lldiv(long long num, long long denom) > { > lldiv_t r; > r.quot = num / denom; > r.rem = num % denom; > if (num >= 0 && r.rem < 0) { > r.quot++; > r.rem -= denom; > } > return (r); > } > > I get the following code emitted for the return if the alias line is present: > > LBB0_3: # %if.end > movl 64(%esp), %eax > movsd 24(%esp), %xmm0 > movsd 32(%esp), %xmm1 > movsd %xmm1, 8(%eax) > movsd %xmm0, (%eax) > addl $56, %esp > popl %esi > ret > .Ltmp0: > .size _lldiv, .Ltmp0-_lldiv > > > .weak lldiv > lldiv = _lldiv > > And this if it isn't: > LBB0_3: # %if.end > movl 64(%esp), %eax > movsd 24(%esp), %xmm0 > movsd 32(%esp), %xmm1 > movsd %xmm1, 8(%eax) > movsd %xmm0, (%eax) > addl $56, %esp > popl %esi > ret $4 > .Ltmp0: > .size _lldiv, .Ltmp0-_lldiv > > Other than the $4 on the return address, the code is otherwise identical. The > alias version crashes, of course. Is there supposed to be an implicit pop of > the return structure pointer? What could cause an alias to mess this up?Bad version: define void @_lldiv(%struct.lldiv_t* noalias %agg.result, i64 %num, i64 %denom) nounwind { Good version: define void @_lldiv(%struct.lldiv_t* noalias sret %agg.result, i64 %num, i64 %denom) nounwind { Looks like a bug in clang's IR generation; please file a bug. -Eli
Apparently Analagous Threads
- [LLVMdev] Odd weak symbol thing on i386
- [LLVMdev] Suboptimal code due to excessive spilling
- [LLVMdev] Suboptimal code due to excessive spilling
- wineg++ problem with the standard library
- [Codegen bug in LLVM 3.8?] br following `fcmp une` is present in ll, absent in asm