"H.J. Lu" <hjl.to...@gmail.com> writes:
> On Mon, Oct 29, 2012 at 5:11 PM, H.J. Lu <hjl.to...@gmail.com> wrote:
>> On Mon, Oct 29, 2012 at 4:41 PM, H.J. Lu <hjl.to...@gmail.com> wrote:
>>> On Mon, Oct 29, 2012 at 9:38 AM, Vladimir Makarov
>>> <vmaka...@redhat.com> wrote:
>>>> On 12-10-29 12:21 PM, Richard Sandiford wrote:
>>>>>
>>>>> Vladimir Makarov <vmaka...@redhat.com> writes:
>>>>>>
>>>>>>     H.J. in
>>>>>>
>>>>>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55116
>>>>>>
>>>>>>     reported an interesting address
>>>>>>
>>>>>> (and:DI (subreg:DI (plus:SI (ashift:SI (reg:SI 96 [ glob_vol_int.22 ])
>>>>>>                   (const_int 2 [0x2]))
>>>>>>               (symbol_ref:SI ("glob_vol_int_arr") <var_decl
>>>>>> 0x7ffff03c2720 glob_vol_int_arr>)) 0)
>>>>>>       (const_int 4294967295 [0xffffffff]))
>>>>>>
>>>>>>     which can not be correctly extracted.  Here `and' with `subreg'
>>>>>> behaves as an address mutation.
>>>>>>
>>>>>>     The following patch fixes the problem.
>>>>>>
>>>>>> Ok to commit, Richard?
>>>>>
>>>>> Heh, I wondered if subregs might still be used like that, and was almost
>>>>> tempted to add them just in case.
>>>>>
>>>>> I think this particular case is really a failed canonicalisation and that:
>>>>>
>>>>>     (and:DI (subreg:DI (foo:SI ...) 0) (const_int 0xffffffff))
>>>>>
>>>>> ought to be:
>>>>>
>>>>>     (zero_extend:DI (foo:SI ...))
>>>>
>>>> Yes, that was my thought too.
>>>>
>>>>> But I know I've approved MIPS patches to accept
>>>>> (and:DI ... (const_int 0xffffffff)) as an alternative.
>>>>>
>>>>>> Index: rtlanal.c
>>>>>> ===================================================================
>>>>>> --- rtlanal.c   (revision 192942)
>>>>>> +++ rtlanal.c   (working copy)
>>>>>> @@ -5459,6 +5459,11 @@ strip_address_mutations (rtx *loc, enum
>>>>>>          else if (code == AND && CONST_INT_P (XEXP (*loc, 1)))
>>>>>>           /* (and ... (const_int -X)) is used to align to X bytes.  */
>>>>>>           loc = &XEXP (*loc, 0);
>>>>>> +      else if (code == SUBREG
>>>>>> +              && ! REG_P (XEXP (*loc, 0)) && ! MEM_P (XEXP (*loc, 0)))
>>>>>> +       /* (subreg (operator ...) ...) usually inside and is used for
>>>>>> +          mode conversion too.  */
>>>>>> +       loc = &XEXP (*loc, 0);
>>>>>
>>>>> I think the condition should be:
>>>>>
>>>>>        else if (code == SUBREG
>>>>>                 && !OBJECT_P (SUBREG_REG (*loc))
>>>>>                 && subreg_lowpart (*loc))
>>>>>
>>>>> OK with that change, if it works.
>>>>>
>>>> Yes, it works.
>>>> I've submitted the following patch.
>>>>
>>>
>>> It doesn't work right.  I will create a new testcase.
>>>
>>
>>
>
> This patch limits SUBREG to Pmode.  Tested on Linux/x86-64.
> OK to install?
>
> Thanks.

The address in this case is:

(plus:SI (mult:SI (reg/v:SI 223 [orig:154 j ] [154])
        (const_int 8 [0x8]))
    (subreg:SI (plus:DI (reg/f:DI 20 frame)
            (const_int 32 [0x20])) 0))

which after Uros's subreg simplification patch shouldn't be allowed:
the subreg ought to be on the frame register rather than the plus.

The attached patch seems to work for the testcase.  Does it work
more generally?

Richard


gcc/
        * lra-eliminations.c (lra_eliminate_regs_1): Use simplify_gen_subreg
        rather than gen_rtx_SUBREG.

Index: gcc/lra-eliminations.c
===================================================================
--- gcc/lra-eliminations.c      (revision 192983)
+++ gcc/lra-eliminations.c      (working copy)
@@ -550,7 +550,8 @@
              return x;
            }
          else
-           return gen_rtx_SUBREG (GET_MODE (x), new_rtx, SUBREG_BYTE (x));
+           return simplify_gen_subreg (GET_MODE (x), new_rtx,
+                                       GET_MODE (new_rtx), SUBREG_BYTE (x));
        }
 
       return x;

Reply via email to