public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Mostly rewrite genrecog
@ 2015-04-27 10:20 Richard Sandiford
  2015-04-28 23:18 ` Jeff Law
                   ` (6 more replies)
  0 siblings, 7 replies; 30+ messages in thread
From: Richard Sandiford @ 2015-04-27 10:20 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 16385 bytes --]

I think it's been the case for a while that parallel builds of GCC tend
to serialise around the compilation of insn-recog.c, especially with
higher --enable-checking settings.  This patch tries to speed that
up by replacing most of genrecog with a new algorithm.

I think the main problems with the current code are:

1. Vector architectures have added lots of new instructions that have
   a similar shape and differ only in mode, code or unspec number.
   The current algorithm doesn't have any way of factoring out those
   similarities.

2. When matching a particular instruction, the current code examines
   everything about a SET_DEST before moving on to the SET_SRC.  This has
   two subproblems:

   2a. The destination of a SET isn't very distinctive.  It's usually
       just a register_operand, a memory_operand, a nonimmediate_operand
       or a flags register.  We therefore tend to backtrack to the
       SET_DEST a lot, oscillating between groups of instructions with
       the same kind of destination.

   2b. Backtracking through predicate checks is relatively expensive.
       It would be good to narrow down the "shape" of the instruction
       first and only then check the predicates.  (The backtracking is
       expensive in terms of insn-recog.o compile time too, both because
       we need to copy into argument registers and out of the result
       register, and because it adds more sites where spills are needed.)

3. The code keeps one local variable per rtx depth, so it ends up
   loading the same rtx many times over (mostly when backtracking).
   This is very expensive in rtl-checking builds because each XEXP
   includes a code check and a line-specific failure call.

   In principle the idea of having one local variable per depth
   is good.  But it was originally written that way when all optimisations
   were done at the rtl level and I imagine each local variable mapped
   to one pseudo register.  These days the statements that reload the
   value needed on backtracking lead to many more SSA names and phi
   statements than you'd get with just a single variable per position
   (loaded once, so naturally SSA).  There is still the potential benefit
   of avoiding having sibling rtxes live at once, but fixing (2) above
   reduces that problem.

Also, the code is all goto-based, which makes it rather hard to step through.

The patch deals with these as follows:

1. Detect subpatterns that differ only by mode, code and/or integer
   (e.g. unspec number) and split them out into a common routine.

2. Match the "shape" of the instruction first, in terms of codes,
   integers and vector lengths, and only then check the modes, predicates
   and dups.  When checking the shape, handle SET_SRCs before SET_DESTs.
   In practice this seems to greatly reduce the amount of backtracking.

3. Have one local variable per rtx position.  I tested the patch with
   and without the change and it helped a lot with rtl-checking builds
   without seeming to affect release builds much either way.

As far as debuggability goes, the new code avoids gotos and just
uses "natural" control flow.

The headline stat is that a stage 3 --enable-checking=yes,rtl,df
build of insn-recog.c on my box goes from 7m43s to 2m2s (using the
same stage 2 compiler).  The corresponding --enable-checking=release
change is from 49s to 24s (less impressive, as expected).

The patch seems to speed up recog.  E.g. the time taken to build
fold-const.ii goes from 6.74s before the patch to 6.69s after it;
not a big speed-up, but reproducible.

Here's a comparison of the number of lines of code in insn-recog.c
before and after the patch on one target per config/ CPU:

aarch64-linux-gnueabi                           115526    38169 :   33.04%
alpha-linux-gnu                                  24479    10740 :   43.87%
arm-linux-gnueabi                               169208    67759 :   40.04%
avr-rtems                                        55647    22127 :   39.76%
bfin-elf                                         13928     6498 :   46.65%
c6x-elf                                          29928    13324 :   44.52%
cr16-elf                                          2650     1419 :   53.55%
cris-elf                                         18669     7257 :   38.87%
epiphany-elf                                     19308     6131 :   31.75%
fr30-elf                                          2204     1112 :   50.45%
frv-linux-gnu                                    13541     5950 :   43.94%
h8300-elf                                        19584     9327 :   47.63%
hppa64-hp-hpux11.23                              18299     8549 :   46.72%
ia64-linux-gnu                                   37629    17101 :   45.45%
iq2000-elf                                        2752     1609 :   58.47%
lm32-elf                                          1536      872 :   56.77%
m32c-elf                                         10040     4145 :   41.28%
m32r-elf                                          4436     2307 :   52.01%
m68k-linux-gnu                                   15739     8147 :   51.76%
mcore-elf                                         4816     2577 :   53.51%
mep-elf                                          67335    15929 :   23.66%
microblaze-elf                                    2656     1587 :   59.75%
mips-linux-gnu                                   54543    24186 :   44.34%
mmix                                              2597     1487 :   57.26%
mn10300-elf                                       6384     3294 :   51.60%
moxie-elf                                         1311      659 :   50.27%
msp430-elf                                        6054     2382 :   39.35%
nds32le-elf                                       5953     3152 :   52.95%
nios2-linux-gnu                                   3735     2143 :   57.38%
pdp11                                             2137     1157 :   54.14%
powerpc-eabispe                                 109322    40582 :   37.12%
powerpc-linux-gnu                                82976    32192 :   38.80%
rl78-elf                                          5321     2432 :   45.71%
rx-elf                                           14454     7534 :   52.12%
s390-linux-gnu                                   48487    20454 :   42.18%
sh-linux-gnu                                    104087    41820 :   40.18%
sparc-linux-gnu                                  21912    10509 :   47.96%
spu-elf                                          19937     8182 :   41.04%
tilegx-elf                                       15412     6970 :   45.22%
tilepro-elf                                      11998     5479 :   45.67%
v850-elf                                          8725     4438 :   50.87%
vax-netbsdelf                                     4537     2410 :   53.12%
visium-elf                                       15190     7224 :   47.56%
x86_64-darwin                                   346396   119593 :   34.52%
xstormy16-elf                                     4660     2229 :   47.83%
xtensa-elf                                        2799     1514 :   54.09%

Here's the loadable size of insn-recog.o in an --enable-checking=release
build on an x86_64-linux-gnu box:

aarch64-linux-gnueabi                           443955   298026 :   67.13%
alpha-linux-gnu                                  97194    80893 :   83.23%
arm-linux-gnueabi                               782325   632248 :   80.82%
avr-rtems                                       226827   159763 :   70.43%
bfin-elf                                         52563    42376 :   80.62%
c6x-elf                                         112512    90142 :   80.12%
cr16-elf                                         10446    10006 :   95.79%
cris-elf                                         74771    52634 :   70.39%
epiphany-elf                                     87577    52284 :   59.70%
fr30-elf                                          8041     7713 :   95.92%
frv-linux-gnu                                    53699    47543 :   88.54%
h8300-elf                                        70708    66274 :   93.73%
hppa64-hp-hpux11.23                              71597    57484 :   80.29%
ia64-linux-gnu                                  147286   130632 :   88.69%
iq2000-elf                                       11002    11774 :  107.02%
lm32-elf                                          5894     5798 :   98.37%
m32c-elf                                         36563    28855 :   78.92%
m32r-elf                                         17252    16910 :   98.02%
m68k-linux-gnu                                   58248    59781 :  102.63%
mcore-elf                                        17708    18948 :  107.00%
mep-elf                                         314466   150771 :   47.95%
microblaze-elf                                   10257    10534 :  102.70%
mips-linux-gnu                                  230991   191155 :   82.75%
mmix                                             10782    10678 :   99.04%
mn10300-elf                                      24035    22802 :   94.87%
moxie-elf                                         4622     4198 :   90.83%
msp430-elf                                       21707    16539 :   76.19%
nds32le-elf                                      22041    19444 :   88.22%
nios2-linux-gnu                                  15595    13238 :   84.89%
pdp11                                             7630     8254 :  108.18%
powerpc-eabispe                                 430816   308481 :   71.60%
powerpc-linux-gnu                               317738   248534 :   78.22%
rl78-elf                                         18904    16329 :   86.38%
rx-elf                                           55015    56632 :  102.94%
s390-linux-gnu                                  190584   148961 :   78.16%
sh-linux-gnu                                    408446   307927 :   75.39%
sparc-linux-gnu                                  91016    80640 :   88.60%
spu-elf                                          80387    69151 :   86.02%
tilegx-elf                                       63815    49977 :   78.32%
tilepro-elf                                      51763    39252 :   75.83%
v850-elf                                         32812    28462 :   86.74%
vax-netbsdelf                                    18350    18259 :   99.50%
visium-elf                                       56872    46790 :   82.27%
x86_64-darwin                                  1306182   883169 :   67.61%
xstormy16-elf                                    17044    14430 :   84.66%
xtensa-elf                                       10780     9678 :   89.78%

The same for --enable-checking=yes,rtl:

aarch64-linux-gnueabi                          1790272   507488 :   28.35%
alpha-linux-gnu                                 440058   193826 :   44.05%
arm-linux-gnueabi                              2845568  1299337 :   45.66%
avr-rtems                                       885672   294387 :   33.24%
bfin-elf                                        280606   142836 :   50.90%
c6x-elf                                         486345   259256 :   53.31%
cr16-elf                                         46626    20044 :   42.99%
cris-elf                                        426813   144414 :   33.84%
epiphany-elf                                    353078   122166 :   34.60%
fr30-elf                                         40414    21042 :   52.07%
frv-linux-gnu                                   259550   111335 :   42.90%
h8300-elf                                       355199   158411 :   44.60%
hppa64-hp-hpux11.23                             340584   149009 :   43.75%
ia64-linux-gnu                                  661364   293710 :   44.41%
iq2000-elf                                       41123    26709 :   64.95%
lm32-elf                                         20370    14781 :   72.56%
m32c-elf                                        174344    62000 :   35.56%
m32r-elf                                         74357    41773 :   56.18%
m68k-linux-gnu                                  275733   117445 :   42.59%
mcore-elf                                        85180    48018 :   56.37%
mep-elf                                        1450168   376020 :   25.93%
microblaze-elf                                   44189    26295 :   59.51%
mips-linux-gnu                                  876650   375753 :   42.86%
mmix                                             49882    25363 :   50.85%
mn10300-elf                                     128148    66768 :   52.10%
moxie-elf                                        23388     9011 :   38.53%
msp430-elf                                      114200    34426 :   30.15%
nds32le-elf                                     101416    73677 :   72.65%
nios2-linux-gnu                                  58799    29825 :   50.72%
pdp11                                            32836    18557 :   56.51%
powerpc-eabispe                                1976098   626942 :   31.73%
powerpc-linux-gnu                              1510652   526841 :   34.88%
rl78-elf                                         93675    40538 :   43.28%
rx-elf                                          279748   137284 :   49.07%
s390-linux-gnu                                  857009   316494 :   36.93%
sh-linux-gnu                                   2154337   806571 :   37.44%
sparc-linux-gnu                                 367682   169019 :   45.97%
spu-elf                                         341945   135629 :   39.66%
tilegx-elf                                      235480   112103 :   47.61%
tilepro-elf                                     246231   104137 :   42.29%
v850-elf                                        158028    72875 :   46.12%
vax-netbsdelf                                    85057    37578 :   44.18%
visium-elf                                      257148   103331 :   40.18%
x86_64-darwin                                  5514235  1721777 :   31.22%
xstormy16-elf                                    83456    46128 :   55.27%
xtensa-elf                                       52652    29880 :   56.75%

Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-none-eabi.
Also tested by building the testsuite for each of the targets above
and making sure there were no assembly differences.  Made sure that no
objects in spec2k6 changed for aarch64-linux-gnu (except for perlbench
perl.o and cactusADM datestamp.o, where the differences are timestamps).
OK to install?

Thanks,
Richard

PS. I've attached the new genrecog.c since the diff version is unreadable.


gcc/
	* Makefile.in (build/genrecog.o): Depend on inchash.h.
	(build/genrecog$(build_exeext): Depend on build/hash-table.o and
	build/inchash.o
	* genrecog.c: Rewrite most of the code except for the third page.

Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	2015-04-27 10:42:57.783191573 +0100
+++ gcc/Makefile.in	2015-04-27 10:43:42.878643078 +0100
@@ -2527,7 +2527,8 @@ build/genpeep.o : genpeep.c $(RTL_BASE_H
 build/genpreds.o : genpreds.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)	\
   coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h $(OBSTACK_H)
 build/genrecog.o : genrecog.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)	\
-  coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h
+  coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h		\
+  $(HASH_TABLE_H) inchash.h
 build/genhooks.o : genhooks.c $(TARGET_DEF) $(C_TARGET_DEF)		\
   $(COMMON_TARGET_DEF) $(BCONFIG_H) $(SYSTEM_H) errors.h
 build/genmddump.o : genmddump.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)	\
@@ -2559,6 +2560,8 @@ genprog = $(genprogerr) check checksum c
 # These programs need libs over and above what they get from the above list.
 build/genautomata$(build_exeext) : BUILD_LIBS += -lm
 
+build/genrecog$(build_exeext) : build/hash-table.o build/inchash.o
+
 # For stage1 and when cross-compiling use the build libcpp which is
 # built with NLS disabled.  For stage2+ use the host library and
 # its dependencies.


