Reload pass ignores constraints. Why?

Georg-Johann Lay avr@gjlay.de
Tue Apr 14 09:35:00 GMT 2009


Hi.

Working out recommendations for a new instruction set architecture (no 
silicon yet), I run into the following problem with a port based on 
gcc_4_3_3_release: postreload complains

error: insn does not satisfy its constraints:
(insn 1636 1635 410 35 k_rem_pio2.c:816 (set (reg:SI 28 a12)
         (lshiftrt:SI (reg:SI 28 a12)
             (const_int 8 [0x8]))) 22 {lshrsi3} (nil))
k_rem_pio2.c:910: internal compiler error: in 
reload_cse_simplify_operands, at postreload.c:395

The reason is obvious: Pass greg chooses reg a12 which is not in class 
"d" as required by this insn:

(define_insn "lshrsi3"
   [(set (match_operand:SI 0 "register_operand"                 "=d ,d 
  ,d")
         (lshiftrt:SI (match_operand:SI 1 "register_operand"     "d ,0 
  ,d")
                      (match_operand:SI 2 "reg_or_u5_operand"    "d ,Ku4 
,Ku5")))]
   ""
   "...")

"Ku4" is an unsigned 4-bit constant, "Ku5" likewise.
The register set consists of two disjoint register classes "a" and "d":
a-regs are used to access memory, address arithmetic, etc.
d-regs are used to perform arithmetic
Both classes allow SImode=Pmode, a12 is an element of "a".

In pass lreg everything is all right:

*lreg*
(insn:HI 408 202 409 17 k_rem_pio2.c:816 (set (reg:SI 569)
         (const_int -1 [0xffffffff])) 2 {*movsi_insn} 
(expr_list:REG_EQUIV (const_int -1 [0xffffffff])
         (nil)))

(insn:HI 409 408 400 17 k_rem_pio2.c:816 (set (reg:SI 570)
         (lshiftrt:SI (reg:SI 569)
             (const_int 8 [0x8]))) 22 {lshrsi3} (expr_list:REG_EQUIV 
(const_int 16777215 [0xffffff])
         (expr_list:REG_DEAD (reg:SI 569)
             (nil))))

This is the cheapest way to load the desired constant 0xffffff into a 
register: load -1 and shift it right by 8. The sequence was expanded in 
pass expand. But despite the constraints "d" in the insns, greg 
allocates a12:

*greg*
(insn 1635 407 1636 35 k_rem_pio2.c:816 (set (reg:SI 28 a12)
         (const_int -1 [0xffffffff])) 2 {*movsi_insn} (nil))

(insn 1636 1635 410 35 k_rem_pio2.c:816 (set (reg:SI 28 a12)
         (lshiftrt:SI (reg:SI 28 a12)
             (const_int 8 [0x8]))) 22 {lshrsi3} (nil))

movsi knows how to move all kinds of memory, registers and constants. 
There is no secondary reload needed to copy from "a" to "d" or from "d" 
to "a". -1 is allright for both "a" and "d". The classes are big enough 
so that CLASS_LIKELY_SPILLED_P is false for them. 
PREFERRED_(OUTPUT_)RELOAD_CLASS does nothing.

According to GCC internals this should work without any problems:

 > Any operand expression can be reloaded by copying it into a register.
 > So if an operand's constraints allow some kind of register, it is
 > certain to be safe.  It need not permit all classes of registers; the
 > compiler knows how to copy a register into another register of the
 > proper class in order to make an instruction valid.

What am I missing? Would be great if some expert could give me a hint.

I browsed SVN for bug fixes in reload/ira, but no fix seems to address 
this problem. Is therer a problem with REG_EQUIV notes that make reload 
blindly take some register?

To give it a try I also defined a "d_register_operand" predicate which 
leads to "unrecognizable insn", just as I expected...

Thanks very mutch



More information about the Gcc-help mailing list