[RFC] Implementing detection of saturation and rounding arithmetic

Andre Simoes Dias Vieira andre.simoesdiasvieira@arm.com
Tue Jun 8 15:00:40 GMT 2021


Hi Bin,

Thank you for the reply, I have some questions, see below.

On 07/06/2021 12:28, Bin.Cheng wrote:
> On Fri, Jun 4, 2021 at 12:35 AM Andre Vieira (lists) via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
>
> Hi Andre,
> I didn't look into the details of the IV sharing RFC.  It seems to me
> costing outside uses is trying to generate better code for later code
> (epilogue loop here).  The only problem is IVOPTs doesn't know that
> the outside use is not in the final form - which will be transformed
> by IVOPTs again.
>
> I think this example is not good at describing your problem because it
> shows exactly that considering outside use results in better code,
> compared to the other two approaches.
I don't quite understand what you are saying here :( What do you mean by 
final form? It seems to me that costing uses inside and outside loop the 
same way is wrong because calculating the IV inside the loop has to be 
done every iteration, whereas if you can resolve it to a single update 
(without an IV) then you can sink it outside the loop. This is why I 
think this example shows why we need to cost these uses differently.
>> 2) Is there a cleaner way to generate the optimal 'post-increment' use
>> for the outside-use variable? I first thought the position in the
>> candidate might be something I could use or even the var_at_stmt
>> functionality, but the outside IV has the actual increment of the
>> variable as it's use, rather than the outside uses. This is this RFC's
>> main weakness I find.
> To answer why IVOPTs behaves like this w/o your two patches.  The main
> problem is the point IVOPTs rewrites outside use IV - I don't remember
> the exact point - but looks like at the end of loop while before
> incrementing instruction of main IV.  It's a known issue that outside
> use should be costed/re-written on the exit edge along which its value
> flows out of loop.  I had a patch a long time ago but discarded it,
> because it didn't bring obvious improvement and is complicated in case
> of multi-exit edges.
Yeah I haven't looked at multi-exit edges and I understand that 
complicates things. But for now we could disable the special casing of 
outside uses when dealing with multi-exit loops and keep the current 
behavior.
>
> But in general, I am less convinced that any of the two patches is the
> right direction solving IV sharing issue between vectorized loop and
> epilogue loop.  I would need to read the previous RFC before giving
> further comments though.

The previous RFC still has a lot of unanswered questions too, but 
regardless of that, take the following (non-vectorizer) example:

#include <arm_neon.h>
#include <arm_sve.h>

void bar (char  * __restrict__ a, char * __restrict__ b, char * 
__restrict__ c, unsigned long long n)
{
     svbool_t all_true = svptrue_b8 ();
   unsigned long long i = 0;
     for (; i < (n & ~(svcntb() - 1)); i += svcntb()) {
       svuint8_t va = svld1 (all_true, (uint8_t*)a);
       svuint8_t vb = svld1 (all_true, (uint8_t*)b);
       svst1 (all_true, (uint8_t *)c, svadd_z (all_true, va,vb));
       a += svcntb();
       b += svcntb();
       c += svcntb();
   }
   svbool_t pred;
   for (; i < (n); i += svcntb()) {
       pred = svwhilelt_b8 (i, n);
       svuint8_t va = svld1 (pred, (uint8_t*)a);
       svuint8_t vb = svld1 (pred, (uint8_t*)b);
       svst1 (pred, (uint8_t *)c, svadd_z (pred, va,vb));
       a += svcntb();
       b += svcntb();
       c += svcntb();
   }


Current IVOPTs will use 4 iterators for the first loop, when it could do 
with just 1. In fact, if you use my patches it will create just a single 
IV and sink the uses and it is then able to merge them with loads & 
stores of the next loop.

I am not saying setting outside costs to 0 is the right thing to do by 
the way. It is absolutely not! It will break cost considerations for 
other cases. Like I said above I've been playing around with using 
'!use->outside' as a multiplier for the cost. Unfortunately it won't 
help with the case above, because this seems to choose 'infinite_cost' 
because the candidate IV has a lower precision than the use IV. I don't 
quite understand yet how candidates are created, but something I'm going 
to try to look at. Just wanted to show this as an example of how IVOPTs 
would not improve code with multiple loops that don't involve the 
vectorizer.

BR,
Andre


>
> Thanks,
> bin


More information about the Gcc-patches mailing list