Re: Reload pass ignores constraints. Why?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Ian Lance Taylor schrieb:
Georg-Johann Lay <avr@xxxxxxxx> writes:

When calculate_needs_all_insns runs on the insn the insn looks like
this (other insn numbers than above as I proceed my very work
regardless of the possible bug)

calculate_needs_all_insns[__kernel_rem_pio2:greg(180)]: (insn:HI 409
438 400 17 k_rem_pio2.c:816 (set (reg:SI 566)
        (lshiftrt:SI (reg:SI 0 d0 [565])
            (const_int 8 [0x8]))) 22 {lshrsi3} (expr_list:REG_EQUIV
(const_int 16777215 [0xffffff])
        (expr_list:REG_DEAD (reg:SI 0 d0 [565])

Someone already replaced #1 with d0, a reg of the right class
"d". Maybe a function parameter or return value is propagated.

However, calculate_needs_all_insns decides that there are no reloads
needed. reload1.c:1554 reads:

	  /* Skip insns that only set an equivalence.  */
	  if (set && REG_P (SET_DEST (set))
	      && reg_renumber[REGNO (SET_DEST (set))] < 0
	      && (reg_equiv_constant[REGNO (SET_DEST (set))]
		  || (reg_equiv_invariant[REGNO (SET_DEST (set))]))
		      && reg_equiv_init[REGNO (SET_DEST (set))])
              continue;

Before lreg, the insn is tagged REG_EQUAL but lreg then retags it as
REG_EQUIV.

So is the problem in lreg because it says REG_EQUIV?
Or is it wrong to omit REG_EQUIV insns from reload?

Neither is the problem.

This case happens when a pseudo-register which is equivalent to a
constant or a memory location is not given a hard register.  Reload is
supposed to replace every use of the register with the constant.  The
insn would then normally be deleted.  I don't know why it wasn't deleted
in your case.

One way to address this would probably be to define
LEGITIMATE_CONSTANT_P such that it rejects 0xffffff.  If you don't do

This will force the 0xffffff into constant pool, which adds penalty of +100% in code size and even more in execution time.

that--if LEGITIMATE_CONSTANT_P accepts 0xffffff--then you need to ensure
that your movsi insn will handle 0xffffff directly, without using any
pseudo-registers when can_create_pseudo_p returns false.

That works, of course. But I must admit that I prefer to express what is going on in terms of algebra, i.e. in terms of RTL instead of acting as if the core could handle the constant and just printng out some asm sequencs. movsi expands constants that cannot be loaded in one machine instruction to a movesi_insn and an arithmetic insn, and movsi_insn therefore allows only constants that are easy to load.

Many RISC machines employ MOV/ADD sequences to load large const_int and emit appropriate RTL. Just printing out several instructions in one asm string would bypasses all optimizations like CSE, Schedule, etc.

What I do not understand is that a MOV/ADD sequence (which covers large constants) works on RTL level, whereas MOV/SHIFTRT (which is more efficient in some cases) shreds global alloc. Other strategies could be MOV/[AND|IOR|XOR|BSWAP...] which won't work either, though.

greg treats the shift insn as if it was a movsi_insn. I still think it's not correct what is going on -- at least as far as I ungerstand the internals. They do not say a single word about that large const_int must not be expanded into insn sequences. They say an insn alternative was *always* safe if it allowed some kind of general register.

Many thanks for your explanations! It's much clearer now. It's much more important to me to understand gcc better and learn more about it than to quench out some bits of efficiency in the generated code ;-)

Georg-Johann

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux