| 35 | |
| 36 | template <class Range> |
| 37 | static void cse_range(module& m, Range&& r) |
| 38 | { |
| 39 | std::unordered_multimap<std::string, instruction_ref> instructions; |
| 40 | std::unordered_set<instruction_ref> processed_ins; |
| 41 | for(auto ins : r) |
| 42 | { |
| 43 | // Skip dead instructions |
| 44 | if(ins->outputs().empty()) |
| 45 | continue; |
| 46 | |
| 47 | // Find instruction with the same name |
| 48 | auto found_instructions = range(instructions.equal_range(ins->name())); |
| 49 | for(const auto& pp : found_instructions) |
| 50 | { |
| 51 | auto eq = pp.second; |
| 52 | if(contains(processed_ins, eq)) |
| 53 | continue; |
| 54 | if(*eq != *ins) |
| 55 | continue; |
| 56 | m.replace_instruction(ins, eq); |
| 57 | processed_ins.emplace(ins); |
| 58 | std::vector<instruction_ref> outputs; |
| 59 | std::copy_if(eq->outputs().begin(), |
| 60 | eq->outputs().end(), |
| 61 | std::back_inserter(outputs), |
| 62 | [&](auto x) { return m.has_instruction(x); }); |
| 63 | |
| 64 | std::sort(outputs.begin(), outputs.end(), [&](auto x, auto y) { |
| 65 | return std::distance(eq, x) < std::distance(eq, y); |
| 66 | }); |
| 67 | cse_range(m, outputs); |
| 68 | } |
| 69 | instructions.emplace(ins->name(), ins); |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | void eliminate_common_subexpression::apply(module& m) const { cse_range(m, iterator_for(m)); } |
| 74 |
no test coverage detected