This is an archive of the discontinued LLVM Phabricator instance.

[llvm-exegesis] parallel snippet generator: avoid Read-After-Write pitfail for instrs w/ tied variables
ClosedPublic

Authored by lebedev.ri on Dec 4 2022, 4:42 PM.

Details

Summary

As it is being discussed in https://github.com/llvm/llvm-project/issues/59325,
at least for the instructions with tied variables,
when trying to parallelize the instructions,
register selection is rather bad, and may either
use a register which we have used for def,
or vice versa.

That introduces serialization, and leads to
overly pessimistic inverse throughput measurement.

The new implementation avoids that,

New result:

$ ninja llvm-exegesis && ./bin/llvm-exegesis --mode=inverse_throughput --opcode-name=VFMADD132PDr --max-configs-per-opcode=9182
ninja: no work to do.
Check generated assembly with: /usr/bin/objdump -d /tmp/snippet-4af034.o
---
mode:            inverse_throughput
key:
  instructions:
    - 'VFMADD132PDr XMM3 XMM3 XMM4 XMM8'
    - 'VFMADD132PDr XMM5 XMM5 XMM14 XMM7'
    - 'VFMADD132PDr XMM10 XMM10 XMM11 XMM15'
    - 'VFMADD132PDr XMM13 XMM13 XMM15 XMM15'
    - 'VFMADD132PDr XMM12 XMM12 XMM11 XMM1'
    - 'VFMADD132PDr XMM0 XMM0 XMM6 XMM9'
    - 'VFMADD132PDr XMM2 XMM2 XMM15 XMM11'
  config:          ''
  register_initial_values:
    - 'XMM3=0x0'
    - 'XMM4=0x0'
    - 'XMM8=0x0'
    - 'MXCSR=0x0'
    - 'XMM5=0x0'
    - 'XMM14=0x0'
    - 'XMM7=0x0'
    - 'XMM10=0x0'
    - 'XMM11=0x0'
    - 'XMM15=0x0'
    - 'XMM13=0x0'
    - 'XMM12=0x0'
    - 'XMM1=0x0'
    - 'XMM0=0x0'
    - 'XMM6=0x0'
    - 'XMM9=0x0'
    - 'XMM2=0x0'
cpu_name:        znver3
llvm_triple:     x86_64-unknown-linux-gnu
num_repetitions: 10000
measurements:
  - { key: inverse_throughput, value: 0.6403, per_snippet_value: 4.4821 }
error:           ''
info:            instruction has tied variables, avoiding Read-After-Write issue, picking random def and use registers not aliasing each other, randomizing registers for uses
assembled_snippet: 4883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F1C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F24244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F04244883C4104883EC04C70424801F0000C5F8AE14244883C4044883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F2C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F34244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F3C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F14244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F1C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F3C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F2C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F24244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F0C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F04244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F34244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F0C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F14244883C410C4C2D998D8C4E28998EFC442A198D7C4428198EFC462A198E1C4C2C998C1C4C28198D3C4C2D998D8C4E28998EFC442A198D7C4428198EFC462A198E1C4C2C998C1C4C28198D3C4C2D998D8C4E28998EFC442A198D7C4428198EFC462A198E1C4C2C998C1C4C28198D3C4C2D998D8C4E28998EFC442A198D7C4428198EFC462A198E1C4C2C998C1C4C28198D3C3
...
Check generated assembly with: /usr/bin/objdump -d /tmp/snippet-f05c2f.o
---
mode:            inverse_throughput
key:
  instructions:
    - 'VFMADD132PDr XMM15 XMM15 XMM11 XMM2'
    - 'VFMADD132PDr XMM5 XMM5 XMM11 XMM2'
    - 'VFMADD132PDr XMM14 XMM14 XMM11 XMM2'
    - 'VFMADD132PDr XMM4 XMM4 XMM11 XMM2'
    - 'VFMADD132PDr XMM8 XMM8 XMM11 XMM2'
    - 'VFMADD132PDr XMM3 XMM3 XMM11 XMM2'
    - 'VFMADD132PDr XMM10 XMM10 XMM11 XMM2'
    - 'VFMADD132PDr XMM7 XMM7 XMM11 XMM2'
    - 'VFMADD132PDr XMM13 XMM13 XMM11 XMM2'
    - 'VFMADD132PDr XMM9 XMM9 XMM11 XMM2'
    - 'VFMADD132PDr XMM1 XMM1 XMM11 XMM2'
    - 'VFMADD132PDr XMM6 XMM6 XMM11 XMM2'
    - 'VFMADD132PDr XMM0 XMM0 XMM11 XMM2'
    - 'VFMADD132PDr XMM12 XMM12 XMM11 XMM2'
  config:          ''
  register_initial_values:
    - 'XMM15=0x0'
    - 'XMM11=0x0'
    - 'XMM2=0x0'
    - 'MXCSR=0x0'
    - 'XMM5=0x0'
    - 'XMM14=0x0'
    - 'XMM4=0x0'
    - 'XMM8=0x0'
    - 'XMM3=0x0'
    - 'XMM10=0x0'
    - 'XMM7=0x0'
    - 'XMM13=0x0'
    - 'XMM9=0x0'
    - 'XMM1=0x0'
    - 'XMM6=0x0'
    - 'XMM0=0x0'
    - 'XMM12=0x0'
