private void LoopCheck() { var graph = new Graph <Absy>(new HashSet <Tuple <Absy, Absy> >(atomicityLabels.Keys)); graph.AddSource(initialState); graph.ComputeLoops(); var edgeToLoopHeader = new Dictionary <Tuple <Absy, Absy>, Block>(); foreach (Block header in graph.SortHeadersByDominance()) { foreach (var source in graph.BackEdgeNodes(header)) { edgeToLoopHeader[new Tuple <Absy, Absy>(source, header)] = header; foreach (var node in graph.NaturalLoops(header, source)) { if (node == header) { continue; } foreach (var pred in graph.Predecessors(node)) { var edge = new Tuple <Absy, Absy>(pred, node); if (edgeToLoopHeader.ContainsKey(edge)) { continue; } edgeToLoopHeader[edge] = header; } } } } var parentLoopHeader = new Dictionary <Block, Block>(); foreach (Block header in graph.Headers) { foreach (var pred in graph.Predecessors(header).Except(graph.BackEdgeNodes(header))) { var edge = new Tuple <Absy, Absy>(pred, header); if (edgeToLoopHeader.ContainsKey(edge)) { parentLoopHeader[header] = edgeToLoopHeader[edge]; break; } } } var yieldingLoopHeaders = new HashSet <Block>(graph.Headers.OfType <Block>() .Where(header => civlTypeChecker.IsYieldingLoopHeader(header, currLayerNum))); foreach (var header in parentLoopHeader.Keys) { var parentHeader = parentLoopHeader[header]; if (yieldingLoopHeaders.Contains(header) && !yieldingLoopHeaders.Contains(parentHeader)) { civlTypeChecker.Error(parentHeader, $"Loop header must be yielding at layer {currLayerNum}"); } } foreach (var edge in edgeToLoopHeader.Keys) { var header = edgeToLoopHeader[edge]; if (yieldingLoopHeaders.Contains(header)) { continue; } if (atomicityLabels[edge] == Y) { civlTypeChecker.Error(header, $"Loop header must be yielding at layer {currLayerNum}"); } } }