Patches to fix GCC’s C++ exception handling on NetBSD/VAX

2016-03-21 Thread Jake Hamby
Hi all,

For several years I’ve been eager to find the time to fix the bugs in C++ 
exceptions on VAX to get them working on NetBSD, because they’ve been broken 
for many years and it looked like only a few changes were needed to get them 
working. Without C++ exceptions, the NetBSD test suite can’t be run. The good 
news is that I was able to fix all the bugs in the VAX machine description to 
make C++ exceptions work in GCC 4.8.5 (version unimportant). I wrote a blog 
post explaining the bugs, with patches:

> http://jakehamby.com/?p=7

Here’s a short summary, with the diffs in text form at the end of this email.

1) Replace #define FRAME_POINTER_CFA_OFFSET(FNDECL) 0 with #define 
ARG_POINTER_CFA_OFFSET(FNDECL) 0 in gcc/config/vax/elf.h and 
gcc/config/vax/vax.h. This changes the definition of __builtin_dwarf_cfa() to 
return %ap instead of %fp, which correctly points to CFA. Previously, the stack 
unwinder was crashing in _Unwind_RaiseException() trying to follow bad pointers 
from the initial CFA.

2) Define EH_RETURN_DATA_REGNO(N) to include only R2 and R3 (instead of R2-R5) 
and add code to vax_expand_prologue() in gcc/config/vax/vax.c to add R2-R3 to 
the procedure entry mask but only if crtl->calls_eh_return is set. This fixes a 
crash when the stack unwinder tried to write values to R2 and R3 in the 
previous stack frame via __builtin_eh_return_data_regno (0) and 
__builtin_eh_return_data_regno (1).

3) Removed definitions of EH_RETURN_STACKADJ_RTX and STARTING_FRAME_OFFSET from 
gcc/config/vax/elf.h. It’s not necessary to remember the stack adjustment or to 
waste four bytes on every stack frame for a value that’s not needed. Also 
remove the suspicious changes in gcc/config/vax/vax.md to the definitions of 
call_pop and call_value regarding DW_CFA_GNU_args_size and EH unwinding. I 
reverted to the previous versions from an older version of GCC, adding a few 
useful comments that had been removed.

4) The last bug is the one I understand the least. I’m hoping someone reading 
this can implement a correct fix. What I was seeing after making all the 
previous changes to fix the other bugs is that my test program failed to catch 
any exceptions, but instead returned normally to the original return path.

Investigation revealed that GCC was correctly generating the necessary move 
instruction to copy the second parameter passed to __builtin_eh_return() into 
the return address, because EH_RETURN_HANDLER_RTX had been defined correctly in 
config/vax/elf.h. Here’s what the call looks like in gcc/except.c:

#ifdef EH_RETURN_HANDLER_RTX
  rtx insn = emit_move_insn (EH_RETURN_HANDLER_RTX, crtl->eh.ehr_handler);
#else
  error ("__builtin_eh_return not supported on this target");
#endif

The problem was that the optimizer is deleting the final move instruction when 
I compile with -O or higher. The assembly code at -O0 (no optimization) 
generated for the __builtin_eh_return() call at the end of 
_Unwind_RaiseException() looked like:

calls $2,_Unwind_DebugHook
movl -12(%fp),%r1
movl %r1,16(%fp)
ret
.cfi_endproc

But then when I compiled with -O1 or -O2, all I saw was:

calls $2,_Unwind_DebugHook
ret
.cfi_endproc

This was a mystery for me and I don’t know enough about how the final peephole 
optimizer works to really track down why it thinks it can remove the move call 
to store the previous return address. My workaround was to add a call to 
RTX_FRAME_RELATED_P (insn) = 1; after the emit_move_insn() in gcc/except.c, 
which was used in vax_expand_prologue() to mark the procedure entry mask.

By making this change, the optimizer no longer removes the call to write the 
value to the previous stack pointer, but it adds an extra line of .cfi 
exception info, which seems unnecessary since the code is immediately going to 
return from the call and any adjustment made by the DWARF stack unwinder will 
already have been done. Here’s what the optimized code looks like with the 
patch (%r6 had been loaded earlier):

calls $2,_Unwind_DebugHook
movl %r6,16(%fp)
.cfi_offset 6, -36
ret
.cfi_endproc

With that final change, C++ exception handling now finally works on NetBSD/vax, 
and I was able to successfully run the vast majority of the tests in the ATF 
testsuite, which had been completely inaccessible when I started due to both 
atf-run and atf-report immediately dumping core due to the bad pointers that I 
fixed. Now I have a bunch of new bugs to track down fixes for, but I think this 
was the hardest set of problems that needed to be solved to bring NetBSD on VAX 
up to the level of the other NetBSD ports.

Here are the diffs I have so far. They should apply to any recent version of 
GCC (tested on GCC 4.8.5). With the exception of the hack to gcc/except.c, the 
other diffs are ready to submit to NetBSD as well as to upstream GCC. The fix 
I’d like to see for the final problem I discovered of the emit_mov

Re: Patches to fix GCC’s C++ exception handling on NetBSD/VAX

2016-03-26 Thread Jake Hamby
> On Mar 23, 2016, at 05:56, Christos Zoulas  wrote:
> 
> In article ,
> Jake Hamby   wrote:
> 
> Hi,
> 
> Thanks a lot for your patch. I applied it to our gcc-5 in the tree.
> Unfortunately gcc-5 seems that it was never tested to even compile.
> I fixed the simple compilation issue, but it fails to compile some
> files with an internal error trying to construct a dwarf frame info
> element with the wrong register. If you have some time, can you
> take a look? I will too.
> 
> Thanks,
> 
> christos

Hi Christos,

I just rebased my patches on top of GCC 5.3, which I see you have recently 
switched to. Here’s a brief explanation of how I patched the dwarf frame error.

The problem is that FIRST_PSEUDO_REGISTER should be increased from 16 to 17, 
because PSW is considered a real register for DWARF debug purposes. This 
necessitated changing a few other macros, but nothing major. Since it’s marked 
as one of the FIXED_REGISTERS, it never actually gets used. Currently I’m doing 
a full build with GCC 5.3 and CONFIGURE_ARGS += —enable-checking=all, which is 
very much slower, of course.

One bug I discovered with —enable-checking=all on GCC 4.8.5 is a call to XEXP() 
that may not be valid, but which can be prevented by checking the other 
conditions first, and then calling XEXP() if the other conditions are true.

There seems to be a code generation bug with C++ that only affects a few 
things. Unfortunately, GCC itself (the native version, not the cross compiler) 
is one of the programs affected. The symptom when compiling almost anything 
complex in GCC 4.8.5 is a stack overflow as it recursively loops around trying 
to expand bits and pieces of the insns. It seems to be branching the wrong way.