cpu_name:        znver3
llvm_triple:     x86_64-unknown-linux-gnu
num_repetitions: 10000
measurements:
  - { key: inverse_throughput, value: 0.5312, per_snippet_value: 7.4368 }
error:           ''
info:            instruction has tied variables, avoiding Read-After-Write issue, picking random def and use registers not aliasing each other, one unique register for each use position
assembled_snippet: 4883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F3C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F1C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F14244883C4104883EC04C70424801F0000C5F8AE14244883C4044883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F2C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F34244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F24244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F04244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F1C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F14244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F3C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F2C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F0C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F0C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F34244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F04244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F24244883C410C462A198FAC4E2A198EAC462A198F2C4E2A198E2C462A198C2C4E2A198DAC462A198D2C4E2A198FAC462A198EAC462A198CAC4E2A198CAC4E2A198F2C4E2A198C2C462A198E2C462A198FAC4E2A198EAC462A198F2C4E2A198E2C462A198C2C4E2A198DAC462A198D2C4E2A198FAC462A198EAC462A198CAC4E2A198CAC4E2A198F2C4E2A198C2C462A198E2C462A198FAC4E2A198EAC462A198F2C4E2A198E2C462A198C2C4E2A198DAC462A198D2C4E2A198FAC462A198EAC462A198CAC4E2A198CAC4E2A198F2C4E2A198C2C462A198E2C462A198FAC4E2A198EAC462A198F2C4E2A198E2C462A198C2C4E2A198DAC462A198D2C4E2A198FAC462A198EAC462A198CAC4E2A198CAC4E2A198F2C4E2A198C2C462A198E2C3
...
Check generated assembly with: /usr/bin/objdump -d /tmp/snippet-c32060.o
---
mode:            inverse_throughput
key:
  instructions:
    - 'VFMADD132PDr XMM10 XMM10 XMM6 XMM6'
    - 'VFMADD132PDr XMM8 XMM8 XMM6 XMM6'
    - 'VFMADD132PDr XMM12 XMM12 XMM6 XMM6'
    - 'VFMADD132PDr XMM9 XMM9 XMM6 XMM6'
    - 'VFMADD132PDr XMM7 XMM7 XMM6 XMM6'
    - 'VFMADD132PDr XMM1 XMM1 XMM6 XMM6'
    - 'VFMADD132PDr XMM0 XMM0 XMM6 XMM6'
    - 'VFMADD132PDr XMM5 XMM5 XMM6 XMM6'
    - 'VFMADD132PDr XMM11 XMM11 XMM6 XMM6'
    - 'VFMADD132PDr XMM2 XMM2 XMM6 XMM6'
    - 'VFMADD132PDr XMM15 XMM15 XMM6 XMM6'
    - 'VFMADD132PDr XMM3 XMM3 XMM6 XMM6'
    - 'VFMADD132PDr XMM14 XMM14 XMM6 XMM6'
    - 'VFMADD132PDr XMM4 XMM4 XMM6 XMM6'
    - 'VFMADD132PDr XMM13 XMM13 XMM6 XMM6'
  config:          ''
  register_initial_values:
    - 'XMM10=0x0'
    - 'XMM6=0x0'
    - 'MXCSR=0x0'
    - 'XMM8=0x0'
    - 'XMM12=0x0'
    - 'XMM9=0x0'
    - 'XMM7=0x0'
    - 'XMM1=0x0'
    - 'XMM0=0x0'
    - 'XMM5=0x0'
    - 'XMM11=0x0'
    - 'XMM2=0x0'
    - 'XMM15=0x0'
    - 'XMM3=0x0'
    - 'XMM14=0x0'
    - 'XMM4=0x0'
    - 'XMM13=0x0'
