I'm using the CCmode model for condition-code handling in a 4.6.1 based
compiler. Every other port I've done used the CC0 model, so I'm probably doing
something misguided here.
I'm down to just 170 failures in the check-gcc testsuites, so it's looking
pretty solid; of the failures about 30 are tests with delay-slots being filled
incorrectly.
The situation I see is where we have source that looks like
if (x != 0)
count++;
if (y != z)
.....
RTL (without delay slot considerations looks like)
jeq $1
add r1,1
$1: cmp r2,r3
jeq $2
branches have delay slots, and are not annullable. When reorg runs, it
realizes that it can't put the add into the delay slot, but it hoists the cmp
instruction into the first branch slot, ala
jeq $1
cmp r2,r3
add r1,1
$1: jeq $r2
......
So, if the first branch is not taken, we set the condition codes needed for the
second branch and clobber them with the add instruction then fall to the
conditional branch using the wrong condition codes.
I emit (clobber (reg:CC CCreg)) with every instruction that can set condition
codes, but it appears that nearly all of them are removed before we reach reorg
where mark_referenced_resources() or mark_set_resources() would detect a
conflict of the CCreg's.
So, am I constructing my RTL incorrectly? Do I need to be making the clobbers
inside a parallel instead of just emitting them sequentially? Or should I just
fall back to a cc0 model where this shouldn't be a problem?
The define_expand pattern for add looks like
(define_expand "add<S:mode>3"
[(set (match_operand:S 0 "nonimmediate_operand")
(plus:S (match_operand:S 1 "general_operand")
(match_operand:S 2 "general_operand")))
(clobber (reg:CC CC_REGNUM))]
""
.....
})
has corresponding define_insn's are
(define_insn "*addsi"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm,rS,rm")
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0, 0, 0,rm")
(match_operand:SI 2 "general_operand" "QI, K, i,rm")))]
,........
)
(define_insn "*addsi_cc"
[(set (reg:CC CC_REGNUM)
(compare:CC
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0, 0, 0,rm")
(match_operand:SI 2 "general_operand" "QI, K, i,rm"))
(const_int 0)))
(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm,rS,rm")
(plus:SI (match_dup 1)
(match_dup 2)))]