// 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; }