cpu_name:        znver3
llvm_triple:     x86_64-unknown-linux-gnu
num_repetitions: 10000
measurements:
  - { key: inverse_throughput, value: 0.5311, per_snippet_value: 7.9665 }
error:           ''
info:            instruction has tied variables, avoiding Read-After-Write issue, picking random def and use registers not aliasing each other, reusing the same register for all uses
assembled_snippet: 4883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F14244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F34244883C4104883EC04C70424801F0000C5F8AE14244883C4044883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F04244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F24244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F0C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F3C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F0C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F04244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F2C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F1C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F14244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F3C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F1C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F34244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F24244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F2C244883C410C462C998D6C462C998C6C462C998E6C462C998CEC4E2C998FEC4E2C998CEC4E2C998C6C4E2C998EEC462C998DEC4E2C998D6C462C998FEC4E2C998DEC462C998F6C4E2C998E6C462C998EEC462C998D6C462C998C6C462C998E6C462C998CEC4E2C998FEC4E2C998CEC4E2C998C6C4E2C998EEC462C998DEC4E2C998D6C462C998FEC4E2C998DEC462C998F6C4E2C998E6C462C998EEC462C998D6C462C998C6C462C998E6C462C998CEC4E2C998FEC4E2C998CEC4E2C998C6C4E2C998EEC462C998DEC4E2C998D6C462C998FEC4E2C998DEC462C998F6C4E2C998E6C462C998EEC462C998D6C462C998C6C462C998E6C462C998CEC4E2C998FEC4E2C998CEC4E2C998C6C4E2C998EEC462C998DEC4E2C998D6C462C998FEC4E2C998DEC462C998F6C4E2C998E6C462C998EEC3
...

Diff Detail

Event Timeline

lebedev.ri created this revision.Dec 4 2022, 4:42 PM
Herald added a project: Restricted Project. · View Herald TranscriptDec 4 2022, 4:42 PM
lebedev.ri requested review of this revision.Dec 4 2022, 4:42 PM
lebedev.ri updated this revision to Diff 479952.Dec 4 2022, 4:44 PM

Err, an actual diff.

lebedev.ri updated this revision to Diff 479954.Dec 4 2022, 5:45 PM
lebedev.ri edited the summary of this revision. (Show Details)

Ok, well, re-using the same use register will likely hit zero idioms and such in some cases,
so let's avoid that and look for one more pattern.

lebedev.ri updated this revision to Diff 479955.Dec 4 2022, 5:52 PM

... and actually ensure that in SingleStaticUseRegPerOperand,
the operands actually won't match...

Thanks @lebedev.ri - I've noticed a few minors, but ideally @courbet or @gchatelet need to review this

llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp
115–116

(trivial) Not sure if we need the 'Use' prefix? RegRandomizationStrategy?

141

Keep MSVC happy:

llvm_unreachable("Unknown UseRegRandomizationStrategy enum");
143

(style) Avoid auto

162

(style) Avoid auto

Much better thanks!

The first code snippet from your example is a bit too short for testing FMA throughput. However, if the tool is able to try different code snippets to get a sense of what the median throughput is, then it should be fine.

Thanks @lebedev.ri - I've noticed a few minors, but ideally @courbet or @gchatelet need to review this

Yeah. There are a few changes i had in mind here though.

Much better thanks!

The first code snippet from your example is a bit too short for testing FMA throughput.

This is essentially due to random.
We now avoid picking overlapping defs/uses, so if we happened to pick
some reg for a use, instead of reusing some reg already-used for use
then we can not pick it for a def, and will run out of registers sooner,
thus shortening the sequence. I've certainly noticed this,
but not quite sure if there is anything to do about it yet.

However, if the tool is able to try different code snippets to get a sense of what the median throughput is, then it should be fine.

That is why that strategy now generates those two extra variants with at most one use reg / at most one use reg per operand.

The overall approach sounds good.

FYI, there is an other way to model all this, that we tried at one point: Simply use an SMT solver and generate constraints (LLVM already depends on S3). That was too slow though, so we abandoned it.

llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp
115–116

+1

133

[nit] getDescription ?

139

Are there cases when this is worse than the previous option ? I'm under the impression that we could just always do that.

142–267

Can you refactor this in a separate function ? It would make it clearer what state is only read and what state is modified by the loop.

random thought - how is exegesis handling the SSE PBLENDVB/BLENDVPS/BLENDVPD instructions? They have an explicit dependency on xmm0 as well which might also be causing issues

