Port-vax archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Silly gcc bugs

On Mon, 8 Feb 2016, Maciej W. Rozycki wrote:

> > This, by the way, is gcc 4.1.3 on NetBSD 6.1.5 since gcc 4.8, AFAIK, is not
> > yet producing code natively.
> > 
> > Even after fixing that, though, compilation fails in the same file:
> > 
> > gchecksum.c: In function 'sha512_transform':
> > gchecksum.c:1250: error: insn does not satisfy its constraints:
> > (insn 516 457 479 2 (set (reg:SI 0 %r0)
> >         (reg/f:SI 17 virtual-stack-vars)) 16 {movsi_2} (nil)
> >     (nil))
> > gchecksum.c:1250: internal compiler error: in reload_cse_simplify_operands, at
> > postreload.c:393
> > 
> > Ideas?
>  This seems to pop up regularly and with a quick setup I've been able to 
> reproduce it with my VAX/Linux 4.1.2 compiler too, so I'll see if I can 
> give it a stab.

 As it is this is due to an issue in the virtual register instantiation 
pass, which should have eliminated references to `virtual-stack-vars' 
early on.  The problem is this insn (one of the few following the same 
pattern; I've chosen the simplest):

(insn 205 204 206 6 (set (reg:SI 150)
        (plus:SI (plus:SI (mult:SI (reg:SI 38 [ D.11363 ])
                    (const_int 8 [0x8]))
                (reg/f:SI 17 virtual-stack-vars))
            (const_int -896 [0xfffffc80]))) -1 (nil)

which is generated from the `movaddrdi' load address RTL pattern and uses 
the indexed addressing mode.

 The reference to the `virtual-stack-vars' virtual register within is 
supposed to be substituted with the frame pointer, offset appropriately, 
in `instantiate_virtual_regs_in_insn'.  But this requires operands to be 
extracted by matching to a known insn and there is none, so the virtual 
register falls through up until reload, at which point the compiler has no 
idea what to do about it and gives up in this spectacular manner.

 I've been able to correct this problem with the use of the patch below.  
Now the virtual register instantiation pass rewrites the insn above into:

(insn 444 204 205 6 (set (reg:SI 240)
        (plus:SI (reg/f:SI 13 %fp)
            (const_int -4 [0xfffffffc]))) -1 (nil)

(insn 205 444 206 6 (set (reg:SI 150)
        (plus:SI (plus:SI (mult:SI (reg:SI 38 [ D.11363 ])
                    (const_int 8 [0x8]))
                (reg:SI 240))
            (const_int -896 [0xfffffc80]))) 57 {*addsi4_mova} (nil)

which is not perfect as the two constants could have been combined, but I 
think it is reasonable and should unblock you now.  Going further would 
require special-casing this RTL in `instantiate_virtual_regs_in_insn' I 
believe; see the place commented with: "Handle a plus involving a virtual 
register by determining if the operands remain valid if they're modified 
in place" in function.c, if curious.  The patterns are needed anyway.

 Two patterns are required in case no immediate offset is requested to 
`virtual-stack-vars' in a reference.  In this case `*addsi4_mova' is one 
that matters and makes things work though.

 I've checked the generated assembly and I think it is correct although I 
can't easily verify it at the run time right now, so I'll appreciate if 
you try this change and let me know if the code that failed to build also 
works correctly.

 If it works for your case, then it would be nice to put it through full 
GCC regression testing too, however doing that in a cross-compilation 
environment is tricky and I'm not set up for native testing with the 
VAX/Linux port, it's simply too immature.  So if someone steps in and does 
that, then I'll appreciate it -- in a native environment it's as easy as 
running `make check' (or maybe `make -C gcc check' to exclude libraries 
from being tested in return for a quicker run) in your build tree.  

 You will need to have TCL and DejaGNU installed to run this testing, and 
maybe also Expect (I'm not sure -- GDB does need it, but I think GCC does 
not).  It will take several hours at the very least on slow hardware, 
maybe even days, so choose your fastest VAX and keep it on a UPS. ;)  

 Running in a cross-compilation environment would speed up things 
considerably as the target machine would be offloaded from compilations -- 
which would then run on the build machine, possibly several orders of 
magnitude faster -- and limited to running test test cases only, so this 
is something definitely to look into sometime.

 You'll need to run this twice, of course, with a vanilla GCC build and 
then again with this change applied, to be able to see -- as the name of 
this testing implies -- if anything has regressed (the first pass would 
not be needed if we had clean vanilla results, but I dare not expecting 
that to be the case).

 By the look of it upstream GCC head requires a change like this too.

 Let me know if you have any questions or comments.

2016-02-14  Maciej W. Rozycki  <macro%linux-mips.org@localhost>

	* config/vax/predicates.md (const_248_operand): New predicate.
	* config/vax/vax.md (*addsi3_mova, *addsi4_mova): New insns.


Index: gcc-4.1.2/gcc/config/vax/predicates.md
--- gcc-4.1.2.orig/gcc/config/vax/predicates.md
+++ gcc-4.1.2/gcc/config/vax/predicates.md
@@ -102,3 +102,11 @@
    (and (match_code "const_int,const_double,subreg,reg,mem")
 	(and (match_operand:DI 0 "general_operand" "")
 	     (not (match_operand:DI 0 "illegal_addsub_di_memory_operand")))))
+;; Match 2, 4, or 8.  Used for mova multiplicands.
+(define_predicate "const_248_operand"
+   (match_code "const_int")
+  return i == 2 || i == 4 || i == 8;
Index: gcc-4.1.2/gcc/config/vax/vax.md
--- gcc-4.1.2.orig/gcc/config/vax/vax.md
+++ gcc-4.1.2/gcc/config/vax/vax.md
@@ -405,6 +405,54 @@
 		 (match_operand:DI 2 "general_operand" "Fsro,Fs")))]
   "* return vax_output_int_add (insn, operands, DImode);")
+;; Scaled additions using mova, needed for virtual register instantiation.
+(define_insn "*addsi3_mova"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
+			  (match_operand 2 "const_248_operand" "n"))
+		 (match_operand:SI 3 "register_operand" "r")))]
+  ""
+  "*
+  int i = INTVAL (operands[2]);
+  switch (i)
+    {
+    case 2:
+      return \"movaw (%3)[%1],%0\";
+    case 4:
+      return \"moval (%3)[%1],%0\";
+    case 8:
+      return \"movaq (%3)[%1],%0\";
+    default:
+      gcc_unreachable ();
+    }
+(define_insn "*addsi4_mova"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(plus:SI (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
+				   (match_operand 2 "const_248_operand" "n"))
+			  (match_operand:SI 3 "register_operand" "r"))
+		 (match_operand:SI 4 "immediate_operand" "i")))]
+  ""
+  "*
+  int i = INTVAL (operands[2]);
+  switch (i)
+    {
+    case 2:
+      return \"movaw %4(%3)[%1],%0\";
+    case 4:
+      return \"moval %4(%3)[%1],%0\";
+    case 8:
+      return \"movaq %4(%3)[%1],%0\";
+    default:
+      gcc_unreachable ();
+    }
 ;;- All kinds of subtract instructions.

Home | Main Index | Thread Index | Old Index