This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug target/21041] [4.0 Regression] ICE: output_operand: Cannot decompose address


------- Additional Comments From uweigand at gcc dot gnu dot org  2005-04-16 15:48 -------
The problem originates in find_reloads_subreg_address, which decides
to widen access to a memory reference.  The instruction we have is:

(insn 129 127 130 10 (parallel [
            (set (reg:SI 106)
                (plus:SI (subreg:SI (reg:QI 104) 0)
                    (subreg:SI (reg:QI 105) 0)))
            (clobber (reg:CC 33 %cc))
        ]) 143 {addsi3} (insn_list:REG_DEP_TRUE 128 (insn_list:REG_DEP_TRUE 127
(nil)))
    (expr_list:REG_DEAD (reg:QI 104)
        (expr_list:REG_DEAD (reg:QI 105)
            (expr_list:REG_UNUSED (reg:CC 33 %cc)
                (nil)))))

and register 104 is equivalent to a memory slot:

(insn 127 128 129 10 (set (reg:QI 104)
        (mem:QI (reg/f:SI 47 [ pretmp.10 ]) [0 S1 A8])) 53 {*movqi}
(insn_list:REG_DEP_TRUE 81 (insn_list:REG_DEP_TRUE 88 (insn_list:REG_DEP_TR
UE 95 (insn_list:REG_DEP_TRUE 102 (insn_list:REG_DEP_TRUE 109
(insn_list:REG_DEP_TRUE 116 (insn_list:REG_DEP_TRUE 123 (nil))))))))
    (expr_list:REG_EQUIV (mem:QI (reg/f:SI 47 [ pretmp.10 ]) [0 S1 A8])
        (nil)))

Now, reg 104 does not get a hard reg assigned. However, register 47 gets
assigned hard reg 0, which is not valid in a memory address.

Because register 104 is now equivalent to an invalid memory reference,
find_reloads_toplev calls find_reloads_subreg_address on the paradoxical
(subreg:SI (reg:QI 104)).

That routine thinks it can replace the subreg with an adjusted equivalent
memory reference (mem:SI (plus (reg 0) (const_int -3))).

It then calls find_reloads_address on that address.  Now, this address
is invalid for *two* reasons: register 0 cannot be used as base register,
and negative displacements are invalid.  find_reloads_address is unable
to cope with this combination, and returns with an address that is still
invalid.

[ If LEGITIMIZE_RELOAD_ADDRESS is active, it fixes the negative displacement
but keeps register 0.  If I disable LEGITIMIZE_RELOAD_ADDRESS, the default
find_reloads_address behaviour will reload register 0, but keep the invalid
displacement. ]

As a workaround, I can add code to LEGITIMIZE_RELOAD_ADDRESS that fixes
both issues and results in a valid address, fixing the ICE.  However, this
has two problems:

1. According to my understanding, L_R_A should never be required for
correctness, but only bring extra performance.  Thus find_reloads_address
alone should also be able to fix the problem.

2. The whole business of widening access to a memory slot is questionable
in this case: if register 47 were to point to the start of a page of memory
preceded by unmapped address space, the widened access would crash.  I had
thought that for this reason, only accesses to *stack slots* can be widened;
scan_paradoxical_subregs would make sure such stack slots are aligned 
properly.  However, in this case just some random memory access is widened.


As a final comment: both test cases in this PR are strictly speaking
invalid C or C++, because uninitialized variables are accessed.  I was
unable to modify the test cases to valid C/C++.  Does the original
unreduced source code also have uninitialized variables?  There have
been some issues in the past where reload would handle uninitialized
pseudos correctly ...

-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21041


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]