[llvm-mca][BtVer2] teach how to identify false dependencies on partially written
authorAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Sun, 15 Jul 2018 11:01:38 +0000 (11:01 +0000)
committerAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Sun, 15 Jul 2018 11:01:38 +0000 (11:01 +0000)
commitff630c2cdc7f805091e8d8cce40692bb9441fd3a
treec5a9574b8fa2836d9ad01248130a3b9f25bbfd76
parent0603bae41cf228ba6489d9aa320835abcce509e5
[llvm-mca][BtVer2] teach how to identify false dependencies on partially written
registers.

The goal of this patch is to improve the throughput analysis in llvm-mca for the
case where instructions perform partial register writes.

On x86, partial register writes are quite difficult to model, mainly because
different processors tend to implement different register merging schemes in
hardware.

When the code contains partial register writes, the IPC (instructions per
cycles) estimated by llvm-mca tends to diverge quite significantly from the
observed IPC (using perf).

Modern AMD processors (at least, from Bulldozer onwards) don't rename partial
registers. Quoting Agner Fog's microarchitecture.pdf:
" The processor always keeps the different parts of an integer register together.
For example, AL and AH are not treated as independent by the out-of-order
execution mechanism. An instruction that writes to part of a register will
therefore have a false dependence on any previous write to the same register or
any part of it."

This patch is a first important step towards improving the analysis of partial
register updates. It changes the semantic of RegisterFile descriptors in
tablegen, and teaches llvm-mca how to identify false dependences in the presence
of partial register writes (for more details: see the new code comments in
include/Target/TargetSchedule.h - class RegisterFile).

This patch doesn't address the case where a write to a part of a register is
followed by a read from the whole register.  On Intel chips, high8 registers
(AH/BH/CH/DH)) can be stored in separate physical registers. However, a later
(dirty) read of the full register (example: AX/EAX) triggers a merge uOp, which
adds extra latency (and potentially affects the pipe usage).
This is a very interesting article on the subject with a very informative answer
from Peter Cordes:
https://stackoverflow.com/questions/45660139/how-exactly-do-partial-registers-on-haswell-skylake-perform-writing-al-seems-to

In future, the definition of RegisterFile can be extended with extra information
that may be used to identify delays caused by merge opcodes triggered by a dirty
read of a partial write.

Differential Revision: https://reviews.llvm.org/D49196

llvm-svn: 337123
llvm/include/llvm/Target/TargetSchedule.td
llvm/lib/Target/X86/X86ScheduleBtVer2.td
llvm/test/tools/llvm-mca/X86/BtVer2/partial-reg-update-2.s
llvm/test/tools/llvm-mca/X86/BtVer2/partial-reg-update-3.s
llvm/test/tools/llvm-mca/X86/BtVer2/partial-reg-update-4.s
llvm/test/tools/llvm-mca/X86/BtVer2/partial-reg-update-5.s
llvm/test/tools/llvm-mca/X86/BtVer2/partial-reg-update-6.s
llvm/tools/llvm-mca/Instruction.cpp
llvm/tools/llvm-mca/Instruction.h
llvm/tools/llvm-mca/RegisterFile.cpp
llvm/tools/llvm-mca/RegisterFile.h