From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30553 invoked by alias); 11 Nov 2008 18:54:26 -0000 Received: (qmail 30407 invoked by uid 22791); 11 Nov 2008 18:54:24 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 11 Nov 2008 18:53:27 +0000 Received: (qmail 2410 invoked from network); 11 Nov 2008 18:53:25 -0000 Received: from unknown (HELO ?192.168.0.193?) (brooks@127.0.0.2) by mail.codesourcery.com with ESMTPA; 11 Nov 2008 18:53:25 -0000 Message-ID: <4919D4D3.3030003@codesourcery.com> Date: Tue, 11 Nov 2008 19:17:00 -0000 From: Brooks Moses User-Agent: Thunderbird 2.0.0.17 (Windows/20080914) MIME-Version: 1.0 To: =?ISO-8859-1?Q?Tobias_Schl=FCter?= CC: Jakub Jelinek , gcc-patches@gcc.gnu.org, fortran@gcc.gnu.org, Steve Kargl , Feng Wang , Brooks Moses Subject: Re: [PATCH] Fold VIEW_CONVERT_EXPR generated by Fortran FE a lot (PR target/35366) References: <20081111131749.GZ3572@tyan-ft48-01.lab.bos.redhat.com> <4919A8A4.8000001@physik.uni-muenchen.de> <20081111161100.GE3572@tyan-ft48-01.lab.bos.redhat.com> <4919B110.6060400@physik.uni-muenchen.de> In-Reply-To: <4919B110.6060400@physik.uni-muenchen.de> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2008-11/txt/msg00466.txt.bz2 Tobias Schlüter wrote, at 11/11/2008 8:21 AM: > Jakub Jelinek wrote: >> For TRANSFER I found: >> http://gcc.gnu.org/ml/gcc-patches/2007-05/msg01903.html >> but I'm still unconvinced. I'd say arguing that the logical must >> hold all the bits is the same as if you said >> real(kind=8), parameter :: a = transfer (transfer (3.1415926d0, 0), 0.d0) >> print *, a >> end >> must print 3.14159... IMO, this equivalence isn't entirely clear. The double-transfer case is called out as a special case in the standard, and it appears to be different from what's required to actually be stored in a logical variable. I'll start with the summary of my conclusions, since this gets a bit complicated and tangly. The conclusion is that the testcases in question are not testing things required by the standard. This bit of code in the transfer testcase is a complicated mess, standard-wise; it's probably illegal, but if we can preserve it as a quality-of-implementation issue, that arguably a good thing. It should be documented in the testcase as QOI, not standard-mandated, though: i = transfer(transfer(ip1, .true.), 0) if (i .ne. ip1) call abort () Meanwhile, these bits of the testcase are definitely relying on undefined behavior when the compiler encounters illegal code, as the function call returns an out-of-range value and the standard doesn't call them out as exceptions. I definitely should have documented these as QOI when I wrote them. It would be nice to preserve them, but I think they're rather unlikely to show up in real code. i = transfer(ap1, 0) if (i .ne. ip1) call abort () a = transfer(ip1, .true.) i = transfer(a, 0) if (i .ne. ip1) call abort () i = ip1 a = transfer(i, .true.) i = transfer(a, 0) if (i .ne. ip1) call abort () As for the Hollerith case: Hollerith with logicals was never included in any Fortran standard, and IMHO there is no call whatsoever for supporting it. Now, to the analysis. I apologize that it's as tangled as it is; I don't have time to further clarify it. >> A precondition of the two transfers giving identity >> is IMHO that no bits are lost, but if the precision of the middle-type >> is smaller than of the other type, it can't be fully preserved. The >> precision of integer(kind=4) is smaller than of real(kind=8), and similarly >> I'd say for logical(kind=4) and integer(kind=4), because logical: >> "The logical type has two values which represent true and false." "IMHO" is unfortunately not the best guide here. According to the F95 spec, the precondition of transfer(transfer(E,D),E) returning identity is "the physical representation of D is as long as or longer than that of E." This is rather more clearly defined than "no bits are lost." In particular, ... > Hm, I haven't found Richard Maine's post that is mentioned in the old > thread, but Fortran has the notion of storage unit. LOGICAL*4, > INTEGER*4 and REAL*4 all occupy 4 storage units. ...the storage unit stuff requires that LOGICAL*4 and INTEGER*4 variables occupy the same amount of space. I assume that we do meet this requirement, even though we use BOOLEAN_TYPE, yes? This is pretty critical, and is clearly required by the standard. > If a circular > transfer(transfer (...) ...) between types with the same number of > storage units is required to return the original value (as Richard Maine > apparently argued), then we'll probably have no choice but to stop using > BOOLEAN_TYPE for LOGICALs. > > Maybe Brooks can point us to the comp.lang.fortran thread. Wow, it's been a long time since I've looked at this! :) The thread is titled "Transfer and variables that don't use all their storage space." and occurred on 2007-04-08. And, when I go back and reread that, I find that I appear to have made a misinterpretation of what Richard was saying. The crux of his argument was this, about why TRANSFER(TRANSFER(-5_8, L), -5_8) is actually illegal when L is a LOGICAL*8: Richard Maine wrote, in comp.lang.fortran, on 2007-04-08: > No. I'm using a back door argument to explain why the code is illegal. > More or less a proof by contradiction, which is perhaps why it seems > contradictory. :-) I arise at a contradiction if I assume the code is > standard conforming. The contradiction is that the standard requires a > result that the standard also prohibits. Thus, I conclude that the > assumption of standard conformance is false. (In particular, the definition of TRANSFER requires this to round-trip, which means that the inner one must return a value that's not a legal LOGICAL value, which means that it must be illegal to call TRANSFER with those arguments.) He then went on to say, on my question of whether it would be valid for the compiler to just throw an error in this case: > I think you could argue that. But then you might get users who > considered it a poor quality of implementation; that one is harder. I > have trouble imagining why anyone would ever want to do such a strange > thing, but James Buskirk can probably come up with something useful. :-) > > I think the more "obvious" thing to do is to use all 8 bytes. But I > don't know what the costs of that are and what the tradoffs might be of > those costs versus the (rare?) usage of an idiom like that. So, given that we seem to have found that the costs of using all 8 bytes, or 4 bytes, or whatever, are rather higher than otherwise expected. As a result, I suppose that the tradeoff is that we go with what might be considered a poor quality of implementation in this case, in return for a better quality of implementation in the case of anything that uses logical variables sensibly. Jakub Jelinek wrote, at 11/11/2008 8:52 AM: > I wonder what you can do with LOGICALs that have values transfered from > INTEGER (other than 0/1). Does the standard define whether something > is executed or not in: > logical, parameter :: l = transfer (234, .false.) > if (l) print *, ".true." > ? I.e. is it supposed to be .false. or .true., or undefined behavior? Even if we were to accept that the double-transfer idiom was legal, the only thing you could legally do with such a LOGICAL value is TRANSFER it to something else. Anything else is undefined behavior. Note that assigning the result of transfer(234, .false.) to a logical variable, in the above example, is undefined behavior. It seems fair to me to declare that it normalizes the result to a standard .true. or .false. value, even if we were to preserve the weird double-transfer semantics. - Brooks