lebedev.ri updated this revision to Diff 480114.Dec 5 2022, 8:10 AM
lebedev.ri marked 8 inline comments as done.

@RKSimon @courbet thank you for taking a look!
Addressing review notes.

llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp
139

If we only have a single register for all use positions,
then we may unintentionally stumble into zero idioms and such,
which is useful, but not always intended,
I think we should just keep all three choices here.

random thought - how is exegesis handling the SSE PBLENDVB/BLENDVPS/BLENDVPD instructions? They have an explicit dependency on xmm0 as well which might also be causing issues

Please let me know if this is bad, or i'm looking at the wrong instruction:

$ ./bin/llvm-exegesis --mode=inverse_throughput --opcode-name=BLENDVPSrr0 --max-configs-per-opcode=9182
Check generated assembly with: /usr/bin/objdump -d /tmp/snippet-77314f.o
---
mode:            inverse_throughput
key:
  instructions:
    - 'BLENDVPSrr0 XMM1 XMM1 XMM5'
    - 'BLENDVPSrr0 XMM12 XMM12 XMM15'
    - 'BLENDVPSrr0 XMM14 XMM14 XMM9'
    - 'BLENDVPSrr0 XMM3 XMM3 XMM8'
    - 'BLENDVPSrr0 XMM7 XMM7 XMM4'
    - 'BLENDVPSrr0 XMM13 XMM13 XMM6'
    - 'BLENDVPSrr0 XMM10 XMM10 XMM8'
    - 'BLENDVPSrr0 XMM11 XMM11 XMM8'
    - 'BLENDVPSrr0 XMM2 XMM2 XMM8'
  config:          ''
  register_initial_values:
    - 'XMM1=0x0'
    - 'XMM5=0x0'
    - 'XMM0=0x0'
    - 'XMM12=0x0'
    - 'XMM15=0x0'
    - 'XMM14=0x0'
    - 'XMM9=0x0'
    - 'XMM3=0x0'
    - 'XMM8=0x0'
    - 'XMM7=0x0'
    - 'XMM4=0x0'
    - 'XMM13=0x0'
    - 'XMM6=0x0'
    - 'XMM10=0x0'
    - 'XMM11=0x0'
    - 'XMM2=0x0'
cpu_name:        znver3
llvm_triple:     x86_64-unknown-linux-gnu
num_repetitions: 10000
measurements:
  - { key: inverse_throughput, value: 0.5294, per_snippet_value: 4.7646 }
error:           ''
info:            instruction has tied variables, avoiding Read-After-Write issue, picking random def and use registers not aliasing each other, for uses, randomizing registers
assembled_snippet: 4883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F0C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F2C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F04244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F24244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F3C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F34244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F0C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F1C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F04244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F3C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F24244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F2C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F34244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F14244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F1C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F14244883C410660F3814CD66450F3814E766450F3814F166410F3814D8660F3814FC66440F3814EE66450F3814D066450F3814D866410F3814D0660F3814CD66450F3814E766450F3814F166410F3814D8660F3814FC66440F3814EE66450F3814D066450F3814D866410F3814D0660F3814CD66450F3814E766450F3814F166410F3814D8660F3814FC66440F3814EE66450F3814D066450F3814D866410F3814D0660F3814CD66450F3814E766450F3814F166410F3814D8660F3814FC66440F3814EE66450F3814D066450F3814D866410F3814D0C3
...
Check generated assembly with: /usr/bin/objdump -d /tmp/snippet-d0b778.o
---
mode:            inverse_throughput
key:
  instructions:
    - 'BLENDVPSrr0 XMM15 XMM15 XMM9'
    - 'BLENDVPSrr0 XMM6 XMM6 XMM9'
    - 'BLENDVPSrr0 XMM13 XMM13 XMM9'
    - 'BLENDVPSrr0 XMM5 XMM5 XMM9'
    - 'BLENDVPSrr0 XMM11 XMM11 XMM9'
    - 'BLENDVPSrr0 XMM3 XMM3 XMM9'
    - 'BLENDVPSrr0 XMM10 XMM10 XMM9'
    - 'BLENDVPSrr0 XMM12 XMM12 XMM9'
    - 'BLENDVPSrr0 XMM8 XMM8 XMM9'
    - 'BLENDVPSrr0 XMM14 XMM14 XMM9'
    - 'BLENDVPSrr0 XMM1 XMM1 XMM9'
    - 'BLENDVPSrr0 XMM4 XMM4 XMM9'
    - 'BLENDVPSrr0 XMM7 XMM7 XMM9'
    - 'BLENDVPSrr0 XMM2 XMM2 XMM9'
  config:          ''
  register_initial_values:
    - 'XMM15=0x0'
    - 'XMM9=0x0'
    - 'XMM0=0x0'
    - 'XMM6=0x0'
    - 'XMM13=0x0'
    - 'XMM5=0x0'
    - 'XMM11=0x0'
    - 'XMM3=0x0'
    - 'XMM10=0x0'
    - 'XMM12=0x0'
    - 'XMM8=0x0'
    - 'XMM14=0x0'
    - 'XMM1=0x0'
    - 'XMM4=0x0'
    - 'XMM7=0x0'
    - 'XMM2=0x0'
