private ValueDispatchNode GatherValueDispatchNodes(
                BoundDecisionDagNode node,
                HashSet <BoundDecisionDagNode> loweredNodes,
                BoundDagTemp input)
            {
                IValueSetFactory fac = ValueSetFactory.ForType(input.Type);

                return(GatherValueDispatchNodes(node, loweredNodes, input, fac));
            }
        /// <summary>
        /// Given a decision dag and a constant-valued input, produce a simplified decision dag that has removed all the
        /// tests that are unnecessary due to that constant value. This simplification affects flow analysis (reachability
        /// and definite assignment) and permits us to simplify the generated code.
        /// </summary>
        public BoundDecisionDag SimplifyDecisionDagIfConstantInput(BoundExpression input)
        {
            if (input.ConstantValue == null)
            {
                return(this);
            }
            else
            {
                ConstantValue inputConstant = input.ConstantValue;
                return(Rewrite(makeReplacement));

                // Make a replacement for a given node, using the precomputed replacements for its successors.
                BoundDecisionDagNode makeReplacement(BoundDecisionDagNode dag, Func <BoundDecisionDagNode, BoundDecisionDagNode> replacement)
                {
                    if (dag is BoundTestDecisionDagNode p)
                    {
                        // This is the key to the optimization. The result of a top-level test might be known if the input is constant.
                        switch (knownResult(p.Test))
                        {
                        case true:
                            return(replacement(p.WhenTrue));

                        case false:
                            return(replacement(p.WhenFalse));
                        }
                    }

                    return(TrivialReplacement(dag, replacement));
                }

                // Is the decision's result known because the input is a constant?
                bool?knownResult(BoundDagTest choice)
                {
                    if (!choice.Input.IsOriginalInput)
                    {
                        // This is a test of something other than the main input; result unknown
                        return(null);
                    }

                    switch (choice)
                    {
                    case BoundDagExplicitNullTest d:
                        return(inputConstant.IsNull);

                    case BoundDagNonNullTest d:
                        return(!inputConstant.IsNull);

                    case BoundDagValueTest d:
                        return(d.Value == inputConstant);

                    case BoundDagTypeTest d:
                        return(inputConstant.IsNull ? (bool?)false : null);

                    case BoundDagRelationalTest d:
                        var f = ValueSetFactory.ForType(input.Type);
                        if (f is null)
                        {
                            return(null);
                        }
                        // TODO: When ValueSetFactory has a method for comparing two values, use it.
                        var set = f.Related(d.Relation.Operator(), d.Value);
                        return(set.Any(BinaryOperatorKind.Equal, inputConstant));

                    default:
                        throw ExceptionUtilities.UnexpectedValue(choice);
                    }
                }
            }
        }