In looking at this, I discovered one really broken issue in the current vax.md, 
namely the three peephole optimizations at the bottom. The comment on the 
bottom one that says “Leave this commented out until we can determine whether 
the second move precedes a jump which relies on the CC flags being set 
correctly.” is absolutely correct and I believe all three should be removed. 
I’ve done so in the diff below, and added a comment explaining why.

I have a theory that the source of any code generation bugs in GCC’s output 
(and I fear that GCC 5.3 won’t necessarily fix, even if the system itself is 
completely stable), is that the CC0 notification handler isn’t doing the right 
thing. I’ll send another email if I make any progress on this issue, but what 
I’ve discovered so far is that it makes no sense for VAX to switch away from 
the CC0 style of condition handling, because almost every single instruction 
updates PSW flags, and in a similar way. So the older style is really optimized 
for VAX, but it took me a very long time to understand exactly what 
vax_notice_update_cc() is doing and why correct behavior of it is so important.

The idea is that some part of the optimizer is able to remove explicit tst / 
cmp insns when a previous one has already set the flags in a way that’s useful. 
So my theory is that the current version mostly works, but it’s very difficult 
to understand as it’s written, and it may be very occasionally giving the wrong 
results due to either bugs in its logic or the instructions emitted not setting 
the flags in the usual way. Unfortunately, the m68k version of NOTICE_UPDATE_CC 
(the only other arch supported by NetBSD that uses the CC0 style) is even more 
convoluted.

So what I’d like to try next is rewriting the VAX version of notice_update_cc 
to use the style that the AVR backend and others use which is to add a “cc” 
attribute to the instructions themselves in the .md file describing what each 
one does in terms of flags. Then the notify function itself becomes much 
simpler, and, hopefully, more likely to be correct. I did spend a few hours 
yesterday investigating whether it would make sense to convert VAX to the newer 
condition codes style that all of the modern CPUs use, but because nearly every 
instruction, including all of the move instructions, clobbers / updates PSW, it 
would be much uglier than adding a cc attribute to every opcode, and, what’s 
worse, it caused all sorts of breakage in the compiler when I tried it because 
the (clobber (reg:CC VAX_PSW_REGNUM)) lines I had added prevented it from 
matching instructions.

I did find a patch on the GCC Bugzilla for a different architecture, where 
someone had gone down the lines of fixing the emit stuff where I found 
breakage. But VAX is so well tuned to the CC0 style that it makes more sense to 
refactor it in place in the style of Atmel AVR, NEC V850, Renesas H8/300, all 
of which are built from a similar template. The m68k backend could benefit from 
being refactored in a similar way, but I’ll focus on VAX for now. :-)

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50582

Even with the patches attached to that bug, and the FIRST_PSEUDO_REGISTER that 
I’ve included bel

Re: Patches to fix GCC’s C++ exception handling on NetBSD/VAX

2016-03-26 Thread Jake Hamby
As an added bonus, I see that my patch set also included an old m68k patch that 
had been sitting in my tree, which fixes a crash when -m68040 is defined. I may 
have submitted it to port-m68k before. It hasn’t been tested with the new 
compiler either. Here’s that patch separately. It only matter when TARGET_68881 
&& TUNE_68040.

-Jake


Index: external/gpl3/gcc/dist/gcc/config/m68k/m68k.md
===
RCS file: /cvsroot/src/external/gpl3/gcc/dist/gcc/config/m68k/m68k.md,v
retrieving revision 1.4
diff -u -u -r1.4 m68k.md
--- external/gpl3/gcc/dist/gcc/config/m68k/m68k.md  24 Jan 2016 09:43:33 
-  1.4
+++ external/gpl3/gcc/dist/gcc/config/m68k/m68k.md  26 Mar 2016 10:42:41 
-
@@ -2132,9 +2132,9 @@
 ;; into the kernel to emulate fintrz.  They should also be faster
 ;; than calling the subroutines fixsfsi or fixdfsi.
 
-(define_insn "fix_truncdfsi2"
+(define_insn "fix_truncsi2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
-   (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"
+   (fix:SI (match_operand:FP 1 "register_operand" "f")))
(clobber (match_scratch:SI 2 "=d"))
(clobber (match_scratch:SI 3 "=d"))]
   "TARGET_68881 && TUNE_68040"
@@ -2143,9 +2143,9 @@
   return "fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w 
#-33,%3\;fmovem%.l %3,%!\;fmove%.l %1,%0\;fmovem%.l %2,%!";
 })
 
-(define_insn "fix_truncdfhi2"
+(define_insn "fix_trunchi2"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
-   (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "f"
+   (fix:HI (match_operand:FP 1 "register_operand" "f")))
(clobber (match_scratch:SI 2 "=d"))
(clobber (match_scratch:SI 3 "=d"))]
   "TARGET_68881 && TUNE_68040"
@@ -2154,9 +2154,9 @@
   return "fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w 
#-33,%3\;fmovem%.l %3,%!\;fmove%.w %1,%0\;fmovem%.l %2,%!";
 })
 
