* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
@ 2008-11-11 22:53 Tobias Burnus
2008-11-12 14:20 ` Jakub Jelinek
0 siblings, 1 reply; 28+ messages in thread
From: Tobias Burnus @ 2008-11-11 22:53 UTC (permalink / raw)
To: gcc-patches, fortran
Hi,
Jakub wrote:
> So would the following be acceptable? It will warn both for
> logical l
> l = 4Hfoob
> and
> l = transfer (42, .true.)
I think that would be sufficent. For completeness:
There is no warning given for
b = transfer(i, b)
I think that is OK, but one could also give one as NAG f95 does:
Warning: TRANSFER to LOGICAL might produce invalid value
I got the first replies to my c.l.f question,
http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/cf874197dc460679
and reading Glen Herrmannsfeldt's and Richard Maine's reply,
there should be no problem:
- Holleriths were usually used with integer since real/logical
are system dependent (e.g. normalization of REAL Holleriths)
- TRANSFER requires that the bit pattern matches
(Richard: "I think to be a mistake"), but
"even if you literally follow that requirement, there turn out to
be gaping loopholes that pretty much prevent the user from being
able to count on bit pattern preservation."
- Assignments, COMMON and EQUIVALENCE: No bit pattern needs to be
preserved
Thus, your patch is OK from the standard and common practice point of
view.
if (expr->representation.string)
{
+ if (TREE_CODE (tmp) == INTEGER_CST)
+ else
I think there is no possibility to ever enter the else branch:
expr->representation.string only occurs for either Holleriths
or for TRANSFER of constants; I would go for a gcc_assert
instead.
The patch is OK from my side.
Brooks Moses wrote:
+ gfc_warning ("Assigning value other than 0 or 1 to LOGICAL"
+ " at %L has undefined result", &expr->where);
> The warning could perhaps be edited a little, too, to reflect that the
> user isn't necessarily thinking of the input as an integer. Maybe:
> "Cannot assign value with bitwise representation other than 0x0 or 0x1
> to LOGICAL at %L".
I find the original string clearer than especially the "0x0 or 0x1".
Tobias
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 22:53 [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366) Tobias Burnus
@ 2008-11-12 14:20 ` Jakub Jelinek
2008-11-12 15:34 ` Paul Richard Thomas
2008-11-12 18:09 ` Feng Wang
0 siblings, 2 replies; 28+ messages in thread
From: Jakub Jelinek @ 2008-11-12 14:20 UTC (permalink / raw)
To: Tobias Burnus; +Cc: gcc-patches, fortran
Hi!
On Tue, Nov 11, 2008 at 11:34:29PM +0100, Tobias Burnus wrote:
> Brooks Moses wrote:
> + gfc_warning ("Assigning value other than 0 or 1 to LOGICAL"
> + " at %L has undefined result", &expr->where);
> > The warning could perhaps be edited a little, too, to reflect that the
> > user isn't necessarily thinking of the input as an integer. Maybe:
> > "Cannot assign value with bitwise representation other than 0x0 or 0x1
> > to LOGICAL at %L".
>
> I find the original string clearer than especially the "0x0 or 0x1".
So, here is an updated patch, which
1) handles transfer (transfer (x, .false.), something) the same way
as transfer (transfer (x, 0), something) (i.e. uses INTEGER_TYPE
of the same mode as the BOOLEAN_TYPE that was used previously)
2) testcases have been updated
3) no checking for INTEGER_CST result from fold_buil1 (V_C_E, ...),
it just uses integer_zerop and integer_onep.
The middle-end side hasn't changed.
Ok for trunk?
2008-11-11 Jakub Jelinek <jakub@redhat.com>
PR target/35366
* fold-const.c (native_encode_string): New function.
(native_encode_expr): Use it for STRING_CST.
* trans-const.c (gfc_conv_constant_to_tree): Warn when
converting an integer outside of LOGICAL's range to
LOGICAL.
* trans-intrinsic.c (gfc_conv_intrinsic_function,
gfc_conv_intrinsic_array_transfer, gfc_conv_intrinsic_transfer):
Use INTEGER_TYPE instead of BOOLEAN_TYPE for TRANSFER as
argument of another TRANSFER.
* gfortran.dg/hollerith.f90: Don't assume a 32-bit value
stored into logical variable will be preserved.
* gfortran.dg/transfer_simplify_4.f90: Remove undefined
cases. Run at all optimization levels. Add a couple of
new tests.
* gfortran.dg/hollerith5.f90: New test.
* gfortran.dg/hollerith_legacy.f90: Add dg-warning.
--- gcc/fold-const.c.jj 2008-11-12 00:43:54.000000000 +0100
+++ gcc/fold-const.c 2008-11-12 11:09:40.000000000 +0100
@@ -7315,6 +7315,37 @@ native_encode_vector (const_tree expr, u
}
+/* Subroutine of native_encode_expr. Encode the STRING_CST
+ specified by EXPR into the buffer PTR of length LEN bytes.
+ Return the number of bytes placed in the buffer, or zero
+ upon failure. */
+
+static int
+native_encode_string (const_tree expr, unsigned char *ptr, int len)
+{
+ tree type = TREE_TYPE (expr);
+ HOST_WIDE_INT total_bytes;
+
+ if (TREE_CODE (type) != ARRAY_TYPE
+ || TREE_CODE (TREE_TYPE (type)) != INTEGER_TYPE
+ || GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (type))) != BITS_PER_UNIT
+ || !host_integerp (TYPE_SIZE_UNIT (type), 0))
+ return 0;
+ total_bytes = tree_low_cst (TYPE_SIZE_UNIT (type), 0);
+ if (total_bytes > len)
+ return 0;
+ if (TREE_STRING_LENGTH (expr) < total_bytes)
+ {
+ memcpy (ptr, TREE_STRING_POINTER (expr), TREE_STRING_LENGTH (expr));
+ memset (ptr + TREE_STRING_LENGTH (expr), 0,
+ total_bytes - TREE_STRING_LENGTH (expr));
+ }
+ else
+ memcpy (ptr, TREE_STRING_POINTER (expr), total_bytes);
+ return total_bytes;
+}
+
+
/* Subroutine of fold_view_convert_expr. Encode the INTEGER_CST,
REAL_CST, COMPLEX_CST or VECTOR_CST specified by EXPR into the
buffer PTR of length LEN bytes. Return the number of bytes
@@ -7337,6 +7368,9 @@ native_encode_expr (const_tree expr, uns
case VECTOR_CST:
return native_encode_vector (expr, ptr, len);
+ case STRING_CST:
+ return native_encode_string (expr, ptr, len);
+
default:
return 0;
}
--- gcc/fortran/trans-intrinsic.c.jj 2008-11-12 00:43:54.000000000 +0100
+++ gcc/fortran/trans-intrinsic.c 2008-11-12 11:35:05.000000000 +0100
@@ -3707,6 +3707,14 @@ gfc_conv_intrinsic_array_transfer (gfc_s
mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
}
+ if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
+ {
+ /* If this TRANSFER is nested in another TRANSFER, use a type
+ that preserves all bits. */
+ if (arg->expr->ts.type == BT_LOGICAL)
+ mold_type = gfc_get_int_type (arg->expr->ts.kind);
+ }
+
if (arg->expr->ts.type == BT_CHARACTER)
{
tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
@@ -3835,6 +3843,13 @@ gfc_conv_intrinsic_transfer (gfc_se * se
arg = arg->next;
type = gfc_typenode_for_spec (&expr->ts);
+ if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
+ {
+ /* If this TRANSFER is nested in another TRANSFER, use a type
+ that preserves all bits. */
+ if (expr->ts.type == BT_LOGICAL)
+ type = gfc_get_int_type (expr->ts.kind);
+ }
if (expr->ts.type == BT_CHARACTER)
{
@@ -4750,20 +4765,30 @@ gfc_conv_intrinsic_function (gfc_se * se
break;
case GFC_ISYM_TRANSFER:
- if (se->ss)
+ if (se->ss && se->ss->useflags)
{
- if (se->ss->useflags)
- {
- /* Access the previously obtained result. */
- gfc_conv_tmp_array_ref (se);
- gfc_advance_se_ss_chain (se);
- break;
- }
- else
- gfc_conv_intrinsic_array_transfer (se, expr);
+ /* Access the previously obtained result. */
+ gfc_conv_tmp_array_ref (se);
+ gfc_advance_se_ss_chain (se);
}
else
- gfc_conv_intrinsic_transfer (se, expr);
+ {
+ /* Ensure double transfer through LOGICAL preserves all
+ the needed bits. */
+ gfc_expr *source = expr->value.function.actual->expr;
+ if (source->expr_type == EXPR_FUNCTION
+ && source->value.function.esym == NULL
+ && source->value.function.isym != NULL
+ && source->value.function.isym->id == GFC_ISYM_TRANSFER
+ && source->ts.type == BT_LOGICAL
+ && expr->ts.type != source->ts.type)
+ source->value.function.name = "__transfer_in_transfer";
+
+ if (se->ss)
+ gfc_conv_intrinsic_array_transfer (se, expr);
+ else
+ gfc_conv_intrinsic_transfer (se, expr);
+ }
break;
case GFC_ISYM_TTYNAM:
--- gcc/fortran/trans-const.c.jj 2008-11-12 00:43:54.000000000 +0100
+++ gcc/fortran/trans-const.c 2008-11-12 11:55:01.000000000 +0100
@@ -281,13 +281,19 @@ gfc_conv_constant_to_tree (gfc_expr * ex
case BT_LOGICAL:
if (expr->representation.string)
- return fold_build1 (VIEW_CONVERT_EXPR,
- gfc_get_logical_type (expr->ts.kind),
- gfc_build_string_const (expr->representation.length,
- expr->representation.string));
+ {
+ tree tmp = fold_build1 (VIEW_CONVERT_EXPR,
+ gfc_get_int_type (expr->ts.kind),
+ gfc_build_string_const (expr->representation.length,
+ expr->representation.string));
+ if (!integer_zerop (tmp) && !integer_onep (tmp))
+ gfc_warning ("Assigning value other than 0 or 1 to LOGICAL"
+ " has undefined result at %L", &expr->where);
+ return fold_convert (gfc_get_logical_type (expr->ts.kind), tmp);
+ }
else
return build_int_cst (gfc_get_logical_type (expr->ts.kind),
- expr->value.logical);
+ expr->value.logical);
case BT_COMPLEX:
if (expr->representation.string)
--- gcc/testsuite/gfortran.dg/transfer_simplify_4.f90.jj 2008-11-12 00:43:54.000000000 +0100
+++ gcc/testsuite/gfortran.dg/transfer_simplify_4.f90 2008-11-12 12:30:46.000000000 +0100
@@ -1,30 +1,39 @@
! { dg-do run }
-! { dg-options "-O0" }
! Tests that the in-memory representation of a transferred variable
! propagates properly.
!
implicit none
integer, parameter :: ip1 = 42
- logical, parameter :: ap1 = transfer(ip1, .true.)
- integer, parameter :: ip2 = transfer(ap1, 0)
+ integer, parameter :: ip2 = transfer(transfer(ip1, .true.), 0)
+ integer :: i, ai(4)
+ logical :: b
- logical :: a
- integer :: i
+ if (ip2 .ne. ip1) call abort ()
i = transfer(transfer(ip1, .true.), 0)
if (i .ne. ip1) call abort ()
- i = transfer(ap1, 0)
- if (i .ne. ip1) call abort ()
-
- a = transfer(ip1, .true.)
- i = transfer(a, 0)
+ i = 42
+ i = transfer(transfer(i, .true.), 0)
if (i .ne. ip1) call abort ()
- i = ip1
- a = transfer(i, .true.)
- i = transfer(a, 0)
- if (i .ne. ip1) call abort ()
+ b = transfer(transfer(.true., 3.1415), .true.)
+ if (.not.b) call abort ()
+
+ b = transfer(transfer(.false., 3.1415), .true.)
+ if (b) call abort ()
+
+ i = 0
+ b = transfer(i, .true.)
+ ! The standard doesn't guarantee here that b will be .false.,
+ ! though in gfortran for all targets it will.
+
+ ai = (/ 42, 42, 42, 42 /)
+ ai = transfer (transfer (ai, .false., 4), ai)
+ if (any(ai .ne. 42)) call abort
+ ai = transfer (transfer ((/ 42, 42, 42, 42 /), &
+& (/ .false., .false., .false., .false. /)), ai)
+ if (any(ai .ne. 42)) call abort
end
--- gcc/testsuite/gfortran.dg/hollerith5.f90.jj 2008-11-12 12:34:26.000000000 +0100
+++ gcc/testsuite/gfortran.dg/hollerith5.f90 2008-11-12 12:40:54.000000000 +0100
@@ -0,0 +1,8 @@
+ ! { dg-do compile }
+ implicit none
+ logical b
+ b = 4Habcd ! { dg-warning "has undefined result" }
+ end
+
+! { dg-warning "Hollerith constant" "const" { target *-*-* } 4 }
+! { dg-warning "Conversion" "conversion" { target *-*-* } 4 }
--- gcc/testsuite/gfortran.dg/hollerith_legacy.f90.jj 2008-09-30 16:56:06.000000000 +0200
+++ gcc/testsuite/gfortran.dg/hollerith_legacy.f90 2008-11-12 12:41:47.000000000 +0100
@@ -21,13 +21,13 @@ data z2/4h(i7),'xxxx','xxxx','xxxx'/
z2 (1,2) = 4h(i8)
i = 4hHell
-l = 4Ho wo
+l = 4Ho wo ! { dg-warning "has undefined result" }
r = 4Hrld!
write (line, '(3A4)') i, l, r
if (line .ne. 'Hello world!') call abort
i = 2Hab
r = 2Hab
-l = 2Hab
+l = 2Hab ! { dg-warning "has undefined result" }
c = 2Hab
write (line, '(3A4, 8A)') i, l, r, c
if (line .ne. 'ab ab ab ab ') call abort
--- gcc/testsuite/gfortran.dg/hollerith.f90.jj 2008-11-12 00:43:54.000000000 +0100
+++ gcc/testsuite/gfortran.dg/hollerith.f90 2008-11-12 12:39:24.000000000 +0100
@@ -8,7 +8,7 @@ character z1(4)
character*4 z2(2,2)
character*80 line
integer i
-logical l
+integer j
real r
character*8 c
@@ -20,15 +20,15 @@ data z2/4h(i7),'xxxx','xxxx','xxxx'/
z2 (1,2) = 4h(i8)
i = 4hHell
-l = 4Ho wo
+j = 4Ho wo
r = 4Hrld!
-write (line, '(3A4)') i, l, r
+write (line, '(3A4)') i, j, r
if (line .ne. 'Hello world!') call abort
i = 2Hab
+j = 2Hab
r = 2Hab
-l = 2Hab
c = 2Hab
-write (line, '(3A4, 8A)') i, l, r, c
+write (line, '(3A4, 8A)') i, j, r, c
if (line .ne. 'ab ab ab ab ') call abort
write(line, '(4A8, "!")' ) x
Jakub
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-12 14:20 ` Jakub Jelinek
@ 2008-11-12 15:34 ` Paul Richard Thomas
2008-11-12 18:09 ` Feng Wang
1 sibling, 0 replies; 28+ messages in thread
From: Paul Richard Thomas @ 2008-11-12 15:34 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: Tobias Burnus, gcc-patches, fortran
Jakub,
I presume that this clears PR33759 as well?
> Ok for trunk?
Yes indeed. Many thanks for the intestinal fortitude that you have displayed:-)
Cheers
Paul
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-12 14:20 ` Jakub Jelinek
2008-11-12 15:34 ` Paul Richard Thomas
@ 2008-11-12 18:09 ` Feng Wang
1 sibling, 0 replies; 28+ messages in thread
From: Feng Wang @ 2008-11-12 18:09 UTC (permalink / raw)
To: Jakub Jelinek, Tobias Burnus; +Cc: gcc-patches, fortran
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=big5, Size: 1640 bytes --]
Hi Jakub, hi all,
--- Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> On Tue, Nov 11, 2008 at 11:34:29PM +0100, Tobias Burnus wrote:
> > Brooks Moses wrote:
> > + gfc_warning ("Assigning value other than 0 or 1 to LOGICAL"
> > + " at %L has undefined result", &expr->where);
> > > The warning could perhaps be edited a little, too, to reflect that the
> > > user isn't necessarily thinking of the input as an integer. Maybe:
> > > "Cannot assign value with bitwise representation other than 0x0 or 0x1
> > > to LOGICAL at %L".
> >
> > I find the original string clearer than especially the "0x0 or 0x1".
>
> So, here is an updated patch, which
> 1) handles transfer (transfer (x, .false.), something) the same way
> as transfer (transfer (x, 0), something) (i.e. uses INTEGER_TYPE
> of the same mode as the BOOLEAN_TYPE that was used previously)
> 2) testcases have been updated
> 3) no checking for INTEGER_CST result from fold_buil1 (V_C_E, ...),
> it just uses integer_zerop and integer_onep.
>
> The middle-end side hasn't changed.
I agree with the use of INTEGER_TYPE, but I don't think it is necessary to give
a warning message. After using INTEGER_TYPE, will other parts still change the
value? What's more, if the warning is given to the transfer and Hollerith
constants, what about the assignment of integer constants? For example:
logical l
l = 45
I cannot access my machine now, so I am not sure that whether this has been
dealt with in some other place.
Best Regards,
Feng Wang
_______________________________________
»¶ÓʹÓó¬´óÈÝÁ¿ÑÅ»¢ÓÊÏä
http://cn.mail.yahoo.com
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 21:46 ` Jakub Jelinek
@ 2008-11-11 22:31 ` Brooks Moses
0 siblings, 0 replies; 28+ messages in thread
From: Brooks Moses @ 2008-11-11 22:31 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: gcc-patches, fortran
Jakub Jelinek wrote, at 11/11/2008 1:35 PM:
> On Tue, Nov 11, 2008 at 01:27:30PM -0800, Brooks Moses wrote:
>>> + else
>>> + gfc_warning ("Assigning value other than 0 or 1 to LOGICAL"
>>> + " at %L might have undefined result", &expr->where);
>> This doesn't -- if I'm understanding it correctly, it warns on any cast
>> of a non-integer value to a logical, regardless of whether the result
>> might or might not in fact be undefined.
>
> No, that's not what it does. This warning is only in case it is constant,
> and stored in memory. So in theory tmp should always be INTEGER_CST.
> I guess I could just assume it (or assert it).
Oh, okay; my mistake from not reading the code thoroughly enough. But,
yes, if it's something that in theory should always be true, then
checking for it as if it's a plausible condition just makes the code
harder to understand.
I think it's reasonable to either assume or assert it, depending on how
confident you are that theory and practice match in this case. Given
that you're creating tmp from a fold_build1 call with an integer type,
it seems safe to assume that it will in fact have an integer TREE_CODE,
and if it doesn't, something is sufficiently broken that it will be
showing up elsewhere too. So I'd just assume it.
The warning could perhaps be edited a little, too, to reflect that the
user isn't necessarily thinking of the input as an integer. Maybe:
"Cannot assign value with bitwise representation other than 0x0 or 0x1
to LOGICAL at %L".
- Brooks
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 15:53 ` Tobias Schlüter
2008-11-11 16:22 ` Jakub Jelinek
2008-11-11 16:22 ` Paul Richard Thomas
@ 2008-11-11 21:56 ` Steve Kargl
2 siblings, 0 replies; 28+ messages in thread
From: Steve Kargl @ 2008-11-11 21:56 UTC (permalink / raw)
To: Tobias Schlüter; +Cc: Jakub Jelinek, gcc-patches, fortran, Feng Wang
On Tue, Nov 11, 2008 at 04:45:40PM +0100, Tobias Schlüter wrote:
> Jakub Jelinek wrote:
> >Unfortrunately, it causes 2 Fortran testsuite failures, hollerith.f90
> >and transfer_simplify_4.f90, both at all optimization levels.
> >I believe the tests are just invalid though. The first one does:
> >logical l
> >l = 4Ho wo
> >and expects all the 32 bits preserved, but that is certainly against
> >the semantics of BOOLEAN_TYPE and from quick skimming of the Fortran
> >standard also LOGICAL type. BOOLEAN_TYPE has just two values, false
> >and true (similarly for LOGICAL .false. and .true.) and so the folder
> >IMHO correctly folds this into
> >l = .true.
> >(4Ho wo is non-zero). The transfer_simplify_4.f90 testcase transfers an
> >integer into logical and back and expects again all the 32-bits to be
> >preserved.
> >
> >Fortran folks, can you please look at these 2 testcases and say whether
> >they are valid Fortran or just undefined behavior?
>
> They are not standard Fortran. Using Hollerith constants this way was
> the way of encoding strings before there was a Character type in
> Fortran, so the current behavior is intentional. Whether there actually
> is code that uses logicals to encode strings, I can't tell. I CCed Feng
> Wang who added the original Hollerith support, and Steve who last
> modified the testcase.
>
My changes in hollerith.f90 were of the form 'complex*16 --> complex(kind=8)'.
It would not have any affect on Jakub proposed patched.
In reviewing the thread, it appears that gfortran may need
to abandon BOOLEAN_TYPE because the description of TRANSFER is
quite clear:
If D and E are scalar variables such that the physical representation
of D is as long as or longer than that of E, the value of
TRANSFER (TRANSFER (E, D), E) shall be the value of E.
unless gfortran can provide a special case for the above. Also, note
that
integer f, e
logical d
e = 42
f = transfer(transfer(e,d),e)
if (f /= e) abort()
end
and
integer f, e
logical d
e = 42
d = transfer(e,d)
f = transfer(d,e)
if (f /= e) abort()
end
can be argued to have different results because the latter has two
explicitly assignments and hence type conversions whereas the
former has only a single assignment with an accompanying type
conversion.
--
Steve
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 21:41 ` Brooks Moses
@ 2008-11-11 21:46 ` Jakub Jelinek
2008-11-11 22:31 ` Brooks Moses
0 siblings, 1 reply; 28+ messages in thread
From: Jakub Jelinek @ 2008-11-11 21:46 UTC (permalink / raw)
To: Brooks Moses; +Cc: gcc-patches, fortran
On Tue, Nov 11, 2008 at 01:27:30PM -0800, Brooks Moses wrote:
> That sounds like a reasonable result. Note, though, that the following
> should not give a warning:
>
> l = transfer(transfer(.true., 3.1415), .true.)
Yes, this compiles without a warning. I'll add a testcase.
> I think we should also add a testcase to confirm that this compiles
> without warning, if we don't have one already:
>
> i = [something defined at runtime]
> l = transfer(i, .true.)
Ok.
> > + else
> > + gfc_warning ("Assigning value other than 0 or 1 to LOGICAL"
> > + " at %L might have undefined result", &expr->where);
>
> This doesn't -- if I'm understanding it correctly, it warns on any cast
> of a non-integer value to a logical, regardless of whether the result
> might or might not in fact be undefined.
No, that's not what it does. This warning is only in case it is constant,
and stored in memory. So in theory tmp should always be INTEGER_CST.
I guess I could just assume it (or assert it).
> Here, we should just get rid of "l" entirely, rather than making it into
> a clone of "i". There's no point in the redundant tests.
Ok.
Jakub
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 21:38 ` Jakub Jelinek
@ 2008-11-11 21:41 ` Brooks Moses
2008-11-11 21:46 ` Jakub Jelinek
0 siblings, 1 reply; 28+ messages in thread
From: Brooks Moses @ 2008-11-11 21:41 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: gcc-patches, fortran
Jakub Jelinek wrote, at 11/11/2008 1:01 PM:
> So would the following be acceptable? It will warn both for
> logical l
> l = 4Hfoob
Personally, I feel that this should be an error, not a warning. But if
distinguishing this from the transfer case complicates the code (which
my interpretation of your patch would suggest that it does), or if other
people feel differently, I don't have a strong opinion here.
> and
> l = transfer (42, .true.)
That sounds like a reasonable result. Note, though, that the following
should not give a warning:
l = transfer(transfer(.true., 3.1415), .true.)
Similarly, there are other things that reliably transfer into integer
values of 0 and 1 (e.g., appropriate string values, though those differ
with endianness) that should not give warnings when transferred to a
logical.
I think we should also add a testcase to confirm that this compiles
without warning, if we don't have one already:
i = [something defined at runtime]
l = transfer(i, .true.)
(Also, we should stop using lower-case ells for logical variables,
because they are horrid for legibility.)
> --- gcc/fortran/trans-const.c.jj 2008-09-30 16:56:44.000000000 +0200
> +++ gcc/fortran/trans-const.c 2008-11-11 21:50:16.000000000 +0100
[...]
> + if (TREE_CODE (tmp) == INTEGER_CST)
> + {
> + if (!integer_zerop (tmp) && !integer_onep (tmp))
> + gfc_warning ("Assigning value other than 0 or 1 to LOGICAL"
> + " at %L has undefined result", &expr->where);
> + }
This looks good.
> + else
> + gfc_warning ("Assigning value other than 0 or 1 to LOGICAL"
> + " at %L might have undefined result", &expr->where);
This doesn't -- if I'm understanding it correctly, it warns on any cast
of a non-integer value to a logical, regardless of whether the result
might or might not in fact be undefined.
I'd be okay with a lack of warning here. Or we could be really fancy
and transfer all non-integer inputs to integers and then do the integer
checks, but that seems excessive.
> --- gcc/testsuite/gfortran.dg/hollerith.f90.jj 2008-09-30 16:56:06.000000000 +0200
> +++ gcc/testsuite/gfortran.dg/hollerith.f90 2008-11-11 13:52:38.000000000 +0100
> @@ -8,7 +8,7 @@ character z1(4)
> character*4 z2(2,2)
> character*80 line
> integer i
> -logical l
> +integer j
> real r
> character*8 c
>
> @@ -20,15 +20,15 @@ data z2/4h(i7),'xxxx','xxxx','xxxx'/
>
> z2 (1,2) = 4h(i8)
> i = 4hHell
> -l = 4Ho wo
> +j = 4Ho wo
> r = 4Hrld!
> -write (line, '(3A4)') i, l, r
> +write (line, '(3A4)') i, j, r
> if (line .ne. 'Hello world!') call abort
> i = 2Hab
> r = 2Hab
> -l = 2Hab
> +j = 2Hab
> c = 2Hab
> -write (line, '(3A4, 8A)') i, l, r, c
> +write (line, '(3A4, 8A)') i, j, r, c
> if (line .ne. 'ab ab ab ab ') call abort
>
> write(line, '(4A8, "!")' ) x
Here, we should just get rid of "l" entirely, rather than making it into
a clone of "i". There's no point in the redundant tests.
> --- gcc/testsuite/gfortran.dg/transfer_simplify_4.f90.jj 2008-09-30 16:56:06.000000000 +0200
> +++ gcc/testsuite/gfortran.dg/transfer_simplify_4.f90 2008-11-11 21:39:07.000000000 +0100
> @@ -6,25 +6,9 @@
> implicit none
>
> integer, parameter :: ip1 = 42
> - logical, parameter :: ap1 = transfer(ip1, .true.)
> - integer, parameter :: ip2 = transfer(ap1, 0)
> -
> - logical :: a
> + integer, parameter :: ip2 = transfer(transfer(ip1, .true.), 0)
> integer :: i
>
> i = transfer(transfer(ip1, .true.), 0)
> if (i .ne. ip1) call abort ()
This needs a comment: "This is a quality-of-implementation issue, not
required by the standard. See discussion at:" and a link to this thread.
Also, you never test the result of ip2. It looks redundant with the
test for i; I don't see the need for both. So I'd suggest either
getting rid of it or testing it.
I've been out of the GFortran loop for long enough that I'd like to have
someone else approve this before committing, but my take is that it's
fine with the above changes.
- Brooks
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 20:50 ` Brooks Moses
@ 2008-11-11 21:38 ` Jakub Jelinek
2008-11-11 21:41 ` Brooks Moses
0 siblings, 1 reply; 28+ messages in thread
From: Jakub Jelinek @ 2008-11-11 21:38 UTC (permalink / raw)
To: Brooks Moses; +Cc: Tobias Burnus, gcc-patches, fortran
On Tue, Nov 11, 2008 at 11:54:25AM -0800, Brooks Moses wrote:
> Tobias Burnus wrote, at 11/11/2008 11:21 AM:
> > The only real problem are Hollerith variables. Here, preserving the bit
> > pattern is crucial. As written before, I think the number of
> > still-in-use programs which use this Fortran-66-only features with
> > LOGICAL variables is very small. However, as (if?) they still exist,
> > some solution needs to be found.
> >
> > (My preferred solution is to stick by default to the current middle-end
> > representation any print a warning or error for assignments of Hollerith
> > constants to logical variables; having a compiler flag to uses
> > internally integer values instead of booleans would be a bonus [I don't
> > see ad hoc how much work this would be].)
>
> I agree. I can see no sensible reason why anyone would have combined
> Hollerith values with LOGICAL variables, and thus see no reason to
> suppose that such code exists. As such, I think it's reasonable to
> print an error if someone tries to do such a thing, and then not worry
> about implementations and compiler flags unless someone happens to
> complain about the error and provides a good reason why they can't
> change their code.
So would the following be acceptable? It will warn both for
logical l
l = 4Hfoob
and
l = transfer (42, .true.)
BTW, even the unmodified gfortran.dg/transfer_simplify_4.f90 tests
fails with vanilla 4.3 or trunk when compiled with -O1 and above,
so claiming we support all of those transfers that way and actually
supporting them only at -O0 is weird. The middle-end hunk hasn't
changed, so I only need Fortran approval...
2008-11-11 Jakub Jelinek <jakub@redhat.com>
PR target/35366
* fold-const.c (native_encode_string): New function.
(native_encode_expr): Use it for STRING_CST.
* trans-const.c (gfc_conv_constant_to_tree): Warn when
converting an integer outside of LOGICAL's range to
LOGICAL.
* gfortran.dg/hollerith.f90: Don't assume a 32-bit value
stored into logical variable will be preserved.
* gfortran.dg/transfer_simplify_4.f90: Remove undefined
cases.
--- gcc/fold-const.c.jj 2008-10-29 18:49:06.000000000 +0100
+++ gcc/fold-const.c 2008-11-11 20:33:49.000000000 +0100
@@ -7315,6 +7315,37 @@ native_encode_vector (const_tree expr, u
}
+/* Subroutine of native_encode_expr. Encode the STRING_CST
+ specified by EXPR into the buffer PTR of length LEN bytes.
+ Return the number of bytes placed in the buffer, or zero
+ upon failure. */
+
+static int
+native_encode_string (const_tree expr, unsigned char *ptr, int len)
+{
+ tree type = TREE_TYPE (expr);
+ HOST_WIDE_INT total_bytes;
+
+ if (TREE_CODE (type) != ARRAY_TYPE
+ || TREE_CODE (TREE_TYPE (type)) != INTEGER_TYPE
+ || GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (type))) != BITS_PER_UNIT
+ || !host_integerp (TYPE_SIZE_UNIT (type), 0))
+ return 0;
+ total_bytes = tree_low_cst (TYPE_SIZE_UNIT (type), 0);
+ if (total_bytes > len)
+ return 0;
+ if (TREE_STRING_LENGTH (expr) < total_bytes)
+ {
+ memcpy (ptr, TREE_STRING_POINTER (expr), TREE_STRING_LENGTH (expr));
+ memset (ptr + TREE_STRING_LENGTH (expr), 0,
+ total_bytes - TREE_STRING_LENGTH (expr));
+ }
+ else
+ memcpy (ptr, TREE_STRING_POINTER (expr), total_bytes);
+ return total_bytes;
+}
+
+
/* Subroutine of fold_view_convert_expr. Encode the INTEGER_CST,
REAL_CST, COMPLEX_CST or VECTOR_CST specified by EXPR into the
buffer PTR of length LEN bytes. Return the number of bytes
@@ -7337,6 +7368,9 @@ native_encode_expr (const_tree expr, uns
case VECTOR_CST:
return native_encode_vector (expr, ptr, len);
+ case STRING_CST:
+ return native_encode_string (expr, ptr, len);
+
default:
return 0;
}
--- gcc/fortran/trans-const.c.jj 2008-09-30 16:56:44.000000000 +0200
+++ gcc/fortran/trans-const.c 2008-11-11 21:50:16.000000000 +0100
@@ -281,13 +281,25 @@ gfc_conv_constant_to_tree (gfc_expr * ex
case BT_LOGICAL:
if (expr->representation.string)
- return fold_build1 (VIEW_CONVERT_EXPR,
- gfc_get_logical_type (expr->ts.kind),
- gfc_build_string_const (expr->representation.length,
- expr->representation.string));
+ {
+ tree tmp = fold_build1 (VIEW_CONVERT_EXPR,
+ gfc_get_int_type (expr->ts.kind),
+ gfc_build_string_const (expr->representation.length,
+ expr->representation.string));
+ if (TREE_CODE (tmp) == INTEGER_CST)
+ {
+ if (!integer_zerop (tmp) && !integer_onep (tmp))
+ gfc_warning ("Assigning value other than 0 or 1 to LOGICAL"
+ " at %L has undefined result", &expr->where);
+ }
+ else
+ gfc_warning ("Assigning value other than 0 or 1 to LOGICAL"
+ " at %L might have undefined result", &expr->where);
+ return fold_convert (gfc_get_logical_type (expr->ts.kind), tmp);
+ }
else
return build_int_cst (gfc_get_logical_type (expr->ts.kind),
- expr->value.logical);
+ expr->value.logical);
case BT_COMPLEX:
if (expr->representation.string)
--- gcc/testsuite/gfortran.dg/hollerith.f90.jj 2008-09-30 16:56:06.000000000 +0200
+++ gcc/testsuite/gfortran.dg/hollerith.f90 2008-11-11 13:52:38.000000000 +0100
@@ -8,7 +8,7 @@ character z1(4)
character*4 z2(2,2)
character*80 line
integer i
-logical l
+integer j
real r
character*8 c
@@ -20,15 +20,15 @@ data z2/4h(i7),'xxxx','xxxx','xxxx'/
z2 (1,2) = 4h(i8)
i = 4hHell
-l = 4Ho wo
+j = 4Ho wo
r = 4Hrld!
-write (line, '(3A4)') i, l, r
+write (line, '(3A4)') i, j, r
if (line .ne. 'Hello world!') call abort
i = 2Hab
r = 2Hab
-l = 2Hab
+j = 2Hab
c = 2Hab
-write (line, '(3A4, 8A)') i, l, r, c
+write (line, '(3A4, 8A)') i, j, r, c
if (line .ne. 'ab ab ab ab ') call abort
write(line, '(4A8, "!")' ) x
--- gcc/testsuite/gfortran.dg/transfer_simplify_4.f90.jj 2008-09-30 16:56:06.000000000 +0200
+++ gcc/testsuite/gfortran.dg/transfer_simplify_4.f90 2008-11-11 21:39:07.000000000 +0100
@@ -6,25 +6,9 @@
implicit none
integer, parameter :: ip1 = 42
- logical, parameter :: ap1 = transfer(ip1, .true.)
- integer, parameter :: ip2 = transfer(ap1, 0)
-
- logical :: a
+ integer, parameter :: ip2 = transfer(transfer(ip1, .true.), 0)
integer :: i
i = transfer(transfer(ip1, .true.), 0)
if (i .ne. ip1) call abort ()
-
- 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 ()
-
end
Jakub
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 18:10 ` Jakub Jelinek
` (2 preceding siblings ...)
2008-11-11 19:36 ` Tobias Burnus
@ 2008-11-11 21:27 ` Thomas Koenig
3 siblings, 0 replies; 28+ messages in thread
From: Thomas Koenig @ 2008-11-11 21:27 UTC (permalink / raw)
To: Jakub Jelinek
Cc: Tobias Schlüter, gcc-patches, fortran, Steve Kargl,
Feng Wang, Brooks Moses
On Tue, 2008-11-11 at 18:49 +0100, Jakub Jelinek wrote:
> How is LOGICAL supposed to behave if it is storage associated with an
> integer? Defined only if the integer stored has been 0 or 1, or 0 .false.
> and non-zero .true., or something else?
0 is .false., 1 is .true., anything else is undefined.
We already make use of this in the library. For example, for mask
arguments, we only check the lower byte.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 19:36 ` Tobias Burnus
@ 2008-11-11 20:50 ` Brooks Moses
2008-11-11 21:38 ` Jakub Jelinek
0 siblings, 1 reply; 28+ messages in thread
From: Brooks Moses @ 2008-11-11 20:50 UTC (permalink / raw)
To: Tobias Burnus; +Cc: gcc-patches, fortran, Brooks Moses
Tobias Burnus wrote, at 11/11/2008 11:21 AM:
> The only real problem are Hollerith variables. Here, preserving the bit
> pattern is crucial. As written before, I think the number of
> still-in-use programs which use this Fortran-66-only features with
> LOGICAL variables is very small. However, as (if?) they still exist,
> some solution needs to be found.
>
> (My preferred solution is to stick by default to the current middle-end
> representation any print a warning or error for assignments of Hollerith
> constants to logical variables; having a compiler flag to uses
> internally integer values instead of booleans would be a bonus [I don't
> see ad hoc how much work this would be].)
I agree. I can see no sensible reason why anyone would have combined
Hollerith values with LOGICAL variables, and thus see no reason to
suppose that such code exists. As such, I think it's reasonable to
print an error if someone tries to do such a thing, and then not worry
about implementations and compiler flags unless someone happens to
complain about the error and provides a good reason why they can't
change their code.
- Brooks
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 19:34 ` Jakub Jelinek
@ 2008-11-11 19:38 ` Brooks Moses
0 siblings, 0 replies; 28+ messages in thread
From: Brooks Moses @ 2008-11-11 19:38 UTC (permalink / raw)
To: Jakub Jelinek
Cc: Tobias Schlüter, gcc-patches, fortran, Steve Kargl,
Feng Wang, Brooks Moses
Jakub Jelinek wrote, at 11/11/2008 11:12 AM:
> As I said earlier, transfer (transfer (234, .false.), 0) is already
> identity, as that never goes through middle-end and BOOLEAN_TYPE.
> If assigning transfer (234, .false.) to logical is undefined behavior,
> then the only problematic case is
> integer :: i, j
> i = 234
> ...
> j = transfer (transfer (i, .false.), 0)
> (when it is non-constant). Currently the FE expands this as
> 2 separate transfers and the optimizers will be able to see through them,
> but I'd say the FE could look through the
> transfer in the first argument and do whatever the standard requires,
> before handing it to the middle-end. In this case change it to
> j = transfer (i, 0) (or just i).
We could, yes. At this point, I don't think it's worth the bother (and
risk of additional bugs) of implementing it, until we get a case where
someone actually complains about it. (And, frankly, I wish I hadn't
implemented it for the constant-folding case; as I recall, it made the
code rather a good bit more complex, and from today's perspective I
don't see the point.)
It might be useful to put something explicit into the TRANSFER
documentation pointing out the undefined behavior in the case of LOGICAL
values for the MOLD argument, though.
- Brooks
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 18:10 ` Jakub Jelinek
2008-11-11 19:07 ` Janne Blomqvist
2008-11-11 19:22 ` Brooks Moses
@ 2008-11-11 19:36 ` Tobias Burnus
2008-11-11 20:50 ` Brooks Moses
2008-11-11 21:27 ` Thomas Koenig
3 siblings, 1 reply; 28+ messages in thread
From: Tobias Burnus @ 2008-11-11 19:36 UTC (permalink / raw)
To: Jakub Jelinek
Cc: Tobias Schlüter, gcc-patches, fortran, Steve Kargl,
Feng Wang, Brooks Moses
Jakub Jelinek wrote:
> How is LOGICAL supposed to behave if it is storage associated with an
> integer? Defined only if the integer stored has been 0 or 1, or 0 .false.
> and non-zero .true., or something else?
>
Note: I strongly believe that EQUIVALENCE*, COMMON* and TRANSFER are no
true problems - using them is outside the Fortran standard and using
them does not make much sense. (* here applies: "When a variable of a
given type becomes defined, all associated variables of different type
become undefined.").
The only real problem are Hollerith variables. Here, preserving the bit
pattern is crucial. As written before, I think the number of
still-in-use programs which use this Fortran-66-only features with
LOGICAL variables is very small. However, as (if?) they still exist,
some solution needs to be found.
(My preferred solution is to stick by default to the current middle-end
representation any print a warning or error for assignments of Hollerith
constants to logical variables; having a compiler flag to uses
internally integer values instead of booleans would be a bonus [I don't
see ad hoc how much work this would be].)
> But does the standard really say anything about this? Isn't assignment
> to a LOGICAL value supposed to set to to .false. or .true.?
>
I think the standard leaves this to the implementor as long as for
"logical = .true." "logical" is true and for "logical = .false." it is
false, the program should be standard conform, independent what internal
value "logical" has; that the bit pattern remains the same is a pure
convenience.
* * *
For whatever it is worth: I posted to comp.lang.fortran to ask whether
there is anything in the Fortran 77 to 2008 standard which mandates that
the bit pattern is preserved (I don't think so); I further asked whether
there is some compelling real-world case for preserving it. See:
http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/cf874197dc460679#
Tobias
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 19:17 ` Brooks Moses
@ 2008-11-11 19:34 ` Jakub Jelinek
2008-11-11 19:38 ` Brooks Moses
0 siblings, 1 reply; 28+ messages in thread
From: Jakub Jelinek @ 2008-11-11 19:34 UTC (permalink / raw)
To: Brooks Moses
Cc: Tobias Schlüter, gcc-patches, fortran, Steve Kargl,
Feng Wang, Brooks Moses
On Tue, Nov 11, 2008 at 10:54:11AM -0800, Brooks Moses wrote:
> 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.
As I said earlier, transfer (transfer (234, .false.), 0) is already
identity, as that never goes through middle-end and BOOLEAN_TYPE.
If assigning transfer (234, .false.) to logical is undefined behavior,
then the only problematic case is
integer :: i, j
i = 234
...
j = transfer (transfer (i, .false.), 0)
(when it is non-constant). Currently the FE expands this as
2 separate transfers and the optimizers will be able to see through them,
but I'd say the FE could look through the
transfer in the first argument and do whatever the standard requires,
before handing it to the middle-end. In this case change it to
j = transfer (i, 0) (or just i).
Jakub
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 18:10 ` Jakub Jelinek
2008-11-11 19:07 ` Janne Blomqvist
@ 2008-11-11 19:22 ` Brooks Moses
2008-11-11 19:36 ` Tobias Burnus
2008-11-11 21:27 ` Thomas Koenig
3 siblings, 0 replies; 28+ messages in thread
From: Brooks Moses @ 2008-11-11 19:22 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: gcc-patches, fortran, Brooks Moses
Jakub Jelinek wrote, at 11/11/2008 9:49 AM:
> How is LOGICAL supposed to behave if it is storage associated with an
> integer? Defined only if the integer stored has been 0 or 1, or 0 .false.
> and non-zero .true., or something else?
Either one of those makes sense to me. Like all type-punning (other
than transfer round-trips in cases where they're legal), it's
implementation defined, and either one of those is as good a definition
as any.
(Personally, I'm in favor of the 0->false, 1->true, other->undefined
version, on grounds that it's the least necessary specification and thus
easiest to maintain compatibility with in the future.)
- Brooks
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 16:26 ` Tobias Schlüter
2008-11-11 17:21 ` Jakub Jelinek
@ 2008-11-11 19:17 ` Brooks Moses
2008-11-11 19:34 ` Jakub Jelinek
1 sibling, 1 reply; 28+ messages in thread
From: Brooks Moses @ 2008-11-11 19:17 UTC (permalink / raw)
To: Tobias Schlüter
Cc: Jakub Jelinek, gcc-patches, fortran, Steve Kargl, Feng Wang,
Brooks Moses
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
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 18:10 ` Jakub Jelinek
@ 2008-11-11 19:07 ` Janne Blomqvist
2008-11-11 19:22 ` Brooks Moses
` (2 subsequent siblings)
3 siblings, 0 replies; 28+ messages in thread
From: Janne Blomqvist @ 2008-11-11 19:07 UTC (permalink / raw)
To: Jakub Jelinek
Cc: Tobias Schlüter, gcc-patches, fortran, Steve Kargl,
Feng Wang, Brooks Moses
On Tue, Nov 11, 2008 at 19:49, Jakub Jelinek <jakub@redhat.com> wrote:
> On Tue, Nov 11, 2008 at 06:01:52PM +0100, Tobias Schlüter wrote:
>> Jakub Jelinek wrote:
>>> On Tue, Nov 11, 2008 at 05:21:36PM +0100, Tobias Schlüter wrote:
>>>> 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. 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.
>>>
>>> That's pretty sad. Stopping using BOOLEAN_TYPE is going to break
>>> basically everything, so certainly can't be done for 4.4. I expect
>>> that you'd need to add a lot of conversions everywhere, from the
>>> logical*N INTEGER_TYPE to correspondingly sized BOOLEAN_TYPE and back
>>> all the time.
>>
>> Maybe setting TYPE_PRECISION to bit_size in gfc_build_logical_type()
>> would do the trick without any further changes? This depends on how the
>> middle-end deals with BOOLEAN_TYPES with TYPE_PRECISION > 1.
>
> It wouldn't help:
>
> /* Boolean type (true or false are the only values). Looks like an
> INTEGRAL_TYPE. */
> DEFTREECODE (BOOLEAN_TYPE, "boolean_type", tcc_type, 0)
>
> On the other side, if you have to convert from INTEGER_TYPE to BOOLEAN_TYPE
> all the time, the generated code will be very abysmal.
>
> How is LOGICAL supposed to behave if it is storage associated with an
> integer? Defined only if the integer stored has been 0 or 1, or 0 .false.
> and non-zero .true., or something else?
The standard doesn't specify what is the internal representation of
logical values, other than that the size of default LOGICAL is the
same as other types of default kind. If you search on google groups
for "Richard Maine transfer logical" you'll find the threads "Transfer
and variables that don't use all their storage space." and "Trying to
use a logical as an array index" with arguments about this point
(Richard Maine was the editor of the Fortran 2003 standard, so he
generally knows what he's talking about).
The loophole seems to be that if the transfer generates an illegal
value, then the program becomes non-standard and the compiler can do
whatever it wants.
I.e. while the point of transfer is more or less to do type-punning
via straight-forward copying of bits, the resulting bit patterns must
be a valid bit pattern for the type in question if the program is to
be standard-conforming.
--
Janne Blomqvist
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 17:22 ` Tobias Schlüter
@ 2008-11-11 18:10 ` Jakub Jelinek
2008-11-11 19:07 ` Janne Blomqvist
` (3 more replies)
0 siblings, 4 replies; 28+ messages in thread
From: Jakub Jelinek @ 2008-11-11 18:10 UTC (permalink / raw)
To: Tobias Schlüter
Cc: gcc-patches, fortran, Steve Kargl, Feng Wang, Brooks Moses
On Tue, Nov 11, 2008 at 06:01:52PM +0100, Tobias Schlüter wrote:
> Jakub Jelinek wrote:
>> On Tue, Nov 11, 2008 at 05:21:36PM +0100, Tobias Schlüter wrote:
>>> 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. 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.
>>
>> That's pretty sad. Stopping using BOOLEAN_TYPE is going to break
>> basically everything, so certainly can't be done for 4.4. I expect
>> that you'd need to add a lot of conversions everywhere, from the
>> logical*N INTEGER_TYPE to correspondingly sized BOOLEAN_TYPE and back
>> all the time.
>
> Maybe setting TYPE_PRECISION to bit_size in gfc_build_logical_type()
> would do the trick without any further changes? This depends on how the
> middle-end deals with BOOLEAN_TYPES with TYPE_PRECISION > 1.
It wouldn't help:
/* Boolean type (true or false are the only values). Looks like an
INTEGRAL_TYPE. */
DEFTREECODE (BOOLEAN_TYPE, "boolean_type", tcc_type, 0)
On the other side, if you have to convert from INTEGER_TYPE to BOOLEAN_TYPE
all the time, the generated code will be very abysmal.
How is LOGICAL supposed to behave if it is storage associated with an
integer? Defined only if the integer stored has been 0 or 1, or 0 .false.
and non-zero .true., or something else?
Also, even with my patch
integer, parameter :: i = transfer (transfer (42, .true.), 0)
will work as the standard requires (in this case the transfers
are resolved in the FE, and only one VIEW_CONVERT_EXPR is created
(and folded to 42). But that's not what is failing in
transfer_simplify_4.f90. What fails is:
a = transfer(ip1, .true.)
i = transfer(a, 0)
if (i .ne. ip1) call abort ()
(as ip1 is parameter, then this is the same as
a = transfer(42, .true.)
i = transfer(a, 0)
if (i .ne. ip1) call abort ()
). If I modify the testcase slightly:
implicit none
integer :: ip1
logical :: a
integer :: i
ip1 = 42
a = transfer(ip1, .true.)
i = transfer(a, 0)
if (i .ne. ip1) call abort ()
end
then it fails even with unpatched gfortran (even with 4.3) at -O1 and higher.
But does the standard really say anything about this? Isn't assignment
to a LOGICAL value supposed to set to to .false. or .true.?
Jakub
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 16:22 ` Jakub Jelinek
2008-11-11 16:26 ` Tobias Schlüter
@ 2008-11-11 17:30 ` Tobias Burnus
1 sibling, 0 replies; 28+ messages in thread
From: Tobias Burnus @ 2008-11-11 17:30 UTC (permalink / raw)
To: Jakub Jelinek
Cc: Tobias Schlüter, gcc-patches, fortran, Steve Kargl, Feng Wang
Hi,
Jakub Jelinek wrote:
> If using logicals is required to store all the bits of the constants
> (and similarly for TRANSFER from integer to logical), then I'm afraid the
> Fortran FE would have to stop using BOOLEAN_TYPE for logical, as the
> middle-end BOOLEAN_TYPE really has the semantics that it is either false or
> true, nothing else.
>
According to the standard, what TRANSFER does is implementation
dependent (though one can assume that most of the time the bits are
transferred one-to-one).
In words of the standard: "Result Value. If the physical representation
of the result has the same length as that of SOURCE, the physical
representation of the result is that of SOURCE." The point is: The
standard does not tell what is meant by "physical representation"; I
read it such that the standard does not 100% require that an integer ->
logical -> integer round trip yields the same result. (Though it should
if possible.=
In any case, I don't see any use in doing such round trips - and I also
do not see any use in TRANSFERring anything to logical as it is
completely opaque which bit pattern is regarded as .true. and what as
.false. For instance:
- gfortran (and C) use "== 0" for .false. and "!= 0" for .true. where by
default transfer(.true., 0) == 1.
- Intel's ifort has the same 0 and 1 defaults, but e.g. "2" is FALSE
- (other compilers might have different choices, taking only the
highest/lowest bit, or ...)
(I think TRANSFERring to logical is based on the misconception that
INTEGER and LOGICAL are internally the same data type, similarly to
_Bool and int in C.)
* * *
Regarding Holleriths: They were added in Fortran 66 while LOGICAL exists
since Fortran IV. In Fortran 77 the CHARACTER type was introduced and
Hollerith was deleted from the standard (but it is still listed in
Appendix C). Appendix C has: "Hollerith data, other than constants, are
identified under the guise of a name of type integer, real, or logical."
(See http://gcc.gnu.org/wiki/GFortranStandards for links to the various
Fortran standards.)
Thus that "logical = 4Ho wo" yielding "1" _is_ a problem for certain old
code, though as Holleriths were deleted, this conversion is OK from the
standard perspective.
I assume that by far the most Fortran programs use INTEGER for
Holleriths, but I don't rule out the possibility that some use LOGICAL.
* * *
You see that I'm mainly concerned about Holleriths and less about "(some
type) -> logical -> (some type)" transfers.
I'm wondering whether one needs some special flag to use optionally
internally integers instead of booleans for LOGICAL, with a warning
printed if the option is disabled (as it should be by default) in case a
TRANSFER to a LOGICAL or an assignment of a Hollerith to a logical
variable is found.
But as default I'm in favour to keep the status quo in the front end:
Use the middle end's boolean type for LOGICAL. And I'm in favour of
doing the folding as Jakub's patch does.
Tobias
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 17:21 ` Jakub Jelinek
@ 2008-11-11 17:22 ` Tobias Schlüter
2008-11-11 18:10 ` Jakub Jelinek
0 siblings, 1 reply; 28+ messages in thread
From: Tobias Schlüter @ 2008-11-11 17:22 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: gcc-patches, fortran, Steve Kargl, Feng Wang, Brooks Moses
Jakub Jelinek wrote:
> On Tue, Nov 11, 2008 at 05:21:36PM +0100, Tobias Schlüter wrote:
>> 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. 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.
>
> That's pretty sad. Stopping using BOOLEAN_TYPE is going to break
> basically everything, so certainly can't be done for 4.4. I expect
> that you'd need to add a lot of conversions everywhere, from the
> logical*N INTEGER_TYPE to correspondingly sized BOOLEAN_TYPE and back
> all the time.
Maybe setting TYPE_PRECISION to bit_size in gfc_build_logical_type()
would do the trick without any further changes? This depends on how the
middle-end deals with BOOLEAN_TYPES with TYPE_PRECISION > 1.
Cheers,
- Tobi
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 16:26 ` Tobias Schlüter
@ 2008-11-11 17:21 ` Jakub Jelinek
2008-11-11 17:22 ` Tobias Schlüter
2008-11-11 19:17 ` Brooks Moses
1 sibling, 1 reply; 28+ messages in thread
From: Jakub Jelinek @ 2008-11-11 17:21 UTC (permalink / raw)
To: Tobias Schlüter
Cc: gcc-patches, fortran, Steve Kargl, Feng Wang, Brooks Moses
On Tue, Nov 11, 2008 at 05:21:36PM +0100, Tobias Schlüter wrote:
> 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. 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.
That's pretty sad. Stopping using BOOLEAN_TYPE is going to break
basically everything, so certainly can't be done for 4.4. I expect
that you'd need to add a lot of conversions everywhere, from the
logical*N INTEGER_TYPE to correspondingly sized BOOLEAN_TYPE and back
all the time.
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?
I guess I could in fold_view_convert_expr temporarily
/* XXX: Fortran workaround - the FE sometimes wants BOOLEAN_TYPE semantics
and sometimes not. */
if (TREE_CODE (type) == BOOLEAN_TYPE && TREE_CODE (expr) == STRING_CST)
return NULL_TREE;
and the FE would need to make sure the STRING_CST has enough aligned type
(on the STRING_CST TREE_TYPE (string_cst) = copy_node (TREE_TYPE (string_cst));
and TYPE_ALIGN (TREE_TYPE (string_cst)) = TYPE_ALIGN (gfc_get_logical_type
(expr->ts.kind)); TYPE_USER_ALIGN (TREE_TYPE (string_cst)) = 1;),
but guess Richi isn't going to look favourably at it. Unfortunately
the result of TRANSFER is supposed to be a constant :(, so we can't play
games with asm, volatile or some other optimization barrier.
Jakub
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 16:22 ` Paul Richard Thomas
@ 2008-11-11 16:45 ` Tobias Schlüter
0 siblings, 0 replies; 28+ messages in thread
From: Tobias Schlüter @ 2008-11-11 16:45 UTC (permalink / raw)
To: Paul Richard Thomas
Cc: Jakub Jelinek, gcc-patches, fortran, Steve Kargl, Feng Wang
Paul Richard Thomas wrote:
> Tobi and Jakub,
>
>> They are not standard Fortran. Using Hollerith constants this way was the
>> way of encoding strings before there was a Character type in Fortran, so the
>> current behavior is intentional. Whether there actually is code that uses
>> logicals to encode strings, I can't tell. I CCed Feng Wang who added the
>> original Hollerith support, and Steve who last modified the testcase.
>
> I am not so sure about that in the case of transfer_simplify_4.f90 -
> we have already had serious amounts of correspondence about it as
> witnessed in PR33759. What the standard says is:
Yes sorry, I phrased this wrongly, I had intended to only talk about the
use of Hollerith constants. But this is moot because due to what both
Jakub and you rightfully pointed out, LOGICAL will likely have to seize
being a BOOLEAN_TYPE. Which in turn will restore the traditional
Hollerith behavior. If all goes well.
Cheers,
- Tobi
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 16:22 ` Jakub Jelinek
@ 2008-11-11 16:26 ` Tobias Schlüter
2008-11-11 17:21 ` Jakub Jelinek
2008-11-11 19:17 ` Brooks Moses
2008-11-11 17:30 ` Tobias Burnus
1 sibling, 2 replies; 28+ messages in thread
From: Tobias Schlüter @ 2008-11-11 16:26 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: gcc-patches, fortran, Steve Kargl, Feng Wang, Brooks Moses
Jakub Jelinek wrote:
>> They are not standard Fortran. Using Hollerith constants this way was
>> the way of encoding strings before there was a Character type in
>> Fortran, so the current behavior is intentional. Whether there actually
>> is code that uses logicals to encode strings, I can't tell. I CCed Feng
>> Wang who added the original Hollerith support, and Steve who last
>> modified the testcase.
>
> If using logicals is required to store all the bits of the constants
> (and similarly for TRANSFER from integer to logical), then I'm afraid the
> Fortran FE would have to stop using BOOLEAN_TYPE for logical, as the
> middle-end BOOLEAN_TYPE really has the semantics that it is either false or
> true, nothing else.
> 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... 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."
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. 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.
Cheers,
- Tobi
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 15:53 ` Tobias Schlüter
@ 2008-11-11 16:22 ` Jakub Jelinek
2008-11-11 16:26 ` Tobias Schlüter
2008-11-11 17:30 ` Tobias Burnus
2008-11-11 16:22 ` Paul Richard Thomas
2008-11-11 21:56 ` Steve Kargl
2 siblings, 2 replies; 28+ messages in thread
From: Jakub Jelinek @ 2008-11-11 16:22 UTC (permalink / raw)
To: Tobias Schlüter; +Cc: gcc-patches, fortran, Steve Kargl, Feng Wang
On Tue, Nov 11, 2008 at 04:45:40PM +0100, Tobias Schlüter wrote:
> Jakub Jelinek wrote:
>> Unfortrunately, it causes 2 Fortran testsuite failures, hollerith.f90
>> and transfer_simplify_4.f90, both at all optimization levels.
>> I believe the tests are just invalid though. The first one does:
>> logical l
>> l = 4Ho wo
>> and expects all the 32 bits preserved, but that is certainly against
>> the semantics of BOOLEAN_TYPE and from quick skimming of the Fortran
>> standard also LOGICAL type. BOOLEAN_TYPE has just two values, false
>> and true (similarly for LOGICAL .false. and .true.) and so the folder
>> IMHO correctly folds this into
>> l = .true.
>> (4Ho wo is non-zero). The transfer_simplify_4.f90 testcase transfers an
>> integer into logical and back and expects again all the 32-bits to be
>> preserved.
>>
>> Fortran folks, can you please look at these 2 testcases and say whether
>> they are valid Fortran or just undefined behavior?
>
> They are not standard Fortran. Using Hollerith constants this way was
> the way of encoding strings before there was a Character type in
> Fortran, so the current behavior is intentional. Whether there actually
> is code that uses logicals to encode strings, I can't tell. I CCed Feng
> Wang who added the original Hollerith support, and Steve who last
> modified the testcase.
If using logicals is required to store all the bits of the constants
(and similarly for TRANSFER from integer to logical), then I'm afraid the
Fortran FE would have to stop using BOOLEAN_TYPE for logical, as the
middle-end BOOLEAN_TYPE really has the semantics that it is either false or
true, nothing else.
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... 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."
Jakub
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 15:53 ` Tobias Schlüter
2008-11-11 16:22 ` Jakub Jelinek
@ 2008-11-11 16:22 ` Paul Richard Thomas
2008-11-11 16:45 ` Tobias Schlüter
2008-11-11 21:56 ` Steve Kargl
2 siblings, 1 reply; 28+ messages in thread
From: Paul Richard Thomas @ 2008-11-11 16:22 UTC (permalink / raw)
To: Tobias Schlüter
Cc: Jakub Jelinek, gcc-patches, fortran, Steve Kargl, Feng Wang
Tobi and Jakub,
> They are not standard Fortran. Using Hollerith constants this way was the
> way of encoding strings before there was a Character type in Fortran, so the
> current behavior is intentional. Whether there actually is code that uses
> logicals to encode strings, I can't tell. I CCed Feng Wang who added the
> original Hollerith support, and Steve who last modified the testcase.
I am not so sure about that in the case of transfer_simplify_4.f90 -
we have already had serious amounts of correspondence about it as
witnessed in PR33759. What the standard says is:
>
13.14.110 TRANSFER (SOURCE, MOLD [, SIZE])
Description. Returns a result with a physical representation identical
to that of SOURCE but interpreted with the type and type parameters of
MOLD.
Class. Transformational function.
Arguments.
SOURCE may be of any type and may be scalar or array valued.
MOLD may be of any type and may be scalar or array valued.
SIZE (optional) shall be scalar and of type integer. The corresponding
actual argument shall not be an optional dummy argument.
Result Characteristics. The result is of the same type and type
parameters as MOLD.
Case (i): If MOLD is a scalar and SIZE is absent, the result is a scalar.
Case (ii): If MOLD is array valued and SIZE is absent, the result is
array valued and of rank one. Its size is as small as possible such
that its physical representation is not shorter than that of SOURCE.
Case (iii): If SIZE is present, the result is array valued of rank one
and size SIZE.
Result Value. If the physical representation of the result has the
same length as that of SOURCE, the physical representation of the
result is that of SOURCE. If the physical representation of the result
is longer than that of SOURCE, the physical representation of the
leading part is that of SOURCE and the remainder is undefined. If the
physical representation of the result is shorter than that of SOURCE,
the physical representation of the result is the leading part of
SOURCE. If D and E are scalar variables such that the physical
representation of D is as long as or longer than that of E, the value
of TRANSFER (TRANSFER (E, D), E) shall be the value of E. IF D is an
array and E is an array of rank one, the value of TRANSFER (TRANSFER
(E, D), E, SIZE (E)) shall be the value of E.
or... as Jakub paraphrases it:
> (4Ho wo is non-zero). The transfer_simplify_4.f90 testcase transfers an
> integer into logical and back and expects again all the 32-bits to be
> preserved.
I would say that it conforms to the standard.
Cheers
Paul
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 13:27 Jakub Jelinek
2008-11-11 15:40 ` Richard Guenther
@ 2008-11-11 15:53 ` Tobias Schlüter
2008-11-11 16:22 ` Jakub Jelinek
` (2 more replies)
1 sibling, 3 replies; 28+ messages in thread
From: Tobias Schlüter @ 2008-11-11 15:53 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: gcc-patches, fortran, Steve Kargl, Feng Wang
Jakub Jelinek wrote:
> Unfortrunately, it causes 2 Fortran testsuite failures, hollerith.f90
> and transfer_simplify_4.f90, both at all optimization levels.
> I believe the tests are just invalid though. The first one does:
> logical l
> l = 4Ho wo
> and expects all the 32 bits preserved, but that is certainly against
> the semantics of BOOLEAN_TYPE and from quick skimming of the Fortran
> standard also LOGICAL type. BOOLEAN_TYPE has just two values, false
> and true (similarly for LOGICAL .false. and .true.) and so the folder
> IMHO correctly folds this into
> l = .true.
> (4Ho wo is non-zero). The transfer_simplify_4.f90 testcase transfers an
> integer into logical and back and expects again all the 32-bits to be
> preserved.
>
> Fortran folks, can you please look at these 2 testcases and say whether
> they are valid Fortran or just undefined behavior?
They are not standard Fortran. Using Hollerith constants this way was
the way of encoding strings before there was a Character type in
Fortran, so the current behavior is intentional. Whether there actually
is code that uses logicals to encode strings, I can't tell. I CCed Feng
Wang who added the original Hollerith support, and Steve who last
modified the testcase.
Cheers,
- Tobi
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
2008-11-11 13:27 Jakub Jelinek
@ 2008-11-11 15:40 ` Richard Guenther
2008-11-11 15:53 ` Tobias Schlüter
1 sibling, 0 replies; 28+ messages in thread
From: Richard Guenther @ 2008-11-11 15:40 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: gcc-patches, fortran
On Tue, Nov 11, 2008 at 7:17 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> Fortran FE generates VIEW_CONVERT_EXPR of STRING_CST quite a lot, but
> fold-const isn't able to fold it, so GCC generates very inefficient
> and (in some cases also buggy, as can be seen on the equiv_7.f90
> on powerpc64-darwin with -m64 -Os) code.
>
> I've bootstrapped/regtested this on x86_64-linux.
>
> Unfortrunately, it causes 2 Fortran testsuite failures, hollerith.f90
> and transfer_simplify_4.f90, both at all optimization levels.
> I believe the tests are just invalid though. The first one does:
> logical l
> l = 4Ho wo
> and expects all the 32 bits preserved, but that is certainly against
> the semantics of BOOLEAN_TYPE and from quick skimming of the Fortran
> standard also LOGICAL type. BOOLEAN_TYPE has just two values, false
> and true (similarly for LOGICAL .false. and .true.) and so the folder
> IMHO correctly folds this into
> l = .true.
> (4Ho wo is non-zero). The transfer_simplify_4.f90 testcase transfers an
> integer into logical and back and expects again all the 32-bits to be
> preserved.
>
> Fortran folks, can you please look at these 2 testcases and say whether
> they are valid Fortran or just undefined behavior?
The patch is ok if the fortran folks are happy with it.
Thanks,
Richard.
> 2008-11-11 Jakub Jelinek <jakub@redhat.com>
>
> PR target/35366
> * fold-const.c (native_encode_string): New function.
> (native_encode_expr): Use it for STRING_CST.
>
> * gfortran.dg/hollerith.f90: Don't assume a 32-bit value
> stored into logical variable will be preserved.
> * gfortran.dg/transfer_simplify_4.f90: Removed.
>
> --- gcc/fold-const.c.jj 2008-10-29 18:49:06.000000000 +0100
> +++ gcc/fold-const.c 2008-11-11 11:41:34.000000000 +0100
> @@ -7315,6 +7315,37 @@ native_encode_vector (const_tree expr, u
> }
>
>
> +/* Subroutine of native_encode_expr. Encode the STRING_CST
> + specified by EXPR into the buffer PTR of length LEN bytes.
> + Return the number of bytes placed in the buffer, or zero
> + upon failure. */
> +
> +static int
> +native_encode_string (const_tree expr, unsigned char *ptr, int len)
> +{
> + tree type = TREE_TYPE (expr);
> + HOST_WIDE_INT total_bytes;
> +
> + if (TREE_CODE (type) != ARRAY_TYPE
> + || TREE_CODE (TREE_TYPE (type)) != INTEGER_TYPE
> + || GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (type))) != BITS_PER_UNIT
> + || !host_integerp (TYPE_SIZE_UNIT (type), 0))
> + return 0;
> + total_bytes = tree_low_cst (TYPE_SIZE_UNIT (type), 0);
> + if (total_bytes > len)
> + return 0;
> + if (TREE_STRING_LENGTH (expr) < total_bytes)
> + {
> + memcpy (ptr, TREE_STRING_POINTER (expr), TREE_STRING_LENGTH (expr));
> + memset (ptr + TREE_STRING_LENGTH (expr), 0,
> + total_bytes - TREE_STRING_LENGTH (expr));
> + }
> + else
> + memcpy (ptr, TREE_STRING_POINTER (expr), total_bytes);
> + return total_bytes;
> +}
> +
> +
> /* Subroutine of fold_view_convert_expr. Encode the INTEGER_CST,
> REAL_CST, COMPLEX_CST or VECTOR_CST specified by EXPR into the
> buffer PTR of length LEN bytes. Return the number of bytes
> @@ -7337,6 +7368,9 @@ native_encode_expr (const_tree expr, uns
> case VECTOR_CST:
> return native_encode_vector (expr, ptr, len);
>
> + case STRING_CST:
> + return native_encode_string (expr, ptr, len);
> +
> default:
> return 0;
> }
> --- gcc/testsuite/gfortran.dg/hollerith.f90.jj2 2008-09-30 16:56:06.000000000 +0200
> +++ gcc/testsuite/gfortran.dg/hollerith.f90 2008-11-11 13:52:38.000000000 +0100
> @@ -8,7 +8,7 @@ character z1(4)
> character*4 z2(2,2)
> character*80 line
> integer i
> -logical l
> +integer j
> real r
> character*8 c
>
> @@ -20,15 +20,15 @@ data z2/4h(i7),'xxxx','xxxx','xxxx'/
>
> z2 (1,2) = 4h(i8)
> i = 4hHell
> -l = 4Ho wo
> +j = 4Ho wo
> r = 4Hrld!
> -write (line, '(3A4)') i, l, r
> +write (line, '(3A4)') i, j, r
> if (line .ne. 'Hello world!') call abort
> i = 2Hab
> r = 2Hab
> -l = 2Hab
> +j = 2Hab
> c = 2Hab
> -write (line, '(3A4, 8A)') i, l, r, c
> +write (line, '(3A4, 8A)') i, j, r, c
> if (line .ne. 'ab ab ab ab ') call abort
>
> write(line, '(4A8, "!")' ) x
> --- gcc/testsuite/gfortran.dg/transfer_simplify_4.f90 2008-09-30 16:56:06.000000000 +0200
> +++ gcc/testsuite/gfortran.dg/transfer_simplify_4.f90 2008-09-30 10:18:57.740011359 +0200
> @@ -1,30 +0,0 @@
> -! { dg-do run }
> -! { dg-options "-O0" }
> -! Tests that the in-memory representation of a transferred variable
> -! propagates properly.
> -!
> - implicit none
> -
> - integer, parameter :: ip1 = 42
> - logical, parameter :: ap1 = transfer(ip1, .true.)
> - integer, parameter :: ip2 = transfer(ap1, 0)
> -
> - logical :: a
> - integer :: i
> -
> - i = transfer(transfer(ip1, .true.), 0)
> - if (i .ne. ip1) call abort ()
> -
> - 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 ()
> -
> -end
>
> Jakub
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366)
@ 2008-11-11 13:27 Jakub Jelinek
2008-11-11 15:40 ` Richard Guenther
2008-11-11 15:53 ` Tobias Schlüter
0 siblings, 2 replies; 28+ messages in thread
From: Jakub Jelinek @ 2008-11-11 13:27 UTC (permalink / raw)
To: gcc-patches; +Cc: fortran
Hi!
Fortran FE generates VIEW_CONVERT_EXPR of STRING_CST quite a lot, but
fold-const isn't able to fold it, so GCC generates very inefficient
and (in some cases also buggy, as can be seen on the equiv_7.f90
on powerpc64-darwin with -m64 -Os) code.
I've bootstrapped/regtested this on x86_64-linux.
Unfortrunately, it causes 2 Fortran testsuite failures, hollerith.f90
and transfer_simplify_4.f90, both at all optimization levels.
I believe the tests are just invalid though. The first one does:
logical l
l = 4Ho wo
and expects all the 32 bits preserved, but that is certainly against
the semantics of BOOLEAN_TYPE and from quick skimming of the Fortran
standard also LOGICAL type. BOOLEAN_TYPE has just two values, false
and true (similarly for LOGICAL .false. and .true.) and so the folder
IMHO correctly folds this into
l = .true.
(4Ho wo is non-zero). The transfer_simplify_4.f90 testcase transfers an
integer into logical and back and expects again all the 32-bits to be
preserved.
Fortran folks, can you please look at these 2 testcases and say whether
they are valid Fortran or just undefined behavior?
2008-11-11 Jakub Jelinek <jakub@redhat.com>
PR target/35366
* fold-const.c (native_encode_string): New function.
(native_encode_expr): Use it for STRING_CST.
* gfortran.dg/hollerith.f90: Don't assume a 32-bit value
stored into logical variable will be preserved.
* gfortran.dg/transfer_simplify_4.f90: Removed.
--- gcc/fold-const.c.jj 2008-10-29 18:49:06.000000000 +0100
+++ gcc/fold-const.c 2008-11-11 11:41:34.000000000 +0100
@@ -7315,6 +7315,37 @@ native_encode_vector (const_tree expr, u
}
+/* Subroutine of native_encode_expr. Encode the STRING_CST
+ specified by EXPR into the buffer PTR of length LEN bytes.
+ Return the number of bytes placed in the buffer, or zero
+ upon failure. */
+
+static int
+native_encode_string (const_tree expr, unsigned char *ptr, int len)
+{
+ tree type = TREE_TYPE (expr);
+ HOST_WIDE_INT total_bytes;
+
+ if (TREE_CODE (type) != ARRAY_TYPE
+ || TREE_CODE (TREE_TYPE (type)) != INTEGER_TYPE
+ || GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (type))) != BITS_PER_UNIT
+ || !host_integerp (TYPE_SIZE_UNIT (type), 0))
+ return 0;
+ total_bytes = tree_low_cst (TYPE_SIZE_UNIT (type), 0);
+ if (total_bytes > len)
+ return 0;
+ if (TREE_STRING_LENGTH (expr) < total_bytes)
+ {
+ memcpy (ptr, TREE_STRING_POINTER (expr), TREE_STRING_LENGTH (expr));
+ memset (ptr + TREE_STRING_LENGTH (expr), 0,
+ total_bytes - TREE_STRING_LENGTH (expr));
+ }
+ else
+ memcpy (ptr, TREE_STRING_POINTER (expr), total_bytes);
+ return total_bytes;
+}
+
+
/* Subroutine of fold_view_convert_expr. Encode the INTEGER_CST,
REAL_CST, COMPLEX_CST or VECTOR_CST specified by EXPR into the
buffer PTR of length LEN bytes. Return the number of bytes
@@ -7337,6 +7368,9 @@ native_encode_expr (const_tree expr, uns
case VECTOR_CST:
return native_encode_vector (expr, ptr, len);
+ case STRING_CST:
+ return native_encode_string (expr, ptr, len);
+
default:
return 0;
}
--- gcc/testsuite/gfortran.dg/hollerith.f90.jj2 2008-09-30 16:56:06.000000000 +0200
+++ gcc/testsuite/gfortran.dg/hollerith.f90 2008-11-11 13:52:38.000000000 +0100
@@ -8,7 +8,7 @@ character z1(4)
character*4 z2(2,2)
character*80 line
integer i
-logical l
+integer j
real r
character*8 c
@@ -20,15 +20,15 @@ data z2/4h(i7),'xxxx','xxxx','xxxx'/
z2 (1,2) = 4h(i8)
i = 4hHell
-l = 4Ho wo
+j = 4Ho wo
r = 4Hrld!
-write (line, '(3A4)') i, l, r
+write (line, '(3A4)') i, j, r
if (line .ne. 'Hello world!') call abort
i = 2Hab
r = 2Hab
-l = 2Hab
+j = 2Hab
c = 2Hab
-write (line, '(3A4, 8A)') i, l, r, c
+write (line, '(3A4, 8A)') i, j, r, c
if (line .ne. 'ab ab ab ab ') call abort
write(line, '(4A8, "!")' ) x
--- gcc/testsuite/gfortran.dg/transfer_simplify_4.f90 2008-09-30 16:56:06.000000000 +0200
+++ gcc/testsuite/gfortran.dg/transfer_simplify_4.f90 2008-09-30 10:18:57.740011359 +0200
@@ -1,30 +0,0 @@
-! { dg-do run }
-! { dg-options "-O0" }
-! Tests that the in-memory representation of a transferred variable
-! propagates properly.
-!
- implicit none
-
- integer, parameter :: ip1 = 42
- logical, parameter :: ap1 = transfer(ip1, .true.)
- integer, parameter :: ip2 = transfer(ap1, 0)
-
- logical :: a
- integer :: i
-
- i = transfer(transfer(ip1, .true.), 0)
- if (i .ne. ip1) call abort ()
-
- 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 ()
-
-end
Jakub
^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2008-11-12 17:42 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-11-11 22:53 [PATCH] Fold VIEW_CONVERT_EXPR <type, STRING_CST> generated by Fortran FE a lot (PR target/35366) Tobias Burnus
2008-11-12 14:20 ` Jakub Jelinek
2008-11-12 15:34 ` Paul Richard Thomas
2008-11-12 18:09 ` Feng Wang
-- strict thread matches above, loose matches on Subject: below --
2008-11-11 13:27 Jakub Jelinek
2008-11-11 15:40 ` Richard Guenther
2008-11-11 15:53 ` Tobias Schlüter
2008-11-11 16:22 ` Jakub Jelinek
2008-11-11 16:26 ` Tobias Schlüter
2008-11-11 17:21 ` Jakub Jelinek
2008-11-11 17:22 ` Tobias Schlüter
2008-11-11 18:10 ` Jakub Jelinek
2008-11-11 19:07 ` Janne Blomqvist
2008-11-11 19:22 ` Brooks Moses
2008-11-11 19:36 ` Tobias Burnus
2008-11-11 20:50 ` Brooks Moses
2008-11-11 21:38 ` Jakub Jelinek
2008-11-11 21:41 ` Brooks Moses
2008-11-11 21:46 ` Jakub Jelinek
2008-11-11 22:31 ` Brooks Moses
2008-11-11 21:27 ` Thomas Koenig
2008-11-11 19:17 ` Brooks Moses
2008-11-11 19:34 ` Jakub Jelinek
2008-11-11 19:38 ` Brooks Moses
2008-11-11 17:30 ` Tobias Burnus
2008-11-11 16:22 ` Paul Richard Thomas
2008-11-11 16:45 ` Tobias Schlüter
2008-11-11 21:56 ` Steve Kargl
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).