I was looking into how SelectionDAG scheduling is done in LLVM for different backends, and I noticed that for the X86 backend, even though it sets scheduling preferences of ILP or RegisterPressure depending on architecture, in the end, it ends up using source scheduling. I realized this is because it overrides enableMachineScheduler to return true. Is there any specific reasons why it was done this way, and also, what happens to be class mainly responsible for the X86 scheduling then?
The MachineScheduler is consider the standard scheduler and does a better job at tracking among other things register pressure and machine state/latencies, features a more modular design etc.
The SelectionDAG schedulers are still here because:
- We need to bring the selection graph back into a linear order for the MI representation. While we would like the SelectionDAG scheduler to be as simple as an RPO walk, it also does:
- Duplicating/Rematerializing of flag producing nodes in order to avoid unnecessary spilling/restoring of flag registers (which is an expensive operation on most architectures).
Scheduling for any other goals in the selection dag scheduler and using something else than the source/fast scheduler is considered deprecated.
That said for some targets the machine scheduler tuning efforts were never finished (or maybe just never verified?) so that they still use the other selection dag scheduler.
Thanks that clears things up. So if I want to mess around with how schedules are generated, looking at the MachineScheduler pass is the best place now?
Yes looking at the MachineScheduler.cpp and the
SchedMachienModels in the targets along with -debug-only=machine-scheduler / -print-machineinstrs is the way to understand scheduling.
Cool, thanks for the help!