-(define_insn "fix_truncdfqi2"
+(define_insn "fix_truncqi2"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
-   (fix:QI (fix:DF (match_operand:DF 1 "register_operand" "f"
+   (fix:QI (match_operand:FP 1 "register_operand" "f")))
(clobber (match_scratch:SI 2 "=d"))
(clobber (match_scratch:SI 3 "=d"))]
   "TARGET_68881 && TUNE_68040"



Re: Patches to fix GCC’s C++ exception handling on NetBSD/VAX

2016-03-26 Thread Jake Hamby
Unfortunately, my previous patch that included a change to gcc/config/vax/vax.h 
that increased FIRST_PSEUDO_REGISTER from 16 to 17 breaks the C++ exception 
handling that I’d worked so hard to get right with the rest of the patch. I 
believe I need to define DWARF_FRAME_REGISTERS to 16 in the same file to fix 
the size of the array that libgcc/unwind-dw2.c creates. The i386 backend and 
several others also define it their .h file for the same reason (compatibility 
with hardcoded frame offsets).

Here’s the first part of the patch to vax.h that increases 
FIRST_PSEUDO_REGISTER and also adds a definition of DWARF_FRAME_REGISTERS as 
16, with suitable comment. I’m testing it now. I know that C++ exceptions were 
working before I increased FIRST_PSEUDO_REGISTER to 17.

Regards,
Jake

Index: external/gpl3/gcc.old/dist/gcc/config/vax/vax.h
===
RCS file: /cvsroot/src/external/gpl3/gcc.old/dist/gcc/config/vax/vax.h,v
retrieving revision 1.3
diff -u -r1.3 vax.h
--- external/gpl3/gcc.old/dist/gcc/config/vax/vax.h 23 Sep 2015 03:39:18 
-  1.3
+++ external/gpl3/gcc.old/dist/gcc/config/vax/vax.h 26 Mar 2016 14:34:29 
-
@@ -119,13 +119,17 @@
The hardware registers are assigned numbers for the compiler
from 0 to just below FIRST_PSEUDO_REGISTER.
All registers that the compiler knows about must be given numbers,
-   even those that are not normally considered general registers.  */
-#define FIRST_PSEUDO_REGISTER 16
+   even those that are not normally considered general registers.
+   This includes PSW, which the VAX backend did not originally include.  */
+#define FIRST_PSEUDO_REGISTER 17
+
+/* For compatibility, DWARF_FRAME_REGISTERS must still be 16.  */
+#define DWARF_FRAME_REGISTERS 16
 
 /* 1 for registers that have pervasive standard uses
and are not available for the register allocator.
-   On the VAX, these are the AP, FP, SP and PC.  */
-#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}
+   On the VAX, these are the AP, FP, SP, PC, and PSW.  */
+#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}
 
 /* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any



Re: Patches to fix GCC's C++ exception_handling on NetBSD/VAX

2016-03-27 Thread Jake Hamby
Thank you for the offer. I already tested it on an Amiga 3000 w/ 68040 card 
when I made the fix. The bug manifested as the cross-compiler crashing with a 
failure to find a suitable insn, because it couldn’t find the correct FP 
instruction to expand to. I believe it manifested when running ./build.sh 
release with “-m68040” set in CPUFLAGS. I will test it myself and see if it’s 
still an issue without the patch. If you look at the .md file, there’s an 
entirely different code path to generate the same instructions when 
"TARGET_68881 && TUNE_68040" aren't defined.

At the time I made the change, I had already been testing the code on an Amiga 
3000 w/ 68040 card, so I know that the generated code is likely correct (also, 
the assembler accepted it). So I’m assuming that it’s a fairly safe thing. It 
was the difference between the build succeeding or failing, and not an issue 
with the generated code.

So the only thing I can suggest is that you can try a build with the patch and 
make sure it's stable. I was never able to produce a build without it, because 
"TARGET_68881 && TUNE_68040" was excluding the other choices when building, I 
believe, libm or libc or the kernel or something like that. I do have a test 
case for C++ exceptions on VAX, which I will send separately.

Thanks,
Jake


> On Mar 27, 2016, at 10:08, Mikael Pettersson  wrote:
> 
> Jake Hamby writes:
>> As an added bonus, I see that my patch set also included an old m68k patch
>> that had been sitting in my tree, which fixes a crash when -m68040 is 
>> defined.
>> I may have submitted it to port-m68k before. It hasn't been tested with the
>> new compiler either. Here's that patch separately. It only matter when
>> TARGET_68881 && TUNE_68040.
> 
> Do you have a test case or some recipe for reproducing the crash?
> I'd be happy to test this patch on Linux/M68K.
> 
> /Mikael
> 
>> 
>> -Jake
>> 
>> 
>> Index: external/gpl3/gcc/dist/gcc/config/m68k/m68k.md
>> 
>> RCS file: /cvsroot/src/external/gpl3/gcc/dist/gcc/config/m68k/m68k.md,v
>> retrieving revision 1.4
>> diff -u -u -r1.4 m68k.md
>> --- external/gpl3/gcc/dist/gcc/config/m68k/m68k.md   24 Jan 2016 09:43:33 
>> -  1.4
>> +++ external/gpl3/gcc/dist/gcc/config/m68k/m68k.md   26 Mar 2016 10:42:41 
>> -
>> @@ -2132,9 +2132,9 @@
>> ;; into the kernel to emulate fintrz.  They should also be faster
>> ;; than calling the subroutines fixsfsi or fixdfsi.
>> 
>> -(define_insn "fix_truncdfsi2"
>> +(define_insn "fix_truncsi2"
>>   [(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
>> -(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"
>> +(fix:SI (match_operand:FP 1 "register_operand" "f")))
>>(clobber (match_scratch:SI 2 "=d"))
>>(clobber (match_scratch:SI 3 "=d"))]
>>   "TARGET_68881 && TUNE_68040"
>> @@ -2143,9 +2143,9 @@
>>   return "fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w 
>> #-33,%3\;fmovem%.l %3,%!\;fmove%.l %1,%0\;fmovem%.l %2,%!";
>> })
>> 
>> -(define_insn "fix_truncdfhi2"
>> +(define_insn "fix_trunchi2"
>>   [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
>> -(fix:HI (fix:DF (match_operand:DF 1 "register_operand" "f"
>> +(fix:HI (match_operand:FP 1 "register_operand" "f")))
>>(clobber (match_scratch:SI 2 "=d"))
>>(clobber (match_scratch:SI 3 "=d"))]
>>   "TARGET_68881 && TUNE_68040"
>> @@ -2154,9 +2154,9 @@
>>   return "fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w 
>> #-33,%3\;fmovem%.l %3,%!\;fmove%.w %1,%0\;fmovem%.l %2,%!";
>> })
>> 
>> -(define_insn "fix_truncdfqi2"
>> +(define_insn "fix_truncqi2"
>>   [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
>> -(fix:QI (fix:DF (match_operand:DF 1 "register_operand" "f"
>> +(fix:QI (match_operand:FP 1 "register_operand" "f")))
>>(clobber (match_scratch:SI 2 "=d"))
>>(clobber (match_scratch:SI 3 "=d"))]
>>   "TARGET_68881 && TUNE_68040"
> 
> -- 



Re: Patches to fix GCC’s C++ exception handling on NetBSD/VAX

2016-03-27 Thread Jake Hamby
ndition code settings.  On VAX, the default value is "clobber".
;; The V flag is often set to zero, or else it has a special meaning,
;; usually related to testing for a signed integer range overflow.
;; "cmp_czn", "cmp_zn", and "cmp_z" are all assumed to modify V, and
;; none is expected to modify C.  "plus" is used after an add/sub,
;; when the flags, including C, return info about the result,
;; including a carry bit to use with, e.g. "adwc".

;; The important thing to note is that the C flag, in the case of "plus",
;; doesn't reflect the results of a signed integer comparison,
;; as "cmp_czn" does.  Finally, "cmp_zn_use_c" and "cmp_z_use_cn" indicate
;; that all four flags are updated: Z and N, or Z alone, will be a comparison,
;; but C is set to 0, or some other value, instead of retaining its old value.
;; Only instructions of type "compare" set the C, Z, and N flags correctly
;; for both signed and unsigned ordered comparisons.

;; For branching, only Z is needed to test for equality, between two
;; operands or between the first operand and 0.  The N flag is necessary
;; to test for less than zero, and for FP or signed integer comparisons.
;; Both N and Z are required to branch on signed (a <= b) or (a > b).
;; For comparing unsigned integers, the C flag is used instead of N.
;; Both C and Z are required to branch on unsigned (a <= b) or (a > b).

;; The VAX instruction set is biased towards leaving C alone, relative to
;; the other flags, which tend to be modified on almost every instruction.
;; It's possible to cache the results of two signed int comparison,
;; as long as they're of the form (a < b) or (a >= b), where b may be 0,
;; in the C flag, while other instructions modify the other flags. Then,
;; a test for a branch can be saved later by referring to the previous value.
;; The cc attributes are intended so that this optimization may be performed.

(define_attr "cc" "none,cmp_czn,cmp_zn,cmp_zn_use_c,
cmp_z,cmp_z_use_czn,plus,clobber"
  (const_string "clobber"))


I'll send another email once I have something substantial to contribute. I give 
my permission to NetBSD and the FSF to integrate any or all of my changes under 
the copyright terms of the original files. Please let me know if I have to do 
any additional legal stuff for code contributions. I'm doing this on my own 
time and not on behalf of any company or organization.

Best regards,
Jake


> On Mar 26, 2016, at 07:38, Jake Hamby  wrote:
> 
> Unfortunately, my previous patch that included a change to 
> gcc/config/vax/vax.h that increased FIRST_PSEUDO_REGISTER from 16 to 17 
> breaks the C++ exception handling that I’d worked so hard to get right with 
> the rest of the patch. I believe I need to define DWARF_FRAME_REGISTERS to 16 
> in the same file to fix the size of the array that libgcc/unwind-dw2.c 
> creates. The i386 backend and several others also define it their .h file for 
> the same reason (compatibility with hardcoded frame offsets).
> 
> Here’s the first part of the patch to vax.h that increases 
> FIRST_PSEUDO_REGISTER and also adds a definition of DWARF_FRAME_REGISTERS as 
> 16, with suitable comment. I’m testing it now. I know that C++ exceptions 
> were working before I increased FIRST_PSEUDO_REGISTER to 17.
> 
> Regards,
> Jake
> 
> Index: external/gpl3/gcc.old/dist/gcc/config/vax/vax.h
> ===
> RCS file: /cvsroot/src/external/gpl3/gcc.old/dist/gcc/config/vax/vax.h,v
> retrieving revision 1.3
> diff -u -r1.3 vax.h
> --- external/gpl3/gcc.old/dist/gcc/config/vax/vax.h   23 Sep 2015 03:39:18 
> -  1.3
> +++ external/gpl3/gcc.old/dist/gcc/config/vax/vax.h   26 Mar 2016 14:34:29 
> -
> @@ -119,13 +119,17 @@
>The hardware registers are assigned numbers for the compiler
>from 0 to just below FIRST_PSEUDO_REGISTER.
>All registers that the compiler knows about must be given numbers,
> -   even those that are not normally considered general registers.  */
> -#define FIRST_PSEUDO_REGISTER 16
> +   even those that are not normally considered general registers.
> +   This includes PSW, which the VAX backend did not originally include.  */
> +#define FIRST_PSEUDO_REGISTER 17
> +
> +/* For compatibility, DWARF_FRAME_REGISTERS must still be 16.  */
> +#define DWARF_FRAME_REGISTERS 16
> 
> /* 1 for registers that have pervasive standard uses
>and are not available for the register allocator.
> -   On the VAX, these are the AP, FP, SP and PC.  */
> -#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}
> +   On the VAX, these are the AP, FP, SP, PC, and PSW.  */
> +#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}
> 
> /* 1 for registers not available across function calls.
>These must include the FIXED_REGISTERS and also any
> 



Re: Patches to fix GCC’s C++ exception handling on NetBSD/VAX

2016-03-27 Thread Jake Hamby
The results you want to see for the test program are the following:

throwtest(0) returned 0
throwtest(1) returned 1
Caught int exception: 123
Caught double exception: 123.45
Caught float exception: 678.900024
enter recursive_throw(6)
calling recursive_throw(5)
enter recursive_throw(5)
calling recursive_throw(4)
enter recursive_throw(4)
calling recursive_throw(3)
enter recursive_throw(3)
calling recursive_throw(2)
enter recursive_throw(2)
calling recursive_throw(1)
enter recursive_throw(1)
calling recursive_throw(0)
enter recursive_throw(0)
throwing exception
Caught int exception: 456

Before I made the changes I've submitted, this worked on m68k and presumably 
everywhere else but VAX. On VAX, it crashed due to the pointer size 
discrepancies that I already talked about. I believe that it should be possible 
to improve GCC's backend by allowing %ap to be used as an additional general 
register (removing it from FIXED_REGISTERS, but leaving it in 
CALL_USED_REGISTERS, since it's modified on CALLS), without breaking the DWARF 
stack unwinding stuff, since the .cfi information it's emitting notes the 
correct %fp offset to find the frame, which it actually uses instead of the %ap 
in stack unwinding.

Gaining an additional general register to use within a function would be a nice 
win if it worked. But there are at two problems that must be solved before 
doing this (that I know of). The first is that certain combinations of VAX 
instructions and addressing modes seem to have problems when %ap, %fp, and/or 
%sp are used. I discovered this in the OpenVMS VAX Macro reference (which is 
essentially an updated version of the 1977 VAX architecture handbook), in Table 
8-5, General Register Addressing.

An additional source of info on which modes fail with address faults when AP or 
above is used, SimH's vax_cpu.c correctly handles this, and you can trace these 
macros to find the conditions:

#define CHECK_FOR_PCif (rn == nPC) \
RSVD_ADDR_FAULT
#define CHECK_FOR_SPif (rn >= nSP) \
RSVD_ADDR_FAULT
#define CHECK_FOR_APif (rn >= nAP) \
RSVD_ADDR_FAULT

So as long as the correct code is added to vax.md and vax.c to never emit move 
instructions under the wrong circumstances when %ap is involved, it could be 
used as a general register. I wonder if the use of %ap to find address 
arguments is a special case that happens to never emit anything that would fail 
(with a SIGILL, I believe).

But the other problem with making %ap available as a general (with a few 
special cases) register is that it would break one part of the patch I 
submitted at the beginning of the thread to fix C++ exceptions. One necessary 
part of that fix was to change "#define FRAME_POINTER_CFA_OFFSET(FNDECL) 0" to 
"#define ARG_POINTER_CFA_OFFSET(FNDECL) 0", which correctly generates the code 
to return the value for __builtin_dwarf_cfa () (as an offset of 0 from %ap).

When I was working on that fix, it seemed like it should be possible, since the 
DWARF / CFA code that's in there now is using an offset from %fp that it knows, 
that an improved fix would define FRAME_POINTER_CFA_OFFSET(FNDECL) as something 
that knows how to return the current CFA (canonical frame address) as an offset 
from %fp, since that's what it's using for all the .cfi_* directives. But I 
don't know what a correct definition of FRAME_POINTER_CFA_OFFSET should be in 
order for it to return that value, instead of 0, because I know that a 0 offset 
from %fp is definitely wrong, and it's not a fixed offset either (it depends on 
the number of registers saved in the procedure entry mask). Fortunately, %ap 
points directly to CFA, so that always works.

Just some thoughts on future areas for improval... I'm very happy to be able to 
run the NetBSD testsuite on VAX now. It gives me a lot of confidence as to what 
works and what doesn't. Most of the stuff I expected to fail (like libm tests, 
since it's not IEEE FP) failed, and most of the rest succeeded.

-Jake


> On Mar 27, 2016, at 15:34, Jake Hamby  wrote:
> 
> I'm very pleased to report that I was able to successfully build a NetBSD/vax 
> system using the checked-in GCC 5.3, with the patches I've submitted, setting 
> FIRST_PSEUDO_REGISTER to 17 and DWARF_FRAME_REGISTERS to 16. The kernel 
> produced with GCC 5.3 crashes (on a real VS4000/90 and also SimH) in UVM, 
> which may be a bug in the kernel that different optimization exposed, or a 
> bug in GCC's generated code.
> 
> If you don't set DWARF_FRAME_REGISTERS to 16, then C++ exceptions break 
> again, and GDB suddenly can't deal with the larger debug frames because of 
> the data structure size mismatch between GCC and GDB. But with that 
> additional define, you can raise FIRST_PSEUDO_REGISTER to include PSW (wh

Bad CC0 optimizer in VAX backend (was Re: Patches to fix GCC’s C++ exception handling on NetBSD/VAX)

2016-03-28 Thread Jake Hamby
tatus.flags = CC_NO_OVERFLOW;
  cc_status.value1 = SET_DEST (exp);
  cc_status.value2 = SET_SRC (exp);
}
+  else if (cc != CC_NONE)
+   CC_STATUS_INIT;
 }
   else if (GET_CODE (exp) == PARALLEL
   && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
 {
-  if (GET_CODE (SET_SRC (XVECEXP (exp, 0, 0))) == CALL)
+  rtx exp0 = XVECEXP (exp, 0, 0);
+  if (GET_CODE (SET_SRC (exp0)) == CALL)
CC_STATUS_INIT;
-  else if (GET_CODE (SET_DEST (XVECEXP (exp, 0, 0))) != PC)
+  else if (GET_CODE (SET_DEST (exp0)) != PC
+  && cc == CC_COMPARE)
{
- cc_status.flags = 0;
- cc_status.value1 = SET_DEST (XVECEXP (exp, 0, 0));
- cc_status.value2 = SET_SRC (XVECEXP (exp, 0, 0));
+ cc_status.flags = CC_NO_OVERFLOW;
+ cc_status.value1 = SET_DEST (exp0);
+ cc_status.value2 = SET_SRC (exp0);
}
-  else
+  else if (cc != CC_NONE)
/* PARALLELs whose first element sets the PC are aob,
   sob insns.  They do change the cc's.  */
CC_STATUS_INIT;
 }
-  else
+  else if (cc != CC_NONE)
 CC_STATUS_INIT;
+
   if (cc_status.value1 && REG_P (cc_status.value1)
   && cc_status.value2
   && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
@@ -1909,12 +1904,20 @@
 return true;
   if (indirectable_address_p (x, strict, false))
 return true;
-  xfoo0 = XEXP (x, 0);
-  if (MEM_P (x) && indirectable_address_p (xfoo0, strict, true))
-return true;
-  if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
-  && BASE_REGISTER_P (xfoo0, strict))
-return true;
+  /* Note: avoid calling XEXP until needed.  It may not be a valid type.
+ This fixes an assertion failure when RTX checking is enabled.  */
+  if (MEM_P (x))
+{
+  xfoo0 = XEXP (x, 0);
+  if (indirectable_address_p (xfoo0, strict, true))
+   return true;
+}
+  if (GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
+{
+  xfoo0 = XEXP (x, 0);
+  if (BASE_REGISTER_P (xfoo0, strict))
+   return true;
+}
   return false;
 }
 

> On Mar 27, 2016, at 16:06, Jake Hamby  wrote:
> 
> The results you want to see for the test program are the following:
> 
> throwtest(0) returned 0
> throwtest(1) returned 1
> Caught int exception: 123
> Caught double exception: 123.45
> Caught float exception: 678.900024
> enter recursive_throw(6)
> calling recursive_throw(5)
> enter recursive_throw(5)
> calling recursive_throw(4)
> enter recursive_throw(4)
> calling recursive_throw(3)
> enter recursive_throw(3)
> calling recursive_throw(2)
> enter recursive_throw(2)
> calling recursive_throw(1)
> enter recursive_throw(1)
> calling recursive_throw(0)
> enter recursive_throw(0)
> throwing exception
> Caught int exception: 456
> 
> Before I made the changes I've submitted, this worked on m68k and presumably 
> everywhere else but VAX. On VAX, it crashed due to the pointer size 
> discrepancies that I already talked about. I believe that it should be 
> possible to improve GCC's backend by allowing %ap to be used as an additional 
> general register (removing it from FIXED_REGISTERS, but leaving it in 
> CALL_USED_REGISTERS, since it's modified on CALLS), without breaking the 
> DWARF stack unwinding stuff, since the .cfi information it's emitting notes 
> the correct %fp offset to find the frame, which it actually uses instead of 
> the %ap in stack unwinding.
> 
> Gaining an additional general register to use within a function would be a 
> nice win if it worked. But there are at two problems that must be solved 
> before doing this (that I know of). The first is that certain combinations of 
> VAX instructions and addressing modes seem to have problems when %ap, %fp, 
> and/or %sp are used. I discovered this in the OpenVMS VAX Macro reference 
> (which is essentially an updated version of the 1977 VAX architecture 
> handbook), in Table 8-5, General Register Addressing.
> 
> An additional source of info on which modes fail with address faults when AP 
> or above is used, SimH's vax_cpu.c correctly handles this, and you can trace 
> these macros to find the conditions:
> 
> #define CHECK_FOR_PCif (rn == nPC) \
>RSVD_ADDR_FAULT
> #define CHECK_FOR_SPif (rn >= nSP) \
>RSVD_ADDR_FAULT
> #define CHECK_FOR_APif (rn >= nAP) \
>RSVD_ADDR_FAULT
> 
> So as long as the correct code is added to vax.md and vax.c to never emit 
> move instructions under the wrong circumstances when %ap is involved, it 
> could be used as a general register. I wonder if the use of %ap to find 
> address arguments is a special case that happens to ne

Patches to fix optimizer bug & C++ exceptions for GCC VAX backend

2016-03-28 Thread Jake Hamby
Amazingly enough, my patch worked well enough that my NetBSD VAX kernel built 
with GCC 5.3 is no longer crashing. I feel pretty good about what I have so far 
so here's the complete diff for both the C++ exception fix and the bad 
condition codes optimizer bug. It should be good enough to check into NetBSD 
current, at least, and I believe it does fix most, if not all, of the bad code 
generation bugs with optimization on VAX.

-Jake

Index: gcc/except.c
===
RCS file: /cvsroot/src/external/gpl3/gcc/dist/gcc/except.c,v
retrieving revision 1.3
diff -u -r1.3 except.c
--- gcc/except.c23 Mar 2016 15:51:36 -  1.3
+++ gcc/except.c28 Mar 2016 23:24:40 -
@@ -2288,7 +2288,8 @@
 #endif
 {
 #ifdef EH_RETURN_HANDLER_RTX
-  emit_move_insn (EH_RETURN_HANDLER_RTX, crtl->eh.ehr_handler);
+  rtx insn = emit_move_insn (EH_RETURN_HANDLER_RTX, crtl->eh.ehr_handler);
+  RTX_FRAME_RELATED_P (insn) = 1;  // XXX FIXME in VAX backend?
 #else
   error ("__builtin_eh_return not supported on this target");
 #endif
Index: gcc/config/vax/builtins.md
===
RCS file: /cvsroot/src/external/gpl3/gcc/dist/gcc/config/vax/builtins.md,v
retrieving revision 1.5
diff -u -r1.5 builtins.md
--- gcc/config/vax/builtins.md  24 Jan 2016 09:43:34 -  1.5
+++ gcc/config/vax/builtins.md  28 Mar 2016 23:24:40 -
@@ -50,7 +50,8 @@
(ctz:SI (match_operand:SI 1 "general_operand" "nrmT")))
(set (cc0) (match_dup 0))]
   ""
-  "ffs $0,$32,%1,%0")
+  "ffs $0,$32,%1,%0"
+  [(set_attr "cc" "clobber")])
 
 (define_expand "sync_lock_test_and_set"
   [(set (match_operand:VAXint 0 "nonimmediate_operand" "=&g")
@@ -88,7 +89,8 @@
   (match_dup 1))
  (const_int 1))])]
   ""
-  "jbssi %1,%0,%l2")
+  "jbssi %1,%0,%l2"
+  [(set_attr "cc" "none")])
 
 (define_insn "jbbssihi"
   [(parallel
@@ -105,7 +107,8 @@
   (match_dup 1))
  (const_int 1))])]
   ""
-  "jbssi %1,%0,%l2")
+  "jbssi %1,%0,%l2"
+  [(set_attr "cc" "none")])
 
 (define_insn "jbbssisi"
   [(parallel
@@ -122,8 +125,8 @@
   (match_dup 1))
  (const_int 1))])]
   ""
-  "jbssi %1,%0,%l2")
-
+  "jbssi %1,%0,%l2"
+  [(set_attr "cc" "none")])
 
 (define_expand "sync_lock_release"
   [(set (match_operand:VAXint 0 "memory_operand" "+m")
@@ -160,7 +163,8 @@
   (match_dup 1))
  (const_int 0))])]
   ""
-  "jbcci %1,%0,%l2")
+  "jbcci %1,%0,%l2"
+  [(set_attr "cc" "none")])
 
 (define_insn "jbbccihi"
   [(parallel
@@ -177,7 +181,8 @@
   (match_dup 1))
  (const_int 0))])]
   ""
-  "jbcci %1,%0,%l2")
+  "jbcci %1,%0,%l2"
+  [(set_attr "cc" "none")])
 
 (define_insn "jbbccisi"
   [(parallel
@@ -194,4 +199,5 @@
   (match_dup 1))
  (const_int 0))])]
   ""
