Bug 19382 - ACATS cxb4005 cxb5002 simple To_COBOL/To_Fortran test fails at runtime on s390-linux
Summary: ACATS cxb4005 cxb5002 simple To_COBOL/To_Fortran test fails at runtime on s39...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.0.0
: P2 normal
Target Milestone: 4.1.0
Assignee: Not yet assigned to anyone
URL:
Keywords: alias, wrong-code
Depends on:
Blocks: 33724
  Show dependency treegraph
 
Reported: 2005-01-11 21:10 UTC by Laurent GUERBY
Modified: 2007-10-10 11:34 UTC (History)
2 users (show)

See Also:
Host: s390-linux
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Laurent GUERBY 2005-01-11 21:10:53 UTC
,.,. CXB5002 ACATS 2.5 05-01-11 13:45:01
---- CXB5002 Check that functions To_Fortran and To_Ada produce correct 
                results.
   * CXB5002 Incorrect result from procedure To_Fortran - 1.
   * CXB5002 Incorrect value returned from function To_Ada - 1.
**** CXB5002 FAILED ****************************.
Comment 1 Ulrich Weigand 2005-01-15 00:45:51 UTC
This is caused by instruction scheduling not noticing a dependency,
apparently because alias sets are set up incorrectly.

At the end of the tree optimizer phase we have:

<L29>:;
  fortran_character_1[1]{lb: 1 sz: 1} =
VIEW_CONVERT_EXPR<interfaces__fortran__character_set[1:1]>(*SR.237)[1]{lb: 1 sz: 1};
  tc_fortran_character_1.26 = (const <unnamed type> *) &tc_fortran_character_1;
  D.2019 = *tc_fortran_character_1.26;

<bb 56>:
  D.2020 = (integer) D.2019;
  fortran_character_1.27 = (interfaces__fortran__character_set[1:1] *)
&fortran_character_1;
  D.2023 = *(const <unnamed type> *) fortran_character_1.27;

<bb 57>:
  if (D.2020 - (integer) D.2023 != 0) goto <L30>; else goto <L31>;

<L30>:;
  D.2026 = C.29;
  report__failed (D.2026);


which gets expanded into RTL like so:

(insn 497 496 499 73 (set (mem/s/j:QI (reg/f:SI 39 virtual-stack-vars) [11
fortran_character_1+0 S1 A64])
        (mem/s/j:QI (reg/f:SI 123 [ SR.237 ]) [11 S1 A8])) -1 (nil)
    (nil))

[snip]

(insn 503 502 504 74 (set (reg:SI 268 [ fortran_character_1.27 ])
        (reg/f:SI 39 virtual-stack-vars)) -1 (nil)
    (nil))

(insn 504 503 505 74 (set (reg:QI 267 [ D.2023 ])
        (mem:QI (reg:SI 268 [ fortran_character_1.27 ]) [28 S1 A8])) -1 (nil)
    (expr_list:REG_EH_REGION (const_int 2 [0x2])
        (nil)))

Notice how the store to fortran_character uses alias set 11,
while the read (via the fortran_character_1.27 pointer) uses
alias set 28.

The whole section gets further simplified to

(insn 1955 506 1956 56 (parallel [
            (set (mem/s/j:BLK (plus:SI (reg/f:SI 15 %r15)
                        (const_int 96 [0x60])) [11 fortran_character_1+0 S1 A64])
                (mem/s/j:BLK (reg/f:SI 4 %r4 [orig:123 SR.237 ] [123]) [11 S1 A8]))
            (use (const_int 1 [0x1]))
        ]) 61 {*mvc} (nil)
    (expr_list:REG_DEAD (reg/f:SI 4 %r4 [orig:123 SR.237 ] [123])
        (nil)))

(insn 1956 1955 508 56 (parallel [
            (set (reg:CCZ 33 %cc)
                (compare:CCZ (mem:BLK (plus:SI (reg/f:SI 15 %r15)
                            (const_int 96 [0x60])) [28 S1 A8])
                    (mem:BLK (plus:SI (reg/f:SI 15 %r15)
                            (const_int 97 [0x61])) [28 S1 A8])))
            (use (const_int 1 [0x1]))
        ]) 31 {*clc} (nil)
    (nil))

I.e. first the store to fortran_character, the the compare.
The scheduler now swaps the two insns, causing incorrect code
to be generated.  It hasn't recognized the dependency, presumably
because the alias sets are incorrect ...
Comment 2 Arnaud Charlet 2005-03-17 10:47:43 UTC
Is this test still failing ?

Arno
Comment 3 Laurent GUERBY 2005-03-18 18:46:43 UTC
Still fails on 4.0.0 20050317 (prerelease) testsuite on s390-ibm-linux-gnu
according to:
http://gcc.gnu.org/ml/gcc-testresults/2005-03/msg01185.html
Comment 4 Laurent GUERBY 2005-07-05 08:26:24 UTC
Still failing as of 4.0.1 RC3 (20050702)
http://gcc.gnu.org/ml/gcc-testresults/2005-07/msg00183.html
Comment 5 Laurent GUERBY 2005-09-15 19:17:16 UTC
On 4.1.0 20050914 on s390-linux, two tests have similar failures:

,.,. CXB4005 ACATS 2.5 05-09-14 20:15:52
---- CXB4005 Check that the functions To_COBOL and To_Ada produce
                correct results.
   * CXB4005 Incorrect result from function To_COBOL - 1.
   * CXB4005 Incorrect result from function To_COBOL after modification 
                to Ada_To_COBOL mapping array - 1.
