Run a general set-based data flow analysis. Args: blocks: All basic blocks cfg: Control-flow graph for the code gen_and_kill: Implementation of gen and kill functions for each op initial: Value of analysis for the entry points (for a forward analysis) or the
(
blocks: list[BasicBlock],
cfg: CFG,
gen_and_kill: OpVisitor[GenAndKill[T]],
initial: set[T],
kind: int,
backward: bool,
universe: set[T] | None = None,
)
| 524 | |
| 525 | |
| 526 | def run_analysis( |
| 527 | blocks: list[BasicBlock], |
| 528 | cfg: CFG, |
| 529 | gen_and_kill: OpVisitor[GenAndKill[T]], |
| 530 | initial: set[T], |
| 531 | kind: int, |
| 532 | backward: bool, |
| 533 | universe: set[T] | None = None, |
| 534 | ) -> AnalysisResult[T]: |
| 535 | """Run a general set-based data flow analysis. |
| 536 | |
| 537 | Args: |
| 538 | blocks: All basic blocks |
| 539 | cfg: Control-flow graph for the code |
| 540 | gen_and_kill: Implementation of gen and kill functions for each op |
| 541 | initial: Value of analysis for the entry points (for a forward analysis) or the |
| 542 | exit points (for a backward analysis) |
| 543 | kind: MUST_ANALYSIS or MAYBE_ANALYSIS |
| 544 | backward: If False, the analysis is a forward analysis; it's backward otherwise |
| 545 | universe: For a must analysis, the set of all possible values. This is the starting |
| 546 | value for the work list algorithm, which will narrow this down until reaching a |
| 547 | fixed point. For a maybe analysis the iteration always starts from an empty set |
| 548 | and this argument is ignored. |
| 549 | |
| 550 | Return analysis results: (before, after) |
| 551 | """ |
| 552 | block_gen = {} |
| 553 | block_kill = {} |
| 554 | |
| 555 | # Calculate kill and gen sets for entire basic blocks. |
| 556 | for block in blocks: |
| 557 | gen: set[T] = set() |
| 558 | kill: set[T] = set() |
| 559 | ops = block.ops |
| 560 | if backward: |
| 561 | ops = list(reversed(ops)) |
| 562 | for op in ops: |
| 563 | opgen, opkill = op.accept(gen_and_kill) |
| 564 | if opkill: |
| 565 | gen -= opkill |
| 566 | |
| 567 | if opgen: |
| 568 | gen |= opgen |
| 569 | kill -= opgen |
| 570 | |
| 571 | if opkill: |
| 572 | kill |= opkill |
| 573 | |
| 574 | block_gen[block] = gen |
| 575 | block_kill[block] = kill |
| 576 | |
| 577 | # Set up initial state for worklist algorithm. |
| 578 | worklist = list(blocks) |
| 579 | if not backward: |
| 580 | worklist.reverse() # Reverse for a small performance improvement |
| 581 | workset = set(worklist) |
| 582 | before: dict[BasicBlock, set[T]] = {} |
| 583 | after: dict[BasicBlock, set[T]] = {} |
no test coverage detected
searching dependent graphs…