| 1051 | } |
| 1052 | |
| 1053 | StatusOr<StateMap::CondId> FunctionalizeCond::JoinCondStatesMerge( |
| 1054 | Node* merge, StateMap::CondId src, StateMap::CondId dst) { |
| 1055 | // Determine the flow state when joining two states for a merge |
| 1056 | // node. Combining the two states for a merge node is effectively performing a |
| 1057 | // disjunction of the states along the different input edges. For a merge that |
| 1058 | // can be transformed into a If the two inputs paths have to have a predicate |
| 1059 | // on which they differ (e.g., along one edge predicate `p` has to hold while |
| 1060 | // on another it should not). This function first determines this predicate |
| 1061 | // and then the resultant state is the common path between the two inputs |
| 1062 | // followed by s(p, both). |
| 1063 | VLOG(4) << "Joining (for merge) " << DebugString(src) << " and " |
| 1064 | << DebugString(dst); |
| 1065 | if (state_map_.IsEmpty(dst)) return src; |
| 1066 | if (state_map_.IsEmpty(src)) { |
| 1067 | return errors::Internal("Merge node ", merge->name(), |
| 1068 | " has input that's not in any CondContext."); |
| 1069 | } |
| 1070 | |
| 1071 | if (state_map_.IsDead(src)) return src; |
| 1072 | if (state_map_.IsDead(dst)) return dst; |
| 1073 | |
| 1074 | std::vector<StateMap::CondState::value_type> diff; |
| 1075 | StateMap::CondState merged; |
| 1076 | std::set_symmetric_difference(src->begin(), src->end(), dst->begin(), |
| 1077 | dst->end(), std::back_inserter(diff), |
| 1078 | CondStateLess()); |
| 1079 | std::set_intersection(src->begin(), src->end(), dst->begin(), dst->end(), |
| 1080 | std::inserter(merged, merged.begin()), CondStateLess()); |
| 1081 | |
| 1082 | // Update mapping from merge node to predicate. |
| 1083 | if (diff.size() == 2) { |
| 1084 | auto pred = diff[0].first; |
| 1085 | bool different_branches = (diff[0].second != diff[1].second) && |
| 1086 | (diff[0].second == BranchType::kThenBranch || |
| 1087 | diff[0].second == BranchType::kElseBranch) && |
| 1088 | (diff[1].second == BranchType::kThenBranch || |
| 1089 | diff[1].second == BranchType::kElseBranch); |
| 1090 | if (!(pred == diff[1].first) || !different_branches) |
| 1091 | return errors::InvalidArgument( |
| 1092 | "Unable to determine predicate for merge node"); |
| 1093 | merge_to_predicate_[merge] = pred; |
| 1094 | } else { |
| 1095 | return errors::InvalidArgument( |
| 1096 | "Merge of two inputs that differ on more than one predicate ", |
| 1097 | DebugString(src), " and ", DebugString(dst)); |
| 1098 | } |
| 1099 | |
| 1100 | return state_map_.GetCondId(merged); |
| 1101 | } |
| 1102 | |
| 1103 | StateMap::CondId FunctionalizeCond::StateAlongEdge(const Edge* e) { |
| 1104 | Node* src = e->src(); |
nothing calls this directly
no test coverage detected