| 298 | } |
| 299 | |
| 300 | void memory_coloring::apply(module& m) const |
| 301 | { |
| 302 | const std::size_t alignment = find_max_alignment(m, allocation_op); |
| 303 | auto conflict_table = build_conflict_table(m, allocation_op); |
| 304 | auto as = allocation_segment::build(m, conflict_table, alignment); |
| 305 | |
| 306 | // All allocations should have a segment |
| 307 | assert(std::all_of(conflict_table.begin(), conflict_table.end(), [&](auto&& pp) { |
| 308 | return as.get_segment(pp.first); |
| 309 | })); |
| 310 | |
| 311 | // Adjacent allocations should not have overlapping segments |
| 312 | assert(std::none_of(conflict_table.begin(), conflict_table.end(), [&](auto&& pp) { |
| 313 | auto* x = as.get_segment(pp.first); |
| 314 | return std::any_of(pp.second.begin(), pp.second.end(), [&](auto ins) { |
| 315 | auto* y = as.get_segment(ins); |
| 316 | assert(x and y); |
| 317 | return is_overlap(*x, *y); |
| 318 | }); |
| 319 | })); |
| 320 | |
| 321 | // Print out segments |
| 322 | if(enabled(MIGRAPHX_DEBUG_MEMORY_COLORING{})) |
| 323 | { |
| 324 | for(auto&& pp : conflict_table) |
| 325 | { |
| 326 | std::cout << "------- conflict -------" << std::endl; |
| 327 | auto s1 = as.ins2segment.at(pp.first); |
| 328 | std::cout << s1.first << ", " << s1.second << ": "; |
| 329 | m.debug_print(pp.first); |
| 330 | for(auto ins : pp.second) |
| 331 | { |
| 332 | auto s2 = as.ins2segment.at(ins); |
| 333 | std::cout << s2.first << ", " << s2.second << ": "; |
| 334 | m.debug_print(ins); |
| 335 | } |
| 336 | } |
| 337 | } |
| 338 | |
| 339 | // Total memory |
| 340 | std::size_t n = as.max() * alignment; |
| 341 | |
| 342 | // Replace allocations |
| 343 | auto mem = m.add_parameter("scratch", shape{shape::int8_type, {n}}); |
| 344 | for(auto&& [ins, seg] : as.ins2segment) |
| 345 | { |
| 346 | assert(ins->name() == allocation_op); |
| 347 | auto s = ins->get_shape(); |
| 348 | std::size_t offset = seg.first * alignment; |
| 349 | assert(offset < n); |
| 350 | m.replace_instruction( |
| 351 | ins, make_op("load", {{"shape", to_value(s)}, {"offset", offset}}), mem); |
| 352 | } |
| 353 | |
| 354 | // Replace zero allocation |
| 355 | for(auto ins : iterator_for(m)) |
| 356 | { |
| 357 | if(ins->name() != allocation_op) |
nothing calls this directly
no test coverage detected