private void pinMain(int minWeight, boolean useOrder, TaskMonitor monitor)
			throws CancelledException {
		int i = 0;										// The main index into fragments, the n-gram list
		monitor.setMessage("Pinning all...");
		monitor.setIndeterminate(false);
		monitor.initialize(fragments.size());
		ArrayList<DataNGram> matchList = new ArrayList<>();
		while (i < fragments.size()) {
			if (i % 1000 == 0) {
				monitor.setProgress(i);
			}
			i = collectEqualHash(i, matchList, minWeight);

			if (matchList.size() == 2) {					// Exactly 2 matching n-grams. Possible pair.
				DataNGram gram0 = matchList.get(0);
				DataNGram gram1 = matchList.get(1);
				if (gram0.graphsDiffer(gram1)) {			// Check that one n-gram comes from each side
					DataVertex left = gram0.root.graph.side == Side.LEFT ? gram0.root : gram1.root;
					DataVertex right =
						gram0.root.graph.side == Side.RIGHT ? gram0.root : gram1.root;
					ngramPinner(left, right, gram0.depth);	// Pin the match and everything above it
				}
			}
			else if (matchList.size() > 2) {				// More then 2 matching n-grams
				breakTieWithCtrlFlow(matchList, useOrder, monitor);
				if (useOrder) {
					matchViaOperator(matchList);
				}
			}
		}
	}
Do one pass of the pinning algorithm.  The n-gram list is run through once.  For each set of
n-grams with matching hashes, if there are exactly 2, the associated data-flow vertices are paired. 
If there are more then 2,  we attempt to "break the tie" by associating control-flow n-grams to
the subset of data-flow vertices and pairing these.
@param minWeight is the weight threshold for considering an n-gram in the list for matching
@param useOrder is true if block and operand order should be used to break ties
@param monitor is the TaskMonitor
@throws CancelledException if the user cancels the task
Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/graphanalysis/Pinning.java