[-- Attachment #2: genrecog.c.bz2 --]
[-- Type: application/octet-stream, Size: 34987 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-04-27 10:20 Mostly rewrite genrecog Richard Sandiford
@ 2015-04-28 23:18 ` Jeff Law
  2015-04-29 13:59   ` Richard Sandiford
  2015-04-29  8:52 ` Eric Botcazou
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 30+ messages in thread
From: Jeff Law @ 2015-04-28 23:18 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 04/27/2015 04:20 AM, Richard Sandiford wrote:
> I think it's been the case for a while that parallel builds of GCC tend
> to serialise around the compilation of insn-recog.c, especially with
> higher --enable-checking settings.  This patch tries to speed that
> up by replacing most of genrecog with a new algorithm.
>
> I think the main problems with the current code are:
>
> 1. Vector architectures have added lots of new instructions that have
>     a similar shape and differ only in mode, code or unspec number.
>     The current algorithm doesn't have any way of factoring out those
>     similarities.
>
> 2. When matching a particular instruction, the current code examines
>     everything about a SET_DEST before moving on to the SET_SRC.  This has
>     two subproblems:
>
>     2a. The destination of a SET isn't very distinctive.  It's usually
>         just a register_operand, a memory_operand, a nonimmediate_operand
>         or a flags register.  We therefore tend to backtrack to the
>         SET_DEST a lot, oscillating between groups of instructions with
>         the same kind of destination.
>
>     2b. Backtracking through predicate checks is relatively expensive.
>         It would be good to narrow down the "shape" of the instruction
>         first and only then check the predicates.  (The backtracking is
>         expensive in terms of insn-recog.o compile time too, both because
>         we need to copy into argument registers and out of the result
>         register, and because it adds more sites where spills are needed.)
>
> 3. The code keeps one local variable per rtx depth, so it ends up
>     loading the same rtx many times over (mostly when backtracking).
>     This is very expensive in rtl-checking builds because each XEXP
>     includes a code check and a line-specific failure call.
>
>     In principle the idea of having one local variable per depth
>     is good.  But it was originally written that way when all optimisations
>     were done at the rtl level and I imagine each local variable mapped
>     to one pseudo register.  These days the statements that reload the
>     value needed on backtracking lead to many more SSA names and phi
>     statements than you'd get with just a single variable per position
>     (loaded once, so naturally SSA).  There is still the potential benefit
>     of avoiding having sibling rtxes live at once, but fixing (2) above
>     reduces that problem.
>
> Also, the code is all goto-based, which makes it rather hard to step through.
>
> The patch deals with these as follows:
>
> 1. Detect subpatterns that differ only by mode, code and/or integer
>     (e.g. unspec number) and split them out into a common routine.
>
> 2. Match the "shape" of the instruction first, in terms of codes,
>     integers and vector lengths, and only then check the modes, predicates
>     and dups.  When checking the shape, handle SET_SRCs before SET_DESTs.
>     In practice this seems to greatly reduce the amount of backtracking.
>
> 3. Have one local variable per rtx position.  I tested the patch with
>     and without the change and it helped a lot with rtl-checking builds
>     without seeming to affect release builds much either way.
>
> As far as debuggability goes, the new code avoids gotos and just
> uses "natural" control flow.
>
> The headline stat is that a stage 3 --enable-checking=yes,rtl,df
> build of insn-recog.c on my box goes from 7m43s to 2m2s (using the
> same stage 2 compiler).  The corresponding --enable-checking=release
> change is from 49s to 24s (less impressive, as expected).
>
> The patch seems to speed up recog.  E.g. the time taken to build
> fold-const.ii goes from 6.74s before the patch to 6.69s after it;
> not a big speed-up, but reproducible.
[ big snip ]

I don't see anything that makes me think we don't want this :-)

It's interesting to note that the regressions in loadable size of a 
release-checking insn-recog aren't any mainstream ports.  Hell, I'd 
probably claim they're all fringe ports (iq2000, m68k, mcore, 
microblaze, pdp11, rx)


> Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-none-eabi.
> Also tested by building the testsuite for each of the targets above
> and making sure there were no assembly differences.  Made sure that no
> objects in spec2k6 changed for aarch64-linux-gnu (except for perlbench
> perl.o and cactusADM datestamp.o, where the differences are timestamps).
> OK to install?
To be very blunt, I'm probably not capable of reviewing the new code. 
You're going to know it best and you should probably own it.

Given your history with gcc and attention to detail, I'm comfortable 
with approving this knowing you'll deal with any issues as they arise.

The one thing I would ask is that you make sure to include the recently 
added matching constraint checking bits in genrecog.  I'm assuming all 
the older sanity checks that have been in genrecog for a longer period 
of time have been kept.

Jeff

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-04-27 10:20 Mostly rewrite genrecog Richard Sandiford
  2015-04-28 23:18 ` Jeff Law
@ 2015-04-29  8:52 ` Eric Botcazou
  2015-04-29 13:51   ` Richard Sandiford
  2015-04-30  6:54 ` Bin.Cheng
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 30+ messages in thread
From: Eric Botcazou @ 2015-04-29  8:52 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: gcc-patches

> I think it's been the case for a while that parallel builds of GCC tend
> to serialise around the compilation of insn-recog.c, especially with
> higher --enable-checking settings.  This patch tries to speed that
> up by replacing most of genrecog with a new algorithm.

I can confirm this, especially with --enable-checking=rtl.

> Also, the code is all goto-based, which makes it rather hard to step
> through.

Do you mean the code in genrecog.c or the generated code in insn-recog.c?

> The patch deals with these as follows:
> 
> 1. Detect subpatterns that differ only by mode, code and/or integer
>    (e.g. unspec number) and split them out into a common routine.
> 
> 2. Match the "shape" of the instruction first, in terms of codes,
>    integers and vector lengths, and only then check the modes, predicates
>    and dups.  When checking the shape, handle SET_SRCs before SET_DESTs.
>    In practice this seems to greatly reduce the amount of backtracking.
> 
> 3. Have one local variable per rtx position.  I tested the patch with
>    and without the change and it helped a lot with rtl-checking builds
>    without seeming to affect release builds much either way.
> 
> As far as debuggability goes, the new code avoids gotos and just
> uses "natural" control flow.

See below.

> The headline stat is that a stage 3 --enable-checking=yes,rtl,df
> build of insn-recog.c on my box goes from 7m43s to 2m2s (using the
> same stage 2 compiler).  The corresponding --enable-checking=release
> change is from 49s to 24s (less impressive, as expected).

The first figure is quite impressive, great work!

> PS. I've attached the new genrecog.c since the diff version is unreadable.

Small request: you didn't change a single line of the head comment, yet the 
size of the file is doubled.  Could you add a sketch of the algorithm to the 
head comment, e.g. by copy-and-pasting the above part of your message?

The old code contained a couple of DEBUG_FUNCTIONs but the new one doesn't.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-04-29  8:52 ` Eric Botcazou
@ 2015-04-29 13:51   ` Richard Sandiford
  2015-04-30 10:44     ` Eric Botcazou
  0 siblings, 1 reply; 30+ messages in thread
From: Richard Sandiford @ 2015-04-29 13:51 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

Eric Botcazou <ebotcazou@adacore.com> writes:
>> Also, the code is all goto-based, which makes it rather hard to step
>> through.
>
> Do you mean the code in genrecog.c or the generated code in insn-recog.c?

The generated code.  genrecog.c itself isn't bad. :-)

>> PS. I've attached the new genrecog.c since the diff version is unreadable.
>
> Small request: you didn't change a single line of the head comment, yet the 
> size of the file is doubled.  Could you add a sketch of the algorithm to the 
> head comment, e.g. by copy-and-pasting the above part of your message?

OK.  I'd left the head comment alone because it just described the
interface, which hasn't changed.  But I suppose past lack of commentary
doesn't justify future lack of commentary.  Here's what I added:

   At a high level, the algorithm used in this file is as follows:

   1. Build up a decision tree for each routine, using the following
      approach to matching an rtx:

      - First determine the "shape" of the rtx, based on GET_CODE,
	XVECLEN and XINT.  This phase examines SET_SRCs before SET_DESTs
	since SET_SRCs tend to be more distinctive.  It examines other
	operands in numerical order, since the canonicalization rules
	prefer putting complex operands of commutative operators first.

      - Next check modes and predicates.  This phase examines all
	operands in numerical order, even for SETs, since the mode of a
	SET_DEST is exact while the mode of a SET_SRC can be VOIDmode
	for constant integers.

      - Next check match_dups.

      - Finally check the C condition and (where appropriate) pnum_clobbers.

   2. Try to optimize the tree by removing redundant tests, CSEing tests,
      folding tests together, etc.

   3. Look for common subtrees and split them out into "pattern" routines.
      These common subtrees can be identical or they can differ in mode,
      code, or integer (usually an UNSPEC or UNSPEC_VOLATILE code).
      In the latter case the users of the pattern routine pass the
      appropriate mode, etc., as argument.  For example, if two patterns
      contain:

         (plus:SI (match_operand:SI 1 "register_operand")
	          (match_operand:SI 2 "register_operand"))

      we can split the associated matching code out into a subroutine.
      If a pattern contains:

         (minus:DI (match_operand:DI 1 "register_operand")
	           (match_operand:DI 2 "register_operand"))

      then we can consider using the same matching routine for both
      the plus and minus expressions, passing PLUS and SImode in the
      former case and MINUS and DImode in the latter case.

      The main aim of this phase is to reduce the compile time of the
      insn-recog.c code and to reduce the amount of object code in
      insn-recog.o.

   4. Split the matching trees into functions, trying to limit the
      size of each function to a sensible amount.

      Again, the main aim of this phase is to reduce the compile time
      of insn-recog.c.  (It doesn't help with the size of insn-recog.o.)

   5. Write out C++ code for each function.

BTW, hope at least part of the doubling in size is due to more commentary
in the code itself.

> The old code contained a couple of DEBUG_FUNCTIONs but the new one doesn't.

Yeah, but I don't know how useful they were.  I had to debug the old
code several times and never used them.

I'd rather leave stuff like that to someone who wants it rather than try
to write routines speculatively in the hope that someone would find them
useful.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-04-28 23:18 ` Jeff Law
@ 2015-04-29 13:59   ` Richard Sandiford
  0 siblings, 0 replies; 30+ messages in thread
From: Richard Sandiford @ 2015-04-29 13:59 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches

Jeff Law <law@redhat.com> writes:
> On 04/27/2015 04:20 AM, Richard Sandiford wrote:
>> Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-none-eabi.
>> Also tested by building the testsuite for each of the targets above
>> and making sure there were no assembly differences.  Made sure that no
>> objects in spec2k6 changed for aarch64-linux-gnu (except for perlbench
>> perl.o and cactusADM datestamp.o, where the differences are timestamps).
>> OK to install?
> To be very blunt, I'm probably not capable of reviewing the new code. 
> You're going to know it best and you should probably own it.
>
> Given your history with gcc and attention to detail, I'm comfortable 
> with approving this knowing you'll deal with any issues as they arise.

Thanks, applied.

> The one thing I would ask is that you make sure to include the recently 
> added matching constraint checking bits in genrecog.  I'm assuming all 
> the older sanity checks that have been in genrecog for a longer period 
> of time have been kept.

Yeah, Chen Gang's changes are all still in there.  All the older checks
should still be in there too.

Richard

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-04-27 10:20 Mostly rewrite genrecog Richard Sandiford
  2015-04-28 23:18 ` Jeff Law
  2015-04-29  8:52 ` Eric Botcazou
@ 2015-04-30  6:54 ` Bin.Cheng
  2015-04-30 11:58   ` Richard Sandiford
  2015-04-30  7:17 ` Andreas Schwab
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 30+ messages in thread
From: Bin.Cheng @ 2015-04-30  6:54 UTC (permalink / raw)
  To: gcc-patches List, richard.sandiford

On Mon, Apr 27, 2015 at 6:20 PM, Richard Sandiford
<richard.sandiford@arm.com> wrote:
> I think it's been the case for a while that parallel builds of GCC tend
> to serialise around the compilation of insn-recog.c, especially with
> higher --enable-checking settings.  This patch tries to speed that
> up by replacing most of genrecog with a new algorithm.
>
> I think the main problems with the current code are:
>
> 1. Vector architectures have added lots of new instructions that have
>    a similar shape and differ only in mode, code or unspec number.
>    The current algorithm doesn't have any way of factoring out those
>    similarities.
>
> 2. When matching a particular instruction, the current code examines
>    everything about a SET_DEST before moving on to the SET_SRC.  This has
>    two subproblems:
>
>    2a. The destination of a SET isn't very distinctive.  It's usually
>        just a register_operand, a memory_operand, a nonimmediate_operand
>        or a flags register.  We therefore tend to backtrack to the
>        SET_DEST a lot, oscillating between groups of instructions with
>        the same kind of destination.
>
>    2b. Backtracking through predicate checks is relatively expensive.
>        It would be good to narrow down the "shape" of the instruction
>        first and only then check the predicates.  (The backtracking is
>        expensive in terms of insn-recog.o compile time too, both because
>        we need to copy into argument registers and out of the result
>        register, and because it adds more sites where spills are needed.)
>
> 3. The code keeps one local variable per rtx depth, so it ends up
>    loading the same rtx many times over (mostly when backtracking).
>    This is very expensive in rtl-checking builds because each XEXP
>    includes a code check and a line-specific failure call.
>
>    In principle the idea of having one local variable per depth
>    is good.  But it was originally written that way when all optimisations
>    were done at the rtl level and I imagine each local variable mapped
>    to one pseudo register.  These days the statements that reload the
>    value needed on backtracking lead to many more SSA names and phi
>    statements than you'd get with just a single variable per position
>    (loaded once, so naturally SSA).  There is still the potential benefit
>    of avoiding having sibling rtxes live at once, but fixing (2) above
>    reduces that problem.
>
> Also, the code is all goto-based, which makes it rather hard to step through.
>
> The patch deals with these as follows:
>
> 1. Detect subpatterns that differ only by mode, code and/or integer
>    (e.g. unspec number) and split them out into a common routine.
>
> 2. Match the "shape" of the instruction first, in terms of codes,
>    integers and vector lengths, and only then check the modes, predicates
>    and dups.  When checking the shape, handle SET_SRCs before SET_DESTs.
>    In practice this seems to greatly reduce the amount of backtracking.
>
> 3. Have one local variable per rtx position.  I tested the patch with
>    and without the change and it helped a lot with rtl-checking builds
>    without seeming to affect release builds much either way.
>
> As far as debuggability goes, the new code avoids gotos and just
> uses "natural" control flow.
>
> The headline stat is that a stage 3 --enable-checking=yes,rtl,df
> build of insn-recog.c on my box goes from 7m43s to 2m2s (using the
> same stage 2 compiler).  The corresponding --enable-checking=release
> change is from 49s to 24s (less impressive, as expected).
>
> The patch seems to speed up recog.  E.g. the time taken to build
> fold-const.ii goes from 6.74s before the patch to 6.69s after it;
> not a big speed-up, but reproducible.
>
> Here's a comparison of the number of lines of code in insn-recog.c
> before and after the patch on one target per config/ CPU:
>
> aarch64-linux-gnueabi                           115526    38169 :   33.04%
> alpha-linux-gnu                                  24479    10740 :   43.87%
> arm-linux-gnueabi                               169208    67759 :   40.04%
> avr-rtems                                        55647    22127 :   39.76%
> bfin-elf                                         13928     6498 :   46.65%
> c6x-elf                                          29928    13324 :   44.52%
> cr16-elf                                          2650     1419 :   53.55%
> cris-elf                                         18669     7257 :   38.87%
> epiphany-elf                                     19308     6131 :   31.75%
> fr30-elf                                          2204     1112 :   50.45%
> frv-linux-gnu                                    13541     5950 :   43.94%
> h8300-elf                                        19584     9327 :   47.63%
> hppa64-hp-hpux11.23                              18299     8549 :   46.72%
> ia64-linux-gnu                                   37629    17101 :   45.45%
> iq2000-elf                                        2752     1609 :   58.47%
> lm32-elf                                          1536      872 :   56.77%
> m32c-elf                                         10040     4145 :   41.28%
> m32r-elf                                          4436     2307 :   52.01%
> m68k-linux-gnu                                   15739     8147 :   51.76%
> mcore-elf                                         4816     2577 :   53.51%
> mep-elf                                          67335    15929 :   23.66%
> microblaze-elf                                    2656     1587 :   59.75%
> mips-linux-gnu                                   54543    24186 :   44.34%
> mmix                                              2597     1487 :   57.26%
> mn10300-elf                                       6384     3294 :   51.60%
> moxie-elf                                         1311      659 :   50.27%
> msp430-elf                                        6054     2382 :   39.35%
> nds32le-elf                                       5953     3152 :   52.95%
> nios2-linux-gnu                                   3735     2143 :   57.38%
> pdp11                                             2137     1157 :   54.14%
> powerpc-eabispe                                 109322    40582 :   37.12%
> powerpc-linux-gnu                                82976    32192 :   38.80%
> rl78-elf                                          5321     2432 :   45.71%
> rx-elf                                           14454     7534 :   52.12%
> s390-linux-gnu                                   48487    20454 :   42.18%
> sh-linux-gnu                                    104087    41820 :   40.18%
> sparc-linux-gnu                                  21912    10509 :   47.96%
> spu-elf                                          19937     8182 :   41.04%
> tilegx-elf                                       15412     6970 :   45.22%
> tilepro-elf                                      11998     5479 :   45.67%
> v850-elf                                          8725     4438 :   50.87%
> vax-netbsdelf                                     4537     2410 :   53.12%
> visium-elf                                       15190     7224 :   47.56%
> x86_64-darwin                                   346396   119593 :   34.52%
> xstormy16-elf                                     4660     2229 :   47.83%
> xtensa-elf                                        2799     1514 :   54.09%
>
> Here's the loadable size of insn-recog.o in an --enable-checking=release
> build on an x86_64-linux-gnu box:
>
> aarch64-linux-gnueabi                           443955   298026 :   67.13%
> alpha-linux-gnu                                  97194    80893 :   83.23%
> arm-linux-gnueabi                               782325   632248 :   80.82%
> avr-rtems                                       226827   159763 :   70.43%
> bfin-elf                                         52563    42376 :   80.62%
> c6x-elf                                         112512    90142 :   80.12%
> cr16-elf                                         10446    10006 :   95.79%
> cris-elf                                         74771    52634 :   70.39%
> epiphany-elf                                     87577    52284 :   59.70%
> fr30-elf                                          8041     7713 :   95.92%
> frv-linux-gnu                                    53699    47543 :   88.54%
> h8300-elf                                        70708    66274 :   93.73%
> hppa64-hp-hpux11.23                              71597    57484 :   80.29%
> ia64-linux-gnu                                  147286   130632 :   88.69%
> iq2000-elf                                       11002    11774 :  107.02%
> lm32-elf                                          5894     5798 :   98.37%
> m32c-elf                                         36563    28855 :   78.92%
> m32r-elf                                         17252    16910 :   98.02%
> m68k-linux-gnu                                   58248    59781 :  102.63%
> mcore-elf                                        17708    18948 :  107.00%
> mep-elf                                         314466   150771 :   47.95%
> microblaze-elf                                   10257    10534 :  102.70%
> mips-linux-gnu                                  230991   191155 :   82.75%
> mmix                                             10782    10678 :   99.04%
> mn10300-elf                                      24035    22802 :   94.87%
> moxie-elf                                         4622     4198 :   90.83%
> msp430-elf                                       21707    16539 :   76.19%
> nds32le-elf                                      22041    19444 :   88.22%
> nios2-linux-gnu                                  15595    13238 :   84.89%
> pdp11                                             7630     8254 :  108.18%
> powerpc-eabispe                                 430816   308481 :   71.60%
> powerpc-linux-gnu                               317738   248534 :   78.22%
> rl78-elf                                         18904    16329 :   86.38%
> rx-elf                                           55015    56632 :  102.94%
> s390-linux-gnu                                  190584   148961 :   78.16%
> sh-linux-gnu                                    408446   307927 :   75.39%
> sparc-linux-gnu                                  91016    80640 :   88.60%
> spu-elf                                          80387    69151 :   86.02%
> tilegx-elf                                       63815    49977 :   78.32%
> tilepro-elf                                      51763    39252 :   75.83%
> v850-elf                                         32812    28462 :   86.74%
> vax-netbsdelf                                    18350    18259 :   99.50%
> visium-elf                                       56872    46790 :   82.27%
> x86_64-darwin                                  1306182   883169 :   67.61%
> xstormy16-elf                                    17044    14430 :   84.66%
> xtensa-elf                                       10780     9678 :   89.78%
>
> The same for --enable-checking=yes,rtl:
>
> aarch64-linux-gnueabi                          1790272   507488 :   28.35%
> alpha-linux-gnu                                 440058   193826 :   44.05%
> arm-linux-gnueabi                              2845568  1299337 :   45.66%
> avr-rtems                                       885672   294387 :   33.24%
> bfin-elf                                        280606   142836 :   50.90%
> c6x-elf                                         486345   259256 :   53.31%
> cr16-elf                                         46626    20044 :   42.99%
> cris-elf                                        426813   144414 :   33.84%
> epiphany-elf                                    353078   122166 :   34.60%
> fr30-elf                                         40414    21042 :   52.07%
> frv-linux-gnu                                   259550   111335 :   42.90%
> h8300-elf                                       355199   158411 :   44.60%
> hppa64-hp-hpux11.23                             340584   149009 :   43.75%
> ia64-linux-gnu                                  661364   293710 :   44.41%
> iq2000-elf                                       41123    26709 :   64.95%
> lm32-elf                                         20370    14781 :   72.56%
> m32c-elf                                        174344    62000 :   35.56%
> m32r-elf                                         74357    41773 :   56.18%
> m68k-linux-gnu                                  275733   117445 :   42.59%
> mcore-elf                                        85180    48018 :   56.37%
> mep-elf                                        1450168   376020 :   25.93%
> microblaze-elf                                   44189    26295 :   59.51%
> mips-linux-gnu                                  876650   375753 :   42.86%
> mmix                                             49882    25363 :   50.85%
> mn10300-elf                                     128148    66768 :   52.10%
> moxie-elf                                        23388     9011 :   38.53%
> msp430-elf                                      114200    34426 :   30.15%
> nds32le-elf                                     101416    73677 :   72.65%
> nios2-linux-gnu                                  58799    29825 :   50.72%
> pdp11                                            32836    18557 :   56.51%
> powerpc-eabispe                                1976098   626942 :   31.73%
> powerpc-linux-gnu                              1510652   526841 :   34.88%
> rl78-elf                                         93675    40538 :   43.28%
> rx-elf                                          279748   137284 :   49.07%
> s390-linux-gnu                                  857009   316494 :   36.93%
> sh-linux-gnu                                   2154337   806571 :   37.44%
> sparc-linux-gnu                                 367682   169019 :   45.97%
> spu-elf                                         341945   135629 :   39.66%
> tilegx-elf                                      235480   112103 :   47.61%
> tilepro-elf                                     246231   104137 :   42.29%
> v850-elf                                        158028    72875 :   46.12%
> vax-netbsdelf                                    85057    37578 :   44.18%
> visium-elf                                      257148   103331 :   40.18%
> x86_64-darwin                                  5514235  1721777 :   31.22%
> xstormy16-elf                                    83456    46128 :   55.27%
> xtensa-elf                                       52652    29880 :   56.75%
>
> Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-none-eabi.
> Also tested by building the testsuite for each of the targets above
> and making sure there were no assembly differences.  Made sure that no
> objects in spec2k6 changed for aarch64-linux-gnu (except for perlbench
> perl.o and cactusADM datestamp.o, where the differences are timestamps).
> OK to install?
>
> Thanks,
> Richard
>
> PS. I've attached the new genrecog.c since the diff version is unreadable.
>
>
> gcc/
>         * Makefile.in (build/genrecog.o): Depend on inchash.h.
>         (build/genrecog$(build_exeext): Depend on build/hash-table.o and
>         build/inchash.o
>         * genrecog.c: Rewrite most of the code except for the third page.
>
> Index: gcc/Makefile.in
> ===================================================================
> --- gcc/Makefile.in     2015-04-27 10:42:57.783191573 +0100
> +++ gcc/Makefile.in     2015-04-27 10:43:42.878643078 +0100
> @@ -2527,7 +2527,8 @@ build/genpeep.o : genpeep.c $(RTL_BASE_H
>  build/genpreds.o : genpreds.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)   \
>    coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h $(OBSTACK_H)
>  build/genrecog.o : genrecog.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)   \
> -  coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h
> +  coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h              \
> +  $(HASH_TABLE_H) inchash.h
>  build/genhooks.o : genhooks.c $(TARGET_DEF) $(C_TARGET_DEF)            \
>    $(COMMON_TARGET_DEF) $(BCONFIG_H) $(SYSTEM_H) errors.h
>  build/genmddump.o : genmddump.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
> @@ -2559,6 +2560,8 @@ genprog = $(genprogerr) check checksum c
>  # These programs need libs over and above what they get from the above list.
>  build/genautomata$(build_exeext) : BUILD_LIBS += -lm
>
> +build/genrecog$(build_exeext) : build/hash-table.o build/inchash.o
> +
>  # For stage1 and when cross-compiling use the build libcpp which is
>  # built with NLS disabled.  For stage2+ use the host library and
>  # its dependencies.
>
Hi Richard,
I noticed that this patch caused ICE for gcc.target/arm/mmx-2.c on
arm-none-linux-gnueabi.  Could you please have a look at it?

The log message is as below,
/projects/.../src/gcc/gcc/testsuite/gcc.target/arm/mmx-2.c: In function 'foo':
/projects/.../src/gcc/gcc/testsuite/gcc.target/arm/mmx-2.c:166:1:
error: unrecognizable insn:
(insn 541 540 542 2 (set (reg:V4HI 512 [ D.4809 ])
        (vec_merge:V4HI (vec_select:V4HI (reg:V4HI 510 [ D.4806 ])
                (parallel [
                        (const_int 2 [0x2])
                        (const_int 0 [0])
                        (const_int 3 [0x3])
                        (const_int 1 [0x1])
                    ]))
            (vec_select:V4HI (reg:V4HI 511 [ D.4806 ])
                (parallel [
                        (const_int 0 [0])
                        (const_int 2 [0x2])
                        (const_int 1 [0x1])
                        (const_int 3 [0x3])
                    ]))
            (const_int 5 [0x5])))
/projects/.../src/gcc/gcc/testsuite/gcc.target/arm/mmx-2.c:159 -1
     (nil))
/projects/.../src/gcc/gcc/testsuite/gcc.target/arm/mmx-2.c:166:1:
internal compiler error: in extract_insn, at recog.c:2341
0xa42d2a _fatal_insn(char const*, rtx_def const*, char const*, int, char const*)
    /projects/.../src/gcc/gcc/rtl-error.c:110
0xa42d59 _fatal_insn_not_found(rtx_def const*, char const*, int, char const*)
    /projects/.../src/gcc/gcc/rtl-error.c:118
0xa15ff7 extract_insn(rtx_insn*)
    /projects/.../src/gcc/gcc/recog.c:2341
0x7ffb42 instantiate_virtual_regs_in_insn
    /projects/.../src/gcc/gcc/function.c:1598
0x7ffb42 instantiate_virtual_regs
    /projects/.../src/gcc/gcc/function.c:1966
0x7ffb42 execute
    /projects/.../src/gcc/gcc/function.c:2015
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.

GCC is configured with

gcc/configure --target=arm-none-linux-gnueabi --prefix=
--with-sysroot=... --enable-shared --disable-libsanitizer
--disable-libssp --disable-libmudflap
--with-plugin-ld=arm-none-linux-gnueabi-ld --enable-checking=yes
--enable-languages=c,c++,fortran --with-gmp=... --with-mpfr=...
--with-mpc=... --with-isl=... --with-cloog=... --with-arch=armv7-a
--with-fpu=vfpv3-d16 --with-float=softfp --with-arch=armv7-a

Thanks,
bin

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-04-27 10:20 Mostly rewrite genrecog Richard Sandiford
                   ` (2 preceding siblings ...)
  2015-04-30  6:54 ` Bin.Cheng
@ 2015-04-30  7:17 ` Andreas Schwab
  2015-04-30  7:58   ` Richard Sandiford
  2015-05-07  8:59 ` [nvptx] " Thomas Schwinge
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 30+ messages in thread
From: Andreas Schwab @ 2015-04-30  7:17 UTC (permalink / raw)
  To: gcc-patches; +Cc: richard.sandiford

Richard Sandiford <richard.sandiford@arm.com> writes:

> /* Represents a test and the action that should be taken on the result.
>    If a transition exists for the test outcome, the machine switches
>    to the transition's target state.  If no suitable transition exists,
>    the machine either falls through to the next decision or, if there are no
>    more decisions to try, fails the match.  */
> struct decision : list_head <transition>
> {
>   decision (const test &);
>
>   void set_parent (list_head <decision> *s);
>   bool if_statement_p (uint64_t * = 0) const;
>
>   /* The state to which this decision belongs.  */
>   state *s;
>
>   /* Links to other decisions in the same state.  */
>   decision *prev, *next;
>
>   /* The test to perform.  */
>   struct test test;
> };

../../gcc/genrecog.c:1467: error: declaration of 'test decision::test'
../../gcc/genrecog.c:1051: error: changes meaning of 'test' from 'struct test'

Bootstrap compiler is gcc 4.3.4.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-04-30  7:17 ` Andreas Schwab
@ 2015-04-30  7:58   ` Richard Sandiford
  2015-04-30 12:10     ` Andreas Schwab
  0 siblings, 1 reply; 30+ messages in thread
From: Richard Sandiford @ 2015-04-30  7:58 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: gcc-patches

Andreas Schwab <schwab@linux-m68k.org> writes:
> Richard Sandiford <richard.sandiford@arm.com> writes:
>
>> /* Represents a test and the action that should be taken on the result.
>>    If a transition exists for the test outcome, the machine switches
>>    to the transition's target state.  If no suitable transition exists,
>>    the machine either falls through to the next decision or, if there are no
>>    more decisions to try, fails the match.  */
>> struct decision : list_head <transition>
>> {
>>   decision (const test &);
>>
>>   void set_parent (list_head <decision> *s);
>>   bool if_statement_p (uint64_t * = 0) const;
>>
>>   /* The state to which this decision belongs.  */
>>   state *s;
>>
>>   /* Links to other decisions in the same state.  */
>>   decision *prev, *next;
>>
>>   /* The test to perform.  */
>>   struct test test;
>> };
>
> ../../gcc/genrecog.c:1467: error: declaration of 'test decision::test'
> ../../gcc/genrecog.c:1051: error: changes meaning of 'test' from 'struct test'
>
> Bootstrap compiler is gcc 4.3.4.

Bah.  Does it like "::test test" instead of "struct test test"?

Richard

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-04-29 13:51   ` Richard Sandiford
@ 2015-04-30 10:44     ` Eric Botcazou
  0 siblings, 0 replies; 30+ messages in thread
From: Eric Botcazou @ 2015-04-30 10:44 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: gcc-patches

> The generated code.  genrecog.c itself isn't bad. :-)

Nice work then.

> OK.  I'd left the head comment alone because it just described the
> interface, which hasn't changed.  But I suppose past lack of commentary
> doesn't justify future lack of commentary.  Here's what I added:
> [...]
> BTW, hope at least part of the doubling in size is due to more commentary
> in the code itself.

I see.  Thanks a lot for writing down the description of the algorithm!

> I'd rather leave stuff like that to someone who wants it rather than try
> to write routines speculatively in the hope that someone would find them
> useful.

OK.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-04-30  6:54 ` Bin.Cheng
@ 2015-04-30 11:58   ` Richard Sandiford
  0 siblings, 0 replies; 30+ messages in thread
From: Richard Sandiford @ 2015-04-30 11:58 UTC (permalink / raw)
  To: Bin.Cheng; +Cc: gcc-patches List

Bin.Cheng <amker.cheng@gmail.com> writes:
> Hi Richard,
> I noticed that this patch caused ICE for gcc.target/arm/mmx-2.c on
> arm-none-linux-gnueabi.  Could you please have a look at it?
>
> The log message is as below,
> /projects/.../src/gcc/gcc/testsuite/gcc.target/arm/mmx-2.c: In function 'foo':
> /projects/.../src/gcc/gcc/testsuite/gcc.target/arm/mmx-2.c:166:1:
> error: unrecognizable insn:
> (insn 541 540 542 2 (set (reg:V4HI 512 [ D.4809 ])
>         (vec_merge:V4HI (vec_select:V4HI (reg:V4HI 510 [ D.4806 ])
>                 (parallel [
>                         (const_int 2 [0x2])
>                         (const_int 0 [0])
>                         (const_int 3 [0x3])
>                         (const_int 1 [0x1])
>                     ]))
>             (vec_select:V4HI (reg:V4HI 511 [ D.4806 ])
>                 (parallel [
>                         (const_int 0 [0])
>                         (const_int 2 [0x2])
>                         (const_int 1 [0x1])
>                         (const_int 3 [0x3])
>                     ]))
>             (const_int 5 [0x5])))
> /projects/.../src/gcc/gcc/testsuite/gcc.target/arm/mmx-2.c:159 -1
>      (nil))
> /projects/.../src/gcc/gcc/testsuite/gcc.target/arm/mmx-2.c:166:1:
> internal compiler error: in extract_insn, at recog.c:2341
> 0xa42d2a _fatal_insn(char const*, rtx_def const*, char const*, int, char const*)
>     /projects/.../src/gcc/gcc/rtl-error.c:110
> 0xa42d59 _fatal_insn_not_found(rtx_def const*, char const*, int, char const*)
>     /projects/.../src/gcc/gcc/rtl-error.c:118
> 0xa15ff7 extract_insn(rtx_insn*)
>     /projects/.../src/gcc/gcc/recog.c:2341
> 0x7ffb42 instantiate_virtual_regs_in_insn
>     /projects/.../src/gcc/gcc/function.c:1598
> 0x7ffb42 instantiate_virtual_regs
>     /projects/.../src/gcc/gcc/function.c:1966
> 0x7ffb42 execute
>     /projects/.../src/gcc/gcc/function.c:2015
> Please submit a full bug report,
> with preprocessed source if appropriate.
> Please include the complete backtrace with any bug report.
> See <http://gcc.gnu.org/bugs.html> for instructions.
>
> GCC is configured with
>
> gcc/configure --target=arm-none-linux-gnueabi --prefix=
> --with-sysroot=... --enable-shared --disable-libsanitizer
> --disable-libssp --disable-libmudflap
> --with-plugin-ld=arm-none-linux-gnueabi-ld --enable-checking=yes
> --enable-languages=c,c++,fortran --with-gmp=... --with-mpfr=...
> --with-mpc=... --with-isl=... --with-cloog=... --with-arch=armv7-a
> --with-fpu=vfpv3-d16 --with-float=softfp --with-arch=armv7-a

Sorry about that, thought I'd tested that combination.

I installed the patch below as obvious after testing on arm-linux-gnu.

Thanks,
Richard


gcc/
	* genrecog.c (simplify_tests): Check that CONST_INT and XWINT tests
	are for the same position.

Index: gcc/genrecog.c
===================================================================
--- gcc/genrecog.c	2015-04-30 09:06:17.706538299 +0100
+++ gcc/genrecog.c	2015-04-30 12:49:58.689309916 +0100
@@ -1597,7 +1597,8 @@ simplify_tests (state *s)
 	  && d->if_statement_p (&label)
 	  && label == CONST_INT)
 	if (decision *second = d->first->to->singleton ())
-	  if (second->test.kind == test::WIDE_INT_FIELD
+	  if (d->test.pos == second->test.pos
+	      && second->test.kind == test::WIDE_INT_FIELD
 	      && second->test.u.opno == 0
 	      && second->if_statement_p (&label)
 	      && IN_RANGE (int64_t (label),

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-04-30  7:58   ` Richard Sandiford
@ 2015-04-30 12:10     ` Andreas Schwab
  2015-04-30 12:33       ` Richard Biener
  0 siblings, 1 reply; 30+ messages in thread
From: Andreas Schwab @ 2015-04-30 12:10 UTC (permalink / raw)
  To: gcc-patches; +Cc: richard.sandiford

Richard Sandiford <richard.sandiford@arm.com> writes:

> Andreas Schwab <schwab@linux-m68k.org> writes:
>> Richard Sandiford <richard.sandiford@arm.com> writes:
>>
>>> /* Represents a test and the action that should be taken on the result.
>>>    If a transition exists for the test outcome, the machine switches
>>>    to the transition's target state.  If no suitable transition exists,
>>>    the machine either falls through to the next decision or, if there are no
>>>    more decisions to try, fails the match.  */
>>> struct decision : list_head <transition>
>>> {
>>>   decision (const test &);
>>>
>>>   void set_parent (list_head <decision> *s);
>>>   bool if_statement_p (uint64_t * = 0) const;
>>>
>>>   /* The state to which this decision belongs.  */
>>>   state *s;
>>>
>>>   /* Links to other decisions in the same state.  */
>>>   decision *prev, *next;
>>>
>>>   /* The test to perform.  */
>>>   struct test test;
>>> };
>>
>> ../../gcc/genrecog.c:1467: error: declaration of 'test decision::test'
>> ../../gcc/genrecog.c:1051: error: changes meaning of 'test' from 'struct test'
>>
>> Bootstrap compiler is gcc 4.3.4.
>
> Bah.  Does it like "::test test" instead of "struct test test"?

Same error.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-04-30 12:10     ` Andreas Schwab
@ 2015-04-30 12:33       ` Richard Biener
  2015-04-30 16:27         ` Richard Sandiford
  0 siblings, 1 reply; 30+ messages in thread
From: Richard Biener @ 2015-04-30 12:33 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: gcc-patches, richard.sandiford

On Thu, Apr 30, 2015 at 2:08 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
> Richard Sandiford <richard.sandiford@arm.com> writes:
>
>> Andreas Schwab <schwab@linux-m68k.org> writes:
>>> Richard Sandiford <richard.sandiford@arm.com> writes:
>>>
>>>> /* Represents a test and the action that should be taken on the result.
>>>>    If a transition exists for the test outcome, the machine switches
>>>>    to the transition's target state.  If no suitable transition exists,
>>>>    the machine either falls through to the next decision or, if there are no
>>>>    more decisions to try, fails the match.  */
>>>> struct decision : list_head <transition>
>>>> {
>>>>   decision (const test &);
>>>>
>>>>   void set_parent (list_head <decision> *s);
>>>>   bool if_statement_p (uint64_t * = 0) const;
>>>>
>>>>   /* The state to which this decision belongs.  */
>>>>   state *s;
>>>>
>>>>   /* Links to other decisions in the same state.  */
>>>>   decision *prev, *next;
>>>>
>>>>   /* The test to perform.  */
>>>>   struct test test;
>>>> };
>>>
>>> ../../gcc/genrecog.c:1467: error: declaration of 'test decision::test'
>>> ../../gcc/genrecog.c:1051: error: changes meaning of 'test' from 'struct test'
>>>
>>> Bootstrap compiler is gcc 4.3.4.
>>
>> Bah.  Does it like "::test test" instead of "struct test test"?
>
> Same error.

You have to use a different name I believe (or -fpermissive).

Richard.

> Andreas.
>
> --
> Andreas Schwab, schwab@linux-m68k.org
> GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
> "And now for something completely different."

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-04-30 12:33       ` Richard Biener
@ 2015-04-30 16:27         ` Richard Sandiford
  2015-05-01 12:42           ` Richard Sandiford
  0 siblings, 1 reply; 30+ messages in thread
From: Richard Sandiford @ 2015-04-30 16:27 UTC (permalink / raw)
  To: Richard Biener; +Cc: Andreas Schwab, gcc-patches

Richard Biener <richard.guenther@gmail.com> writes:
> On Thu, Apr 30, 2015 at 2:08 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
>> Richard Sandiford <richard.sandiford@arm.com> writes:
>>
>>> Andreas Schwab <schwab@linux-m68k.org> writes:
>>>> Richard Sandiford <richard.sandiford@arm.com> writes:
>>>>
>>>>> /* Represents a test and the action that should be taken on the result.
>>>>>    If a transition exists for the test outcome, the machine switches
>>>>>    to the transition's target state.  If no suitable transition exists,
>>>>>    the machine either falls through to the next decision or, if there are no
>>>>>    more decisions to try, fails the match.  */
>>>>> struct decision : list_head <transition>
>>>>> {
>>>>>   decision (const test &);
>>>>>
>>>>>   void set_parent (list_head <decision> *s);
>>>>>   bool if_statement_p (uint64_t * = 0) const;
>>>>>
>>>>>   /* The state to which this decision belongs.  */
>>>>>   state *s;
>>>>>
>>>>>   /* Links to other decisions in the same state.  */
>>>>>   decision *prev, *next;
>>>>>
>>>>>   /* The test to perform.  */
>>>>>   struct test test;
>>>>> };
>>>>
>>>> ../../gcc/genrecog.c:1467: error: declaration of 'test decision::test'
>>>> ../../gcc/genrecog.c:1051: error: changes meaning of 'test' from
>>>> struct test'
>>>>
>>>> Bootstrap compiler is gcc 4.3.4.
>>>
>>> Bah.  Does it like "::test test" instead of "struct test test"?
>>
>> Same error.
>
> You have to use a different name I believe (or -fpermissive).

Hmm, but then why does it work with more recent compilers?

Thanks,
Richard

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-04-30 16:27         ` Richard Sandiford
@ 2015-05-01 12:42           ` Richard Sandiford
  2015-05-01 13:57             ` Jeff Law
  0 siblings, 1 reply; 30+ messages in thread
From: Richard Sandiford @ 2015-05-01 12:42 UTC (permalink / raw)
  To: Richard Biener; +Cc: Andreas Schwab, gcc-patches

Richard Sandiford <richard.sandiford@arm.com> writes:
> Richard Biener <richard.guenther@gmail.com> writes:
>> On Thu, Apr 30, 2015 at 2:08 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
>>> Richard Sandiford <richard.sandiford@arm.com> writes:
>>>
>>>> Andreas Schwab <schwab@linux-m68k.org> writes:
>>>>> Richard Sandiford <richard.sandiford@arm.com> writes:
>>>>>
>>>>>> /* Represents a test and the action that should be taken on the result.
>>>>>>    If a transition exists for the test outcome, the machine switches
>>>>>>    to the transition's target state.  If no suitable transition exists,
>>>>>>    the machine either falls through to the next decision or, if there are no
>>>>>>    more decisions to try, fails the match.  */
>>>>>> struct decision : list_head <transition>
>>>>>> {
>>>>>>   decision (const test &);
>>>>>>
>>>>>>   void set_parent (list_head <decision> *s);
>>>>>>   bool if_statement_p (uint64_t * = 0) const;
>>>>>>
>>>>>>   /* The state to which this decision belongs.  */
>>>>>>   state *s;
>>>>>>
>>>>>>   /* Links to other decisions in the same state.  */
>>>>>>   decision *prev, *next;
>>>>>>
>>>>>>   /* The test to perform.  */
>>>>>>   struct test test;
>>>>>> };
>>>>>
>>>>> ../../gcc/genrecog.c:1467: error: declaration of 'test decision::test'
>>>>> ../../gcc/genrecog.c:1051: error: changes meaning of 'test' from
>>>>> struct test'
>>>>>
>>>>> Bootstrap compiler is gcc 4.3.4.
>>>>
>>>> Bah.  Does it like "::test test" instead of "struct test test"?
>>>
>>> Same error.
>>
>> You have to use a different name I believe (or -fpermissive).
>
> Hmm, but then why does it work with more recent compilers?

Whatever the reason, I suppose the path of least resistance is to
rename the thing.

Tested on x86_64-linux-gnu.  OK to install?

Thanks,
Richard


gcc/
	* genrecog.c (test): Rename to rtx_test.  Update rest of file
	accordingly.

Index: gcc/genrecog.c
===================================================================
--- gcc/genrecog.c	2015-04-30 17:45:29.662231979 +0100
+++ gcc/genrecog.c	2015-04-30 17:45:29.806230258 +0100
@@ -1047,9 +1047,9 @@ struct pattern_use
 };
 
 /* Represents a test performed by a decision.  */
-struct test
+struct rtx_test
 {
-  test ();
+  rtx_test ();
 
   /* The types of test that can be performed.  Most of them take as input
      an rtx X.  Some also take as input a transition label LABEL; the others
@@ -1140,136 +1140,136 @@ struct test
     acceptance_type acceptance;
   } u;
 
-  static test code (position *);
-  static test mode (position *);
-  static test int_field (position *, int);
-  static test wide_int_field (position *, int);
-  static test veclen (position *);
-  static test peep2_count (int);
-  static test veclen_ge (position *, int);
-  static test predicate (position *, const pred_data *, machine_mode);
-  static test duplicate (position *, int);
-  static test pattern (position *, pattern_use *);
-  static test have_num_clobbers ();
-  static test c_test (const char *);
-  static test set_op (position *, int);
-  static test accept (const acceptance_type &);
+  static rtx_test code (position *);
+  static rtx_test mode (position *);
+  static rtx_test int_field (position *, int);
+  static rtx_test wide_int_field (position *, int);
+  static rtx_test veclen (position *);
+  static rtx_test peep2_count (int);
+  static rtx_test veclen_ge (position *, int);
+  static rtx_test predicate (position *, const pred_data *, machine_mode);
+  static rtx_test duplicate (position *, int);
+  static rtx_test pattern (position *, pattern_use *);
+  static rtx_test have_num_clobbers ();
+  static rtx_test c_test (const char *);
+  static rtx_test set_op (position *, int);
+  static rtx_test accept (const acceptance_type &);
 
   bool terminal_p () const;
   bool single_outcome_p () const;
 
 private:
-  test (position *, kind_enum);
+  rtx_test (position *, kind_enum);
 };
 
-test::test () {}
+rtx_test::rtx_test () {}
 
-test::test (position *pos_in, kind_enum kind_in)
+rtx_test::rtx_test (position *pos_in, kind_enum kind_in)
   : pos (pos_in), pos_operand (-1), kind (kind_in) {}
 
-test
-test::code (position *pos)
+rtx_test
+rtx_test::code (position *pos)
 {
-  return test (pos, test::CODE);
+  return rtx_test (pos, rtx_test::CODE);
 }
 
-test
-test::mode (position *pos)
+rtx_test
+rtx_test::mode (position *pos)
 {
-  return test (pos, test::MODE);
+  return rtx_test (pos, rtx_test::MODE);
 }
 
-test
-test::int_field (position *pos, int opno)
+rtx_test
+rtx_test::int_field (position *pos, int opno)
 {
-  test res (pos, test::INT_FIELD);
+  rtx_test res (pos, rtx_test::INT_FIELD);
   res.u.opno = opno;
   return res;
 }
 
-test
-test::wide_int_field (position *pos, int opno)
+rtx_test
+rtx_test::wide_int_field (position *pos, int opno)
 {
-  test res (pos, test::WIDE_INT_FIELD);
+  rtx_test res (pos, rtx_test::WIDE_INT_FIELD);
   res.u.opno = opno;
   return res;
 }
 
-test
-test::veclen (position *pos)
+rtx_test
+rtx_test::veclen (position *pos)
 {
-  return test (pos, test::VECLEN);
+  return rtx_test (pos, rtx_test::VECLEN);
 }
 
-test
-test::peep2_count (int min_len)
+rtx_test
+rtx_test::peep2_count (int min_len)
 {
-  test res (0, test::PEEP2_COUNT);
+  rtx_test res (0, rtx_test::PEEP2_COUNT);
   res.u.min_len = min_len;
   return res;
 }
 
-test
-test::veclen_ge (position *pos, int min_len)
+rtx_test
+rtx_test::veclen_ge (position *pos, int min_len)
 {
-  test res (pos, test::VECLEN_GE);
+  rtx_test res (pos, rtx_test::VECLEN_GE);
   res.u.min_len = min_len;
   return res;
 }
 
-test
-test::predicate (position *pos, const struct pred_data *data,
-		 machine_mode mode)
+rtx_test
+rtx_test::predicate (position *pos, const struct pred_data *data,
+		     machine_mode mode)
 {
-  test res (pos, test::PREDICATE);
+  rtx_test res (pos, rtx_test::PREDICATE);
   res.u.predicate.data = data;
   res.u.predicate.mode_is_param = false;
   res.u.predicate.mode = mode;
   return res;
 }
 
-test
-test::duplicate (position *pos, int opno)
+rtx_test
+rtx_test::duplicate (position *pos, int opno)
 {
-  test res (pos, test::DUPLICATE);
+  rtx_test res (pos, rtx_test::DUPLICATE);
   res.u.opno = opno;
   return res;
 }
 
-test
-test::pattern (position *pos, pattern_use *pattern)
+rtx_test
+rtx_test::pattern (position *pos, pattern_use *pattern)
 {
-  test res (pos, test::PATTERN);
+  rtx_test res (pos, rtx_test::PATTERN);
   res.u.pattern = pattern;
   return res;
 }
 
-test
-test::have_num_clobbers ()
+rtx_test
+rtx_test::have_num_clobbers ()
 {
-  return test (0, test::HAVE_NUM_CLOBBERS);
+  return rtx_test (0, rtx_test::HAVE_NUM_CLOBBERS);
 }
 
-test
-test::c_test (const char *string)
+rtx_test
+rtx_test::c_test (const char *string)
 {
-  test res (0, test::C_TEST);
+  rtx_test res (0, rtx_test::C_TEST);
   res.u.string = string;
   return res;
 }
 
-test
-test::set_op (position *pos, int opno)
+rtx_test
+rtx_test::set_op (position *pos, int opno)
 {
-  test res (pos, test::SET_OP);
+  rtx_test res (pos, rtx_test::SET_OP);
   res.u.opno = opno;
   return res;
 }
 
-test
-test::accept (const acceptance_type &acceptance)
+rtx_test
+rtx_test::accept (const acceptance_type &acceptance)
 {
-  test res (0, test::ACCEPT);
+  rtx_test res (0, rtx_test::ACCEPT);
   res.u.acceptance = acceptance;
   return res;
 }
@@ -1277,66 +1277,66 @@ test::accept (const acceptance_type &acc
 /* Return true if the test represents an unconditionally successful match.  */
 
 bool
-test::terminal_p () const
+rtx_test::terminal_p () const
 {
-  return kind == test::ACCEPT && u.acceptance.type != PEEPHOLE2;
+  return kind == rtx_test::ACCEPT && u.acceptance.type != PEEPHOLE2;
 }
 
 /* Return true if the test is a boolean that is always true.  */
 
 bool
-test::single_outcome_p () const
+rtx_test::single_outcome_p () const
 {
-  return terminal_p () || kind == test::SET_OP;
+  return terminal_p () || kind == rtx_test::SET_OP;
 }
 
 bool
-operator == (const test &a, const test &b)
+operator == (const rtx_test &a, const rtx_test &b)
 {
   if (a.pos != b.pos || a.kind != b.kind)
     return false;
   switch (a.kind)
     {
-    case test::CODE:
-    case test::MODE:
-    case test::VECLEN:
-    case test::HAVE_NUM_CLOBBERS:
+    case rtx_test::CODE:
+    case rtx_test::MODE:
+    case rtx_test::VECLEN:
+    case rtx_test::HAVE_NUM_CLOBBERS:
       return true;
 
-    case test::PEEP2_COUNT:
-    case test::VECLEN_GE:
+    case rtx_test::PEEP2_COUNT:
+    case rtx_test::VECLEN_GE:
       return a.u.min_len == b.u.min_len;
 
-    case test::INT_FIELD:
-    case test::WIDE_INT_FIELD:
-    case test::DUPLICATE:
-    case test::SET_OP:
+    case rtx_test::INT_FIELD:
+    case rtx_test::WIDE_INT_FIELD:
+    case rtx_test::DUPLICATE:
+    case rtx_test::SET_OP:
       return a.u.opno == b.u.opno;
 
-    case test::SAVED_CONST_INT:
+    case rtx_test::SAVED_CONST_INT:
       return (a.u.integer.is_param == b.u.integer.is_param
 	      && a.u.integer.value == b.u.integer.value);
 
-    case test::PREDICATE:
+    case rtx_test::PREDICATE:
       return (a.u.predicate.data == b.u.predicate.data
 	      && a.u.predicate.mode_is_param == b.u.predicate.mode_is_param
 	      && a.u.predicate.mode == b.u.predicate.mode);
 
-    case test::PATTERN:
+    case rtx_test::PATTERN:
       return (a.u.pattern->routine == b.u.pattern->routine
 	      && a.u.pattern->params == b.u.pattern->params);
 
-    case test::C_TEST:
+    case rtx_test::C_TEST:
       return strcmp (a.u.string, b.u.string) == 0;
 
-    case test::ACCEPT:
+    case rtx_test::ACCEPT:
       return a.u.acceptance == b.u.acceptance;
     }
   gcc_unreachable ();
 }
 
 bool
-operator != (const test &a, const test &b)
+operator != (const rtx_test &a, const rtx_test &b)
 {
   return !operator == (a, b);
 }
@@ -1420,8 +1420,8 @@ struct transition
   transition *prev, *next;
 
   /* The transition should be taken when T has one of these values.
-     E.g. for test::CODE this is a set of codes, while for booleans like
-     test::PREDICATE it is always a singleton "true".  The labels are
+     E.g. for rtx_test::CODE this is a set of codes, while for booleans like
+     rtx_test::PREDICATE it is always a singleton "true".  The labels are
      sorted in ascending order.  */
   int_set labels;
 
@@ -1439,7 +1439,7 @@ struct transition
   bool optional;
 
   /* True if LABELS contains parameter numbers rather than constants.
-     E.g. if this is true for a test::CODE, the label is the number
+     E.g. if this is true for a rtx_test::CODE, the label is the number
      of an rtx_code parameter rather than an rtx_code itself.
      LABELS is always a singleton when this variable is true.  */
   bool is_param;
@@ -1452,7 +1452,7 @@ struct transition
    more decisions to try, fails the match.  */
 struct decision : list_head <transition>
 {
-  decision (const test &);
+  decision (const rtx_test &);
 
   void set_parent (list_head <decision> *s);
   bool if_statement_p (uint64_t * = 0) const;
@@ -1464,7 +1464,7 @@ struct decision : list_head <transition>
   decision *prev, *next;
 
   /* The test to perform.  */
-  struct test test;
+  rtx_test test;
 };
 
 /* Represents one machine state.  For each state the machine tries a list
@@ -1488,7 +1488,7 @@ transition::set_parent (list_head <trans
   from = static_cast <decision *> (from_in);
 }
 
-decision::decision (const struct test &test_in)
+decision::decision (const rtx_test &test_in)
   : prev (0), next (0), test (test_in) {}
 
 /* Set the state to which this decision belongs.  */
@@ -1518,7 +1518,7 @@ decision::if_statement_p (uint64_t *labe
    TRANS.  */
 
 static void
-add_decision (state *from, const test &test, transition *trans)
+add_decision (state *from, const rtx_test &test, transition *trans)
 {
   decision *d = new decision (test);
   from->push_back (d);
@@ -1530,7 +1530,7 @@ add_decision (state *from, const test &t
    should be optional.  Return the new state.  */
 
 static state *
-add_decision (state *from, const test &test, int_set labels, bool optional)
+add_decision (state *from, const rtx_test &test, int_set labels, bool optional)
 {
   state *to = new state;
   add_decision (from, test, new transition (labels, to, optional));
@@ -1542,7 +1542,7 @@ add_decision (state *from, const test &t
    optional.  */
 
 static decision *
-insert_decision_before (state::range r, const test &test,
+insert_decision_before (state::range r, const rtx_test &test,
 			const int_set &labels, bool optional)
 {
   decision *newd = new decision (test);
@@ -1593,18 +1593,18 @@ simplify_tests (state *s)
       uint64_t label;
       /* Convert checks for GET_CODE (x) == CONST_INT and XWINT (x, 0) == N
 	 into checks for const_int_rtx[N'], if N is suitably small.  */
-      if (d->test.kind == test::CODE
+      if (d->test.kind == rtx_test::CODE
 	  && d->if_statement_p (&label)
 	  && label == CONST_INT)
 	if (decision *second = d->first->to->singleton ())
 	  if (d->test.pos == second->test.pos
-	      && second->test.kind == test::WIDE_INT_FIELD
+	      && second->test.kind == rtx_test::WIDE_INT_FIELD
 	      && second->test.u.opno == 0
 	      && second->if_statement_p (&label)
 	      && IN_RANGE (int64_t (label),
 			   -MAX_SAVED_CONST_INT, MAX_SAVED_CONST_INT))
 	    {
-	      d->test.kind = test::SAVED_CONST_INT;
+	      d->test.kind = rtx_test::SAVED_CONST_INT;
 	      d->test.u.integer.is_param = false;
 	      d->test.u.integer.value = label;
 	      d->replace (d->first, second->release ());
@@ -1619,7 +1619,7 @@ simplify_tests (state *s)
 	 paths that reach that code test require the same predicate
 	 to be true.  cse_tests will then put the predicate test in
 	 series with the code test.  */
-      if (d->test.kind == test::CODE)
+      if (d->test.kind == rtx_test::CODE)
 	if (transition *trans = d->singleton ())
 	  {
 	    state *s = trans->to;
@@ -1630,7 +1630,7 @@ simplify_tests (state *s)
 		transition *trans2 = d2->singleton ();
 		if (!trans2)
 		  break;
-		if (d2->test.kind == test::PREDICATE)
+		if (d2->test.kind == rtx_test::PREDICATE)
 		  {
 		    d->test = d2->test;
 		    trans->labels = int_set (true);
@@ -1654,7 +1654,7 @@ simplify_tests (state *s)
 static bool
 common_test_p (decision *d, transition *common, vec <transition *> *where)
 {
-  if (d->test.kind == test::ACCEPT)
+  if (d->test.kind == rtx_test::ACCEPT)
     /* We found a successful return that didn't require COMMON.  */
     return false;
   if (d->test == common->from->test)
@@ -1702,20 +1702,20 @@ struct known_conditions
    as positive proof.  */
 
 static bool
-safe_to_hoist_p (decision *d, const test &test, known_conditions *kc)
+safe_to_hoist_p (decision *d, const rtx_test &test, known_conditions *kc)
 {
   switch (test.kind)
     {
-    case test::C_TEST:
+    case rtx_test::C_TEST:
       /* In general, C tests require everything else to have been
 	 verified and all operands to have been set up.  */
       return false;
 
-    case test::ACCEPT:
+    case rtx_test::ACCEPT:
       /* Don't accept something before all conditions have been tested.  */
       return false;
 
-    case test::PREDICATE:
+    case rtx_test::PREDICATE:
       /* Don't move a predicate over a test for VECLEN_GE, since the
 	 predicate used in a match_parallel can legitimately expect the
 	 length to be checked first.  */
@@ -1723,21 +1723,21 @@ safe_to_hoist_p (decision *d, const test
 	   subd->test != test;
 	   subd = subd->first->to->first)
 	if (subd->test.pos == test.pos
-	    && subd->test.kind == test::VECLEN_GE)
+	    && subd->test.kind == rtx_test::VECLEN_GE)
 	  return false;
       goto any_rtx;
 
-    case test::DUPLICATE:
+    case rtx_test::DUPLICATE:
       /* Don't test for a match_dup until the associated operand has
 	 been set.  */
       if (!kc->set_operands[test.u.opno])
 	return false;
       goto any_rtx;
 
-    case test::CODE:
-    case test::MODE:
-    case test::SAVED_CONST_INT:
-    case test::SET_OP:
+    case rtx_test::CODE:
+    case rtx_test::MODE:
+    case rtx_test::SAVED_CONST_INT:
+    case rtx_test::SET_OP:
     any_rtx:
       /* Check whether it is safe to access the rtx under test.  */
       switch (test.pos->type)
@@ -1753,20 +1753,20 @@ safe_to_hoist_p (decision *d, const test
 	}
       gcc_unreachable ();
 
-    case test::INT_FIELD:
-    case test::WIDE_INT_FIELD:
-    case test::VECLEN:
-    case test::VECLEN_GE:
+    case rtx_test::INT_FIELD:
+    case rtx_test::WIDE_INT_FIELD:
+    case rtx_test::VECLEN:
+    case rtx_test::VECLEN_GE:
       /* These tests access a specific part of an rtx, so are only safe
 	 once we know what the rtx is.  */
       return kc->position_tests[test.pos->id] & TESTED_CODE;
 
-    case test::PEEP2_COUNT:
-    case test::HAVE_NUM_CLOBBERS:
+    case rtx_test::PEEP2_COUNT:
+    case rtx_test::HAVE_NUM_CLOBBERS:
       /* These tests can be performed anywhere.  */
       return true;
 
-    case test::PATTERN:
+    case rtx_test::PATTERN:
       gcc_unreachable ();
     }
   gcc_unreachable ();
@@ -1887,8 +1887,8 @@ cse_tests (position *pos, state *s, know
       /* Make sure that safe_to_hoist_p isn't being overly conservative.
 	 It should realize that D's test is safe in the current
 	 environment.  */
-      gcc_assert (d->test.kind == test::C_TEST
-		  || d->test.kind == test::ACCEPT
+      gcc_assert (d->test.kind == rtx_test::C_TEST
+		  || d->test.kind == rtx_test::ACCEPT
 		  || safe_to_hoist_p (d, d->test, kc));
 
       /* D won't be changed any further by the current optimization.
@@ -1896,24 +1896,24 @@ cse_tests (position *pos, state *s, know
       int prev = 0;
       switch (d->test.kind)
 	{
-	case test::CODE:
+	case rtx_test::CODE:
 	  prev = kc->position_tests[d->test.pos->id];
 	  kc->position_tests[d->test.pos->id] |= TESTED_CODE;
 	  break;
 
-	case test::VECLEN:
-	case test::VECLEN_GE:
+	case rtx_test::VECLEN:
+	case rtx_test::VECLEN_GE:
 	  prev = kc->position_tests[d->test.pos->id];
 	  kc->position_tests[d->test.pos->id] |= TESTED_VECLEN;
 	  break;
 
-	case test::SET_OP:
+	case rtx_test::SET_OP:
 	  prev = kc->set_operands[d->test.u.opno];
 	  gcc_assert (!prev);
 	  kc->set_operands[d->test.u.opno] = true;
 	  break;
 
-	case test::PEEP2_COUNT:
+	case rtx_test::PEEP2_COUNT:
 	  prev = kc->peep2_count;
 	  kc->peep2_count = MAX (prev, d->test.u.min_len);
 	  break;
@@ -1925,17 +1925,17 @@ cse_tests (position *pos, state *s, know
 	cse_tests (d->test.pos ? d->test.pos : pos, trans->to, kc);
       switch (d->test.kind)
 	{
-	case test::CODE:
-	case test::VECLEN:
-	case test::VECLEN_GE:
+	case rtx_test::CODE:
+	case rtx_test::VECLEN:
+	case rtx_test::VECLEN_GE:
 	  kc->position_tests[d->test.pos->id] = prev;
 	  break;
 
-	case test::SET_OP:
+	case rtx_test::SET_OP:
 	  kc->set_operands[d->test.u.opno] = prev;
 	  break;
 
-	case test::PEEP2_COUNT:
+	case rtx_test::PEEP2_COUNT:
 	  kc->peep2_count = prev;
 	  break;
 
@@ -1949,33 +1949,33 @@ cse_tests (position *pos, state *s, know
    or parameter::UNSET if none.  */
 
 parameter::type_enum
-transition_parameter_type (test::kind_enum kind)
+transition_parameter_type (rtx_test::kind_enum kind)
 {
   switch (kind)
     {
-    case test::CODE:
+    case rtx_test::CODE:
       return parameter::CODE;
 
-    case test::MODE:
+    case rtx_test::MODE:
       return parameter::MODE;
 
-    case test::INT_FIELD:
-    case test::VECLEN:
-    case test::PATTERN:
+    case rtx_test::INT_FIELD:
+    case rtx_test::VECLEN:
+    case rtx_test::PATTERN:
       return parameter::INT;
 
-    case test::WIDE_INT_FIELD:
+    case rtx_test::WIDE_INT_FIELD:
       return parameter::WIDE_INT;
 
-    case test::PEEP2_COUNT:
-    case test::VECLEN_GE:
-    case test::SAVED_CONST_INT:
-    case test::PREDICATE:
-    case test::DUPLICATE:
-    case test::HAVE_NUM_CLOBBERS:
-    case test::C_TEST:
-    case test::SET_OP:
-    case test::ACCEPT:
+    case rtx_test::PEEP2_COUNT:
+    case rtx_test::VECLEN_GE:
+    case rtx_test::SAVED_CONST_INT:
+    case rtx_test::PREDICATE:
+    case rtx_test::DUPLICATE:
+    case rtx_test::HAVE_NUM_CLOBBERS:
+    case rtx_test::C_TEST:
+    case rtx_test::SET_OP:
+    case rtx_test::ACCEPT:
       return parameter::UNSET;
     }
   gcc_unreachable ();
@@ -1993,11 +1993,11 @@ find_operand_positions (state *s, vec <i
       int this_operand = (d->test.pos ? operand_pos[d->test.pos->id] : -1);
       if (this_operand >= 0)
 	d->test.pos_operand = this_operand;
-      if (d->test.kind == test::SET_OP)
+      if (d->test.kind == rtx_test::SET_OP)
 	operand_pos[d->test.pos->id] = d->test.u.opno;
       for (transition *trans = d->first; trans; trans = trans->next)
 	find_operand_positions (trans->to, operand_pos);
-      if (d->test.kind == test::SET_OP)
+      if (d->test.kind == rtx_test::SET_OP)
 	operand_pos[d->test.pos->id] = this_operand;
     }
 }
@@ -2065,7 +2065,7 @@ get_stats (state *s)
 	  for_d.num_decisions += 1;
 	  for_d.longest_path += 1;
 	}
-      if (d->test.kind == test::ACCEPT)
+      if (d->test.kind == rtx_test::ACCEPT)
 	{
 	  for_d.longest_path_code = d->test.u.acceptance.u.full.code;
 	  for_d.longest_backtrack_code = d->test.u.acceptance.u.full.code;
@@ -2379,21 +2379,21 @@ update_parameters (vec <parameter> &to,
    PARAMB alone.  */
 
 static bool
-compatible_tests_p (const test &a, const test &b,
+compatible_tests_p (const rtx_test &a, const rtx_test &b,
 		    parameter *parama, parameter *paramb)
 {
   if (a.kind != b.kind)
     return false;
   switch (a.kind)
     {
-    case test::PREDICATE:
+    case rtx_test::PREDICATE:
       if (a.u.predicate.data != b.u.predicate.data)
 	return false;
       *parama = parameter (parameter::MODE, false, a.u.predicate.mode);
       *paramb = parameter (parameter::MODE, false, b.u.predicate.mode);
       return true;
 
-    case test::SAVED_CONST_INT:
+    case rtx_test::SAVED_CONST_INT:
       *parama = parameter (parameter::INT, false, a.u.integer.value);
       *paramb = parameter (parameter::INT, false, b.u.integer.value);
       return true;
@@ -2667,7 +2667,7 @@ merge_patterns (merge_state_info *sinfo1
 	     parameterizing the first N const_ints of the vector
 	     and then (once we reach the maximum number of parameters)
 	     we go on to match the other elements exactly.  */
-	  if (d1->test.kind == test::WIDE_INT_FIELD)
+	  if (d1->test.kind == rtx_test::WIDE_INT_FIELD)
 	    return false;
 
 	  /* See whether the label has a generalizable type.  */
@@ -2803,7 +2803,7 @@ init_pattern_use (create_pattern_info *c
   pattern_use *use = new pattern_use;
   use->routine = pat->routine;
   use->params.splice (params);
-  decision *d = new decision (test::pattern (res->root, use));
+  decision *d = new decision (rtx_test::pattern (res->root, use));
 
   /* If the original decision could use an element of operands[] instead
      of an rtx variable, try to transfer it to the new decision.  */
@@ -2823,7 +2823,7 @@ add_pattern_acceptance (create_pattern_i
   acceptance.type = SUBPATTERN;
   acceptance.partial_p = false;
   acceptance.u.full.code = cpi->next_result;
-  add_decision (s, test::accept (acceptance), true, false);
+  add_decision (s, rtx_test::accept (acceptance), true, false);
   cpi->next_result += 1;
 }
 
@@ -2860,12 +2860,12 @@ populate_pattern_routine (create_pattern
       const parameter &param = params[pat->param_test];
       switch (newd->test.kind)
 	{
-	case test::PREDICATE:
+	case rtx_test::PREDICATE:
 	  newd->test.u.predicate.mode_is_param = param.is_param;
 	  newd->test.u.predicate.mode = param.value;
 	  break;
 
-	case test::SAVED_CONST_INT:
+	case rtx_test::SAVED_CONST_INT:
 	  newd->test.u.integer.is_param = param.is_param;
 	  newd->test.u.integer.value = param.value;
 	  break;
@@ -2875,9 +2875,9 @@ populate_pattern_routine (create_pattern
 	  break;
 	}
     }
-  if (d->test.kind == test::C_TEST)
+  if (d->test.kind == rtx_test::C_TEST)
     routine->insn_p = true;
-  else if (d->test.kind == test::HAVE_NUM_CLOBBERS)
+  else if (d->test.kind == rtx_test::HAVE_NUM_CLOBBERS)
     routine->pnum_clobbers_p = true;
   news->push_back (newd);
 
@@ -3038,11 +3038,11 @@ split_out_patterns (vec <merge_state_inf
 	 and so couldn't be shared between states).  */
       if (decision *d = sinfo->s->singleton ())
 	/* ACCEPT states are unique, so don't even try to merge them.  */
-	if (d->test.kind != test::ACCEPT
+	if (d->test.kind != rtx_test::ACCEPT
 	    && (pattern_have_num_clobbers_p
-		|| d->test.kind != test::HAVE_NUM_CLOBBERS)
+		|| d->test.kind != rtx_test::HAVE_NUM_CLOBBERS)
 	    && (pattern_c_test_p
-		|| d->test.kind != test::C_TEST))
+		|| d->test.kind != rtx_test::C_TEST))
 	  {
 	    merge_state_info **slot = hashtab.find_slot (sinfo, INSERT);
 	    sinfo->prev_same_test = *slot;
@@ -3290,7 +3290,7 @@ create_subroutine (routine_type type, st
   acceptance.partial_p = true;
   acceptance.u.subroutine_id = procs.length ();
   state *news = new state;
-  add_decision (news, test::accept (acceptance), true, false);
+  add_decision (news, rtx_test::accept (acceptance), true, false);
   return news;
 }
 
@@ -3327,8 +3327,8 @@ find_subroutines (routine_type type, sta
 		if (!newd->test.single_outcome_p ())
 		  size.num_statements += 1;
 		trans = newd->singleton ();
-		if (newd->test.kind == test::SET_OP
-		    || newd->test.kind == test::ACCEPT)
+		if (newd->test.kind == rtx_test::SET_OP
+		    || newd->test.kind == rtx_test::ACCEPT)
 		  break;
 	      }
 	  /* The target of TRANS is a subroutine candidate.  First recurse
@@ -3866,9 +3866,9 @@ match_pattern_2 (state *s, rtx top_patte
 	    if (code == MATCH_PARALLEL || code == MATCH_PAR_DUP)
 	      {
 		/* Check that we have a parallel with enough elements.  */
-		s = add_decision (s, test::code (pos), PARALLEL, false);
+		s = add_decision (s, rtx_test::code (pos), PARALLEL, false);
 		int min_len = XVECLEN (pattern, 2);
-		s = add_decision (s, test::veclen_ge (pos, min_len),
+		s = add_decision (s, rtx_test::veclen_ge (pos, min_len),
 				  true, false);
 	      }
 	    else
@@ -3883,7 +3883,7 @@ match_pattern_2 (state *s, rtx top_patte
 		bool need_codes = (pred
 				   && (code == MATCH_OPERATOR
 				       || code == MATCH_OP_DUP));
-		s = add_decision (s, test::code (pos), codes, !need_codes);
+		s = add_decision (s, rtx_test::code (pos), codes, !need_codes);
 	      }
 
 	    /* Postpone the predicate check until we've checked the rest
@@ -3924,7 +3924,7 @@ match_pattern_2 (state *s, rtx top_patte
 	default:
 	  {
 	    /* Check that the rtx has the right code.  */
-	    s = add_decision (s, test::code (pos), code, false);
+	    s = add_decision (s, rtx_test::code (pos), code, false);
 
 	    /* Queue a test for the mode if one is specified.  */
 	    if (GET_MODE (pattern) != VOIDmode)
@@ -3949,7 +3949,8 @@ match_pattern_2 (state *s, rtx top_patte
 		      /* Make sure the vector has the right number of
 			 elements.  */
 		      int length = XVECLEN (pattern, i);
-		      s = add_decision (s, test::veclen (pos), length, false);
+		      s = add_decision (s, rtx_test::veclen (pos),
+					length, false);
 
 		      position **subpos2_ptr = &pos->xvecexp0s;
 		      for (int j = 0; j < length; j++)
@@ -3965,13 +3966,13 @@ match_pattern_2 (state *s, rtx top_patte
 
 		  case 'i':
 		    /* Make sure that XINT (X, I) has the right value.  */
-		    s = add_decision (s, test::int_field (pos, i),
+		    s = add_decision (s, rtx_test::int_field (pos, i),
 				      XINT (pattern, i), false);
 		    break;
 
 		  case 'w':
 		    /* Make sure that XWINT (X, I) has the right value.  */
-		    s = add_decision (s, test::wide_int_field (pos, i),
+		    s = add_decision (s, rtx_test::wide_int_field (pos, i),
 				      XWINT (pattern, 0), false);
 		    break;
 
@@ -4037,7 +4038,7 @@ match_pattern_2 (state *s, rtx top_patte
 		   and DImode register_operands, as described above.  */
 		machine_mode mode = GET_MODE (e->pattern);
 		if (safe_predicate_mode (pred, mode))
-		  s = add_decision (s, test::mode (e->pos), mode, true);
+		  s = add_decision (s, rtx_test::mode (e->pos), mode, true);
 
 		/* Assign to operands[] first, so that the rtx usually doesn't
 		   need to be live across the call to the predicate.
@@ -4046,19 +4047,21 @@ match_pattern_2 (state *s, rtx top_patte
 		   since we fully expect to assign to operands[] at some point,
 		   and since the caller usually writes to other parts of
 		   recog_data anyway.  */
-		s = add_decision (s, test::set_op (e->pos, opno), true, false);
-		s = add_decision (s, test::predicate (e->pos, pred, mode),
+		s = add_decision (s, rtx_test::set_op (e->pos, opno),
+				  true, false);
+		s = add_decision (s, rtx_test::predicate (e->pos, pred, mode),
 				  true, false);
 	      }
 	    else
 	      /* Historically we've ignored the mode when there's no
 		 predicate.  Just set up operands[] unconditionally.  */
-	      s = add_decision (s, test::set_op (e->pos, opno), true, false);
+	      s = add_decision (s, rtx_test::set_op (e->pos, opno),
+				true, false);
 	    break;
 	  }
 
 	default:
-	  s = add_decision (s, test::mode (e->pos),
+	  s = add_decision (s, rtx_test::mode (e->pos),
 			    GET_MODE (e->pattern), false);
 	  break;
 	}
@@ -4066,7 +4069,7 @@ match_pattern_2 (state *s, rtx top_patte
 
   /* Finally add rtx_equal_p checks for duplicated operands.  */
   FOR_EACH_VEC_ELT (dup_tests, i, e)
-    s = add_decision (s, test::duplicate (e->pos, XINT (e->pattern, 0)),
+    s = add_decision (s, rtx_test::duplicate (e->pos, XINT (e->pattern, 0)),
 		      true, false);
   return s;
 }
@@ -4098,7 +4101,7 @@ match_pattern_1 (state *s, rtx top_patte
 	      position *subpos = next_position (subpos_ptr, &root_pos,
 						POS_PEEP2_INSN, count);
 	      if (count > 0)
-		s = add_decision (s, test::peep2_count (count + 1),
+		s = add_decision (s, rtx_test::peep2_count (count + 1),
 				  true, false);
 	      s = match_pattern_2 (s, top_pattern, subpos, x);
 	      subpos_ptr = &subpos->next;
@@ -4115,15 +4118,15 @@ match_pattern_1 (state *s, rtx top_patte
       /* If the match is only valid when extra clobbers are added,
 	 make sure we're able to pass that information to the caller.  */
       if (acceptance.type == RECOG && acceptance.u.full.u.num_clobbers)
-	s = add_decision (s, test::have_num_clobbers (), true, false);
+	s = add_decision (s, rtx_test::have_num_clobbers (), true, false);
     }
 
   /* Make sure that the C test is true.  */
   if (maybe_eval_c_test (c_test) != 1)
-    s = add_decision (s, test::c_test (c_test), true, false);
+    s = add_decision (s, rtx_test::c_test (c_test), true, false);
 
   /* Accept the pattern.  */
-  add_decision (s, test::accept (acceptance), true, false);
+  add_decision (s, rtx_test::accept (acceptance), true, false);
 }
 
 /* Like match_pattern_1, but (if merge_states_p) try to merge the
@@ -4321,7 +4324,7 @@ struct output_state
 terminal_pattern_p (decision *d, unsigned int *base_out,
 		    unsigned int *count_out)
 {
-  if (d->test.kind != test::PATTERN)
+  if (d->test.kind != rtx_test::PATTERN)
     return false;
   unsigned int base = 0;
   unsigned int count = 0;
@@ -4330,7 +4333,7 @@ terminal_pattern_p (decision *d, unsigne
       if (trans->is_param || trans->labels.length () != 1)
 	return false;
       decision *subd = trans->to->singleton ();
-      if (!subd || subd->test.kind != test::ACCEPT)
+      if (!subd || subd->test.kind != rtx_test::ACCEPT)
 	return false;
       unsigned int this_base = (subd->test.u.acceptance.u.full.code
 				- trans->labels[0]);
@@ -4349,7 +4352,7 @@ terminal_pattern_p (decision *d, unsigne
    already available in state OS.  */
 
 static bool
-test_position_available_p (output_state *os, const test &test)
+test_position_available_p (output_state *os, const rtx_test &test)
 {
   return (!test.pos
 	  || test.pos_operand >= 0
@@ -4461,7 +4464,7 @@ print_parameter_value (const parameter &
 /* Print the C expression for the rtx tested by TEST.  */
 
 static void
-print_test_rtx (output_state *os, const test &test)
+print_test_rtx (output_state *os, const rtx_test &test)
 {
   if (test.pos_operand >= 0)
     printf ("operands[%d]", test.pos_operand);
@@ -4472,41 +4475,41 @@ print_test_rtx (output_state *os, const
 /* Print the C expression for non-boolean test TEST.  */
 
 static void
-print_nonbool_test (output_state *os, const test &test)
+print_nonbool_test (output_state *os, const rtx_test &test)
 {
   switch (test.kind)
     {
-    case test::CODE:
+    case rtx_test::CODE:
       printf ("GET_CODE (");
       print_test_rtx (os, test);
       printf (")");
       break;
 
-    case test::MODE:
+    case rtx_test::MODE:
       printf ("GET_MODE (");
       print_test_rtx (os, test);
       printf (")");
       break;
 
-    case test::VECLEN:
+    case rtx_test::VECLEN:
       printf ("XVECLEN (");
       print_test_rtx (os, test);
       printf (", 0)");
       break;
 
-    case test::INT_FIELD:
+    case rtx_test::INT_FIELD:
       printf ("XINT (");
       print_test_rtx (os, test);
       printf (", %d)", test.u.opno);
       break;
 
-    case test::WIDE_INT_FIELD:
+    case rtx_test::WIDE_INT_FIELD:
       printf ("XWINT (");
       print_test_rtx (os, test);
       printf (", %d)", test.u.opno);
       break;
 
-    case test::PATTERN:
+    case rtx_test::PATTERN:
       {
 	pattern_routine *routine = test.u.pattern->routine;
 	printf ("pattern%d (", routine->pattern_id);
@@ -4536,15 +4539,15 @@ print_nonbool_test (output_state *os, co
 	break;
       }
 
-    case test::PEEP2_COUNT:
-    case test::VECLEN_GE:
-    case test::SAVED_CONST_INT:
-    case test::DUPLICATE:
-    case test::PREDICATE:
-    case test::SET_OP:
-    case test::HAVE_NUM_CLOBBERS:
-    case test::C_TEST:
-    case test::ACCEPT:
+    case rtx_test::PEEP2_COUNT:
+    case rtx_test::VECLEN_GE:
+    case rtx_test::SAVED_CONST_INT:
+    case rtx_test::DUPLICATE:
+    case rtx_test::PREDICATE:
+    case rtx_test::SET_OP:
+    case rtx_test::HAVE_NUM_CLOBBERS:
+    case rtx_test::C_TEST:
+    case rtx_test::ACCEPT:
       gcc_unreachable ();
     }
 }
@@ -4553,7 +4556,7 @@ print_nonbool_test (output_state *os, co
    decision performs TEST.  Print the C code for the label.  */
 
 static void
-print_label_value (const test &test, bool is_param, uint64_t value)
+print_label_value (const rtx_test &test, bool is_param, uint64_t value)
 {
   print_parameter_value (parameter (transition_parameter_type (test.kind),
 				    is_param, value));
@@ -4564,24 +4567,24 @@ print_label_value (const test &test, boo
    Test for inequality if INVERT_P, otherwise test for equality.  */
 
 static void
-print_test (output_state *os, const test &test, bool is_param, uint64_t value,
-	    bool invert_p)
+print_test (output_state *os, const rtx_test &test, bool is_param,
+	    uint64_t value, bool invert_p)
 {
   switch (test.kind)
     {
       /* Handle the non-boolean TESTs.  */
-    case test::CODE:
-    case test::MODE:
-    case test::VECLEN:
-    case test::INT_FIELD:
-    case test::WIDE_INT_FIELD:
-    case test::PATTERN:
+    case rtx_test::CODE:
+    case rtx_test::MODE:
+    case rtx_test::VECLEN:
+    case rtx_test::INT_FIELD:
+    case rtx_test::WIDE_INT_FIELD:
+    case rtx_test::PATTERN:
       print_nonbool_test (os, test);
       printf (" %s ", invert_p ? "!=" : "==");
       print_label_value (test, is_param, value);
       break;
 
-    case test::SAVED_CONST_INT:
+    case rtx_test::SAVED_CONST_INT:
       gcc_assert (!is_param && value == 1);
       print_test_rtx (os, test);
       printf (" %s const_int_rtx[MAX_SAVED_CONST_INT + ",
@@ -4592,20 +4595,20 @@ print_test (output_state *os, const test
       printf ("]");
       break;
 
-    case test::PEEP2_COUNT:
+    case rtx_test::PEEP2_COUNT:
       gcc_assert (!is_param && value == 1);
       printf ("peep2_current_count %s %d", invert_p ? "<" : ">=",
 	      test.u.min_len);
       break;
 
-    case test::VECLEN_GE:
+    case rtx_test::VECLEN_GE:
       gcc_assert (!is_param && value == 1);
       printf ("XVECLEN (");
       print_test_rtx (os, test);
       printf (", 0) %s %d", invert_p ? "<" : ">=", test.u.min_len);
       break;
 
-    case test::PREDICATE:
+    case rtx_test::PREDICATE:
       gcc_assert (!is_param && value == 1);
       printf ("%s%s (", invert_p ? "!" : "", test.u.predicate.data->name);
       print_test_rtx (os, test);
@@ -4616,27 +4619,27 @@ print_test (output_state *os, const test
       printf (")");
       break;
 
-    case test::DUPLICATE:
+    case rtx_test::DUPLICATE:
       gcc_assert (!is_param && value == 1);
       printf ("%srtx_equal_p (", invert_p ? "!" : "");
       print_test_rtx (os, test);
       printf (", operands[%d])", test.u.opno);
       break;
 
-    case test::HAVE_NUM_CLOBBERS:
+    case rtx_test::HAVE_NUM_CLOBBERS:
       gcc_assert (!is_param && value == 1);
       printf ("pnum_clobbers %s NULL", invert_p ? "==" : "!=");
       break;
 
-    case test::C_TEST:
+    case rtx_test::C_TEST:
       gcc_assert (!is_param && value == 1);
       if (invert_p)
 	printf ("!");
       print_c_condition (test.u.string);
       break;
 
-    case test::ACCEPT:
-    case test::SET_OP:
+    case rtx_test::ACCEPT:
+    case rtx_test::SET_OP:
       gcc_unreachable ();
     }
 }
@@ -4812,9 +4815,9 @@ print_decision (output_state *os, decisi
 	  return ES_FALLTHROUGH;
 	}
     }
-  else if (d->test.kind == test::ACCEPT)
+  else if (d->test.kind == rtx_test::ACCEPT)
     return print_acceptance (d->test.u.acceptance, indent, is_final);
-  else if (d->test.kind == test::SET_OP)
+  else if (d->test.kind == rtx_test::SET_OP)
     {
       printf_indent (indent, "operands[%d] = ", d->test.u.opno);
       print_test_rtx (os, d->test);
@@ -4843,8 +4846,8 @@ print_decision (output_state *os, decisi
 	{
 	  d = trans->to->singleton ();
 	  if (!d
-	      || d->test.kind == test::ACCEPT
-	      || d->test.kind == test::SET_OP
+	      || d->test.kind == rtx_test::ACCEPT
+	      || d->test.kind == rtx_test::SET_OP
 	      || !d->if_statement_p (&label)
 	      || !test_position_available_p (os, d->test))
 	    break;
@@ -4869,7 +4872,7 @@ print_decision (output_state *os, decisi
 	  return print_state (os, to, indent, is_final);
 	}
       else if (to->singleton ()
-	       && to->first->test.kind == test::ACCEPT
+	       && to->first->test.kind == rtx_test::ACCEPT
 	       && single_statement_p (to->first->test.u.acceptance))
 	{
 	  /* The target of the transition is a simple "return" statement.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-05-01 12:42           ` Richard Sandiford
@ 2015-05-01 13:57             ` Jeff Law
  0 siblings, 0 replies; 30+ messages in thread
From: Jeff Law @ 2015-05-01 13:57 UTC (permalink / raw)
  To: Richard Biener, Andreas Schwab, gcc-patches, richard.sandiford

On 05/01/2015 06:41 AM, Richard Sandiford wrote:
> Richard Sandiford <richard.sandiford@arm.com> writes:
>> Richard Biener <richard.guenther@gmail.com> writes:
>>> On Thu, Apr 30, 2015 at 2:08 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
>>>> Richard Sandiford <richard.sandiford@arm.com> writes:
>>>>
>>>>> Andreas Schwab <schwab@linux-m68k.org> writes:
>>>>>> Richard Sandiford <richard.sandiford@arm.com> writes:
>>>>>>
>>>>>>> /* Represents a test and the action that should be taken on the result.
>>>>>>>     If a transition exists for the test outcome, the machine switches
>>>>>>>     to the transition's target state.  If no suitable transition exists,
>>>>>>>     the machine either falls through to the next decision or, if there are no
>>>>>>>     more decisions to try, fails the match.  */
>>>>>>> struct decision : list_head <transition>
>>>>>>> {
>>>>>>>    decision (const test &);
>>>>>>>
>>>>>>>    void set_parent (list_head <decision> *s);
>>>>>>>    bool if_statement_p (uint64_t * = 0) const;
>>>>>>>
>>>>>>>    /* The state to which this decision belongs.  */
>>>>>>>    state *s;
>>>>>>>
>>>>>>>    /* Links to other decisions in the same state.  */
>>>>>>>    decision *prev, *next;
>>>>>>>
>>>>>>>    /* The test to perform.  */
>>>>>>>    struct test test;
>>>>>>> };
>>>>>>
>>>>>> ../../gcc/genrecog.c:1467: error: declaration of 'test decision::test'
>>>>>> ../../gcc/genrecog.c:1051: error: changes meaning of 'test' from
>>>>>> struct test'
>>>>>>
>>>>>> Bootstrap compiler is gcc 4.3.4.
>>>>>
>>>>> Bah.  Does it like "::test test" instead of "struct test test"?
>>>>
>>>> Same error.
>>>
>>> You have to use a different name I believe (or -fpermissive).
>>
>> Hmm, but then why does it work with more recent compilers?
>
> Whatever the reason, I suppose the path of least resistance is to
> rename the thing.
>
> Tested on x86_64-linux-gnu.  OK to install?
>
> Thanks,
> Richard
>
>
> gcc/
> 	* genrecog.c (test): Rename to rtx_test.  Update rest of file
> 	accordingly.
OK.
jeff

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [nvptx] Re: Mostly rewrite genrecog
  2015-04-27 10:20 Mostly rewrite genrecog Richard Sandiford
                   ` (3 preceding siblings ...)
  2015-04-30  7:17 ` Andreas Schwab
@ 2015-05-07  8:59 ` Thomas Schwinge
  2015-05-07  9:14   ` Jakub Jelinek
  2015-05-08  9:10 ` genrecog: Address -Wsign-compare diagnostics (was: Mostly rewrite genrecog) Thomas Schwinge
  2015-05-16  8:13 ` Mostly rewrite genrecog Andreas Krebbel
  6 siblings, 1 reply; 30+ messages in thread
From: Thomas Schwinge @ 2015-05-07  8:59 UTC (permalink / raw)
  To: Richard Sandiford, Bernd Schmidt; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2809 bytes --]

Hi!

On Mon, 27 Apr 2015 11:20:30 +0100, Richard Sandiford <richard.sandiford@arm.com> wrote:
> I think it's been the case for a while that parallel builds of GCC tend
> to serialise around the compilation of insn-recog.c, especially with
> higher --enable-checking settings.  This patch tries to speed that
> up by replacing most of genrecog with a new algorithm.  [...]

> Here's a comparison of the number of lines of code in insn-recog.c
> before and after the patch on one target per config/ CPU:
> 
> aarch64-linux-gnueabi                           115526    38169 :   33.04%
> alpha-linux-gnu                                  24479    10740 :   43.87%
> arm-linux-gnueabi                               169208    67759 :   40.04%
> avr-rtems                                        55647    22127 :   39.76%
> bfin-elf                                         13928     6498 :   46.65%
> c6x-elf                                          29928    13324 :   44.52%
> [...]

Nice work!  For a nvptx-none build of r222446 and r222860, respectively:

    $ wc -l {prev/,}build-gcc/gcc/insn-recog.c | head -n -1
      5042 prev/build-gcc/gcc/insn-recog.c
      2570 build-gcc/gcc/insn-recog.c


I'm mostly illiterate regarding GCC's machine description files, and
genrecog, but noticed one thing: with the genrecog rewrite, I get the
following diff compared to a previous build log:

     build/genrecog [...]/source-gcc/gcc/common.md [...]/source-gcc/gcc/config/nvptx/nvptx.md \
               insn-conditions.md > tmp-recog.c
    -[...]/source-gcc/gcc/config/nvptx/nvptx.md:1206: warning: operand 0 missing mode?
    -[...]/source-gcc/gcc/config/nvptx/nvptx.md:1206: warning: operand 1 missing mode?
    +Statistics for recog:
    +  Number of decisions:    799
    +  longest path:            28 (code:    208)
    +  longest backtrack:        2 (code:    136)
    +Statistics for split_insns:
    +  Number of decisions:      0
    +  longest path:             0 (code:     -1)
    +  longest backtrack:        0 (code:     -1)
    +Statistics for peephole2_insns:
    +  Number of decisions:      0
    +  longest path:             0 (code:     -1)
    +  longest backtrack:        0 (code:     -1)
    +Shared 655 out of 1350 states by creating 153 new states, saving 502

gcc/config/nvptx/nvptx.md:

    1206 (define_insn "allocate_stack"
    1207   [(set (match_operand 0 "nvptx_register_operand" "=R")
    1208         (unspec [(match_operand 1 "nvptx_register_operand" "R")]
    1209                   UNSPEC_ALLOCA))]
    1210   ""
    1211   "%.\\tcall (%0), %%alloca, (%1);")

Are these two (former) warnings a) something that should still be
reported by genrecog, and b) something that should be addressed (Bernd)?


Grüße,
 Thomas

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 472 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [nvptx] Re: Mostly rewrite genrecog
  2015-05-07  8:59 ` [nvptx] " Thomas Schwinge
@ 2015-05-07  9:14   ` Jakub Jelinek
  2015-05-21  8:09     ` Thomas Schwinge
  0 siblings, 1 reply; 30+ messages in thread
From: Jakub Jelinek @ 2015-05-07  9:14 UTC (permalink / raw)
  To: Thomas Schwinge; +Cc: Richard Sandiford, Bernd Schmidt, gcc-patches

On Thu, May 07, 2015 at 10:59:01AM +0200, Thomas Schwinge wrote:
>      build/genrecog [...]/source-gcc/gcc/common.md [...]/source-gcc/gcc/config/nvptx/nvptx.md \
>                insn-conditions.md > tmp-recog.c
>     -[...]/source-gcc/gcc/config/nvptx/nvptx.md:1206: warning: operand 0 missing mode?
>     -[...]/source-gcc/gcc/config/nvptx/nvptx.md:1206: warning: operand 1 missing mode?
> 
> gcc/config/nvptx/nvptx.md:
> 
>     1206 (define_insn "allocate_stack"
>     1207   [(set (match_operand 0 "nvptx_register_operand" "=R")
>     1208         (unspec [(match_operand 1 "nvptx_register_operand" "R")]
>     1209                   UNSPEC_ALLOCA))]
>     1210   ""
>     1211   "%.\\tcall (%0), %%alloca, (%1);")
> 
> Are these two (former) warnings a) something that should still be
> reported by genrecog, 

Yes.

> and b) something that should be addressed (Bernd)?

Yes.  Supposedly you want :P on both match_operand and unspec too, but
as this serves not just as an insn pattern, but also as expander that
needs to have this particular name, supposedly you want:

(define_expand "allocate_stack"
  [(match_operand 0 "nvptx_register_operand")
   (match_operand 1 "nvptx_register_operand")]
  ""
{
  if (TARGET_ABI64)
    emit_insn (gen_allocate_stack_di (operands[0], operands[1]));
  else
    emit_insn (gen_allocate_stack_si (operands[0], operands[1]));
  DONE;
})

(define_insn "allocate_stack_<mode>"
  [(set (match_operand:P 0 "nvptx_register_operand" "=R")
	(unspec:P [(match_operand:P 1 "nvptx_register_operand" "R")]
		   UNSPEC_ALLOCA))]
  ""
  "%.\\tcall (%0), %%alloca, (%1);")

rr so.  Of course, as even latest Cuda drop doesn't support alloca, this is
quite dubious, perhaps better would be sorry on it.

BTW, with Cuda 7.0, even printf doesn't work anymore, is that known?

	Jakub

^ permalink raw reply	[flat|nested] 30+ messages in thread

* genrecog: Address -Wsign-compare diagnostics (was: Mostly rewrite genrecog)
  2015-04-27 10:20 Mostly rewrite genrecog Richard Sandiford
                   ` (4 preceding siblings ...)
  2015-05-07  8:59 ` [nvptx] " Thomas Schwinge
@ 2015-05-08  9:10 ` Thomas Schwinge
  2015-05-08 14:43   ` genrecog: Address -Wsign-compare diagnostics Richard Sandiford
  2015-05-08 18:39   ` Jeff Law
  2015-05-16  8:13 ` Mostly rewrite genrecog Andreas Krebbel
  6 siblings, 2 replies; 30+ messages in thread
From: Thomas Schwinge @ 2015-05-08  9:10 UTC (permalink / raw)
  To: Richard Sandiford, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3572 bytes --]

