Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2019-03

Vectorisation, optimisation etc.

9 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

J. Gareth Moreton

Hi everyone,
So with the false start that was pure inline assembly, I like to talk about how to move forward with FPC, or at least with x86_64.  To Florian in particular, what is the current state of the compiler's support of the 256-bit YMM registers? I remember you telling me not to enable support of them when I was implementing vectorcall, since you were still working on it.  I ask because if that was my next big optimisation of x86_64, it would be vectorisation of things like for-loops and making use of FMA instructions if allowed, for example.
One thing to note with vectorcall is that it's not just for floating-point parameters, but it can pass integer-type vectors too.  I'll have to double-check my code, but it may require a bit of metadata for vectorcall procedures so it uses the correct move command ((V)MOVAPS = single, (V)MOVAPD = double, (V)MOVDQA = integer) - using the wrong one invokes a notable performance penalty.
For something more cross-platform, I think pure functions are still on the books, but like with a few things, including some node-level optimisations, the XML node dump would need merging so I and others can more easily study the generated nodes for debugging and development purposes. By the way, is there any progress about the whole register virtualisation thing? The part where virtual registers are changed into real ones occurs before the peephole optimizer, while moving it to after that point will allow for better register usage, but when I blindly tried it myself I just got a load of segmentation faults, so it's presumably not that straightforward, although when programming my prototype Deep Optimizer (utilises assembly-level data flow analysis), I was able to remove required registers completely, but because it was after virtual registers were changed to real ones, said registers were already allocated on the stack.

Gareth aka. Kit

Reply by email

Ben Grasset
to J. Gareth Moreton

On Wed, Mar 27, 2019 at 11:32 AM J. Gareth Moreton <

Show quoted text 5 lines
wrote: So with the false start that was pure inline assembly, I like to talk about how to move forward with FPC, or at least with x86_64.

