private static void GenerateCandidateForEnabledness(GPUVerifier verifier, Implementation impl, IRegion region) { Block header = region.Header(); if (verifier.UniformityAnalyser.IsUniform(impl.Name, header)) { return; } var cfg = Program.GraphFromImpl(impl); Dictionary <Block, HashSet <Block> > controlDependence = cfg.ControlDependence(); controlDependence.TransitiveClosure(); cfg.ComputeLoops(); var loopNodes = cfg.BackEdgeNodes(header).Select(item => cfg.NaturalLoops(header, item)).SelectMany(item => item); Expr guardEnclosingLoop = null; foreach (var b in controlDependence.Keys.Where(item => controlDependence[item].Contains(region.Header()))) { foreach (var succ in cfg.Successors(b).Where(item => cfg.DominatorMap.DominatedBy(header, item))) { var guard = MaybeExtractGuard(verifier, impl, succ); if (guard != null) { guardEnclosingLoop = guardEnclosingLoop == null ? guard : Expr.And(guardEnclosingLoop, guard); break; } } } if (guardEnclosingLoop != null) { verifier.AddCandidateInvariant( region, Expr.Imp(Expr.Ident(verifier.FindOrCreateEnabledVariable()), guardEnclosingLoop), "conditionsImpliedByEnabledness"); } var cfgDual = cfg.Dual(new Block()); Block loopConditionDominator = header; // The dominator might have multiple successors while (cfg.Successors(loopConditionDominator).Count(item => loopNodes.Contains(item)) > 1) { // Find the immediate post-dominator of the successors Block block = null; foreach (var succ in cfg.Successors(loopConditionDominator).Where(item => loopNodes.Contains(item))) { if (block == null) { block = succ; } else { block = cfgDual.DominatorMap.LeastCommonAncestor(block, succ); } } // Use the immediate post-dominator loopConditionDominator = block; } Expr guardIncludingLoopCondition = null; foreach (var succ in cfg.Successors(loopConditionDominator).Where(item => loopNodes.Contains(item))) { var guard = MaybeExtractGuard(verifier, impl, succ); if (guard != null) { // There is at most one successor, so it's safe not use GuardIncludingLoopCondition on the rhs guardIncludingLoopCondition = guardEnclosingLoop == null ? guard : Expr.And(guardEnclosingLoop, guard); break; } } if (guardIncludingLoopCondition != null) { verifier.AddCandidateInvariant( region, Expr.Imp(guardIncludingLoopCondition, Expr.Ident(verifier.FindOrCreateEnabledVariable())), "conditionsImplyingEnabledness", "do_not_predicate"); } }