I'm looking for help with an if-convert problem.
I have a local arm based target, but with most of the conditional execution
patterns disabled. Before the first if-conversion pass we have the following
RTL:
(set (reg2) (const_int 0))
(set (CC) (compare (reg1) (const_int 0)))
(jump if (CC) (label_ref 1)
(set (reg2) (const_int 1))
(label 1)
(jump if (CC) (label_ref 2))
...
The CE1 pass recognises the first conditional branch as a store-flag
sequence, and replaces it with a abs/sub/shift sequence:
(set (CC) (compare (reg1) (const_int 0)))
(parallel (set (reg2) (abs (reg1)))
(clobber (CC)))
(sub/shift)
(jump if (CC) (label_ref 2))
The problem is that it does this without any liveness information. An ARM the
abs instruction clobbers the condition code register (CC).
The CC was live over this block and is still needed for the second conditional
branch. Things go rapidly downhill from there.
I can't reproduce the bug with FSF sources, However I believe this is a latent
bug that could effect any targets that use specific hard registers. CC is the
most common example, but I guess this could also happen with other fixed
registers (e.g. multipliers with fixed output registers).
Ideally I guess we'd do something similar to combine, and use life information
to avoid clobbering useful values. However we don't have life info, and I
guess calculating it would be expensive.
The best compromise I've been able to come up with is the scan the replacement
sequence for new sets/clobbers of hard registers, and reject the replacement
if this occurs. This scanning is fairly ugly, but quicker than full life
analysis and hopefully won't cause too many pessimizations, though I'd have
to check x86.
Any suggestions?
Paul