This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: i370 port


I've managed to isolate the problem to a small test program.

Any suggestions on how to debug this?

Thanks. Paul.




C:\devel\gcc\gcc>type bug27.c /* This program demonstrates a bug in a modification to GCC 3.4.6 */ /* It generates the below error when compiled with -O2 */

#if 0
bug27.c: In function `foo':
bug27.c:28: error: unrecognizable insn:
(insn 116 34 35 2 (set (reg:SI 5 5)
       (plus:SI (plus:SI (reg:SI 2 2 [orig:54 i ] [54])
               (reg/f:SI 13 13))
           (const_int 104 [0x68]))) -1 (nil)
   (nil))
bug27.c:28: internal compiler error: in ZZZ_680, at recog.c:2083
#endif

void foo(int c)
{
   int x[3];
   int y[3];
   int i;

   for (i = 0; i < 2; i++)
   {
       if (c == 1) x[i] &= y[i];
       else if (c == 2) x[i] |= y[i];
   }

   return;
}

C:\devel\gcc\gcc>





-----Original Message----- From: Paul Edwards
Sent: Friday, April 06, 2012 3:50 PM
To: Ulrich Weigand
Cc: gcc@gcc.gnu.org
Subject: Re: i370 port


I have made this change:

C:\devel\gcc\gcc\config\i370>cvs diff -c -r 1.23 i370.md
Index: i370.md
===================================================================
RCS file: c:\cvsroot/gcc/gcc/config/i370/i370.md,v
retrieving revision 1.23
retrieving revision 1.24
diff -c -r1.23 -r1.24
*** i370.md     6 Apr 2012 03:57:08 -0000       1.23
--- i370.md     6 Apr 2012 04:03:21 -0000       1.24
***************
*** 843,848 ****
--- 843,853 ----
       /*return \"STM  %1,%N1,%0\"; */
       return \"ST     %1,%0\;ST       %N1,4+%0\";
     }
+   if (GET_CODE (operands[1]) == CONST_INT)
+     {
+       mvs_check_page (0, 6, 8);
+       return \"MVC    %O0(8,%R0),%W1\";
+     }
   mvs_check_page (0, 6, 8);
   return \"MVC        %O0(8,%R0),%1\";
 }"

C:\devel\gcc\gcc\config\i370>


And it has had a good effect:


diff old/cpplib.s new/cpplib.s
1670c1670
<          MVC   120(8,13),=F'0'
---
MVC 120(8,13),=XL8'0000000000000000'
1796c1796
<          MVC   120(8,13),=F'0'
---
MVC 120(8,13),=XL8'0000000000000000'




However, I'm still stuck. Because when I make this change:

C:\devel\gcc\gcc\config\i370>cvs diff -r 1.17 i370.h
Index: i370.h
===================================================================
RCS file: c:\cvsroot/gcc/gcc/config/i370/i370.h,v
retrieving revision 1.17
retrieving revision 1.18
diff -r1.17 -r1.18
599a600,602
#define EXTRA_MEMORY_CONSTRAINT(C, STR) \
  ((C) == 'S')


It triggers off a problem with plus:SI


C:\devel\gcc\gcc>stdcompm global.c

C:\devel\gcc\gcc>gccmvs -DUSE_MEMMGR -Os -S -DHAVE_CONFIG_H -DIN_GCC -DPUREISO
-
I ../../pdos/pdpclib -I . -I config/i370 -I ../include         global.c
global.c: In function `find_reg':
global.c:1325: error: unrecognizable insn:
(insn 2432 130 131 12 (set (reg:SI 15 15)
       (plus:SI (plus:SI (reg:SI 4 4 [orig:82 allocno ] [82])
               (reg:SI 3 3 [87]))
           (const_int 44 [0x2c]))) -1 (nil)
   (nil))
global.c:1325: internal compiler error: in ZZZ_680, at recog.c:2083
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://gccmvs.sourceforge.net> for instructions.

C:\devel\gcc\gcc>


Seems to be a problem when adding very small const_ints (in the above case, 44) that can fit into a LA. I tried to isolate which plus:SI rule was causing the problem by commenting out these:

;
; addsi3 instruction pattern(s).
;
; The following insn is used when it is known that operand one is an
address,
; frame, stack or argument pointer, and operand two is a constant that is
; small enough to fit in the displacement field.
; Notice that we can't allow the frame pointer to used as a normal register
; because of this insn.
;

