diff mbox

[tree-ssa-address] Use simplify_gen_binary in gen_addr_rtx

Message ID 585955CF.3010501@foss.arm.com
State New
Headers show

Commit Message

Kyrill Tkachov Dec. 20, 2016, 4:01 p.m. UTC
Hi all,

The testcase in this patch generates bogus assembly for arm with -O1 -mfloat-abi=soft:
        strd    r4, [#0, r3]

This is due to non-canonical RTL being generated during expansion:
(set (mem:DI (plus:SI (const_int 0 [0])
                 (reg/f:SI 153)) [0 MEM[symbol: a, index: _26, offset: 0B]+0 S8 A64])
         (reg:DI 154))

Note the (plus (const_int 0) (reg)). This is being generated in gen_addr_rtx in tree-ssa-address.c
where it creates an explicit PLUS rtx through gen_rtx_PLUS, which doesn't try to canonicalise its arguments
or simplify. The correct thing to do is to use simplify_gen_binary that will handle all this properly.

I didn't change the other gen_rtx_PLUS calls in this function as their results is later used in XEXP operations
that seem to rely on a PLUS expression being explicitly produced, but this particular call doesn't, so it's okay
to change it. With this patch the sane assembly is generated:
         strd    r4, [r3]

Bootstrapped and tested on arm-none-linux-gnueabihf, x86_64, aarch64-none-linux-gnu.

Ok for trunk?

Thanks,
Kyrill

2016-12-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     * tree-ssa-address.c (gen_addr_rtx): Use simplify_gen_binary to add
     *addr to act_elem.

2016-12-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     * gcc.dg/20161219.c: New test.

Comments

Richard Biener Dec. 20, 2016, 5:30 p.m. UTC | #1
On December 20, 2016 5:01:19 PM GMT+01:00, Kyrill Tkachov <kyrylo.tkachov@foss.arm.com> wrote:
>Hi all,
>
>The testcase in this patch generates bogus assembly for arm with -O1
>-mfloat-abi=soft:
>        strd    r4, [#0, r3]
>
>This is due to non-canonical RTL being generated during expansion:
>(set (mem:DI (plus:SI (const_int 0 [0])
>   (reg/f:SI 153)) [0 MEM[symbol: a, index: _26, offset: 0B]+0 S8 A64])
>         (reg:DI 154))
>
>Note the (plus (const_int 0) (reg)). This is being generated in
>gen_addr_rtx in tree-ssa-address.c
>where it creates an explicit PLUS rtx through gen_rtx_PLUS, which
>doesn't try to canonicalise its arguments
>or simplify. The correct thing to do is to use simplify_gen_binary that
>will handle all this properly.

But it has to match up the validity check which passes down exactly the same RTL(?)  Or does this stem from propagation simplifying a MEM after IVOPTs?

>I didn't change the other gen_rtx_PLUS calls in this function as their
>results is later used in XEXP operations
>that seem to rely on a PLUS expression being explicitly produced, but
>this particular call doesn't, so it's okay
>to change it. With this patch the sane assembly is generated:
>         strd    r4, [r3]
>
>Bootstrapped and tested on arm-none-linux-gnueabihf, x86_64,
>aarch64-none-linux-gnu.
>
>Ok for trunk?
>
>Thanks,
>Kyrill
>
>2016-12-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>
>    * tree-ssa-address.c (gen_addr_rtx): Use simplify_gen_binary to add
>     *addr to act_elem.
>
>2016-12-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>
>     * gcc.dg/20161219.c: New test.
Kyrill Tkachov Dec. 21, 2016, 9:40 a.m. UTC | #2
On 20/12/16 17:30, Richard Biener wrote:
> On December 20, 2016 5:01:19 PM GMT+01:00, Kyrill Tkachov <kyrylo.tkachov@foss.arm.com> wrote:
>> Hi all,
>>
>> The testcase in this patch generates bogus assembly for arm with -O1
>> -mfloat-abi=soft:
>>         strd    r4, [#0, r3]
>>
>> This is due to non-canonical RTL being generated during expansion:
>> (set (mem:DI (plus:SI (const_int 0 [0])
>>    (reg/f:SI 153)) [0 MEM[symbol: a, index: _26, offset: 0B]+0 S8 A64])
>>          (reg:DI 154))
>>
>> Note the (plus (const_int 0) (reg)). This is being generated in
>> gen_addr_rtx in tree-ssa-address.c
>> where it creates an explicit PLUS rtx through gen_rtx_PLUS, which
>> doesn't try to canonicalise its arguments
>> or simplify. The correct thing to do is to use simplify_gen_binary that
>> will handle all this properly.
> But it has to match up the validity check which passes down exactly the same RTL(?)  Or does this stem from propagation simplifying a MEM after IVOPTs?

You mean TARGET_LEGITIMATE_ADDRESS_P? Yes, it gets passed on to that, but the arm implementation of that
doesn't try to handle non-canonical RTL (plus (const0_rtx) (reg) is not canonical).
Or do you mean some other check?

Thanks,
Kyrill

>> I didn't change the other gen_rtx_PLUS calls in this function as their
>> results is later used in XEXP operations
>> that seem to rely on a PLUS expression being explicitly produced, but
>> this particular call doesn't, so it's okay
>> to change it. With this patch the sane assembly is generated:
>>          strd    r4, [r3]
>>
>> Bootstrapped and tested on arm-none-linux-gnueabihf, x86_64,
>> aarch64-none-linux-gnu.
>>
>> Ok for trunk?
>>
>> Thanks,
>> Kyrill
>>
>> 2016-12-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>
>>     * tree-ssa-address.c (gen_addr_rtx): Use simplify_gen_binary to add
>>      *addr to act_elem.
>>
>> 2016-12-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>
>>      * gcc.dg/20161219.c: New test.
>
Richard Biener Jan. 4, 2017, 2:19 p.m. UTC | #3
On Wed, Dec 21, 2016 at 10:40 AM, Kyrill Tkachov
<kyrylo.tkachov@foss.arm.com> wrote:
>
> On 20/12/16 17:30, Richard Biener wrote:
>>
>> On December 20, 2016 5:01:19 PM GMT+01:00, Kyrill Tkachov
>> <kyrylo.tkachov@foss.arm.com> wrote:
>>>
>>> Hi all,
>>>
>>> The testcase in this patch generates bogus assembly for arm with -O1
>>> -mfloat-abi=soft:
>>>         strd    r4, [#0, r3]
>>>
>>> This is due to non-canonical RTL being generated during expansion:
>>> (set (mem:DI (plus:SI (const_int 0 [0])
>>>    (reg/f:SI 153)) [0 MEM[symbol: a, index: _26, offset: 0B]+0 S8 A64])
>>>          (reg:DI 154))
>>>
>>> Note the (plus (const_int 0) (reg)). This is being generated in
>>> gen_addr_rtx in tree-ssa-address.c
>>> where it creates an explicit PLUS rtx through gen_rtx_PLUS, which
>>> doesn't try to canonicalise its arguments
>>> or simplify. The correct thing to do is to use simplify_gen_binary that
>>> will handle all this properly.
>>
>> But it has to match up the validity check which passes down exactly the
>> same RTL(?)  Or does this stem from propagation simplifying a MEM after
>> IVOPTs?
>
>
> You mean TARGET_LEGITIMATE_ADDRESS_P? Yes, it gets passed on to that, but
> the arm implementation of that
> doesn't try to handle non-canonical RTL (plus (const0_rtx) (reg) is not
> canonical).
> Or do you mean some other check?

Ok, now looking at the actual patch and the code in question.  For your testcase
it happens that symbol == const0_rtx?  In this case please amend the
if (symbol) check like we do for the base, thus

   if (symbol && symbol != const0_rtx)

Richard.

> Thanks,
> Kyrill
>
>
>>> I didn't change the other gen_rtx_PLUS calls in this function as their
>>> results is later used in XEXP operations
>>> that seem to rely on a PLUS expression being explicitly produced, but
>>> this particular call doesn't, so it's okay
>>> to change it. With this patch the sane assembly is generated:
>>>          strd    r4, [r3]
>>>
>>> Bootstrapped and tested on arm-none-linux-gnueabihf, x86_64,
>>> aarch64-none-linux-gnu.
>>>
>>> Ok for trunk?
>>>
>>> Thanks,
>>> Kyrill
>>>
>>> 2016-12-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>>
>>>     * tree-ssa-address.c (gen_addr_rtx): Use simplify_gen_binary to add
>>>      *addr to act_elem.
>>>
>>> 2016-12-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>>
>>>      * gcc.dg/20161219.c: New test.
>>
>>
>
Kyrill Tkachov Jan. 4, 2017, 3:07 p.m. UTC | #4
On 04/01/17 14:19, Richard Biener wrote:
> On Wed, Dec 21, 2016 at 10:40 AM, Kyrill Tkachov
> <kyrylo.tkachov@foss.arm.com> wrote:
>> On 20/12/16 17:30, Richard Biener wrote:
>>> On December 20, 2016 5:01:19 PM GMT+01:00, Kyrill Tkachov
>>> <kyrylo.tkachov@foss.arm.com> wrote:
>>>> Hi all,
>>>>
>>>> The testcase in this patch generates bogus assembly for arm with -O1
>>>> -mfloat-abi=soft:
>>>>          strd    r4, [#0, r3]
>>>>
>>>> This is due to non-canonical RTL being generated during expansion:
>>>> (set (mem:DI (plus:SI (const_int 0 [0])
>>>>     (reg/f:SI 153)) [0 MEM[symbol: a, index: _26, offset: 0B]+0 S8 A64])
>>>>           (reg:DI 154))
>>>>
>>>> Note the (plus (const_int 0) (reg)). This is being generated in
>>>> gen_addr_rtx in tree-ssa-address.c
>>>> where it creates an explicit PLUS rtx through gen_rtx_PLUS, which
>>>> doesn't try to canonicalise its arguments
>>>> or simplify. The correct thing to do is to use simplify_gen_binary that
>>>> will handle all this properly.
>>> But it has to match up the validity check which passes down exactly the
>>> same RTL(?)  Or does this stem from propagation simplifying a MEM after
>>> IVOPTs?
>>
>> You mean TARGET_LEGITIMATE_ADDRESS_P? Yes, it gets passed on to that, but
>> the arm implementation of that
>> doesn't try to handle non-canonical RTL (plus (const0_rtx) (reg) is not
>> canonical).
>> Or do you mean some other check?
> Ok, now looking at the actual patch and the code in question.  For your testcase
> it happens that symbol == const0_rtx?  In this case please amend the
> if (symbol) check like we do for the base, thus
>
>     if (symbol && symbol != const0_rtx)

No, symbol is not const0_rtx (it's just a symbol_ref).
index is const0_rtx and so gets assigned to *addr at the beginning of the function.
base and step are NULL_RTX.
So at the time of the check:
        if (*addr)
          *addr = gen_rtx_PLUS (address_mode, *addr, act_elem);
        else
          *addr = act_elem;

*addr is const0_rtx. Do you want to amend that check to:
     if (*addr && *addr != const0_rtx) ?

I haven't looked where the const0_rtx index comes from, so I don't know if it
could have other CONST_INT values that may cause trouble.

Kyrill

> Richard.
>
>> Thanks,
>> Kyrill
>>
>>
>>>> I didn't change the other gen_rtx_PLUS calls in this function as their
>>>> results is later used in XEXP operations
>>>> that seem to rely on a PLUS expression being explicitly produced, but
>>>> this particular call doesn't, so it's okay
>>>> to change it. With this patch the sane assembly is generated:
>>>>           strd    r4, [r3]
>>>>
>>>> Bootstrapped and tested on arm-none-linux-gnueabihf, x86_64,
>>>> aarch64-none-linux-gnu.
>>>>
>>>> Ok for trunk?
>>>>
>>>> Thanks,
>>>> Kyrill
>>>>
>>>> 2016-12-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>>>
>>>>      * tree-ssa-address.c (gen_addr_rtx): Use simplify_gen_binary to add
>>>>       *addr to act_elem.
>>>>
>>>> 2016-12-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>>>
>>>>       * gcc.dg/20161219.c: New test.
>>>
Richard Biener Jan. 5, 2017, 12:01 p.m. UTC | #5
On Wed, Jan 4, 2017 at 4:07 PM, Kyrill Tkachov
<kyrylo.tkachov@foss.arm.com> wrote:
>
> On 04/01/17 14:19, Richard Biener wrote:
>>
>> On Wed, Dec 21, 2016 at 10:40 AM, Kyrill Tkachov
>> <kyrylo.tkachov@foss.arm.com> wrote:
>>>
>>> On 20/12/16 17:30, Richard Biener wrote:
>>>>
>>>> On December 20, 2016 5:01:19 PM GMT+01:00, Kyrill Tkachov
>>>> <kyrylo.tkachov@foss.arm.com> wrote:
>>>>>
>>>>> Hi all,
>>>>>
>>>>> The testcase in this patch generates bogus assembly for arm with -O1
>>>>> -mfloat-abi=soft:
>>>>>          strd    r4, [#0, r3]
>>>>>
>>>>> This is due to non-canonical RTL being generated during expansion:
>>>>> (set (mem:DI (plus:SI (const_int 0 [0])
>>>>>     (reg/f:SI 153)) [0 MEM[symbol: a, index: _26, offset: 0B]+0 S8
>>>>> A64])
>>>>>           (reg:DI 154))
>>>>>
>>>>> Note the (plus (const_int 0) (reg)). This is being generated in
>>>>> gen_addr_rtx in tree-ssa-address.c
>>>>> where it creates an explicit PLUS rtx through gen_rtx_PLUS, which
>>>>> doesn't try to canonicalise its arguments
>>>>> or simplify. The correct thing to do is to use simplify_gen_binary that
>>>>> will handle all this properly.
>>>>
>>>> But it has to match up the validity check which passes down exactly the
>>>> same RTL(?)  Or does this stem from propagation simplifying a MEM after
>>>> IVOPTs?
>>>
>>>
>>> You mean TARGET_LEGITIMATE_ADDRESS_P? Yes, it gets passed on to that, but
>>> the arm implementation of that
>>> doesn't try to handle non-canonical RTL (plus (const0_rtx) (reg) is not
>>> canonical).
>>> Or do you mean some other check?
>>
>> Ok, now looking at the actual patch and the code in question.  For your
>> testcase
>> it happens that symbol == const0_rtx?  In this case please amend the
>> if (symbol) check like we do for the base, thus
>>
>>     if (symbol && symbol != const0_rtx)
>
>
> No, symbol is not const0_rtx (it's just a symbol_ref).
> index is const0_rtx and so gets assigned to *addr at the beginning of the
> function.
> base and step are NULL_RTX.
> So at the time of the check:
>        if (*addr)
>          *addr = gen_rtx_PLUS (address_mode, *addr, act_elem);
>        else
>          *addr = act_elem;
>
> *addr is const0_rtx. Do you want to amend that check to:
>     if (*addr && *addr != const0_rtx) ?

Hmm, I guess given the if (step) in if (index) *addr can end up being
a not simplified mult.  So instead do

   if (index && index != const0_rtx)

> I haven't looked where the const0_rtx index comes from, so I don't know if
> it
> could have other CONST_INT values that may cause trouble.

Usually this happens when constant folding / propagation happens after
IVOPTs generates the TARGET_MEM_REF.  We do have some canonicalization
foldings for TMR, see maybe_fold_tmr, but that should have made index NULL
if it was constant...  So maybe we fail to fold a stmt at some point.

Btw, I fail to see the bogus asm with my arm-non-eabi cross with -O
-mfloat-abi=soft
so I can't tell how the TMR arrives at RTL expansion.

Richard.

> Kyrill
>
>
>> Richard.
>>
>>> Thanks,
>>> Kyrill
>>>
>>>
>>>>> I didn't change the other gen_rtx_PLUS calls in this function as their
>>>>> results is later used in XEXP operations
>>>>> that seem to rely on a PLUS expression being explicitly produced, but
>>>>> this particular call doesn't, so it's okay
>>>>> to change it. With this patch the sane assembly is generated:
>>>>>           strd    r4, [r3]
>>>>>
>>>>> Bootstrapped and tested on arm-none-linux-gnueabihf, x86_64,
>>>>> aarch64-none-linux-gnu.
>>>>>
>>>>> Ok for trunk?
>>>>>
>>>>> Thanks,
>>>>> Kyrill
>>>>>
>>>>> 2016-12-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>>>>
>>>>>      * tree-ssa-address.c (gen_addr_rtx): Use simplify_gen_binary to
>>>>> add
>>>>>       *addr to act_elem.
>>>>>
>>>>> 2016-12-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>>>>
>>>>>       * gcc.dg/20161219.c: New test.
>>>>
>>>>
>
Kyrill Tkachov Jan. 5, 2017, 12:09 p.m. UTC | #6
On 05/01/17 12:01, Richard Biener wrote:
> On Wed, Jan 4, 2017 at 4:07 PM, Kyrill Tkachov
> <kyrylo.tkachov@foss.arm.com> wrote:
>> On 04/01/17 14:19, Richard Biener wrote:
>>> On Wed, Dec 21, 2016 at 10:40 AM, Kyrill Tkachov
>>> <kyrylo.tkachov@foss.arm.com> wrote:
>>>> On 20/12/16 17:30, Richard Biener wrote:
>>>>> On December 20, 2016 5:01:19 PM GMT+01:00, Kyrill Tkachov
>>>>> <kyrylo.tkachov@foss.arm.com> wrote:
>>>>>> Hi all,
>>>>>>
>>>>>> The testcase in this patch generates bogus assembly for arm with -O1
>>>>>> -mfloat-abi=soft:
>>>>>>           strd    r4, [#0, r3]
>>>>>>
>>>>>> This is due to non-canonical RTL being generated during expansion:
>>>>>> (set (mem:DI (plus:SI (const_int 0 [0])
>>>>>>      (reg/f:SI 153)) [0 MEM[symbol: a, index: _26, offset: 0B]+0 S8
>>>>>> A64])
>>>>>>            (reg:DI 154))
>>>>>>
>>>>>> Note the (plus (const_int 0) (reg)). This is being generated in
>>>>>> gen_addr_rtx in tree-ssa-address.c
>>>>>> where it creates an explicit PLUS rtx through gen_rtx_PLUS, which
>>>>>> doesn't try to canonicalise its arguments
>>>>>> or simplify. The correct thing to do is to use simplify_gen_binary that
>>>>>> will handle all this properly.
>>>>> But it has to match up the validity check which passes down exactly the
>>>>> same RTL(?)  Or does this stem from propagation simplifying a MEM after
>>>>> IVOPTs?
>>>>
>>>> You mean TARGET_LEGITIMATE_ADDRESS_P? Yes, it gets passed on to that, but
>>>> the arm implementation of that
>>>> doesn't try to handle non-canonical RTL (plus (const0_rtx) (reg) is not
>>>> canonical).
>>>> Or do you mean some other check?
>>> Ok, now looking at the actual patch and the code in question.  For your
>>> testcase
>>> it happens that symbol == const0_rtx?  In this case please amend the
>>> if (symbol) check like we do for the base, thus
>>>
>>>      if (symbol && symbol != const0_rtx)
>>
>> No, symbol is not const0_rtx (it's just a symbol_ref).
>> index is const0_rtx and so gets assigned to *addr at the beginning of the
>> function.
>> base and step are NULL_RTX.
>> So at the time of the check:
>>         if (*addr)
>>           *addr = gen_rtx_PLUS (address_mode, *addr, act_elem);
>>         else
>>           *addr = act_elem;
>>
>> *addr is const0_rtx. Do you want to amend that check to:
>>      if (*addr && *addr != const0_rtx) ?
> Hmm, I guess given the if (step) in if (index) *addr can end up being
> a not simplified mult.  So instead do
>
>     if (index && index != const0_rtx)

That works, I'll test a patch for this.

>> I haven't looked where the const0_rtx index comes from, so I don't know if
>> it
>> could have other CONST_INT values that may cause trouble.
> Usually this happens when constant folding / propagation happens after
> IVOPTs generates the TARGET_MEM_REF.  We do have some canonicalization
> foldings for TMR, see maybe_fold_tmr, but that should have made index NULL
> if it was constant...  So maybe we fail to fold a stmt at some point.
>
> Btw, I fail to see the bogus asm with my arm-non-eabi cross with -O
> -mfloat-abi=soft
> so I can't tell how the TMR arrives at RTL expansion.

You'll also want to specify -marm (this doesn't trigger on Thumb) and perhaps -march=armv7-a.

Thanks,
Kyrill

> Richard.
>
>> Kyrill
>>
>>
>>> Richard.
>>>
>>>> Thanks,
>>>> Kyrill
>>>>
>>>>
>>>>>> I didn't change the other gen_rtx_PLUS calls in this function as their
>>>>>> results is later used in XEXP operations
>>>>>> that seem to rely on a PLUS expression being explicitly produced, but
>>>>>> this particular call doesn't, so it's okay
>>>>>> to change it. With this patch the sane assembly is generated:
>>>>>>            strd    r4, [r3]
>>>>>>
>>>>>> Bootstrapped and tested on arm-none-linux-gnueabihf, x86_64,
>>>>>> aarch64-none-linux-gnu.
>>>>>>
>>>>>> Ok for trunk?
>>>>>>
>>>>>> Thanks,
>>>>>> Kyrill
>>>>>>
>>>>>> 2016-12-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>>>>>
>>>>>>       * tree-ssa-address.c (gen_addr_rtx): Use simplify_gen_binary to
>>>>>> add
>>>>>>        *addr to act_elem.
>>>>>>
>>>>>> 2016-12-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>>>>>
>>>>>>        * gcc.dg/20161219.c: New test.
>>>>>
diff mbox

Patch

diff --git a/gcc/testsuite/gcc.dg/20161219.c b/gcc/testsuite/gcc.dg/20161219.c
new file mode 100644
index 0000000000000000000000000000000000000000..93ea8d2364d9ab54704a84e6c0bff0427df82db8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/20161219.c
@@ -0,0 +1,30 @@ 
+/* { dg-do assemble } */
+/* { dg-options "-O1 -w" } */
+
+static long long a[9];
+int b, c, d, e, g;
+
+static int
+fn1 (int *p1)
+{
+  b = 1;
+  for (; b >= 0; b--)
+    {
+      d = 0;
+      for (;; d++)
+	{
+	  e && (a[d] = 0);
+	  if (*p1)
+	    break;
+	  c = (int) a;
+	}
+    }
+  return 0;
+}
+
+int
+main ()
+{
+  int f = fn1 ((int *) f);
+  return f;
+}
diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c
index a53ade0600d01c9d48f6c789b78fd42d7a06a95b..0c7c5902cebb0196c8e27f4eba45ce176cc3f0a5 100644
--- a/gcc/tree-ssa-address.c
+++ b/gcc/tree-ssa-address.c
@@ -154,7 +154,7 @@  gen_addr_rtx (machine_mode address_mode,
 	}
 
       if (*addr)
-	*addr = gen_rtx_PLUS (address_mode, *addr, act_elem);
+	*addr = simplify_gen_binary (PLUS, address_mode, *addr, act_elem);
       else
 	*addr = act_elem;
     }