@@ -321,6 +321,65 @@ struct MappingPass : impl::MappingPassBase<MappingPass> {
321321
322322 using MinQueue = std::priority_queue<Node, std::vector<Node>, std::greater<>>;
323323
324+ struct [[nodiscard]] TrialResult {
325+ explicit TrialResult (Layout layout) : layout (std::move (layout)) {}
326+
327+ // / @brief The computed initial layout.
328+ Layout layout;
329+ // / @brief A vector of SWAPs for each layer.
330+ SmallVector<SmallVector<IndexGate>> swaps;
331+ // / @brief The number of inserted SWAPs.
332+ std::size_t nswaps{};
333+ };
334+
335+ struct SynchronizationMap {
336+ /* *
337+ * @returns true if the operation is contained in the map.
338+ */
339+ bool contains (Operation* op) const { return onHold.contains (op); }
340+
341+ /* *
342+ * @brief Add op with respective iterator and ref count to the map.
343+ */
344+ void add (Operation* op, WireIterator* it, const std::size_t cnt) {
345+ onHold.try_emplace (op, SmallVector<WireIterator*>{it});
346+ // Decrease the cnt by one because the op was visited when adding.
347+ refCount.try_emplace (op, cnt - 1 );
348+ }
349+
350+ /* *
351+ * @brief Decrement ref count of op and potentially release its iterators.
352+ */
353+ std::optional<ArrayRef<WireIterator*>> visit (Operation* op,
354+ WireIterator* it) {
355+ assert (refCount.contains (op) && " expected sync map to contain op" );
356+
357+ // Add iterator for later release.
358+ onHold[op].push_back (it);
359+
360+ // Release iterators whenever the ref count reaches zero.
361+ if (--refCount[op] == 0 ) {
362+ return onHold[op];
363+ }
364+
365+ return std::nullopt ;
366+ }
367+
368+ /* *
369+ * @brief Clear the contents of the map.
370+ */
371+ void clear () {
372+ onHold.clear ();
373+ refCount.clear ();
374+ }
375+
376+ private:
377+ // / @brief Maps operations to to-be-released iterators.
378+ DenseMap<Operation*, SmallVector<WireIterator*, 2 >> onHold;
379+ // / @brief Maps operations to ref counts.
380+ DenseMap<Operation*, std::size_t > refCount;
381+ };
382+
324383public:
325384 using MappingPassBase::MappingPassBase;
326385
@@ -382,17 +441,6 @@ struct MappingPass : impl::MappingPassBase<MappingPass> {
382441 }
383442
384443private:
385- struct [[nodiscard]] TrialResult {
386- explicit TrialResult (Layout layout) : layout (std::move (layout)) {}
387-
388- // / @brief The computed initial layout.
389- Layout layout;
390- // / @brief A vector of SWAPs for each layer.
391- SmallVector<SmallVector<IndexGate>> swaps;
392- // / @brief The number of inserted SWAPs.
393- std::size_t nswaps{};
394- };
395-
396444 /* *
397445 * @brief Find the best trial result in terms of the number of SWAPs.
398446 * @returns the best trial result or nullptr if no result is valid.
@@ -615,28 +663,33 @@ struct MappingPass : impl::MappingPassBase<MappingPass> {
615663 while (shouldContinue (it)) {
616664 const auto res =
617665 TypeSwitch<Operation*, WalkResult>(it.operation ())
618- .Case <UnitaryOpInterface>([&](UnitaryOpInterface op) {
619- assert (op.getNumQubits () > 0 && op.getNumQubits () <= 2 );
666+ .Case <BarrierOp>([&](auto ) {
667+ std::ranges::advance (it, step);
668+ return WalkResult::advance ();
669+ })
670+ .template Case <UnitaryOpInterface>(
671+ [&](UnitaryOpInterface op) {
672+ assert (op.getNumQubits () > 0 && op.getNumQubits () <= 2 );
620673
621- if (op.getNumQubits () == 1 ) {
622- std::ranges::advance (it, step);
623- return WalkResult::advance ();
624- }
674+ if (op.getNumQubits () == 1 ) {
675+ std::ranges::advance (it, step);
676+ return WalkResult::advance ();
677+ }
625678
626- if (visited.contains (op)) {
627- const auto otherIndex = visited[op];
628- layer.insert (std::make_pair (index, otherIndex));
679+ if (visited.contains (op)) {
680+ const auto otherIndex = visited[op];
681+ layer.insert (std::make_pair (index, otherIndex));
629682
630- std::ranges::advance (wires[index], step);
631- std::ranges::advance (wires[otherIndex], step);
683+ std::ranges::advance (wires[index], step);
684+ std::ranges::advance (wires[otherIndex], step);
632685
633- visited.erase (op);
634- } else {
635- visited.try_emplace (op, index);
636- }
686+ visited.erase (op);
687+ } else {
688+ visited.try_emplace (op, index);
689+ }
637690
638- return WalkResult::interrupt ();
639- })
691+ return WalkResult::interrupt ();
692+ })
640693 .template Case <AllocOp, StaticOp, ResetOp, MeasureOp,
641694 DeallocOp>([&](auto ) {
642695 std::ranges::advance (it, step);
@@ -709,25 +762,30 @@ struct MappingPass : impl::MappingPassBase<MappingPass> {
709762 // Helper function that advances the iterator to the input qubit (the
710763 // operation producing it) of a deallocation or two-qubit op.
711764 const auto advFront = [](WireIterator& it) {
765+ auto next = std::next (it);
712766 while (true ) {
713- const auto next = std::next (it);
714767 if (isa<DeallocOp>(next.operation ())) {
715768 break ;
716769 }
717770
771+ if (isa<BarrierOp>(next.operation ())) {
772+ break ;
773+ }
774+
718775 auto op = dyn_cast<UnitaryOpInterface>(next.operation ());
719776 if (op && op.getNumQubits () > 1 ) {
720777 break ;
721778 }
722779
723780 std::ranges::advance (it, 1 );
781+ std::ranges::advance (next, 1 );
724782 }
725783 };
726784
727785 auto wires = toWires (place (dynQubits, result.layout , funcBody, rewriter));
728786
729- DenseMap<Operation*, WireIterator*> seen ;
730- for (const auto [i, swaps] : enumerate( result.swaps ) ) {
787+ SynchronizationMap ready ;
788+ for (const auto & swaps : result.swaps ) {
731789 // Advance all wires to the next front of one-qubit outputs
732790 // (the SSA values).
733791 for_each (wires, advFront);
@@ -760,21 +818,30 @@ struct MappingPass : impl::MappingPassBase<MappingPass> {
760818 std::ranges::advance (wires[hw1], 1 );
761819 }
762820
763- // Jump over "ready" two-qubit gates.
821+ // Jump over "ready" gates.
764822 for (auto & it : wires) {
765823 auto op = dyn_cast<UnitaryOpInterface>(std::next (it).operation ());
766- if (op && op.getNumQubits () > 1 ) {
767- if (seen.contains (op)) {
768- std::ranges::advance (it, 1 );
769- std::ranges::advance (*seen[op], 1 );
770- continue ;
771- }
824+ if (!op) {
825+ continue ;
826+ }
827+
828+ if (op.getNumQubits () < 2 ) {
829+ continue ;
830+ }
772831
773- seen.try_emplace (op, &it);
832+ if (!ready.contains (op)) {
833+ ready.add (op, &it, op.getNumQubits ());
834+ continue ;
835+ }
836+
837+ if (auto opt = ready.visit (op, &it)) {
838+ for (WireIterator* wire : *opt) {
839+ std::ranges::advance (*wire, 1 );
840+ }
774841 }
775842 }
776843
777- seen .clear (); // Prepare for next iteration.
844+ ready .clear (); // Prepare for next iteration.
778845 }
779846 }
780847};
0 commit comments