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