Resource MII computation in MachinePipeliner


I have a question about the resMII computation in the MachinePipeliner. I’m interfacing with ResourceManager under useDFA, and I get a resMII of 16 where I expect no more than six. It seems to try to allocate each instruction in each cycle of its latency, which is adding 2x7 cycles for my two load instructions. However, these load instructions are fully pipelined, so only cause conflict in their issue cycle.

When I rewrite it to this:

  using UPR = std::unique_ptr<DFAPacketizer>;
  SmallVector<UPR, 8> Cycles;
  for (SUnit &SU : DAG->SUnits) {
    MachineInstr *MI = SU.getInstr();
    auto *Room = find_if(Cycles, [MI] (UPR &R) {
          return R->canReserveResources(*MI); });
    if (Room != Resources.end()) {
    auto *NewResource = TII->CreateTargetScheduleState(*ST);
    assert(NewResource->canReserveResources(*MI) && "Reserve error.");

I get the six cycles I expect. Effectively, we only grow the number of cycles if an instruction doesn’t fit anywhere, and the resulting number of cycles gives a lower bound on what we need resource wise. In fact, this is what the comment above SwingSchedulerDAG::calculateResMII suggests it would do.

Where and how would this go wrong?

Then continuing, if this resMII computation is not universally valid, I would like to be able to override it. I think that the methods of ‘ResourceManager’ would form a nice interface class, first of all to separate the two implementation under useDFA, but also to harmonize with the scoreboard hazard recognizer as used in other schedulers later on. I can imagine that TargetInstrInfo could instantiate a specific version of the whole thing. That would also allow me to reserve resources in more than one cycle (scoreboard-like), rather than in a single DFA. Any thoughts on this?

The only thing that went wrong in-tree was CodeGen/Hexagon/swp-resmii-1.ll, which could be fixed by using the same ordering heuristics (FuncUnitOrder) as in the original.
I conclude that the cycle loop in this code isn’t really necessary.

    for (unsigned C = 0; C < NumCycles; ++C)
      while (RI != RE) {
        if ((*RI)->canReserveResources(*MI)) {

I also don’t understand this loop, because the scheduler proper will just reserve resources in the issue cycle, returning from SMSchedule::insert as soon as it can be reserved.