void build(Inst& inst, const Liveness<Tmp>::LocalCalc& localCalc) { inst.forEachDefAndExtraClobberedTmp(type, [&] (Tmp& arg) { // All the Def()s interfere with each other and with all the extra clobbered Tmps. // We should not use forEachDefAndExtraClobberedTmp() here since colored Tmps // do not need interference edges in our implementation. inst.forEachTmp([&] (Tmp& otherArg, Arg::Role role, Arg::Type otherArgType) { if (otherArgType != type) return; if (Arg::isDef(role)) addEdge(arg, otherArg); }); }); if (MoveInstHelper<type>::mayBeCoalescable(inst)) { // We do not want the Use() of this move to interfere with the Def(), even if it is live // after the Move. If we were to add the interference edge, it would be impossible to // coalesce the Move even if the two Tmp never interfere anywhere. Tmp defTmp; Tmp useTmp; inst.forEachTmp([&defTmp, &useTmp] (Tmp& argTmp, Arg::Role role, Arg::Type) { if (Arg::isDef(role)) defTmp = argTmp; else { ASSERT(Arg::isUse(role)); useTmp = argTmp; } }); ASSERT(defTmp); ASSERT(useTmp); unsigned nextMoveIndex = m_coalescingCandidates.size(); m_coalescingCandidates.append({ useTmp, defTmp }); unsigned newIndexInWorklist = m_worklistMoves.addMove(); ASSERT_UNUSED(newIndexInWorklist, newIndexInWorklist == nextMoveIndex); ASSERT(nextMoveIndex <= m_activeMoves.size()); m_activeMoves.ensureSize(nextMoveIndex + 1); for (const Arg& arg : inst.args) { auto& list = m_moveList[AbsoluteTmpHelper<type>::absoluteIndex(arg.tmp())]; list.add(nextMoveIndex); } for (const Tmp& liveTmp : localCalc.live()) { if (liveTmp != useTmp && liveTmp.isGP() == (type == Arg::GP)) addEdge(defTmp, liveTmp); } } else addEdges(inst, localCalc.live()); }