Chris.Dewhurst via llvm-dev
2016-Oct-19 21:27 UTC
[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/20161019/6e832839/attachment.html>
Joerg Sonnenberger via llvm-dev
2016-Oct-19 21:53 UTC
[llvm-dev] [Sparc] vararg double issue on 32 bit Sparc processors
On Wed, Oct 19, 2016 at 09:27:10PM +0000, Chris.Dewhurst via llvm-dev wrote:> 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).Are you using variadic functions on the LLVM or the Clang side? The former is essentially best effort and many things simply are not supported. Joerg
Martin J. O'Riordan via llvm-dev
2016-Oct-19 22:18 UTC
[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 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/20161019/66827c09/attachment.html>
Chris.Dewhurst via llvm-dev
2016-Oct-19 22:36 UTC
[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 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/20161019/e1e5eaa2/attachment.html>
James Y Knight via llvm-dev
2016-Oct-20 16:07 UTC
[llvm-dev] [Sparc] vararg double issue on 32 bit Sparc processors
A complete test-case which can be given to llc to produce incorrect assembly output would be a good start. My initial attempt to reproduce by making a complete function from your example did generate code to load both halves. On Wed, Oct 19, 2016 at 5:27 PM, Chris.Dewhurst via llvm-dev < llvm-dev at lists.llvm.org> wrote:> 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. > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20161020/61abf25a/attachment.html>