-  "jbcci %1,%0,%l2")
+  "jbcci %1,%0,%l2"
+  [(set_attr "cc" "none")])
Index: gcc/config/vax/elf.h
===
RCS file: /cvsroot/src/external/gpl3/gcc/dist/gcc/config/vax/elf.h,v
retrieving revision 1.6
diff -u -r1.6 elf.h
--- gcc/config/vax/elf.h23 Mar 2016 15:51:37 -  1.6
+++ gcc/config/vax/elf.h28 Mar 2016 23:24:40 -
@@ -26,7 +26,7 @@
 #define REGISTER_PREFIX "%"
 #define REGISTER_NAMES \
   { "%r0", "%r1",  "%r2",  "%r3", "%r4", "%r5", "%r6", "%r7", \
-"%r8", "%r9", "%r10", "%r11", "%ap", "%fp", "%sp", "%pc", }
+"%r8", "%r9", "%r10", "%r11", "%ap", "%fp", "%sp", "%pc", "%psw", }
 
 #undef SIZE_TYPE
 #define SIZE_TYPE "long unsigned int"
@@ -45,18 +45,8 @@
count pushed by the CALLS and before the start of the saved registers.  */
 #define INCOMING_FRAME_SP_OFFSET 0
 
-/* Offset from the frame pointer register value to the top of the stack.  */
-#define FRAME_POINTER_CFA_OFFSET(FNDECL) 0
-
-/* We use R2-R5 (call-clobbered) registers for exceptions.  */
-#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 2 : INVALID_REGNUM)
-
-/* Place the top of the stack for the DWARF2 EH stackadj value.  */
-#define EH_RETURN_STACKADJ_RTX \
-  gen_rtx_MEM (SImode, \
-  plus_constant (Pmode,\
- gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM),\
- -4))
+/* We use R2-R3 (call-clobbered) registers for exceptions.  */
+#define EH_RETURN_DATA_REGNO(N) ((N) < 2 ? (N) + 2 : INVALID_REGNUM)
 
 /* Simple store the return handler into the call frame.  */
 #define EH_RETURN_HANDLER_RTX  \
