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

Reply via email to