Change the scheduler's physical register dependency tracking from
registers-and-their-aliases to regunits. This has a couple of advantages
when subregisters are used:
- The dependency tracking is more accurate and creates fewer useless
edges in the dependency graph. An AMDGPU example, edited for clarity:
SU(0): $vgpr1 = V_MOV_B32 $sgpr0
SU(1): $vgpr1 = V_ADDC_U32 0, $vgpr1
SU(2): $vgpr0_vgpr1 = FLAT_LOAD_DWORDX2 $vgpr0_vgpr1, 0, 0
There is a data dependency on $vgpr1 from SU(0) to SU(1) and from
SU(1) to SU(2). But the old dependency tracking code also added a
useless edge from SU(0) to SU(2) because it thought that SU(0)'s def
of $vgpr1 aliased with SU(2)'s use of $vgpr0_vgpr1.
- On targets like AMDGPU that make heavy use of subregisters, each
register can have a huge number of aliases - it can be quadratic in
the size of the largest defined register tuple. There is a much lower
bound on the number of regunits per register, so iterating over
regunits is faster than iterating over aliases.
The LLVM compile-time tracker shows a tiny overall improvement of 0.03%
on X86. I expect a larger compile-time improvement on targets like
AMDGPU.
Recommit after fixing AggressiveAntiDepBreaker in D156880.Details
- Reviewers
fhahn qcolombet nikic craig.topper RKSimon kparzysz hfinkel uweigand rengolin t.p.northover asl MatzeB arsenm - Group Reviewers
Restricted Project - Commits
- rG56d92c17583e: [MachineScheduler] Track physical register dependencies per-regunit
rG1a54671d5405: [MachineScheduler] Track physical register dependencies per-regunit
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
| llvm/lib/CodeGen/ScheduleDAGInstrs.cpp | ||
|---|---|---|
| 226–230 | Not that I know off the top of my head. Should at least add a fixme here | |
| llvm/lib/CodeGen/ScheduleDAGInstrs.cpp | ||
|---|---|---|
| 226–230 | I think you need to use MCRegUnitMaskIterator | |
| llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h | ||
|---|---|---|
| 91 | This should perhaps be renamed as RegUnit2SUnitsMap now when when spare set key is a RegUnit and not a Reg. Caused me some head-ache downstream until I found out that for (Reg2SUnitsMap::iterator I = DAG->Uses.find(*Subreg);
I != DAG->Uses.end(); ++I) {probably isn't working any longer unless I make some changes to use a RegUnit in that find call. | |
| llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h | ||
|---|---|---|
| 91 | Good idea. Done in d9c0166f12f0231df0893a397326efb93935ed26. | |
This should perhaps be renamed as RegUnit2SUnitsMap now when when spare set key is a RegUnit and not a Reg.
Caused me some head-ache downstream until I found out that
for (Reg2SUnitsMap::iterator I = DAG->Uses.find(*Subreg); I != DAG->Uses.end(); ++I) {probably isn't working any longer unless I make some changes to use a RegUnit in that find call.