I've been converting the Blackfin port to take advantage of the new lower-subreg pass, which fortunately involves little more than deleting a few patterns.

One problem is that without an anddi3 expander, we generate poor initial RTL. optabs knows it can do the operation piecewise, so it could generate the following sequence for an operation involving one memory operand:

 reg C = (mem:SI symbol+offset)
 reg A = reg B + reg C;
 reg Z = (mem:SI symbol+offset+4)
 reg X = reg Y + reg Z;

It then passes this to emit_no_conflict_block, which is supposed to wrap it in REG_NO_CONFLICT notes to help the register allocator. This function pulls out any insns not contributing to the final result, and emits them first, leading to:

 reg C = (mem:SI symbol+offset)
 reg Z = (mem:SI symbol+offset+4)
 reg A = reg B + reg C;
 reg X = reg Y + reg Z;

which has higher register pressure (at least in the usual cases where C and Z are dead after their use) and causes more spills than the former sequence on certain testcases. The sad thing is that all the REG_NO_CONFLICT notes later get removed by lower-subreg as they serve no purpose, but the suboptimal insn ordering survives until register allocation.

It would be nice to eliminate REG_NO_CONFLICT altogether, but a quick experiment with the i386 port showed that this idea is a non-starter for now (i386 still has insns operating on DImode, hence in some functions not all DImode registers get lowered, and lack of no_conflict blocks causes poor register allocation when that happens).

I suppose we could add a target macro to let individual ports turn off REG_NO_CONFLICT generation? Any other ideas?


Bernd
--
This footer brought to you by insane German lawmakers.
Analog Devices GmbH      Wilhelm-Wagenfeld-Str. 6      80807 Muenchen
Registergericht Muenchen HRB 40368
Geschaeftsfuehrer Thomas Wessel, Vincent Roche, Joseph E. McDonough

Reply via email to