Hi!

On Mon, 27 Apr 2015 11:20:30 +0100, Richard Sandiford <richard.sandiford@arm.com> wrote:
> This patch [...] by replacing most of genrecog [...]

OK to commit?

Is it a bug that I'm seeing these warnings only in the stage 1 build with
the bootstrap GCC 4.6 compiler, but not anymore later on?  (I have not
verified the C++ standard on the rules for »comparison between signed and
unsigned integer expressions«.)

commit efef4f38205a13da90ca19b6eec1a6526756b433
Author: Thomas Schwinge <thomas@codesourcery.com>
Date:   Fri May 8 10:55:19 2015 +0200

    genrecog: Address -Wsign-compare diagnostics.
    
        g++-4.6 [...] [...]/gcc/genrecog.c
        [...]/gcc/genrecog.c: In function 'state_size find_subroutines(routine_type, state*, vec<state*>&)':
        [...]/gcc/genrecog.c:3338:35: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
        [...]/gcc/genrecog.c:3347:37: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
        [...]/gcc/genrecog.c:3359:29: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
        [...]/gcc/genrecog.c:3365:32: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
    
        3305   state_size size;
             [...]
        3337           state_size to_size = find_subroutines (type, trans->to, procs);
        3338           if (d->next && to_size.depth > MAX_DEPTH)
             [...]
        3347               if (to_size.num_statements < MIN_NUM_STATEMENTS)
             [...]
        3359   if (size.num_statements > MAX_NUM_STATEMENTS)
             [...]
        3365              && size.num_statements > MAX_NUM_STATEMENTS)
    
         175 static const int MAX_DEPTH = 6;
             [...]
         179 static const int MIN_NUM_STATEMENTS = 5;
             [...]
         185 static const int MAX_NUM_STATEMENTS = 200;
             [...]
        3258 struct state_size
        3259 {
             [...]
        3261   unsigned int num_statements;
             [...]
        3265   unsigned int depth;
        3266 };
    
    	gcc/
    	* genrecog.c (MAX_DEPTH, MIN_NUM_STATEMENTS, MAX_NUM_STATEMENTS):
    	Change to unsigned int.