cpu_name:        znver3
llvm_triple:     x86_64-unknown-linux-gnu
num_repetitions: 10000
measurements:
  - { key: inverse_throughput, value: 0.5291, per_snippet_value: 7.4074 }
error:           ''
info:            instruction has tied variables, avoiding Read-After-Write issue, picking random def and use registers not aliasing each other, for uses, one unique register for each position
assembled_snippet: 4883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F3C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F0C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F04244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F34244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F2C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F2C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F1C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F1C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F14244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F24244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F04244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F34244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F0C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F24244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F3C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F14244883C41066450F3814F966410F3814F166450F3814E966410F3814E966450F3814D966410F3814D966450F3814D166450F3814E166450F3814C166450F3814F166410F3814C966410F3814E166410F3814F966410F3814D166450F3814F966410F3814F166450F3814E966410F3814E966450F3814D966410F3814D966450F3814D166450F3814E166450F3814C166450F3814F166410F3814C966410F3814E166410F3814F966410F3814D166450F3814F966410F3814F166450F3814E966410F3814E966450F3814D966410F3814D966450F3814D166450F3814E166450F3814C166450F3814F166410F3814C966410F3814E166410F3814F966410F3814D166450F3814F966410F3814F166450F3814E966410F3814E966450F3814D966410F3814D966450F3814D166450F3814E166450F3814C166450F3814F166410F3814C966410F3814E166410F3814F966410F3814D1C3
...
Check generated assembly with: /usr/bin/objdump -d /tmp/snippet-9024ea.o
---
mode:            inverse_throughput
key:
  instructions:
    - 'BLENDVPSrr0 XMM7 XMM7 XMM5'
    - 'BLENDVPSrr0 XMM15 XMM15 XMM5'
    - 'BLENDVPSrr0 XMM9 XMM9 XMM5'
    - 'BLENDVPSrr0 XMM14 XMM14 XMM5'
    - 'BLENDVPSrr0 XMM12 XMM12 XMM5'
    - 'BLENDVPSrr0 XMM3 XMM3 XMM5'
    - 'BLENDVPSrr0 XMM1 XMM1 XMM5'
    - 'BLENDVPSrr0 XMM6 XMM6 XMM5'
    - 'BLENDVPSrr0 XMM4 XMM4 XMM5'
    - 'BLENDVPSrr0 XMM10 XMM10 XMM5'
    - 'BLENDVPSrr0 XMM8 XMM8 XMM5'
    - 'BLENDVPSrr0 XMM13 XMM13 XMM5'
    - 'BLENDVPSrr0 XMM11 XMM11 XMM5'
    - 'BLENDVPSrr0 XMM2 XMM2 XMM5'
  config:          ''
  register_initial_values:
    - 'XMM7=0x0'
    - 'XMM5=0x0'
    - 'XMM0=0x0'
    - 'XMM15=0x0'
    - 'XMM9=0x0'
    - 'XMM14=0x0'
    - 'XMM12=0x0'
    - 'XMM3=0x0'
    - 'XMM1=0x0'
    - 'XMM6=0x0'
    - 'XMM4=0x0'
    - 'XMM10=0x0'
    - 'XMM8=0x0'
    - 'XMM13=0x0'
    - 'XMM11=0x0'
    - 'XMM2=0x0'
cpu_name:        znver3
llvm_triple:     x86_64-unknown-linux-gnu
num_repetitions: 10000
measurements:
  - { key: inverse_throughput, value: 0.5294, per_snippet_value: 7.4116 }
