If `backedge_predicate` is equal to `symbolic_predicate` & Step where Step does not contain `symbolic_predicate` as an inner (not top-level) operand then returns `Step`. Otherwise returns nullptr.
| 1012 | // does not contain `symbolic_predicate` as an inner (not top-level) operand |
| 1013 | // then returns `Step`. Otherwise returns nullptr. |
| 1014 | Predicate* DeduceStepPredicate(PredicateFactory* predicate_factory, |
| 1015 | Predicate* symbolic_predicate, |
| 1016 | Predicate* backedge_predicate) { |
| 1017 | CHECK(dynamic_cast<SymbolPredicate*>(symbolic_predicate)); |
| 1018 | if (backedge_predicate->kind() != Predicate::Kind::kAnd) { |
| 1019 | return nullptr; |
| 1020 | } |
| 1021 | |
| 1022 | std::vector<Predicate*> and_ops; |
| 1023 | absl::Span<Predicate* const> recurrent_pred_ops = |
| 1024 | backedge_predicate->GetOperands(); |
| 1025 | |
| 1026 | bool found_sym = false; |
| 1027 | for (Predicate* and_op : recurrent_pred_ops) { |
| 1028 | // We want the `symbol_predicate` to be the one of the operands of |
| 1029 | // `backedge_predicate`, |
| 1030 | if (and_op == symbolic_predicate) { |
| 1031 | found_sym = true; |
| 1032 | continue; |
| 1033 | } |
| 1034 | |
| 1035 | // but we don't want it to be present anywhere else in the formula. E.g. we |
| 1036 | // don't want the recurrent predicate to be |
| 1037 | // symbol_predicate&(X|symbol_predicate). |
| 1038 | bool found_sym_as_inner_operand = false; |
| 1039 | auto has_self_as_inner_operand = [&](Predicate* p) { |
| 1040 | if (p == symbolic_predicate) { |
| 1041 | found_sym_as_inner_operand = true; |
| 1042 | return true; // Stop searching, we're done. |
| 1043 | } |
| 1044 | |
| 1045 | // Continue searching. |
| 1046 | return false; |
| 1047 | }; |
| 1048 | |
| 1049 | Predicate::Visit(and_op, has_self_as_inner_operand); |
| 1050 | if (found_sym_as_inner_operand) { |
| 1051 | return nullptr; |
| 1052 | } |
| 1053 | and_ops.push_back(and_op); |
| 1054 | } |
| 1055 | |
| 1056 | return found_sym ? predicate_factory->MakeAndPredicate(and_ops) : nullptr; |
| 1057 | } |
| 1058 | |
| 1059 | Status GetFullFrame(const Node* n, absl::Span<const ControlFlowInfo> cfi_infos, |
| 1060 | std::vector<string>* frame) { |
no test coverage detected