;(define_insn ""
;  [(set (match_operand:SI 0 "register_operand" "=d")
;^I(plus:SI (match_operand:SI 1 "general_operand" "%a")
;^I^I (match_operand:SI 2 "immediate_operand" "J")))]
;  "((REGNO (operands[1]) == FRAME_POINTER_REGNUM || REGNO (operands[1]) ==
ARG$
;  "*
;{
;  check_label_emit ();
;  CC_STATUS_INIT;  /* add assumes CC but LA doesn't set CC */
;  mvs_check_page (0, 4, 0);
;  return \"LA^I%0,%c2(,%1)\";
;}"
;   [(set_attr "length" "4")]
;)

;; The CC status bits for the arithmetic instructions are handled
;; in the NOTICE_UPDATE_CC macro (yeah???) and so they do not need
;; to be set below.  They only need to be invalidated if *not* set
;; (e.g. by BCTR) ... yeah I think that's right ...
;;

;(define_insn "addsi3"
;  [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
;^I(plus:SI (match_operand:SI 1 "general_operand" "%0")
;^I^I (match_operand:SI 2 "general_operand" "g")))]
;  ""
;  "*
;{
;  check_label_emit ();
;  if (REG_P (operands[2]))
;    {
;      mvs_check_page (0, 2, 0);
;      return \"AR^I%0,%2\";
;    }
;  if (GET_CODE (operands[2]) == CONST_INT)
;    {
;      if (INTVAL (operands[2]) == -1)
;^I{
;          CC_STATUS_INIT;  /* add assumes CC but BCTR doesn't set CC */
;^I  mvs_check_page (0, 2, 0);
;^I  return \"BCTR^I%0,0\";
;^I}
;    }
;  mvs_check_page (0, 4, 0);
;  return \"A^I%0,%2\";
;}"
;   [(set_attr "length" "4")]
;)


But that seemed to invoke some sort of bug in the main compiler:


C:\devel\gcc\gcc>stdcompm alias.c

C:\devel\gcc\gcc>gdb --args
gccmvs -DUSE_MEMMGR -Os -S -DHAVE_CONFIG_H -DIN_GCC
-DPUREISO -I ../../pdos/pdpclib -I . -I config/i370 -I ../include
alias.
c
GNU gdb 6.5.50.20060706-cvs (cygwin-special)
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-cygwin"...
(gdb) run
Starting program:
/cygdrive/c/devel/gcc/gcc/gccmvs.exe -DUSE_MEMMGR -Os -S -DHAV
E_CONFIG_H -DIN_GCC -DPUREISO -I ../../pdos/pdpclib -I . -I config/i370 -I
../in
clude alias.c
Error: dll starting at 0x76901000 not found.
Error: dll starting at 0x761f1000 not found.
Error: dll starting at 0x76901000 not found.
Error: dll starting at 0x765f1000 not found.
Loaded symbols for /cygdrive/c/Windows/system32/ntdll.dll
Loaded symbols for /cygdrive/c/Windows/syswow64/kernel32.dll
Loaded symbols for /cygdrive/c/Windows/syswow64/KernelBase.dll

Program received signal SIGSEGV, Segmentation fault.
0x005fca41 in discover_flags_reg () at regmove.c:174
174       if (GET_CODE (tmp) == SET)
(gdb) where
#0  0x005fca41 in discover_flags_reg () at regmove.c:174
#1  0x005fdfd7 in regmove_optimize (f=0x1aaecc0, nregs=29,
   regmove_dump_file=0x0) at regmove.c:1056
#2  0x0064d6bc in rest_of_handle_regmove (decl=0x177a000, insns=0x1aaecc0)
   at toplev.c:2438
#3  0x0064f1af in ZZZ_1833 (decl=0x177a000) at toplev.c:3412
#4  0x00656061 in tree_rest_of_compilation (fndecl=0x177a000,
nested_p=false)
   at tree-optimize.c:168
#5  0x0043e6ec in c_expand_body_1 (fndecl=0x177a000, nested_p=0)
   at c-decl.c:6190
