|
From: Tomas Cernaj on 30 Nov 2007 14:32 Hello everyone, is there any way to tell the Ada compiler that an Address attribute should be constant? I want to use it for accessing fixed memory locations, and without the Address attribute being constant the compiler won't optimize away an indirect access. I couldn't find anything in the RM or GNAT documentation... The point is that I want to use the 'Address construct on the AVR target, which is an 8-bit processor, so the indirect access is quite expensive. I suppose that was a bit unclear, so here's an example: :) I have the following declarations in a package spec file: type T_Type is array (0 .. 7) of Boolean; pragma Pack (T_Type); for T_Type'Size use 8; package TA is new System.Address_To_Access_Conversions (T_Type); X : constant access T_Type := TA.To_Pointer (System.Storage_Elements.To_Address (50)); Y : T_Type; for Y'Address use System.Storage_Elements.To_Address (51); pragma Import (Ada, Y); Note that X is something like a "T_Type * const X" in C. Compiling the following code X (4) := True; Y (5) := True; with GNAT (gcc-4.2 -O -S) yields this assembler output (x86-64): orb $16, 50 ; X (4) := True movq testpkg__y(%rip), %rdx ; Y (5) := True movzbl (%rdx), %eax orl $32, %eax movb %al, (%rdx) That's because the compiler can not assume that Y'Address will not be changed. Thank you for your help, Tomas
From: Samuel Tardieu on 30 Nov 2007 16:42 >>>>> "Tomas" == Tomas Cernaj <tcernaj.WITHOUTTHIS(a)gmx.de> writes: Tomas> That's because the compiler can not assume that Y'Address will Tomas> not be changed. Well, no, that's not the reason (Y'Address is obviously static and constant). This is due to an unfortunate combination of three things: a) because of RM13.3(19), no optimization can be done on Y based on assumptions of no aliases b) to implement this clause, GCC marks the implicitly defined pointer type as volatile c) when this implicitly defined pointer type is marked as volatile, GCC generates code which does read+modify+write here at 3 separate operations rather than using an atomic one I think GNAT is overconservative concerning (b) as I do not think a volatile behaviour is mandated here, and that (c) could generate a better code but this is a separate issue from (b). Sam -- Samuel Tardieu -- sam(a)rfc1149.net -- http://www.rfc1149.net/
From: Samuel Tardieu on 30 Nov 2007 17:22 >>>>> "Sam" == Samuel Tardieu <sam(a)rfc1149.net> writes: >>>>> "Tomas" == Tomas Cernaj <tcernaj.WITHOUTTHIS(a)gmx.de> writes: Tomas> That's because the compiler can not assume that Y'Address will Tomas> not be changed. Sam> Well, no, that's not the reason (Y'Address is obviously static Sam> and constant). This is due to an unfortunate combination of three Sam> things: Sam> a) because of RM13.3(19), no optimization can be done on Y based Sam> on assumptions of no aliases Sam> b) to implement this clause, GCC marks the implicitly defined Sam> pointer type as volatile Sam> c) when this implicitly defined pointer type is marked as Sam> volatile, GCC generates code which does read+modify+write here at Sam> 3 separate operations rather than using an atomic one Sam> I think GNAT is overconservative concerning (b) as I do not think Sam> a volatile behaviour is mandated here, and that (c) could Sam> generate a better code but this is a separate issue from (b). I found a discussion about (b) dating from last September which explains that a lot of Ada code assumes that pragma Volatile is implicit and cannot be easily changed. So I asked about (c) on the GCC developers mailing-list, as it may be a missed optimization. Sam -- Samuel Tardieu -- sam(a)rfc1149.net -- http://www.rfc1149.net/
From: Tomas Cernaj on 2 Dec 2007 17:00 Thank you for your quick response. You've helped me a lot to sort things out. Actually I think there's two problems at hand: 1) the read/modify/write access 2) the indirect access ad 1): As explained by Richard Kenner, the C construct "y |= 32" is by definition equivalent to "y = y | 32", so R/M/W is perfectly OK. However, writing "Y (5) := True" IMO means that we only want to set the corresponding bit, no matter what the rest of the byte/word etc. looks like. I've tried this using a (volatile) bit field in C, and here again gcc generates a R/M/W access. (compiler problem...?) ad 2): I'm not quite sure if I've understood the concept of aliased types you mentioned in (a)... :-| Anyways, I modified the example in my first post to include "pragma Volatile (T_Type);". Here's what gcc generates: movzbl 50, %eax ; X (4) := True orl $16, %eax movb %al, 50 movq testpkg__y(%rip), %rdx ; Y (5) := True movzbl (%rdx), %eax orl $32, %eax movb %al, (%rdx) So X is accessed directly while Y is accessed indirectly. That's why I thought it had something to do with Y'Address not being constant... (I mean that whenever one uses the package where Y is declared one can still change the value of Y'Address). Am I missing a point? Thanks, Tomas
From: Samuel Tardieu on 2 Dec 2007 18:13 >>>>> "Tomas" == Tomas Cernaj <tcernaj.WITHOUTTHIS(a)gmx.de> writes: Tomas> So X is accessed directly while Y is accessed Tomas> indirectly. That's why I thought it had something to do with Tomas> Y'Address not being constant... (I mean that whenever one uses Tomas> the package where Y is declared one can still change the value Tomas> of Y'Address). Tomas> Am I missing a point? Yes: the fact that nobody else can change the value of Y'Address :) Sam -- Samuel Tardieu -- sam(a)rfc1149.net -- http://www.rfc1149.net/
|
Pages: 1 Prev: using jGRASP to compile Ada Next: MI5 Persecution: Browse the Website (3486) |