error:           ''
info:            instruction has tied variables, avoiding Read-After-Write issue, picking random def and use registers not aliasing each other, for uses, reusing the same register for all positions
assembled_snippet: 4883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F3C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F2C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F04244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F3C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F0C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F34244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F24244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F1C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F0C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F34244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F24244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F14244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F04244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F2C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C57A6F1C244883C4104883EC10C7042400000000C744240400000000C744240800000000C744240C00000000C5FA6F14244883C410660F3814FD66440F3814FD66440F3814CD66440F3814F566440F3814E5660F3814DD660F3814CD660F3814F5660F3814E566440F3814D566440F3814C566440F3814ED66440F3814DD660F3814D5660F3814FD66440F3814FD66440F3814CD66440F3814F566440F3814E5660F3814DD660F3814CD660F3814F5660F3814E566440F3814D566440F3814C566440F3814ED66440F3814DD660F3814D5660F3814FD66440F3814FD66440F3814CD66440F3814F566440F3814E5660F3814DD660F3814CD660F3814F5660F3814E566440F3814D566440F3814C566440F3814ED66440F3814DD660F3814D5660F3814FD66440F3814FD66440F3814CD66440F3814F566440F3814E5660F3814DD660F3814CD660F3814F5660F3814E566440F3814D566440F3814C566440F3814ED66440F3814DD660F3814D5C3
...
lebedev.ri updated this revision to Diff 480146.Dec 5 2022, 9:31 AM

And take this to it's logical conclusion by deduplicating the codepaths with/without tied variables.
@courbet any further thoughts?

lebedev.ri added inline comments.Dec 5 2022, 9:35 AM
llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp
158

One thing i was thinking of, are there cases where we have
both defs with tied uses AND defs without tied uses?
If we have (which instruction is that?),
should we just always reuse the reg for defs without tied uses?

RKSimon added inline comments.Dec 5 2022, 9:59 AM
llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp
158

The weirdest x86 instructions for that kind of thing are some of the CMPXCHG reg-reg instructions - maybe some of the MUL/IMUL and DIV/IDIV variants as well?

Cheers - the blendv cases look ok (no defs/uses of xmm0 at all)

lebedev.ri marked an inline comment as done.Dec 5 2022, 10:04 AM
lebedev.ri added inline comments.
llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp
158

What i would like, is --dry-run option for exegesis,
to do everything, EXCEPT actually running the measurements.
It will help with test coverage, too.
If that option was present, i would have an easy way to check if there is such an opcode...

RKSimon added inline comments.Dec 5 2022, 1:52 PM
llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp
158

+1 - the need to have to install libPFM for most of the test coverage is limiting.

lebedev.ri marked 2 inline comments as done.Dec 5 2022, 2:00 PM

(@courbet waiting on you)

llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp
158

Great, i can try to look into that later.

courbet accepted this revision.Dec 5 2022, 11:28 PM
courbet added inline comments.
llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp
139

Ack, thanks.

227

[nit] R

(for the record I also hate having uppercase variable names :) )

This revision is now accepted and ready to land.Dec 5 2022, 11:28 PM
lebedev.ri updated this revision to Diff 480472.Dec 6 2022, 6:54 AM
lebedev.ri marked 2 inline comments as done.

@courbet thank you for the review!
While there, i've also gone ahead, and added necessary constrains
to prevent generation of snippets with pointless strategies.

llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp
317–318

To be fair, one thing we don't do here, is elimination of unreasonable choices.
If there is only a single use reg, there is no difference
between SingleStaticUseRegPerOperand and SingleStaticUseReg.

This revision was landed with ongoing or failed builds.Dec 6 2022, 7:05 AM
This revision was automatically updated to reflect the committed changes.
ormris added a subscriber: ormris.Dec 6 2022, 11:29 AM

This doesn't compile on GCC 7.5.0 (it's older but supported). See this buildbot: https://lab.llvm.org/staging/#/builders/235/builds/731

This doesn't compile on GCC 7.5.0 (it's older but supported). See this buildbot: https://lab.llvm.org/staging/#/builders/235/builds/731

That's not great. It's an obvious compiler bug.
Are you sure that GCC version is actually up to date?
https://godbolt.org/z/YaEd5P86Y

This doesn't compile on GCC 7.5.0 (it's older but supported). See this buildbot: https://lab.llvm.org/staging/#/builders/235/builds/731

That's not great. It's an obvious compiler bug.
Are you sure that GCC version is actually up to date?
https://godbolt.org/z/YaEd5P86Y

Nonetheless, attempted to workaround via e3f908a557d3e463353aad6b41a6fcd77d049c71.