---
 gcc/genrecog.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git gcc/genrecog.c gcc/genrecog.c
index 73e7995..653f753 100644
--- gcc/genrecog.c
+++ gcc/genrecog.c
@@ -172,17 +172,17 @@ static const bool force_unique_params_p = true;
 /* The maximum (approximate) depth of block nesting that an individual
    routine or subroutine should have.  This limit is about keeping the
    output readable rather than reducing compile time.  */
-static const int MAX_DEPTH = 6;
+static const unsigned int MAX_DEPTH = 6;
 
 /* The minimum number of pseudo-statements that a state must have before
    we split it out into a subroutine.  */
-static const int MIN_NUM_STATEMENTS = 5;
+static const unsigned int MIN_NUM_STATEMENTS = 5;
 
 /* The number of pseudo-statements a state can have before we consider
    splitting out substates into subroutines.  This limit is about avoiding
    compile-time problems with very big functions (and also about keeping
    functions within --param optimization limits, etc.).  */
-static const int MAX_NUM_STATEMENTS = 200;
+static const unsigned int MAX_NUM_STATEMENTS = 200;
 
 /* The minimum number of pseudo-statements that can be used in a pattern
    routine.  */


Grüße,
 Thomas

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 472 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: genrecog: Address -Wsign-compare diagnostics
  2015-05-08  9:10 ` genrecog: Address -Wsign-compare diagnostics (was: Mostly rewrite genrecog) Thomas Schwinge
@ 2015-05-08 14:43   ` Richard Sandiford
  2015-05-08 18:39   ` Jeff Law
  1 sibling, 0 replies; 30+ messages in thread
From: Richard Sandiford @ 2015-05-08 14:43 UTC (permalink / raw)
  To: Thomas Schwinge; +Cc: gcc-patches

Thomas Schwinge <thomas@codesourcery.com> writes:
> Hi!
>
> On Mon, 27 Apr 2015 11:20:30 +0100, Richard Sandiford
> <richard.sandiford@arm.com> wrote:
>> This patch [...] by replacing most of genrecog [...]
>
> OK to commit?

Looks good to me FWIW.  Probably counts as obvious.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: genrecog: Address -Wsign-compare diagnostics
  2015-05-08  9:10 ` genrecog: Address -Wsign-compare diagnostics (was: Mostly rewrite genrecog) Thomas Schwinge
  2015-05-08 14:43   ` genrecog: Address -Wsign-compare diagnostics Richard Sandiford
@ 2015-05-08 18:39   ` Jeff Law
  1 sibling, 0 replies; 30+ messages in thread
