On 2011/4/20 11:12 PM, Richard Earnshaw wrote:
> 
> On Wed, 2011-04-20 at 23:06 +0800, Chung-Lin Tang wrote:
>> On 2011/4/20 09:24 PM, Richard Sandiford wrote:
>>> Hi Chung-Lin,
>>>
>>> I'm seeing an ICE with this patch, specifically;
>>>
>>> Chung-Lin Tang <clt...@codesourcery.com> writes:
>>>> +      if (coproc_p)
>>>> +  low = SIGN_MAG_LOW_ADDR_BITS (val, 10);
>>>
>>> We generate:
>>>
>>> Reload 1: reload_out (V4SI) = (mem/c:V4SI (plus:SI (plus:SI (reg/f:SI 11 fp)
>>>                                                             (const_int 
>>> -6144 [0xffffffffffffe800]))
>>>                                                         (const_int 1020 
>>> [0x3fc])) [43 %sfp+-5024 S16 A64])
>>>
>>> but 1020 isn't a legitimate offset for V4SI:
>>>
>>>   /* For quad modes, we restrict the constant offset to be slightly less
>>>      than what the instruction format permits.  We do this because for
>>>      quad mode moves, we will actually decompose them into two separate
>>>      double-mode reads or writes.  INDEX must therefore be a valid
>>>      (double-mode) offset and so should INDEX+8.  */
>>>   if (TARGET_NEON && VALID_NEON_QREG_MODE (mode))
>>>     return (code == CONST_INT
>>>         && INTVAL (index) < 1016
>>>         && INTVAL (index) > -1024
>>>         && (INTVAL (index) & 3) == 0);
>>>
>>> A simple "fix" would be to use 9 instead of 10, but something a little
>>> more subtle might be preferred :-)
>>>
>>> Richard
>>
>> Oh dear, for some reason I mistakenly thought that NEON had a quad-word
>> load/store, sorry :P
>>
>> Reducing from 10 to 9 may be a possible solution, if restricted to the
>> necessary cases. For example:
>>
>> -low = SIGN_MAG_LOW_ADDR_BITS (val, 10);
>> +{
>> +  low = SIGN_MAG_LOW_ADDR_BITS (val, 10);
>> +
>> +  /* NEON quad-word load/stores are made of two double-word accesses,
>> +     so the valid index range is reduced by 8. Treat as 9-bit range if
>> +     we go over it.  */
>> +  if (TARGET_NEON && VALID_NEON_QREG_MODE (mode) && low >= 1016)
>> +    low = SIGN_MAG_LOW_ADDR_BITS (val, 9);
>> +}
>>
>> To Richard Earnshaw, how do you think of a fix like this? Or should we
>> just simply return false under this out-of-range case (it should be rare
>> I hope).
>>
> 
> I don't think it matters a great deal.  The above is fine.
> 
> Note, that some targets don't have LDRD either.  Do we do the right
> thing if we're going to fall back to two LDR instructions?
> 
> R.

The current non-TARGET_LDRD case goes through this path:
    ...
    else
      /* For pre-ARMv5TE (without ldrd), we use ldm/stm(db/da/ib)
         to access doublewords. The supported load/store offsets are
         -8, -4, and 4, which we try to produce here.  */
      low = ((val & 0xf) ^ 0x8) - 0x8;

which uses ldm/stm. This should be safe.

As for pre-ARMv4 ldrh, this is special cased as:
    if (arm_arch4)
      low = SIGN_MAG_LOW_ADDR_BITS (val, 8);
    else
      {
         /* The storehi/movhi_bytes fallbacks can use only
            [-4094,+4094] of the full ldrb/strb index range.  */
         low = SIGN_MAG_LOW_ADDR_BITS (val, 12);
         if (low == 4095 || low == -4095)
           return false;
      }

Although to be frank, I haven't really tested a pre-ARMv4 config; not
very easy to do so in an EABI world :)

I'll take the above NEON QREG mode fix as approved.

Chung-Lin

Reply via email to