This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Use of FLAGS_REGNUM clashes with generates insn


Hi,

After the discussion about the use of CCmode in:
http://gcc.gnu.org/ml/gcc/2011-07/msg00303.html

I am trying to ditch support for the only cc0 attr and add support for CC_REG.

There are two issues that are making the situation more complicated, both of similar nature.

My addition instruction sets all the flags. So I have:
(define_insn "addqi3"
  [(set (match_operand:QI 0 "nonimmediate_operand" "=c")
        (plus:QI (match_operand:QI 1 "nonmemory_operand" "%0")
                 (match_operand:QI 2 "general_operand" "cwmi")))
   (clobber (reg:CC RCC))]
  ""
  "add\\t%0,%f2")

(define_insn "*addqi3_flags"
  [(set (match_operand:QI 0 "nonimmediate_operand" "=c")
        (plus:QI (match_operand:QI 1 "nonmemory_operand" "%0")
                 (match_operand:QI 2 "general_operand" "cwmi")))
   (set (reg RCC)
        (compare (plus:QI (match_dup 1) (match_dup 2))
                 (const_int 0)))]
  "reload_completed && xap_match_ccmode(insn, CCmode)"
  "add\\t%0,%f2")

There's however a problem with this. GCC during reload, after register elimination (eliminating argument pointer for an offset from the stack pointer tries to output the instruction):
(set (reg ...) (plus:QI (reg ...) (const_int ...)))


However, it spills and fails because no rule matches this expression (it's missing the clobber). I fixed this with:

(define_insn_and_split "addqi3_noclobber"
  [(set (match_operand:QI 0 "register_operand" "=c")
        (plus:QI (match_operand:QI 1 "register_operand")
                 (match_operand:QI 2 "immediate_operand")))]
  "reload_in_progress"
  "#"
  "reload_completed"
  [(set (match_dup 0) (match_dup 1))
   (parallel [(set (match_dup 0) (plus:QI (match_dup 0) (match_dup 2)))
              (clobber (reg:CC RCC))])])

And it works. However, the more complex issue comes with register moves. A register move which ends up as a load or store, sets flags N, Z.

I have an expand movqi which expand to a move with the clobber like so:
(define_expand "movqi"
[(parallel [(set (match_operand 0 "nonimmediate_operand")
(match_operand 1 "general_operand"))
(clobber (reg:CC RCC))])]
""
{
/* One of the ops has to be in a register. */
if (!register_operand(operands[0], QImode)
&& ! (register_operand(operands[1], QImode) || const0_rtx == operands[1]))
operands[1] = copy_to_mode_reg(QImode, operands[1]);
})


And all my (define_insn "*mov..." are tagged with a (clobber (reg:CC RCC)). This generates all kinds of trouble since GCC generates moves internally without the clobber that fail to match.

I tried the same trick as above:

(define_insn_and_split "*movqi_noclobber"
  [(set (match_operand:QI 0 "nonimmediate_operand")
        (match_operand:QI 1 "general_operand"))]
  "!reload_completed"
  "#"
  ""
  [(parallel [(set (match_dup 0) (match_dup 1))
              (clobber (reg:CC RCC))])])

This doesn't fix the problem. It actually brings an internal compiler error. I am definitely not doing this the right way.

Any suggestions on how to correctly handle these?

Cheers,
--
PMatos


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]