**** CXB4005 FAILED ****************************.

,.,. CXB5002 ACATS 2.5 05-09-14 20:15:58
---- CXB5002 Check that functions To_Fortran and To_Ada produce correct 
                results.
   * CXB5002 Incorrect result from procedure To_Fortran - 1.
   * CXB5002 Incorrect value returned from function To_Ada - 1.
**** CXB5002 FAILED ****************************.
Comment 6 Laurent GUERBY 2005-09-15 19:19:17 UTC
(In reply to comment #5)
> On 4.1.0 20050914 on s390-linux, two tests have similar failures:

Ooops: 4.0.2 20050913 (prerelease) (since 4.1.0 does not bootstrap because of
PR22533
Comment 7 Ulrich Weigand 2005-09-29 23:52:21 UTC
I've found some time to look a bit more into this.  First of all, here's
a much reduced test case:

procedure CXB4005 is
   type Alphanumeric is array (Positive range <>) of Character;
   TC_Alphanumeric : Alphanumeric(1..1);
begin
   TC_Alphanumeric := "A";
   pragma Assert (TC_Alphanumeric = "A");
end CXB4005;

The assertion fails when built with -O2 -gnata.

The comparsion TC_Alphanumeric = "A" gets translated by the front
end into this tree (02.original):

  if (VIEW_CONVERT_EXPR<character[1:1]>(tc_alphanumeric) != "A")

which get gimplified into (03.generic):

  tc_alphanumeric.0 = (character[1:1] *) &tc_alphanumeric;
  tc_alphanumeric.1 = (const <unnamed type> *) tc_alphanumeric.0;
  D.388 = *tc_alphanumeric.1;
  D.389 = (integer) D.388;
  D.390 = (const <unnamed type> *) "A";
  D.391 = *D.390;
  D.392 = (integer) D.391;
  D.393 = D.389 - D.392;
  if (D.393 != 0)

This transformation happens because an NE_EXPR of array types
is handled by gimplify_variable_sized_compare, which converts
it into an implicit call to memcmp.  This call (with length 1)
is then transformed by fold_builtin_memcmp into the computation
of the difference of the two bytes.

This is done in fold_builtin_memcpy by casting the addresses
to an 'const unsigned char *' and dereferencing that expression,
where that type is constructed as a variant of the predefined
unsigned_char_type_node.  (This type shows up in the above
listings as 'const <unnamed type> *'.)

Now, when the so-casted expression is dereferenced, we obviously
get into aliasing issues.  This works fine in C-based languages,
because there 'unsigned char' is explicitly allowed to alias any
other type -- the fold_builtin_memcpy code is correct really only
when making that assumption.

However, in Ada there is no such special case, and the Ada hook
for get_alias_set does not handle unsigned_char_type_node at all.
Thus the type gets assigned a fresh alias set (that aliases 
nothing at all since the type didn't otherwise occur).


I guess this is really a bug in fold_builtin_memcpy, but I'm not
sure what exactly the proper fix would be.  As a workaround, I've
added the "C-style" treatment of 'char' to the Ada get_alias_set,
and this fixes the symptom as well.  The patch for this is:

Index: gcc/ada/misc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ada/misc.c,v
retrieving revision 1.106
diff -c -p -r1.106 misc.c
*** gcc/ada/misc.c      4 Jul 2005 13:27:09 -0000       1.106
--- gcc/ada/misc.c      29 Sep 2005 23:34:18 -0000
*************** gnat_get_alias_set (tree type)
*** 713,718 ****
--- 713,725 ----
      return
        get_alias_set (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (type)))));

+   /* ??? The middle end occasionally generates 'char' types by itself
+      and implicitly assumes they are allowed to alias everything.  One
+      example is fold_builtin_memcmp, causing PR 19382.  */
+   if (type == char_type_node
+       || type == signed_char_type_node
+       || type == unsigned_char_type_node)
+     return 0;

    return -1;
  }
Comment 8 CVS Commits 2005-10-04 16:14:57 UTC
Subject: Bug 19382

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	uweigand@gcc.gnu.org	2005-10-04 16:14:52

Modified files:
	gcc            : ChangeLog builtins.c 

Log message:
	PR ada/19382
	* builtins.c (fold_builtin_memcmp): When constructing the pointer
	type used to access data in the inlined length == 1 case, use
	build_pointer_type_for_mode with CAN_ALIAS_ALL set to true.
	(fold_builtin_strcmp, fold_builtin_strncmp): Likewise.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.10078&r2=2.10079
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/builtins.c.diff?cvsroot=gcc&r1=1.478&r2=1.479

Comment 9 CVS Commits 2005-10-04 16:16:14 UTC
Subject: Bug 19382

CVSROOT:	/cvs/gcc
Module name:	gcc
Branch: 	gcc-4_0-branch
Changes by:	uweigand@gcc.gnu.org	2005-10-04 16:16:10

Modified files:
	gcc            : ChangeLog builtins.c 

Log message:
	PR ada/19382
	* builtins.c (fold_builtin_memcmp): When constructing the pointer
	type used to access data in the inlined length == 1 case, use
	build_pointer_type_for_mode with CAN_ALIAS_ALL set to true.
	(fold_builtin_strcmp, fold_builtin_strncmp): Likewise.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=2.7592.2.444&r2=2.7592.2.445
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/builtins.c.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=1.426.2.5&r2=1.426.2.6

Comment 10 Andrew Pinski 2005-10-04 16:54:52 UTC
Fixed.