// note. pattern #1:
        // * ref = atom
        // * read(ref)
        // conditions:
        // 1) ref is read only once after it had been assigned
        // 2) atom isn't reassigned before read(ref) takes place
        // 3) if ref is CF$XXXX then atom can be of any node type (not only an atom)
        // transformed into:
        // * read(atom)
        private static bool TryMatchPattern1(DfaHelper dfa, Expression atom)
        {
            var p1_ref = atom as Ref;
            if (p1_ref == null) return false;

            var p1_lastass = dfa.Writes(p1_ref).LastOrDefault();
            if (p1_lastass == null) return false;

            var p1_ref_onlyread_afterass = dfa.Reads(p1_ref).SingleOrDefault2(
                r => dfa.ExecOrderOfStmt(r) >= dfa.ExecOrderOfStmt(p1_lastass));
            if (p1_ref_onlyread_afterass == null) return false;

            var p1_atom = p1_lastass.Rhs;
            if (!p1_ref.Sym.Name.StartsWith("CF$") &&
                !p1_ref.Sym.Name.StartsWith("CS$"))
            {
                if (!p1_atom.IsAtom()) return false;

                var p1_atom_reasses = dfa.Writes(p1_atom).Where(w =>
                    dfa.ExecOrderOfStmt(p1_lastass) <= dfa.ExecOrderOfStmt(w) &&
                    dfa.ExecOrderOfStmt(w) <= dfa.ExecOrderOfStmt(p1_ref_onlyread_afterass));
                if (p1_atom_reasses.IsNotEmpty()) return false;
            }

            dfa.Remove(p1_lastass);
            var p1_ref_onlyread_stmt = p1_ref_onlyread_afterass.Stmt();
            dfa.ReplaceRecursive(p1_ref_onlyread_stmt, p1_ref, p1_atom);
            return true;
        }
        // note. pattern #2: 
        // * atom = atom op any
        // transformed into: 
        // * atom [op=] any
        private static bool TryMatchPattern2(DfaHelper dfa, Expression atom)
        {
            var p2_atom = atom;
            foreach (var p2_ass in dfa.Writes(atom))
            {
                if (!(p2_ass.Rhs is BinaryOperator)) continue;
                var binary = p2_ass.Rhs as BinaryOperator;
                if (!p2_atom.Equiv(binary.Lhs)) continue;

                var p2_opeq = p2_atom.CreateOpPreAssign(binary.OperatorType, binary.Rhs);
                if (p2_opeq == null) return false;

                dfa.Replace(p2_ass, p2_opeq);
                return true;
            }

            return false;
        }