From: Jeff Law @ 2015-05-08 18:39 UTC (permalink / raw)
  To: Thomas Schwinge, Richard Sandiford, gcc-patches

On 05/08/2015 03:09 AM, Thomas Schwinge wrote:
> Hi!
>
> On Mon, 27 Apr 2015 11:20:30 +0100, Richard Sandiford <richard.sandiford@arm.com> wrote:
>> This patch [...] by replacing most of genrecog [...]
>
> OK to commit?
>
> Is it a bug that I'm seeing these warnings only in the stage 1 build with
> the bootstrap GCC 4.6 compiler, but not anymore later on?  (I have not
> verified the C++ standard on the rules for »comparison between signed and
> unsigned integer expressions«.)
>
> commit efef4f38205a13da90ca19b6eec1a6526756b433
> Author: Thomas Schwinge <thomas@codesourcery.com>
> Date:   Fri May 8 10:55:19 2015 +0200
>
>      genrecog: Address -Wsign-compare diagnostics.
>
>          g++-4.6 [...] [...]/gcc/genrecog.c
>          [...]/gcc/genrecog.c: In function 'state_size find_subroutines(routine_type, state*, vec<state*>&)':
>          [...]/gcc/genrecog.c:3338:35: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
>          [...]/gcc/genrecog.c:3347:37: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
>          [...]/gcc/genrecog.c:3359:29: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
>          [...]/gcc/genrecog.c:3365:32: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
>
>          3305   state_size size;
>               [...]
>          3337           state_size to_size = find_subroutines (type, trans->to, procs);
>          3338           if (d->next && to_size.depth > MAX_DEPTH)
>               [...]
>          3347               if (to_size.num_statements < MIN_NUM_STATEMENTS)
>               [...]
>          3359   if (size.num_statements > MAX_NUM_STATEMENTS)
>               [...]
>          3365              && size.num_statements > MAX_NUM_STATEMENTS)
>
>           175 static const int MAX_DEPTH = 6;
>               [...]
>           179 static const int MIN_NUM_STATEMENTS = 5;
>               [...]
>           185 static const int MAX_NUM_STATEMENTS = 200;
>               [...]
>          3258 struct state_size
>          3259 {
>               [...]
>          3261   unsigned int num_statements;
>               [...]
>          3265   unsigned int depth;
>          3266 };
>
>      	gcc/
>      	* genrecog.c (MAX_DEPTH, MIN_NUM_STATEMENTS, MAX_NUM_STATEMENTS):
>      	Change to unsigned int.
> ---
>   gcc/genrecog.c |    6 +++---
>   1 file changed, 3 insertions(+), 3 deletions(-)
OK with a ChangeLog and the usual testing.  Or you can verify the output 
of genrecog doesn't change before/after if you don't want to go through 
the full bootstrap.

