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