#6  0x0043e835 in ZZZ_331 (fndecl=0x177a000) at c-decl.c:6222
#7  0x00487dee in cgraph_expand_function (node=0x177ec3c) at
cgraphunit.c:538
#8  0x00489e7e in cgraph_expand_all_functions () at cgraphunit.c:1542
#9  0x0048a046 in cgraph_optimize () at cgraphunit.c:1607
#10 0x00447d75 in ZZZ_345 () at c-objc-common.c:240
#11 0x0044664b in ZZZ_708 () at c-lang.c:185
#12 0x0044947f in ZZZ_318 (set_yydebug=0) at c-opts.c:1270
#13 0x0064cd88 in compile_file () at toplev.c:1848
#14 0x00650f5a in do_compile () at toplev.c:4695
#15 0x00650ff5 in toplev_main (argc=26, argv=0xcc583c) at toplev.c:4735
#16 0x0054df47 in execute () at gcc.c:2785
#17 0x00551c59 in do_spec (
   spec=0x6a997c "%{E|M|MM:%(trad_capable_cpp) %(cpp_options)
%(cpp_debug_optio
ns)} %{!E:%{!M:%{!MM: %{traditional|ftraditional:%eGNU C no longer
supports -tra
ditional without -E} %{save-temps|traditional-cpp|no-integr"...)
   at gcc.c:4265
#18 0x00556a1b in main (argc=16, argv=0x6e6920) at gcc.c:6437
(gdb)


/* Determine if the pattern generated by add_optab has a clobber, such as might be issued for a flags hard register. To make the code elsewhere simpler, we handle cc0 in this same framework.

  Return the register if one was discovered.  Return NULL_RTX if
  if no flags were found.  Return pc_rtx if we got confused.  */

static rtx
discover_flags_reg (void)
{
 rtx tmp;
 tmp = gen_rtx_REG (word_mode, 10000);
 tmp = gen_add3_insn (tmp, tmp, GEN_INT (2));

 /* If we get something that isn't a simple set, or a
    [(set ..) (clobber ..)], this whole function will go wrong.  */
 if (GET_CODE (tmp) == SET)



I tried commenting out different plus:SI rules, but that also
met with a crash in the main compiler.

So I don't know which plus:SI is causing the problem, and
it seems very strange that the extra memory constraint
triggers off the problem.

Any ideas?

Thanks. Paul.






-----Original Message----- From: Paul Edwards
Sent: Thursday, April 05, 2012 11:31 PM
To: Ulrich Weigand
Cc: gcc@gcc.gnu.org
Subject: Re: i370 port


Hi Ulrich.

I'm getting back to this after a long hiatus.

I have reviewed the 'W' code in PRINT_OPERAND:

else if (CODE == 'W')
 {
   /* hand-built sign-extension of signed 32-bit to 64-bit */
   mvs_page_lit += 8;
   if (0 <=  INTVAL (XV)) {
      fprintf (FILE, "=XL8'00000000");
   } else {
      fprintf (FILE, "=XL8'FFFFFFFF");
   }
   fprintf (FILE, "%08X'", INTVAL (XV));
 }

and it looks to me like it is already correct. If movdi is given a
const_int as a parameter, then sign-extending to 64-bit is
exactly what needs to happen, isn't it?

I'm only expecting to compile programs as 32-bit, so I'm not
expecting more than 32-bit integers. The IFOX assembler
won't do more than that. In case that's the issue.

But regardless I don't know how to make this code:

mvs_check_page (0, 6, 8);
return \"MVC^I%O0(8,%R0),%1\";

make use of that 'W' operand.

Do I change that %1 to %W1 perhaps?

I'll give that a try tomorrow.

Thanks. Paul.





-----Original Message----- From: Ulrich Weigand
Sent: Monday, August 22, 2011 10:22 PM
To: Paul Edwards
Cc: gcc@gcc.gnu.org
Subject: Re: i370 port


Paul Edwards wrote:

  if (operands[1] == const0_rtx)
  {
    CC_STATUS_INIT;
    mvs_check_page (0, 6, 8);
    return \"MVC    %O0(8,%R0),=XL8'00'\";
  }
  mvs_check_page (0, 6, 8);
  return \"MVC    %O0(8,%R0),%1\";
}"
   [(set_attr "length" "8")]
)

forces it to use XL8'00' instead of the default F'0' and that
seems to work.  Does that seem like a proper solution to
you?

Well, there isn't really anything special about const0_rtx. *Any* CONST_INT that shows up as second operand to the movdi pattern must be emitted into an 8 byte literal at this point.

You can do that inline; but the more usual way would be to
define an operand print format that encodes the fact that
a 64-bit operand is requested.

In fact, looking at the i370.h PRINT_OPERAND, there already
seems to be such a format: 'W'.  (Maybe not quite; since 'W'
sign-extends a 32-bit operand to 64-bit.  But since 'W'
doesn't seem to be used anyway, maybe this can be changed.)

Bye,
Ulrich

--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]