jeff

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-04-27 10:20 Mostly rewrite genrecog Richard Sandiford
                   ` (5 preceding siblings ...)
  2015-05-08  9:10 ` genrecog: Address -Wsign-compare diagnostics (was: Mostly rewrite genrecog) Thomas Schwinge
@ 2015-05-16  8:13 ` Andreas Krebbel
  2015-05-17 22:05   ` Richard Sandiford
  6 siblings, 1 reply; 30+ messages in thread
From: Andreas Krebbel @ 2015-05-16  8:13 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

Hi Richard,

I see regressions with the current IBM z13 vector patchset which appear to be related to the new
genrecog.

The following two insn definitions only differ in the mode and predicate of the shift count operand.

(define_insn "lshr<mode>3"
  [(set (match_operand:VI              0 "register_operand"             "=v")
        (lshiftrt:VI (match_operand:VI 1 "register_operand"              "v")
                     (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
  "TARGET_VX"
  "vesrl<bhfgq>\t%v0,%v1,%Y2"
  [(set_attr "op_type" "VRS")])

(define_insn "vlshr<mode>3"
  [(set (match_operand:VI              0 "register_operand" "=v")
        (lshiftrt:VI (match_operand:VI 1 "register_operand"  "v")
                     (match_operand:VI 2 "register_operand"  "v")))]
  "TARGET_VX"
  "vesrlv<bhfgq>\t%v0,%v1,%v2"
  [(set_attr "op_type" "VRR")])


However, the insn-recog.c code only seem to check the predicate. This is a problem since
shift_count_or_setmem_operand does not check the mode.

          if (shift_count_or_setmem_operand (operands[2], SImode)
              &&
#line 717 "/home3/andreas/patched/../gcc/gcc/config/s390/vector.md"
(TARGET_VX))
            return 600; /* lshrv2qi3 */
          if (register_operand (operands[2], V2QImode)
              &&
#line 747 "/home3/andreas/patched/../gcc/gcc/config/s390/vector.md"
(TARGET_VX))
            return 630; /* vlshrv2qi3 */
          break;

I could add a mode check to the predicate. However, I just wanted to check whether this change was
intentional.

Bye,

-Andreas-

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-05-16  8:13 ` Mostly rewrite genrecog Andreas Krebbel
@ 2015-05-17 22:05   ` Richard Sandiford
  2015-05-22 16:14     ` Andreas Krebbel
  0 siblings, 1 reply; 30+ messages in thread
From: Richard Sandiford @ 2015-05-17 22:05 UTC (permalink / raw)
  To: Andreas Krebbel; +Cc: gcc-patches

Andreas Krebbel <krebbel@linux.vnet.ibm.com> writes:
> Hi Richard,
>
> I see regressions with the current IBM z13 vector patchset which appear to be related to the new
> genrecog.
>
> The following two insn definitions only differ in the mode and predicate of the shift count operand.
>
> (define_insn "lshr<mode>3"
>   [(set (match_operand:VI              0 "register_operand"             "=v")
>         (lshiftrt:VI (match_operand:VI 1 "register_operand"              "v")
>                      (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
>   "TARGET_VX"
>   "vesrl<bhfgq>\t%v0,%v1,%Y2"
>   [(set_attr "op_type" "VRS")])
>
> (define_insn "vlshr<mode>3"
>   [(set (match_operand:VI              0 "register_operand" "=v")
>         (lshiftrt:VI (match_operand:VI 1 "register_operand"  "v")
>                      (match_operand:VI 2 "register_operand"  "v")))]
>   "TARGET_VX"
>   "vesrlv<bhfgq>\t%v0,%v1,%v2"
>   [(set_attr "op_type" "VRR")])
>
>
> However, the insn-recog.c code only seem to check the predicate. This is a problem since
> shift_count_or_setmem_operand does not check the mode.

Yeah, it's a bug if a "non-special" predicate doesn't check the mode.
Even old genreog relied on that:

/* After factoring, try to simplify the tests on any one node.
   Tests that are useful for switch statements are recognizable
   by having only a single test on a node -- we'll be manipulating
   nodes with multiple tests:

   If we have mode tests or code tests that are redundant with
   predicates, remove them.  */

although it sounds like the old optimisation didn't trigger for your case.

genpreds.c:mark_mode_tests is supposed to add these tests automatically
if needed.  I suppose it isn't doing so here because the predicate
accepts const_int and because of:

/* Given an RTL expression EXP, find all subexpressions which we may
   assume to perform mode tests.  Normal MATCH_OPERAND does;
   MATCH_CODE does if it applies to the whole expression and accepts
   CONST_INT or CONST_DOUBLE; and we have to assume that MATCH_TEST
   does not.  [...]
*/
static void
mark_mode_tests (rtx exp)
{
  switch (GET_CODE (exp))
    {
[...]
    case MATCH_CODE:
      if (XSTR (exp, 1)[0] != '\0'
        || (!strstr (XSTR (exp, 0), "const_int")
              && !strstr (XSTR (exp, 0), "const_double")))
              NO_MODE_TEST (exp) = 1;
      break;

The code matches the comment, but it doesn't look right.  Perhaps it
was supposed to mean match_codes that _only_ contain const_int and
const_double?  Knowing that the rtx is one of those codes guarantees
that the mode is VOIDmode, but a match_code that includes other rtxes
as well doesn't itself test the mode of those rtxes.

Even then, a predicate that matches const_ints and is passed SImode
mustn't accept const_ints outside the SImode range.  I suppose we
just rely on all predicates to perform some kind of range check.
(The standard ones do of course.)

As a quick workaround, try replacing the case above with:

    case MATCH_CODE:
      if (XSTR (exp, 1)[0] != '\0')
        NO_MODE_TEST (exp) = 1;
      break;

I'll try to come up with a better fix in the meantime.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [nvptx] Re: Mostly rewrite genrecog
  2015-05-07  9:14   ` Jakub Jelinek
@ 2015-05-21  8:09     ` Thomas Schwinge
  2015-05-21 11:57       ` Bernd Schmidt
  0 siblings, 1 reply; 30+ messages in thread
From: Thomas Schwinge @ 2015-05-21  8:09 UTC (permalink / raw)
  To: Jakub Jelinek, Bernd Schmidt, gcc-patches; +Cc: Richard Sandiford

[-- Attachment #1: Type: text/plain, Size: 3817 bytes --]

Hi!

On Thu, 7 May 2015 11:14:37 +0200, Jakub Jelinek <jakub@redhat.com> wrote:
> On Thu, May 07, 2015 at 10:59:01AM +0200, Thomas Schwinge wrote:
> >      build/genrecog [...]/source-gcc/gcc/common.md [...]/source-gcc/gcc/config/nvptx/nvptx.md \
> >                insn-conditions.md > tmp-recog.c
> >     -[...]/source-gcc/gcc/config/nvptx/nvptx.md:1206: warning: operand 0 missing mode?
> >     -[...]/source-gcc/gcc/config/nvptx/nvptx.md:1206: warning: operand 1 missing mode?
> > 
> > gcc/config/nvptx/nvptx.md:
> > 
> >     1206 (define_insn "allocate_stack"
> >     1207   [(set (match_operand 0 "nvptx_register_operand" "=R")
> >     1208         (unspec [(match_operand 1 "nvptx_register_operand" "R")]
> >     1209                   UNSPEC_ALLOCA))]
> >     1210   ""
> >     1211   "%.\\tcall (%0), %%alloca, (%1);")
> > 
> > Are these two (former) warnings a) something that should still be
> > reported by genrecog, 
> 
> Yes.

<http://news.gmane.org/find-root.php?message_id=%3C87twvjtrf4.fsf%40e105548-lin.cambridge.arm.com%3E>.


> > and b) something that should be addressed (Bernd)?
> 
> Yes.  Supposedly you want :P on both match_operand and unspec too, but
> as this serves not just as an insn pattern, but also as expander that
> needs to have this particular name, supposedly you want:
> 
> (define_expand "allocate_stack"
>   [(match_operand 0 "nvptx_register_operand")
>    (match_operand 1 "nvptx_register_operand")]
>   ""
> {
>   if (TARGET_ABI64)
>     emit_insn (gen_allocate_stack_di (operands[0], operands[1]));
>   else
>     emit_insn (gen_allocate_stack_si (operands[0], operands[1]));
>   DONE;
> })
> 
> (define_insn "allocate_stack_<mode>"
>   [(set (match_operand:P 0 "nvptx_register_operand" "=R")
> 	(unspec:P [(match_operand:P 1 "nvptx_register_operand" "R")]
> 		   UNSPEC_ALLOCA))]
>   ""
>   "%.\\tcall (%0), %%alloca, (%1);")
> 
> rr so.

OK to commit?

commit 004e521e8dd1c0236a55e9a69a17cc3333c2a41d
Author: Thomas Schwinge <thomas@codesourcery.com>
Date:   Thu May 7 11:30:26 2015 +0200

    [nvptx] Address genrecog warnings
    
    2015-05-21  Jakub Jelinek  <jakub@redhat.com>
    
    	gcc/
    	* config/nvptx/nvptx.md (allocate_stack): Rename to...
    	(allocate_stack_<mode>): ... this, and add :P on both
    	match_operand and unspec.
    	(allocate_stack): New expander.
---
 gcc/config/nvptx/nvptx.md |   20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git gcc/config/nvptx/nvptx.md gcc/config/nvptx/nvptx.md
index c30de36..a49786c 100644
--- gcc/config/nvptx/nvptx.md
+++ gcc/config/nvptx/nvptx.md
@@ -1203,10 +1203,22 @@
   sorry ("target cannot support nonlocal goto.");
 })
 
-(define_insn "allocate_stack"
-  [(set (match_operand 0 "nvptx_register_operand" "=R")
-	(unspec [(match_operand 1 "nvptx_register_operand" "R")]
-		  UNSPEC_ALLOCA))]
+(define_expand "allocate_stack"
+  [(match_operand 0 "nvptx_register_operand")
+   (match_operand 1 "nvptx_register_operand")]
+  ""
+{
+  if (TARGET_ABI64)
+    emit_insn (gen_allocate_stack_di (operands[0], operands[1]));
+  else
+    emit_insn (gen_allocate_stack_si (operands[0], operands[1]));
+  DONE;
+})
+
+(define_insn "allocate_stack_<mode>"
+  [(set (match_operand:P 0 "nvptx_register_operand" "=R")
+        (unspec:P [(match_operand:P 1 "nvptx_register_operand" "R")]
+                   UNSPEC_ALLOCA))]
   ""
   "%.\\tcall (%0), %%alloca, (%1);")
 


> Of course, as even latest Cuda drop doesn't support alloca, this is
> quite dubious, perhaps better would be sorry on it.
> 
> BTW, with Cuda 7.0, even printf doesn't work anymore, is that known?

I have not yet used that version of CUDA, so don't know about this.  :-|


Grüße,
 Thomas

[-- Attachment #2: Type: application/pgp-signature, Size: 472 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [nvptx] Re: Mostly rewrite genrecog
  2015-05-21  8:09     ` Thomas Schwinge
@ 2015-05-21 11:57       ` Bernd Schmidt
  0 siblings, 0 replies; 30+ messages in thread
From: Bernd Schmidt @ 2015-05-21 11:57 UTC (permalink / raw)
  To: Thomas Schwinge, Jakub Jelinek, gcc-patches; +Cc: Richard Sandiford

On 05/21/2015 09:12 AM, Thomas Schwinge wrote:
>
> OK to commit?
>
>      	gcc/
>      	* config/nvptx/nvptx.md (allocate_stack): Rename to...
>      	(allocate_stack_<mode>): ... this, and add :P on both
>      	match_operand and unspec.
>      	(allocate_stack): New expander.

If you really want to. It doesn't work yet in ptxas so it's a little 
pointless to spend effort on it.


Bernd

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-05-17 22:05   ` Richard Sandiford
@ 2015-05-22 16:14     ` Andreas Krebbel
  2015-05-22 16:32       ` Richard Sandiford
  0 siblings, 1 reply; 30+ messages in thread
From: Andreas Krebbel @ 2015-05-22 16:14 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 05/17/2015 11:12 PM, Richard Sandiford wrote:
> Andreas Krebbel <krebbel@linux.vnet.ibm.com> writes:
>> Hi Richard,
>>
>> I see regressions with the current IBM z13 vector patchset which appear to be related to the new
>> genrecog.
>>
>> The following two insn definitions only differ in the mode and predicate of the shift count operand.
>>
>> (define_insn "lshr<mode>3"
>>   [(set (match_operand:VI              0 "register_operand"             "=v")
>>         (lshiftrt:VI (match_operand:VI 1 "register_operand"              "v")
>>                      (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
>>   "TARGET_VX"
>>   "vesrl<bhfgq>\t%v0,%v1,%Y2"
>>   [(set_attr "op_type" "VRS")])
>>
>> (define_insn "vlshr<mode>3"
>>   [(set (match_operand:VI              0 "register_operand" "=v")
>>         (lshiftrt:VI (match_operand:VI 1 "register_operand"  "v")
>>                      (match_operand:VI 2 "register_operand"  "v")))]
>>   "TARGET_VX"
>>   "vesrlv<bhfgq>\t%v0,%v1,%v2"
>>   [(set_attr "op_type" "VRR")])
>>
>>
>> However, the insn-recog.c code only seem to check the predicate. This is a problem since
>> shift_count_or_setmem_operand does not check the mode.
> 
> Yeah, it's a bug if a "non-special" predicate doesn't check the mode.
> Even old genreog relied on that:
> 
> /* After factoring, try to simplify the tests on any one node.
>    Tests that are useful for switch statements are recognizable
>    by having only a single test on a node -- we'll be manipulating
>    nodes with multiple tests:
> 
>    If we have mode tests or code tests that are redundant with
>    predicates, remove them.  */
> 
> although it sounds like the old optimisation didn't trigger for your case.
> 
> genpreds.c:mark_mode_tests is supposed to add these tests automatically
> if needed.  I suppose it isn't doing so here because the predicate
> accepts const_int and because of:
> 
> /* Given an RTL expression EXP, find all subexpressions which we may
>    assume to perform mode tests.  Normal MATCH_OPERAND does;
>    MATCH_CODE does if it applies to the whole expression and accepts
>    CONST_INT or CONST_DOUBLE; and we have to assume that MATCH_TEST
>    does not.  [...]
> */
> static void
> mark_mode_tests (rtx exp)
> {
>   switch (GET_CODE (exp))
>     {
> [...]
>     case MATCH_CODE:
>       if (XSTR (exp, 1)[0] != '\0'
>         || (!strstr (XSTR (exp, 0), "const_int")
>               && !strstr (XSTR (exp, 0), "const_double")))
>               NO_MODE_TEST (exp) = 1;
>       break;
> 
> The code matches the comment, but it doesn't look right.  Perhaps it
> was supposed to mean match_codes that _only_ contain const_int and
> const_double?  Knowing that the rtx is one of those codes guarantees
> that the mode is VOIDmode, but a match_code that includes other rtxes
> as well doesn't itself test the mode of those rtxes.
> 
> Even then, a predicate that matches const_ints and is passed SImode
> mustn't accept const_ints outside the SImode range.  I suppose we
> just rely on all predicates to perform some kind of range check.
> (The standard ones do of course.)
> 
> As a quick workaround, try replacing the case above with:
> 
>     case MATCH_CODE:
>       if (XSTR (exp, 1)[0] != '\0')
>         NO_MODE_TEST (exp) = 1;
>       break;
> 
> I'll try to come up with a better fix in the meantime.

Thanks for looking into this!
I've applied a patch adding a mode check to shift_count_or_setmem_operand which as expected fixes
the issue for me.

-Andreas-

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: Mostly rewrite genrecog
  2015-05-22 16:14     ` Andreas Krebbel
@ 2015-05-22 16:32       ` Richard Sandiford
  2015-05-29 17:39         ` RFA: Fix mode checks for possibly-constant predicates Richard Sandiford
  0 siblings, 1 reply; 30+ messages in thread
From: Richard Sandiford @ 2015-05-22 16:32 UTC (permalink / raw)
  To: Andreas Krebbel; +Cc: gcc-patches

Andreas Krebbel <krebbel@linux.vnet.ibm.com> writes:
> On 05/17/2015 11:12 PM, Richard Sandiford wrote:
>> Andreas Krebbel <krebbel@linux.vnet.ibm.com> writes:
>>> Hi Richard,
>>>
>>> I see regressions with the current IBM z13 vector patchset which appear to be related to the new
>>> genrecog.
>>>
>>> The following two insn definitions only differ in the mode and predicate of the shift count operand.
>>>
>>> (define_insn "lshr<mode>3"
>>>   [(set (match_operand:VI              0 "register_operand"             "=v")
>>>         (lshiftrt:VI (match_operand:VI 1 "register_operand"              "v")
>>>                      (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
>>>   "TARGET_VX"
>>>   "vesrl<bhfgq>\t%v0,%v1,%Y2"
>>>   [(set_attr "op_type" "VRS")])
>>>
>>> (define_insn "vlshr<mode>3"
>>>   [(set (match_operand:VI              0 "register_operand" "=v")
>>>         (lshiftrt:VI (match_operand:VI 1 "register_operand"  "v")
>>>                      (match_operand:VI 2 "register_operand"  "v")))]
>>>   "TARGET_VX"
>>>   "vesrlv<bhfgq>\t%v0,%v1,%v2"
>>>   [(set_attr "op_type" "VRR")])
>>>
>>>
>>> However, the insn-recog.c code only seem to check the predicate. This is a problem since
>>> shift_count_or_setmem_operand does not check the mode.
>> 
>> Yeah, it's a bug if a "non-special" predicate doesn't check the mode.
>> Even old genreog relied on that:
>> 
>> /* After factoring, try to simplify the tests on any one node.
>>    Tests that are useful for switch statements are recognizable
>>    by having only a single test on a node -- we'll be manipulating
>>    nodes with multiple tests:
>> 
>>    If we have mode tests or code tests that are redundant with
>>    predicates, remove them.  */
>> 
>> although it sounds like the old optimisation didn't trigger for your case.
>> 
>> genpreds.c:mark_mode_tests is supposed to add these tests automatically
>> if needed.  I suppose it isn't doing so here because the predicate
>> accepts const_int and because of:
>> 
>> /* Given an RTL expression EXP, find all subexpressions which we may
>>    assume to perform mode tests.  Normal MATCH_OPERAND does;
>>    MATCH_CODE does if it applies to the whole expression and accepts
>>    CONST_INT or CONST_DOUBLE; and we have to assume that MATCH_TEST
>>    does not.  [...]
>> */
>> static void
>> mark_mode_tests (rtx exp)
>> {
>>   switch (GET_CODE (exp))
>>     {
>> [...]
>>     case MATCH_CODE:
>>       if (XSTR (exp, 1)[0] != '\0'
>>         || (!strstr (XSTR (exp, 0), "const_int")
>>               && !strstr (XSTR (exp, 0), "const_double")))
>>               NO_MODE_TEST (exp) = 1;
>>       break;
>> 
>> The code matches the comment, but it doesn't look right.  Perhaps it
>> was supposed to mean match_codes that _only_ contain const_int and
>> const_double?  Knowing that the rtx is one of those codes guarantees
>> that the mode is VOIDmode, but a match_code that includes other rtxes
>> as well doesn't itself test the mode of those rtxes.
>> 
>> Even then, a predicate that matches const_ints and is passed SImode
>> mustn't accept const_ints outside the SImode range.  I suppose we
>> just rely on all predicates to perform some kind of range check.
>> (The standard ones do of course.)
>> 
>> As a quick workaround, try replacing the case above with:
>> 
>>     case MATCH_CODE:
>>       if (XSTR (exp, 1)[0] != '\0')
>>         NO_MODE_TEST (exp) = 1;
>>       break;
>> 
>> I'll try to come up with a better fix in the meantime.
>
> Thanks for looking into this!
> I've applied a patch adding a mode check to
> shift_count_or_setmem_operand which as expected fixes
> the issue for me.

OK.  After a false start earlier in the week, I've now got a patch
that I think fixes genpreds.c "properly".  Hope to post it soon.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 30+ messages in thread

* RFA: Fix mode checks for possibly-constant predicates
  2015-05-22 16:32       ` Richard Sandiford
@ 2015-05-29 17:39         ` Richard Sandiford
  2015-05-29 19:27           ` Richard Henderson
  0 siblings, 1 reply; 30+ messages in thread
From: Richard Sandiford @ 2015-05-29 17:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: Andreas Krebbel

genrecog relies on a predicate foo_operand (op, mode) checking that OP
really does have mode MODE, with VOIDmode acting as a wildcard.  This was
true even with the old genrecog, but as Andreas found on s390x, new genrecog
is being a bit more aggressive about it.

The problem is that at the moment, genpreds drops the mode check for
anything that can accept a CONST_INT or CONST_DOUBLE, on the basis that
constant integers have a recorded mode of VOIDmode whatever their "real"
logical mode is.  But that means that a predicate that accepts constant
integers and other rtxes like REG won't check the modes of those other
rtxes either.  Even dropping the check for CONST_DOUBLE is wrong, since it
can be a floating-point constant with a real mode.

This patch therefore adjusts the automatic mode test to allow
GET_MODE (op) == VOIDmode in cases where that's necessary.
It also includes CONST_WIDE_INT in the list of constant integer codes.

Bootstrapped & regression-tested on x86_64-linux-gnu.  OK to install?

Thanks,
Richard


gcc/
	* genpreds.c (mark_mode_tests): Mark all MATCH_CODEs as
	NO_MODE_TEST.
	(add_mode_tests): Don't add mode tests if the predicate only
	accepts scalar constant integers.  Otherwise, allow the mode
	of "op" to be VOIDmode if the predicate does accept such integers.

Index: gcc/genpreds.c
===================================================================
--- gcc/genpreds.c	2015-05-22 16:49:55.454319576 +0100
+++ gcc/genpreds.c	2015-05-23 10:46:58.187370110 +0100
@@ -218,11 +218,11 @@ needs_variable (rtx exp, const char *var
 
 /* Given an RTL expression EXP, find all subexpressions which we may
    assume to perform mode tests.  Normal MATCH_OPERAND does;
-   MATCH_CODE does if it applies to the whole expression and accepts
-   CONST_INT or CONST_DOUBLE; and we have to assume that MATCH_TEST
-   does not.  These combine in almost-boolean fashion - the only
-   exception is that (not X) must be assumed not to perform a mode
-   test, whether or not X does.
+   MATCH_CODE doesn't as such (although certain codes always have
+   VOIDmode); and we have to assume that MATCH_TEST does not.
+   These combine in almost-boolean fashion - the only exception is
+   that (not X) must be assumed not to perform a mode test, whether
+   or not X does.
 
    The mark is the RTL /v flag, which is true for subexpressions which
    do *not* perform mode tests.
@@ -244,10 +244,7 @@ mark_mode_tests (rtx exp)
       break;
 
     case MATCH_CODE:
-      if (XSTR (exp, 1)[0] != '\0'
-	  || (!strstr (XSTR (exp, 0), "const_int")
-	      && !strstr (XSTR (exp, 0), "const_double")))
-	NO_MODE_TEST (exp) = 1;
+      NO_MODE_TEST (exp) = 1;
       break;
 
     case MATCH_TEST:
@@ -313,6 +310,33 @@ add_mode_tests (struct pred_data *p)
   if (p->special)
     return;
 
+  /* Check whether the predicate accepts const scalar ints (which always
+     have a stored mode of VOIDmode, but logically have a real mode)
+     and whether it matches anything besides const scalar ints.  */
+  bool matches_const_scalar_int_p = false;
+  bool matches_other_p = false;
+  for (int i = 0; i < NUM_RTX_CODE; ++i)
+    if (p->codes[i])
+      switch (i)
+	{
+	CASE_CONST_SCALAR_INT:
+	  matches_const_scalar_int_p = true;
+	  break;
+
+	default:
+	  matches_other_p = true;
+	  break;
+	}
+
+  /* There's no need for a mode check if the predicate only accepts
+     constant integers.  The code checks in the predicate are enough
+     to establish that the mode is VOIDmode.
+
+     Note that the predicate itself should check whether a scalar
+     integer is in range of the given mode.  */
+  if (!matches_other_p && !p->codes[CONST_DOUBLE])
+    return;
+
   mark_mode_tests (p->exp);
 
   /* If the whole expression already tests the mode, we're done.  */
@@ -320,7 +344,11 @@ add_mode_tests (struct pred_data *p)
     return;
 
   match_test_exp = rtx_alloc (MATCH_TEST);
-  XSTR (match_test_exp, 0) = "mode == VOIDmode || GET_MODE (op) == mode";
+  if (matches_const_scalar_int_p)
+    XSTR (match_test_exp, 0) = ("mode == VOIDmode || GET_MODE (op) == mode"
+				" || GET_MODE (op) == VOIDmode");
+  else
+    XSTR (match_test_exp, 0) = "mode == VOIDmode || GET_MODE (op) == mode";
   and_exp = rtx_alloc (AND);
   XEXP (and_exp, 1) = match_test_exp;
 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: RFA: Fix mode checks for possibly-constant predicates
  2015-05-29 17:39         ` RFA: Fix mode checks for possibly-constant predicates Richard Sandiford
@ 2015-05-29 19:27           ` Richard Henderson
  2015-06-03  7:23             ` Richard Sandiford
  0 siblings, 1 reply; 30+ messages in thread
From: Richard Henderson @ 2015-05-29 19:27 UTC (permalink / raw)
  To: gcc-patches, Andreas Krebbel, richard.sandiford

On 05/29/2015 10:23 AM, Richard Sandiford wrote:
> +  /* Check whether the predicate accepts const scalar ints (which always
> +     have a stored mode of VOIDmode, but logically have a real mode)
> +     and whether it matches anything besides const scalar ints.  */
> +  bool matches_const_scalar_int_p = false;
> +  bool matches_other_p = false;
> +  for (int i = 0; i < NUM_RTX_CODE; ++i)
> +    if (p->codes[i])
> +      switch (i)
> +	{
> +	CASE_CONST_SCALAR_INT:
> +	  matches_const_scalar_int_p = true;
> +	  break;
> +
> +	default:
> +	  matches_other_p = true;
> +	  break;
> +	}
> +
> +  /* There's no need for a mode check if the predicate only accepts
> +     constant integers.  The code checks in the predicate are enough
> +     to establish that the mode is VOIDmode.
> +
> +     Note that the predicate itself should check whether a scalar
> +     integer is in range of the given mode.  */
> +  if (!matches_other_p && !p->codes[CONST_DOUBLE])
> +    return;

I think perhaps it would be cleaner to not use CASE_CONST_SCALAR_INT,
and then do

  switch (i)
    {
    case CONST_INT:
    case CONST_WIDE_INT:
      matches_const_scalar_int_p = true;
      break;

    case CONST_DOUBLE:
      if (!TARGET_SUPPORTS_WIDE_INT)
        matches_const_scalar_int_p = true;
      matches_other_p = true;
      break;

    default:
      matches_other_p = true;
      break;
    }

  if (!matches_other_p)
    return;

Otherwise ok.


r~

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: RFA: Fix mode checks for possibly-constant predicates
  2015-05-29 19:27           ` Richard Henderson
@ 2015-06-03  7:23             ` Richard Sandiford
  2015-06-03  9:39               ` Richard Sandiford
  0 siblings, 1 reply; 30+ messages in thread
From: Richard Sandiford @ 2015-06-03  7:23 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Andreas Krebbel

Richard Henderson <rth@redhat.com> writes:
> On 05/29/2015 10:23 AM, Richard Sandiford wrote:
>> +  /* Check whether the predicate accepts const scalar ints (which always
>> +     have a stored mode of VOIDmode, but logically have a real mode)
>> +     and whether it matches anything besides const scalar ints.  */
>> +  bool matches_const_scalar_int_p = false;
>> +  bool matches_other_p = false;
>> +  for (int i = 0; i < NUM_RTX_CODE; ++i)
>> +    if (p->codes[i])
>> +      switch (i)
>> +	{
>> +	CASE_CONST_SCALAR_INT:
>> +	  matches_const_scalar_int_p = true;
>> +	  break;
>> +
>> +	default:
>> +	  matches_other_p = true;
>> +	  break;
>> +	}
>> +
>> +  /* There's no need for a mode check if the predicate only accepts
>> +     constant integers.  The code checks in the predicate are enough
>> +     to establish that the mode is VOIDmode.
>> +
>> +     Note that the predicate itself should check whether a scalar
>> +     integer is in range of the given mode.  */
>> +  if (!matches_other_p && !p->codes[CONST_DOUBLE])
>> +    return;
>
> I think perhaps it would be cleaner to not use CASE_CONST_SCALAR_INT,
> and then do
>
>   switch (i)
>     {
>     case CONST_INT:
>     case CONST_WIDE_INT:
>       matches_const_scalar_int_p = true;
>       break;
>
>     case CONST_DOUBLE:
>       if (!TARGET_SUPPORTS_WIDE_INT)
>         matches_const_scalar_int_p = true;
>       matches_other_p = true;
>       break;
>
>     default:
>       matches_other_p = true;
>       break;
>     }
>
>   if (!matches_other_p)
>     return;
>
> Otherwise ok.

Ah, yeah, that's better.  Here's what I applied after testing on
x86_64-linux-gnu.

Thanks,
Richard


gcc/
	* genpreds.c (mark_mode_tests): Mark all MATCH_CODEs as
	NO_MODE_TEST.
	(add_mode_tests): Don't add mode tests if the predicate only
	accepts scalar constant integers.  Otherwise, allow the mode
	of "op" to be VOIDmode if the predicate does accept such integers.

Index: gcc/genpreds.c
===================================================================
--- gcc/genpreds.c	2015-06-02 13:32:21.394938060 +0100
+++ gcc/genpreds.c	2015-06-02 13:34:50.377221396 +0100
@@ -218,11 +218,11 @@ needs_variable (rtx exp, const char *var
 
 /* Given an RTL expression EXP, find all subexpressions which we may
    assume to perform mode tests.  Normal MATCH_OPERAND does;
-   MATCH_CODE does if it applies to the whole expression and accepts
-   CONST_INT or CONST_DOUBLE; and we have to assume that MATCH_TEST
-   does not.  These combine in almost-boolean fashion - the only
-   exception is that (not X) must be assumed not to perform a mode
-   test, whether or not X does.
+   MATCH_CODE doesn't as such (although certain codes always have
+   VOIDmode); and we have to assume that MATCH_TEST does not.
+   These combine in almost-boolean fashion - the only exception is
+   that (not X) must be assumed not to perform a mode test, whether
+   or not X does.
 
    The mark is the RTL /v flag, which is true for subexpressions which
    do *not* perform mode tests.
@@ -244,10 +244,7 @@ mark_mode_tests (rtx exp)
       break;
 
     case MATCH_CODE:
-      if (XSTR (exp, 1)[0] != '\0'
-	  || (!strstr (XSTR (exp, 0), "const_int")
-	      && !strstr (XSTR (exp, 0), "const_double")))
-	NO_MODE_TEST (exp) = 1;
+      NO_MODE_TEST (exp) = 1;
       break;
 
     case MATCH_TEST:
@@ -313,6 +310,40 @@ add_mode_tests (struct pred_data *p)
   if (p->special)
     return;
 
+  /* Check whether the predicate accepts const scalar ints (which always
+     have a stored mode of VOIDmode, but logically have a real mode)
+     and whether it matches anything besides const scalar ints.  */
+  bool matches_const_scalar_int_p = false;
+  bool matches_other_p = false;
+  for (int i = 0; i < NUM_RTX_CODE; ++i)
+    if (p->codes[i])
+      switch (i)
+	{
+	case CONST_INT:
+	case CONST_WIDE_INT:
+	  matches_const_scalar_int_p = true;
+	  break;
+
+	case CONST_DOUBLE:
+	  if (!TARGET_SUPPORTS_WIDE_INT)
+	    matches_const_scalar_int_p = true;
+	  matches_other_p = true;
+	  break;
+
+	default:
+	  matches_other_p = true;
+	  break;
+	}
+
+  /* There's no need for a mode check if the predicate only accepts
+     constant integers.  The code checks in the predicate are enough
+     to establish that the mode is VOIDmode.
+
+     Note that the predicate itself should check whether a scalar
+     integer is in range of the given mode.  */
+  if (!matches_other_p)
+    return;
+
   mark_mode_tests (p->exp);
 
   /* If the whole expression already tests the mode, we're done.  */
@@ -320,7 +351,11 @@ add_mode_tests (struct pred_data *p)
     return;
 
   match_test_exp = rtx_alloc (MATCH_TEST);
-  XSTR (match_test_exp, 0) = "mode == VOIDmode || GET_MODE (op) == mode";
+  if (matches_const_scalar_int_p)
+    XSTR (match_test_exp, 0) = ("mode == VOIDmode || GET_MODE (op) == mode"
+				" || GET_MODE (op) == VOIDmode");
+  else
+    XSTR (match_test_exp, 0) = "mode == VOIDmode || GET_MODE (op) == mode";
   and_exp = rtx_alloc (AND);
   XEXP (and_exp, 1) = match_test_exp;
 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: RFA: Fix mode checks for possibly-constant predicates
  2015-06-03  7:23             ` Richard Sandiford
@ 2015-06-03  9:39               ` Richard Sandiford
  0 siblings, 0 replies; 30+ messages in thread
From: Richard Sandiford @ 2015-06-03  9:39 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Andreas Krebbel

Richard Sandiford <richard.sandiford@arm.com> writes:
> Richard Henderson <rth@redhat.com> writes:
>> On 05/29/2015 10:23 AM, Richard Sandiford wrote:
>>> +  /* Check whether the predicate accepts const scalar ints (which always
>>> +     have a stored mode of VOIDmode, but logically have a real mode)
>>> +     and whether it matches anything besides const scalar ints.  */
>>> +  bool matches_const_scalar_int_p = false;
>>> +  bool matches_other_p = false;
>>> +  for (int i = 0; i < NUM_RTX_CODE; ++i)
>>> +    if (p->codes[i])
>>> +      switch (i)
>>> +	{
>>> +	CASE_CONST_SCALAR_INT:
>>> +	  matches_const_scalar_int_p = true;
>>> +	  break;
>>> +
>>> +	default:
>>> +	  matches_other_p = true;
>>> +	  break;
>>> +	}
>>> +
>>> +  /* There's no need for a mode check if the predicate only accepts
>>> +     constant integers.  The code checks in the predicate are enough
>>> +     to establish that the mode is VOIDmode.
>>> +
>>> +     Note that the predicate itself should check whether a scalar
>>> +     integer is in range of the given mode.  */
>>> +  if (!matches_other_p && !p->codes[CONST_DOUBLE])
>>> +    return;
>>
>> I think perhaps it would be cleaner to not use CASE_CONST_SCALAR_INT,
>> and then do
>>
>>   switch (i)
>>     {
>>     case CONST_INT:
>>     case CONST_WIDE_INT:
>>       matches_const_scalar_int_p = true;
>>       break;
>>
>>     case CONST_DOUBLE:
>>       if (!TARGET_SUPPORTS_WIDE_INT)
>>         matches_const_scalar_int_p = true;
>>       matches_other_p = true;
>>       break;
>>
>>     default:
>>       matches_other_p = true;
>>       break;
>>     }
>>
>>   if (!matches_other_p)
>>     return;
>>
>> Otherwise ok.
>
> Ah, yeah, that's better.  Here's what I applied after testing on
> x86_64-linux-gnu.

This broke the build for !TARGET_SUPPORTS_WIDE_INT because the default
definition was in the wrong part of defaults.h:

#ifdef GCC_INSN_FLAGS_H
/* Dependent default target macro definitions

   This section of defaults.h defines target macros that depend on generated
   headers.  This is a bit awkward:  We want to put all default definitions
   for target macros in defaults.h, but some of the defaults depend on the
   HAVE_* flags defines of insn-flags.h.  But insn-flags.h is not always
   included by files that do include defaults.h.

   Fortunately, the default macro definitions that depend on the HAVE_*
   macros are also the ones that will only be used inside GCC itself, i.e.
   not in the gen* programs or in target objects like libgcc.

   Obviously, it would be best to keep this section of defaults.h as small
   as possible, by converting the macros defined below to target hooks or
   functions.
*/
...
#endif /* GCC_INSN_FLAGS_H  */

The macro is supposed to be a configuration invariant and so there's
no reason for it depend on generated headers.  The same goes for
SWITCHABLE_TARGET (oops).

Tested by making sure that aarch64-linux-gnu builds again.  Committed
as obvious.

Thanks,
Richard


gcc/
	* defaults.h (SWITCHABLE_TARGET, TARGET_SUPPORTS_WIDE_INT): Move out
	of GCC_INSN_FLAGS_H block.

Index: gcc/defaults.h
===================================================================
--- gcc/defaults.h	2015-06-03 10:21:20.247590112 +0100
+++ gcc/defaults.h	2015-06-03 10:21:27.015513249 +0100
@@ -1253,6 +1253,18 @@ #define STACK_PUSH_CODE PRE_INC
 # define DEFAULT_FLAG_PIE 0
 #endif
 
+#ifndef SWITCHABLE_TARGET
+#define SWITCHABLE_TARGET 0
+#endif
+
+/* If the target supports integers that are wider than two
+   HOST_WIDE_INTs on the host compiler, then the target should define
+   TARGET_SUPPORTS_WIDE_INT and make the appropriate fixups.
+   Otherwise the compiler really is not robust.  */
+#ifndef TARGET_SUPPORTS_WIDE_INT
+#define TARGET_SUPPORTS_WIDE_INT 0
+#endif
+
 #ifdef GCC_INSN_FLAGS_H
 /* Dependent default target macro definitions
 
@@ -1414,18 +1426,6 @@ #define STACK_CHECK_MAX_VAR_SIZE (STACK_
 #define TARGET_VTABLE_USES_DESCRIPTORS 0
 #endif
 
-#ifndef SWITCHABLE_TARGET
-#define SWITCHABLE_TARGET 0
-#endif
-
-/* If the target supports integers that are wider than two
-   HOST_WIDE_INTs on the host compiler, then the target should define
-   TARGET_SUPPORTS_WIDE_INT and make the appropriate fixups.
-   Otherwise the compiler really is not robust.  */
-#ifndef TARGET_SUPPORTS_WIDE_INT
-#define TARGET_SUPPORTS_WIDE_INT 0
-#endif
-
 #ifndef HAVE_simple_return
 #define HAVE_simple_return 0
 static inline rtx

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2015-06-03  9:33 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-27 10:20 Mostly rewrite genrecog Richard Sandiford
2015-04-28 23:18 ` Jeff Law
2015-04-29 13:59   ` Richard Sandiford
2015-04-29  8:52 ` Eric Botcazou
2015-04-29 13:51   ` Richard Sandiford
2015-04-30 10:44     ` Eric Botcazou
2015-04-30  6:54 ` Bin.Cheng
2015-04-30 11:58   ` Richard Sandiford
2015-04-30  7:17 ` Andreas Schwab
2015-04-30  7:58   ` Richard Sandiford
2015-04-30 12:10     ` Andreas Schwab
2015-04-30 12:33       ` Richard Biener
2015-04-30 16:27         ` Richard Sandiford
2015-05-01 12:42           ` Richard Sandiford
2015-05-01 13:57             ` Jeff Law
2015-05-07  8:59 ` [nvptx] " Thomas Schwinge
2015-05-07  9:14   ` Jakub Jelinek
2015-05-21  8:09     ` Thomas Schwinge
2015-05-21 11:57       ` Bernd Schmidt
2015-05-08  9:10 ` genrecog: Address -Wsign-compare diagnostics (was: Mostly rewrite genrecog) Thomas Schwinge
2015-05-08 14:43   ` genrecog: Address -Wsign-compare diagnostics Richard Sandiford
2015-05-08 18:39   ` Jeff Law
2015-05-16  8:13 ` Mostly rewrite genrecog Andreas Krebbel
2015-05-17 22:05   ` Richard Sandiford
2015-05-22 16:14     ` Andreas Krebbel
2015-05-22 16:32       ` Richard Sandiford
2015-05-29 17:39         ` RFA: Fix mode checks for possibly-constant predicates Richard Sandiford
2015-05-29 19:27           ` Richard Henderson
2015-06-03  7:23             ` Richard Sandiford
2015-06-03  9:39               ` Richard Sandiford

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).