@@ -66,10 +56,6 @@
  16))
 
 
-/* Reserve the top of the stack for exception handler stackadj value.  */
-#undef STARTING_FRAME_OFFSET
-#define STARTING_FRAME_OFFSET -4
-
 /* The VAX wants no space

Re: Patches to fix optimizer bug & C++ exceptions for GCC VAX backend

2016-03-31 Thread Jake Hamby
Hi JBG,

Thanks for the interest! Unfortunately, I need a few more days to work on this 
patch to clean it up and fix a few more bugs, then I'll send out a new version 
to NetBSD port-vax for testing, with ChangeLog entry. Please consider what I 
sent out earlier to be a work-in-progress at this point.

The version I have on my machine is now generating bad code, after trying to 
change a few "clobbers" to "compares", so I need to fix those bugs and also 
further clean up some stuff that I know is broken. For example, there's some 
old code in vax.c marked "#if HOST_BITS_PER_WIDE_INT == 32" and "if 
(HOST_BITS_PER_WIDE_INT == 32)" that will never be used because HOST_WIDE_INT 
is now always 64 (in hwint.h). I found another bug in a NetBSD command 
(/usr/sbin/pkg_info) processing command-line arguments in main() that goes away 
at "-O0". That bug should be easy to track down considering the small size of 
the program and that it's failing immediately in main().

There's one more thing that's broken in the VAX backend which I'd *really* like 
to fix: GCC can't compile many of its own files at -O2, as well as a few other 
.c files in the NetBSD tree, because it can't expand an insn pattern. The 
Makefiles have hacks to add "-O0" on VAX, and when I remove that workaround, I 
get GCC assertion failures, all of the form:

/home/netbsd/current/src/external/gpl3/gcc/dist/gcc/builtins.c: In function 
'void maybe_emit_chk_warning(tree, built_in_function)':
/home/netbsd/current/src/external/gpl3/gcc/dist/gcc/builtins.c:11549:1: error: 
unrecognizable insn:
 }
 ^
(insn 295 294 296 25 (set (reg:SI 111)
(subreg:SI (mem:DI (plus:SI (mult:SI (reg:SI 109)
(const_int 8 [0x8]))
(reg/f:SI 45 [ D.85015 ])) [7 *_98+0 S8 A32]) 4)) 
/home/netbsd/current/src/external/gpl3/gcc/dist/gcc/wide-int.h:799 -1
 (nil))
/home/netbsd/current/src/external/gpl3/gcc/dist/gcc/builtins.c:11549:1: 
internal compiler error: in extract_insn, at recog.c:2343
0xbd0365 _fatal_insn(char const*, rtx_def const*, char const*, int, char const*)

/home/netbsd/current/src/tools/gcc/../../external/gpl3/gcc/dist/gcc/rtl-error.c:110
0xbd03fa _fatal_insn_not_found(rtx_def const*, char const*, int, char const*)

/home/netbsd/current/src/tools/gcc/../../external/gpl3/gcc/dist/gcc/rtl-error.c:118
0xb92a2d extract_insn(rtx_insn*)

/home/netbsd/current/src/tools/gcc/../../external/gpl3/gcc/dist/gcc/recog.c:2343
0x9612cd instantiate_virtual_regs_in_insn

/home/netbsd/current/src/tools/gcc/../../external/gpl3/gcc/dist/gcc/function.c:1598
0x9612cd instantiate_virtual_regs

/home/netbsd/current/src/tools/gcc/../../external/gpl3/gcc/dist/gcc/function.c:1966
0x9612cd execute

/home/netbsd/current/src/tools/gcc/../../external/gpl3/gcc/dist/gcc/function.c:2015

The failures all seem to be related to trying to read a value from an array of 
64-bit values and loading it into a 32-bit register. It seems like there should 
be a special insn defined for this sort of array access, since VAX has mova* 
and pusha* variants to set a value from an address plus an index into a byte, 
word, long, or 64-bit array (it uses movab/pushab, put not the other variants). 
The addressing modes, constraints, and predicates all get very complicated, and 
I still need to understand a bit better what is actually required, and what 
could be simplified and cleaned up.

If anyone has suggestions on how to define an instruction that would solve the 
previous failure, please let me know. Even without a special pattern for the 
"(plus:SI (mult:SI (reg:SI) (const_int 8)))", it should be able to generate 
something. It seems like it's expanding something and then the insn that's 
supposed to go with it isn't matching.

I tried adding define_insns for "movstrictsi" and for "truncdisi2", hoping that 
one of them would solve the "(set (reg:SI (subreg:SI (mem:DI (...)" part of 
the situation, but it didn't help. The "(subreg:SI)" stuff is strange, and I 
don't understand exactly what GCC is expecting the backend to define. I'll keep 
working on things and as soon as I have something that I think is in a 
contributable state and doesn't generate bad code, I'll email it.

Best regards,
Jake

> On Mar 31, 2016, at 07:30, Jan-Benedict Glaw  wrote:
> 
> Hi Jake!
> 
> On Mon, 2016-03-28 16:34:56 -0700, Jake Hamby  wrote:
>> Amazingly enough, my patch worked well enough that my NetBSD VAX
>> kernel built with GCC 5.3 is no longer crashing. I feel pretty good
>> about what I have so far so here's the complete diff for both the
>> C++ exception fix and the bad condition codes optimizer bug. It
>> should be good enough to check into NetBSD current, at least, an

Re: Patches to fix optimizer bug & C++ exceptions for GCC VAX backend

2016-04-01 Thread Jake Hamby
Hi,

I apologize for the poor quality of the initial version of the patch that I 
submitted. I think I may have also mangled it by not disabling the "smart 
quotes" feature on my Mac before I pasted in the diff from the terminal window. 
I intentionally did not use gmail for fear of adding word wraps or converting 
tabs to spaces, but apparently I mangled the patch anyway. I emailed Christos a 
.tar.gz version separately.

Yes, the file you highlighted is definitely not correct and I need to figure 
out how to fix it properly. For some reason the optimizer is deleting the 
emit_move_insn() on VAX, while it seems to work on all the other platforms that 
define EH_RETURN_HANDLER_RTX() and depend on that instruction. So I'm looking 
into fixing it in gcc/config/vax/something. My next step to try to figure out 
what's going on is to dump the trees for all the phases when building 
unwind-dw2.o (the only file where __builtin_eh_return() has to work in GCC when 
libgcc is compiled in order for C++ exceptions to work) with and without "-O", 
and figure out when the instruction is being deleted and why. This only affects 
functions that call __builtin_eh_return() instead of return, but I think 
cc1plus may also need it to be defined correctly for some code that it 
generates.

My theory is that it has to do with liveness detection and a write into the 
stack frame being incorrectly seen as updating a local variable, but that could 
be completely wrong. I was hoping that by cc'ing gcc-patches that somebody more 
familiar with why some phase of the optimizer might decide to delete this 
particular insn that copies data into the stack (to overwrite the return 
address, e.g. to move to EH_RETURN_HANDLER_RTX) immediately before returning.

So far I haven't found any actual bugs in GCC that should be fixed. Perhaps it 
isn't correct to check in a hack like the change to gcc/except.c into 
netbsd-current except temporarily, until there's a correct fix for that part of 
the issue, which is what I'd like to figure out. In the meantime, I would 
highly recommend adding an #ifdef __vax around that line to avoid trouble with 
the other ports.

Now that I think about it, please do not check in the patch to 
gcc/dist/gcc/except.c without an #ifdef __vax, and certainly this isn't ready 
to go into GCC mainline. But I think it will be ready with a few more 
adjustments. The important thing is that I think most, if not all of the 
necessary fixes will be entirely modifications to VAX-related files that can be 
locally patched in NetBSD regardless of whether the GCC maintainers accept them 
or not.

To be honest, my hope by sending out my work now, even in such a rough state, 
would be to try to avoid deprecating the GCC port to VAX, if only because: 1) 
there doesn't seem to be a compelling reason to remove support for it since it 
doesn't use any really old code paths that aren't also used by other backends 
(e.g. m68k and Atmel AVR use cc0, IBM S/390 uses non-IEEE FP formats), so it 
doesn't seem to be preventing any optimizations or code refactoring elsewhere 
in GCC that I could see, 2) even though NetBSD could continue to support VAX 
GCC, I noticed in the ChangeLogs that whenever somebody has made a change to a 
definition that affects the backends, they're usually very good about updating 
all of the backends so that they continue to compile, at least. So leaving the 
VAX backend in the tree would be beneficial from a maintenance standpoint for 
users of it, 3) the VAX backend is perhaps somewhat useful as a test case for 
GCC because so many unusual RTX standard instructions were obviously defined 
*for* it (although x86 defines a lot of them, too), although my interest is 
personally in preserving an interesting piece of computer history, and for 
nostalgia purposes.

I sent an earlier email to port-vax suggesting that future discussions of this 
project aren't relevant to gcc-patches, but I did want to get it on a few 
people's radar on the NetBSD side and try to solicit a bit of help on the 
questions I had as to how to avoid having to add that hack to gcc/except.c to 
make the optimizer not delete the insns. All of the other stuff can be worked 
on in NetBSD-current and avoid bothering the 99% of people who subscribe to 
gcc-patches who have no interest in the VAX backend.

Best regards,
Jake


> On Apr 1, 2016, at 04:37, Bernd Schmidt  wrote:
> 
> Cc'ing Matt Thomas who is listed as the vax maintainer; most of the patch 
> should be reviewed by him IMO. If he is no longer active I'd frankly rather 
> deprecate the port rather than invest effort in keeping it running.
> 
>> Index: gcc/except.c
>> ===
>> RCS file: /cvsroot/src/external/gpl3/gcc/dist/gcc/except.c,v
>> retrieving revision 1.3
>> diff -u -r1.3 except.c
>> --- gcc/except.c 23 Mar 2016 15:51:36 -  1.3
>> +++ gcc/except.c 28 Mar 2016 23:24:40 -
>> @@ -2288,7 +2288,8 @@
>>  #en

Re: Patches to fix optimizer bug & C++ exceptions for GCC VAX backend

2016-04-08 Thread Jake Hamby

> On Apr 4, 2016, at 07:51, Maciej W. Rozycki  wrote:
> 
> On Thu, 31 Mar 2016, Jake Hamby wrote:
> 
>> There's one more thing that's broken in the VAX backend which I'd 
>> *really* like to fix: GCC can't compile many of its own files at -O2, as 
>> well as a few other .c files in the NetBSD tree, because it can't expand 
>> an insn pattern. The Makefiles have hacks to add "-O0" on VAX, and when 
>> I remove that workaround, I get GCC assertion failures, all of the form:
>> 
>> /home/netbsd/current/src/external/gpl3/gcc/dist/gcc/builtins.c: In function 
>> 'void maybe_emit_chk_warning(tree, built_in_function)':
>> /home/netbsd/current/src/external/gpl3/gcc/dist/gcc/builtins.c:11549:1: 
>> error: unrecognizable insn:
>> }
>> ^
>> (insn 295 294 296 25 (set (reg:SI 111)
>>(subreg:SI (mem:DI (plus:SI (mult:SI (reg:SI 109)
>>(const_int 8 [0x8]))
>>(reg/f:SI 45 [ D.85015 ])) [7 *_98+0 S8 A32]) 4)) 
>> /home/netbsd/current/src/external/gpl3/gcc/dist/gcc/wide-int.h:799 -1
>> (nil))
>> /home/netbsd/current/src/external/gpl3/gcc/dist/gcc/builtins.c:11549:1: 
>> internal compiler error: in extract_insn, at recog.c:2343
>> 0xbd0365 _fatal_insn(char const*, rtx_def const*, char const*, int, char 
>> const*)
>>  
>> /home/netbsd/current/src/tools/gcc/../../external/gpl3/gcc/dist/gcc/rtl-error.c:110
>> 0xbd03fa _fatal_insn_not_found(rtx_def const*, char const*, int, char const*)
>>  
>> /home/netbsd/current/src/tools/gcc/../../external/gpl3/gcc/dist/gcc/rtl-error.c:118
>> 0xb92a2d extract_insn(rtx_insn*)
>>  
>> /home/netbsd/current/src/tools/gcc/../../external/gpl3/gcc/dist/gcc/recog.c:2343
>> 0x9612cd instantiate_virtual_regs_in_insn
>>  
>> /home/netbsd/current/src/tools/gcc/../../external/gpl3/gcc/dist/gcc/function.c:1598
>> 0x9612cd instantiate_virtual_regs
>>  
>> /home/netbsd/current/src/tools/gcc/../../external/gpl3/gcc/dist/gcc/function.c:1966
>> 0x9612cd execute
>>  
>> /home/netbsd/current/src/tools/gcc/../../external/gpl3/gcc/dist/gcc/function.c:2015
>> 
>> The failures all seem to be related to trying to read a value from an 
>> array of 64-bit values and loading it into a 32-bit register. It seems 
>> like there should be a special insn defined for this sort of array 
>> access, since VAX has mova* and pusha* variants to set a value from an 
>> address plus an index into a byte, word, long, or 64-bit array (it uses 
>> movab/pushab, put not the other variants). The addressing modes, 
>> constraints, and predicates all get very complicated, and I still need 
>> to understand a bit better what is actually required, and what could be 
>> simplified and cleaned up.
> 
> Please note however that this RTL instruction is a memory reference, not 
> an address load.  So the suitable hardware instruction would be MOVAQ for 
> an indexed DI mode memory load.  If used to set a SI mode subreg at byte 
> number 4 (this would be the second hardware register of a pair a DI mode 
> value is held in) as seen here, it would have to address the immediately 
> preceding register however (so you can't load R0 this way) and it would 
> clobber it.
> 
> So offhand I think you need an RTL instruction splitter to express this, 
> and then avoid fetching 64 bits worth of data from memory -- for the sake 
> of matching the indexed addressing mode -- where you only need 32 bits.  
> At the hardware instruction level I'd use a scratch register (as with 
> MOVAQ you'd have to waste one anyway) to scale the index and then use 
> MOVAL instead with the modified index.  Where no index is used it gets 
> simpler even as you can just bump up the displacement according to the 
> subreg offset.

Thanks for the info! I've discovered a few additional clues which should help, 
namely the optimizer pass that's introducing the problem. Through process of 
elimination, I discovered that adding "-fno-tree-ter" will prevent the 
unrecognizable insn error. Strangely, I can't cause the problem by using 
"-ftree-ter" and -O0, which seems odd, unless the code is checking directly for 
a -O flag.

Here's an example of a similar line of code (it seems to be triggered by 
accessing a 64-bit int array embedded inside a struct) that fails w/ -O, but 
succeeded with the addition of -fno-tree-ter (assembly output with "-dP"):

#(insn 682 680 686 (set (reg:DI 0 %r0 [orig:136 D.5219 ] [136])
#(mem:DI (plus:SI (plus:SI (mult:SI (reg/v:SI 11 %r11 [orig:138 j ] 
[138])
#(const_int 8 [0x8]))
#