It occurred to me today, aren't you the person who fixed the -Sv compiler flag so that it actually works? I'd say expansion on that functionality would be more widely useful than just about anything else I can think of with regards to optimization (because it's so easy to use, and yet so powerful.)

Maybe start with making it fully use AVX instructions for the operations? IIRC, currently, even if you use the AVX or AVX2 compiler flags, it will always generate stuff like this:

vmovups (%rdx),%xmm0
addps (%r8),%xmm0
vmovups %xmm0,(%rax)

rather than using vaddps.

From there you could make it support arrays larger than 4 elements,

e.t.c....

Reply by email

Jeppe Johansen
to Ben Grasset

That can't happen or won't benefit much, before the compiler supports super-natual alignments. So there's a deeper level of support needed.

And personally I don't think that's the right long term direction. It takes a long time to develop and maintain this stuff and you never know what the market will look like in 10 years.
ARM has SVE, and RISC-V has the upcoming vector extension which will move far away from the traditional SIMD stuff.

Compiler support for block vectorization has rarely paid off really well given the amount of work that needs to go into it. So maybe it's better to wait for the next iteration :)

Ben Grasset wrote 25 lines
On Wed, Mar 27, 2019 at 11:32 AM J. Gareth Moreton < > wrote: So with the false start that was pure inline assembly, I like to talk about how to move forward with FPC, or at least with x86_64. It occurred to me today, aren't you the person who fixed the -Sv compiler flag so that it actually works? I'd say expansion on that functionality would be more widely useful than just about anything else I can think of with regards to optimization (because it's so easy to use, and yet so powerful.) Maybe start with making it fully use AVX instructions for the operations? IIRC, currently, even if you use the AVX or AVX2 compiler flags, it will always generate stuff like this: vmovups(%rdx),%xmm0 addps(%r8),%xmm0 vmovups%xmm0,(%rax) rather than using vaddps. From there you could make it support arrays larger than 4 elements, e.t.c....

Reply by email

Ben Grasset
PM Jeppe Johansen wrote
That can't happen or won't benefit much, before the compiler supports super-natual alignments. So there's a deeper level of support needed.

I'm fairly confident the existing functionality could be improved upon in a useful way. Gareth has already done so in the past.

PM Jeppe Johansen wrote 6 lines
And personally I don't think that's the right long term direction. It takes a long time to develop and maintain this stuff and you never know what the market will look like in 10 years. ARM has SVE, and RISC-V has the upcoming vector extension which will move far away from the traditional SIMD stuff.

I sincerely doubt I will be using a RISC-V based desktop PC in 10 years. Also nobody said -Sv could not also be extended to stuff such as ARM Neon at some point down the line if someone was up to it. One thing at a time though.

PM Jeppe Johansen wrote
Compiler support for block vectorization has rarely paid off really well given the amount of work that needs to go into it. So maybe it's better to wait for the next iteration :)

It very objectively pays off in every compiler that has it. I don't think "it's too hard" is a good excuse. I made my previous comment because it seems like Gareth if anyone specifically does *not* think it is too hard.

Reply by email

Jeppe Johansen
Ben Grasset wrote 9 lines
On Sat, Apr 6, 2019 at 5:27 PM Jeppe Johansen < > wrote: That can't happen or won't benefit much, before the compiler supports super-natual alignments. So there's a deeper level of support needed. I'm fairly confident the existing functionality could be improved upon in a useful way. Gareth has already done so in the past.

Perhaps but it's a nightmare in so many places to satisfy requirements for potential uses. Ideally the programmer would specify minimum alignment requirements per type

Show quoted text 13 lines
 On Sat, Apr 6, 2019 at 5:27 PM Jeppe Johansen < > wrote: And personally I don't think that's the right long term direction. It takes a long time to develop and maintain this stuff and you never know what the market will look like in 10 years. ARM has SVE, and RISC-V has the upcoming vector extension which will move far away from the traditional SIMD stuff. I sincerely doubt I will be using a RISC-V based desktop PC in 10 years. Also nobody said -Sv could not also be extended to stuff such as ARM Neon at some point down the line if someone was up to it. One thing at a time though.

It's too hard to say, and the RISC-V foundation has made really bad decisions that will prevent them from getting a good start.

But you will not find anyone who don't think vector extensions are better for software than SIMD. ARM SVE and RISC-V Vector extensions are true vector extensions, whereas the  SSE, AVX, NEON, Advanced SIMD, etc are packed SIMD extensions requiring a ton of hoops and jumps to use in real block vectorized code

Show quoted text 11 lines
On Sat, Apr 6, 2019 at 5:27 PM Jeppe Johansen < > wrote: Compiler support for block vectorization has rarely paid off really well given the amount of work that needs to go into it. So maybe it's better to wait for the next iteration :) It very objectively pays off in every compiler that has it. I don't think "it's too hard" is a good excuse. I made my previous comment because it seems like Gareth if anyone specifically does *not* think it is too hard.

Do you have any quantifiable data to point at here?

Reply by email

J. Gareth Moreton

I was the one that fixed -Sv.  That's me!

Vectorisation is a little tricky, but not impossible, and I like a challenge!
There are options for unaligned memory, although aligned memory is faster, and can be forced if necessary.
The AVX compiler option generating SSE instructions is a bit faulty though... that shouldn't happen.  Lots of things to do!

Gareth aka. Kit

Reply by email

Ben Grasset
to Jeppe Johansen: Perhaps but it's a nightmare in so many places to satisfy requirements for potential…
PM Jeppe Johansen wrote
Perhaps but it's a nightmare in so many places to satisfy requirements for potential uses. Ideally the programmer would specify minimum alignment requirements per type

Actively worrying about alignment in the vast majority of cases is about the least ideal thing I can imagine. As far as I can gather the whole point of the -Sv flag is that it's just a magic thing that makes it possible to do SomeArray + SomeArray or SomeArray * SomeArray in a highly performant way. (Which it does, *mostly*, right now.)

PM Jeppe Johansen wrote 6 lines
But you will not find anyone who don't think vector extensions are better for software than SIMD. ARM SVE and RISC-V Vector extensions are true vector extensions, whereas the SSE, AVX, NEON, Advanced SIMD, etc are packed SIMD extensions requiring a ton of hoops and jumps to use in real block vectorized code

I don't disagree with your general point, however, you seem to be making a (strange IMO) assumption that the *majority* (or even close to it) of people who care about Free Pascal in any way whatsoever are using ARM or RISC-V machines as their "daily drivers", *right now.*

If you honestly can't see why that blatantly is not the case, I'm not sure what to tell you. If that *was* anywhere close to the case, do you think there'd still be so many people out there rambling on about how great Delphi 7 was and how they think generics make their code slower, and other such nonsense? I think not.

PM Jeppe Johansen wrote
Do you have any quantifiable data to point at here?

Well, uh, presumably you've heard of LLVM? There's a reason every big compiler project implemented with it has first-class language bindings to its intrinsics, and that reason is not "just for fun."

Putting LLVM aside even, at the highest possible settings GCC / G++ still runs circles around FPC for reasons that in many cases are *not* related to it doing really crazy optimizations, but just to it being able to properly auto-vectorize code in general.

Even the fact that FPC will not / cannot inline "procedure variable" calls is far from great. Just that alone would result in enormous speedups in a huge amount of places...

Reply by email

Jonas Maebe
to Ben Grasset
Ben Grasset wrote
Even the fact that FPC will not / cannot inline "procedure variable" calls is far from great. Just that alone would result in enormous speedups in a huge amount of places...

I'm sure there is code where that is the case, but I very much doubt this particular functionality would help with most code out there. E.g., if I enable FPC's whole-program devirtualisation on the compiler so that it tries to turn as many virtual calls into direct calls, and then feed the result to LLVM (so it can inline all of those previously indirect calls), the result is barely faster than the original code (it is quite a bit smaller though).

This is in spite of the fact that e.g. all of the originally virtual AfterConstruction and BeforeDestruction calls get removed completely (since they're empty), and quite a bit of the code generator, register allocator and node tree methods also get devirtualised.

Again, I'm sure there are programs where it does make a big difference, but I don't think the suggestion that this would help in "a huge amount of places" is correct in the general case.

Jonas

Reply by email

J. Gareth Moreton

I would consider a size reduction a
success if it doesn't impact performance,
although higher speed is always nice.

A lot of my research is currently waiting
on the XML node dump patch, since
vectorisation would have to be done at the
node level to be most efficient. Also, my
optimiser overhaul is still pending, so I
can't really touch the peephole optimiser
until it is either accepted (if it still
merges!) or rejected.

Gareth aka. Kit

On Sun 07/04/19 10:05 , Jonas Maebe
sent:

Show quoted text 5 lines
On 2019-04-07 03:25, Ben Grasset wrote: > Even the fact that FPC will not /

cannot inline

"procedure variable" > calls is far from great. Just that

alone would

Show quoted text 6 lines
result in enormous > speedups in a huge amount of places... I'm sure there is code where that is the

case, but I very much doubt

this particular functionality would help

with most code out there. E.g.,

if I enable FPC's whole-program

devirtualisation on the compiler so that

it tries to turn as many virtual calls

into direct calls, and then feed

the result to LLVM (so it can inline all

of those previously indirect

calls), the result is barely faster than

the original code (it is quite

Show quoted text 6 lines
a bit smaller though). This is in spite of the fact that e.g.

all of the originally virtual

AfterConstruction and BeforeDestruction

calls get removed completely

(since they're empty), and quite a bit

of the code generator, register

allocator and node tree methods also get

devirtualised.

Again, I'm sure there are programs where

it does make a big difference,

but I don't think the suggestion that

this would help in "a huge

amount of places" is correct in the general

case.

Show quoted text 8 lines
Jonas

Reply by email