[llvm-dev] [Sparc] vararg double issue on 32 bit Sparc processors

Martin J. O'Riordan via llvm-dev llvm-dev at lists.llvm.org
Thu Oct 20 04:22:23 PDT 2016


With my GCC implementation for this, it was the 64-bit 'ldd' and 'std'
handling that I had to change.  It was working ok for big-endian, but since
we use a little-endian Leon4 the usual implementation was getting the two FP
registers loaded the wrong way round, but it wasn't zeroing one of them.
The change I made was just to ensure that the endian ordering was correct
(ditto 64-bit int).

 

If you try hand-written assembly using 'ldd' what happens?  I'm wondering if
there is a hardware issue failing to perform the 64-bit load.  I'm assuming
that you are using a proprietary development board for this, and it is
possible that the bus has not been configured for the 64-bit load store
extensions.  Just a thought.

 

            MartinO

 

From: Chris.Dewhurst [mailto:Chris.Dewhurst at lero.ie] 
Sent: 19 October 2016 23:37
To: Martin.ORiordan at Movidius.com
Cc: 'LLVM Developers' <llvm-dev at lists.llvm.org>
Subject: RE: [llvm-dev] [Sparc] vararg double issue on 32 bit Sparc
processors

 

Hi Martin, 

 

That does sound like a very similar problem. As far as I've been able to
tell, only half the value is loaded and the other half is zeroed-out
(resulting, in fact, in an invalid floating point number, which is trapped
when the register is next used). However, whether the other half is zeroed
specifically by whatever this error is, or if it's just that the two halves
are swapped, I can't be sure because I'm not 100% sure about what the
correct floating-point representation of the number actually should be.

 

Further, I still can't understand why the store and load makes the problem
"go away".

 

This is on a sparc, not sparcel.

 

Chris.

  _____  

From: Martin J. O'Riordan [martin.oriordan at movidius.com]
Sent: 19 October 2016 23:18
To: Chris.Dewhurst
Cc: 'LLVM Developers'
Subject: RE: [llvm-dev] [Sparc] vararg double issue on 32 bit Sparc
processors

Hi Chris,

 

Can I bring this in a bit closer to Leon - is this specifically to do with
64-bit FP transactions with memory?  The reason I ask is that I had similar
problems adapting Sparc Leon 3 and 4 which are V8 Sparc, but with 64-bit
memory bus transactions with the GCC compiler.  It "feels" like the same
problem, but LLVM versus GCC.  In the GCC case, the 64-bit memory
transaction had the register endian ordering the wrong way round; perhaps it
is something similar in LLVM?

 

Are you doing this with "sparc" or "sparcel"?

 

Thanks, MartinO

 

From: llvm-dev [mailto:llvm-dev-bounces at lists.llvm.org] On Behalf Of
Chris.Dewhurst via llvm-dev
Sent: 19 October 2016 22:27
To: llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org> 
Subject: [llvm-dev] [Sparc] vararg double issue on 32 bit Sparc processors

 

Hi, 

 

I've discovered a problem on Sparc processors (specifically, LEON, but I
suspect but can't verify that it also happens on all Sparc processors).

 

The problem is, or appears to be with using double values in Sparc (32 bit).

 

Specifically, double values are not being loaded into registers correctly
within a function using va_args. Only half the value is loaded (i.e. 32,
rather than 64 bits of the value).

 

What I have also found is that the failure does not happen in all
circumstances. The simplest situation I've been able to re-create that
avoids the problem is to put a store and subsequent load instruction around
the va_arg instruction that deals with the double value. e.g. (in an .ll
file):

 

This code fragment does not work:

 

  define void @foo(i32 %v, i8* %ap) local_unnamed_addr {

  entry:

    %ap.addr = alloca i8*, align 4

    store i8* %ap, i8** %ap.addr, align 4

    %0 = va_arg i8** %ap.addr, i64

    %conv = trunc i64 %0 to i32

    %1 = va_arg i8** %ap.addr, double

    ...

 

Whereas this nearly identical code fragment, wrapping the store and load
around the "double" va_arg instruction does work:

 

  define void @foo(i32 %v, i8* %ap) local_unnamed_addr {

    entry:

    %ap.addr = alloca i8*, align 4

    store i8* %ap, i8** %ap.addr, align 4

    %0 = va_arg i8** %ap.addr, i64

    %conv = trunc i64 %0 to i32

    store i32 %conv, i32* @foo_arg, align 4

    %1 = va_arg i8** %ap.addr, double

    %2 = load i32, i32* @foo_arg, align 4

    ...

 

I had been attempting to make various changes to SparcISelLowering.cpp to
try to simulate something similar where the code is output, but I don't feel
as though I'm heading in the right direction. I'm still not sure quite where
the source of the problem lies.

 

I can provide more details on specifics, but rather than head off into
excessive details immediately, I'd appreciate if anyone can help me identify
what direction I really should be taking to fix this problem. I'm not
convinced I've been going about it the right way so far.

 

Chris Dewhurst, Lero, University of Limerick.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20161020/d2c15691/attachment.html>


More information about the llvm-dev mailing list