Egcs 1.1.1 (ARM) bug reloading offsettables
Richard Earnshaw
rearnsha@arm.com
Tue Jan 19 07:06:00 GMT 1999
The following testcase reveals a bug in the reloading code when compiled
with the arm-aout configuration of egcs 1.1.1 (flags -O2). Although I
haven't reproduced this on the trunk, the code in find_reloads for this
case looks to still be doing the same thing.
Analysis:
The ARM md file contains patterns for some instructions that require an
offsettable address. This is so that a small constant can be added to the
address to force the hardware to rotate the data as it is transfered from
memory to the register (this saves an additional shift when extending
half-words).
The original pattern looks like:
(set (reg:SI ) (rotate:SI (mem:SI (address)) (const_int 16)))
address must satisfy the constraints for an offsettable address, and is
normally a single register, or a register plus a suitable constant.
During reload, if the address is a simple register it may get spilled onto
the stack and replaced with a MEM expression representing this -->
(rotate (mem:SI (mem:SI (stack address))) (const_int 16))
For functions with large stack frames the stack address may itself need
reloads pushing in order to be able to address the required slot in the
stack frame; find_reloads_address correctly does this. Unfortunately,
case 'o' in find_reloads ignores this and fails to note that the address
has now been correctly reloaded, doesn't mark the operand as a win, and
then subsequently pushes a single reload for the entire stack-slot access.
In the particular example I have,
(insn 920 917 926 (set (reg:SI 9 r9)
(rotate:SI (mem:SI (mem:SI (plus:SI (reg:SI 11 fp)
(const_int -5796))))
(const_int 16))) 190 {rotated_loadsi} (nil)
(nil))
which was generated when an allocated psuedo (for the address) was spilled
onto the stack. This gets reloaded as
;; 2 correct reloads pushed by find_reloads_address
(set (reg:SI 9 r9) (plus:SI (reg:SI 11 fp) (const_int -4096)))
(set (reg:SI 9 r9) (mem:SI (plus:SI (reg:SI 9 r9) (const_int -1700))))
;; Bogus reload pushed by find_reloads (note this destroys the correct
;; evaluation of r9 above
(set (reg:SI 9 r9) (mem:SI (plus:SI (reg:SI 11 fp) (const_int -5796))))
;; reloaded instruction
(set (reg:SI 9 r9) (rotate:SI (mem:SI (reg:SI 9 r9)) (const_int 16)))
The third instruction (the one marked bogus) causes the compiler to fault
since an offset of -5796 is not valid for a load on the ARM.
The patch below fixes the offsettable address handling in find_reloads to
detect this scenario and avoids pushing the bogus reload that has already
been handled.
Richard.
<date> Richard Earnshaw (rearnsha@arm.com)
*reload.c (find_reloads, case 'o'): MEM(MEM()) is offsettable if
we don't have indirection and the address has been reloaded.
More information about the Gcc-bugs
mailing list