Hi Guys,

  I am stuck on a dataflow problem.  PR 49801 is reported against the RX
  toolchain, but I believe it to be a generic problem.

    http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49801

  The issue I think is the split2 pass which is converting this:

    (set (pc) (if_then_else (geu (reg r1)
                                 (reg r2))
                            (label_ref 13)
                            (pc)))

  into this:

    (set (reg:CC cc) (compare:CC (reg r1)
                                 (reg r2)))

    (set (pc) (if_then_else (geu (reg cc)
                                 (const_int 0))
                            (label_ref 13)
                            (pc)))

  This new pair of insns introduces a definition and use of the
  condition code register (reg cc), but the dataflow information is not
  updated to reflect this.  This causes the following pass (compare
  eliminate) to ICE with a dataflow checking failure if checking is
  enabled:

    shift.c:7:1: internal compiler error: in df_live_verify_transfer_functions, 
at df-problems.c:1816

  The dataflow information for the basic block looks like this:

    ;; Start of basic block ( 0) -> 2
    ;; bb 2 artificial_defs: { }
    ;; bb 2 artificial_uses: { u-1(0){ }}
    ;; lr  in    0 [r0] 1 [r1] 2 [r2]
    ;; lr  use   0 [r0] 1 [r1] 2 [r2]
    ;; lr  def  
    ;; live  in          0 [r0] 1 [r1] 2 [r2]
    ;; live  gen        
    ;; live  kill       

    ;; End of basic block 2 -> ( 3 4)
    ;; lr  out   0 [r0] 1 [r1] 2 [r2]
    ;; live  out         0 [r0] 1 [r1] 2 [r2]

  Ie no mention of the condition code register (register 16).

  The issue I have is that I do not know how to fix this.  I thought
  that adding a call to df_insn_rescan for the newly created insns would
  work, like this:

Index: gcc/recog.c
===================================================================
--- gcc/recog.c (revision 179611)
+++ gcc/recog.c (working copy)
@@ -2841,7 +2841,10 @@
       for (;;)
        {
          if (INSN_P (first))
-           cleanup_subreg_operands (first);
+           {
+             cleanup_subreg_operands (first);
+             df_insn_rescan (first);
+           }
          if (first == last)
            break;
          first = NEXT_INSN (first);

  But this made no difference. :-(  I have considered adding a
  "(set (reg cc)..)" in parallel to the original jump pattern, but I am
  loath to do so because I have found that gcc tends to have issues with
  jump insns that contain parallels.

  Any suggestions ?

Cheers
  Nick

Reply via email to