We would like to eliminate cc0 and the associated machinery from the
compiler, because it is complicated and not supported on popular or
modern processors.  Here is a plan which I think could accomplish that
without unreasonable effort.

1) Modify the programs which read the .md file to look for an
   attribute named clobbercc.  If such an attribute exists, then for
   any instruction pattern which defines clobbercc as "yes" (or
   "true", or whatever), automatically add "(clobber (reg:CC CC_REG))"
   to the instruction.

2) For each target which uses CC:

   2a) Define the clobbercc attribute to be "yes" for each insn which
       changes the condition codes unpredictably.  Typically the
       default would be "yes", and then either clobbercc would be
       written to use cond to select instruction for which it should
       be "no", or those instructions would be marked specifically.

   2b) Convert conditional branch instructions from separate
       cmpMODE/bCOND instructions to a single conditional branch
       instruction, either by saving condition codes in cmpMODE or
       tstMODE or by using cbranch.

   2c) Similarly convert setCOND, movCOND, and addCOND instructions.

   2d) For each converted instruction, write a splitter which takes
       effect after reload and splits the instruction into the
       comparison and the branch (or whatever).  The comparison should
       set CC_REG, and the branch should test CC_REG.

   2e) Rewrite all other instruction patterns which set cc0 to instead
       set CC_REG (and make sure that the clobbercc attribute is not
       "yes" for such instructions).  Rewrite instruction patterns
       which test cc0 to instead test CC_REG.

At this point we have eliminated cc0 for the target.  The generated
code should be correct.  The instruction which sets the condition
codes will be kept in synch with the instruction which uses the
condition codes, because most other instructions will have an
automatically inserted clobber.  However, the generated code will not
be as good, because there will be unnecessary comparison instructions.

(A note for the uninitiated.  We need to write the converted branch
instructions as single instructions which are split after reload
because reload has to be able to move values in and out of memory, and
compute addresses, between arbitrary pairs of instructions.  On cc0
machines, those moves and computations will themselves change the
condition codes, and we will wind up testing the wrong conditions in
the branch instruction.  So reload has to see compare-and-branch as a
single instruction.)

3) Write a new optimization pass enabled on targets which define
   NOTICE_UPDATE_CC.  I think this pass would be run just before
   machine dependent reorg, although perhaps there is a better place
   for it.  Walk through the instructions, calling NOTICE_UPDATE_CC on
   each one.  When we find an instruction which sets CC_REG, check the
   source of the set with the current CC status, just as
   final_scan_insn does now.  If the current CC status is the same,
   delete the instruction which sets CC_REG.

At this point, the generated code quality should be approximately the
same as when the target used cc0.

4) When all targets have been converted, remove all the code in the
   compiler protected by #ifdef HAVE_cc0.  Remove the CC_SETTER and
   CC_USER register notes.  Remove the associated documentation.

5) Profit!

The main ideas here are to use the clobbercc attribute to avoid having
to modify every single instruction, and to use the new optimization
pass to avoid having to write dozens of new peepholes to recover code
quality.  The conversions in steps 2b through 2e above are relatively
mechanical.  Step 2a will require a bit of thought, but should not be
too difficult.

Does anybody see any problems with this approach?  Does anybody think
this is, or is not, implementable?  Does anybody think there is an
approach which is simpler?

Ian

Reply via email to