Skip to main content

Module split

Module split 

Source
Expand description

Splitting critical edges, so that every edge that carries values has somewhere to put them.

Design: spec/10-backend.md section 10.4.

An edge carries values when the block it goes to takes parameters, and giving a parameter its value is a move. The move has to happen on the edge and not before it or after it, because before it is a block that goes somewhere else too and after it is a block that is arrived at from somewhere else too, and in either case the move would run on a path it was not written for. An edge out of a block with one successor can put its moves at the end of that block, since every path through it takes the edge. An edge into a block with one predecessor can put them at the start of that block, for the same reason the other way round. An edge that is neither, which is what a critical edge is, has neither place, and the allocator says so: rucc_regalloc asserts that it never sees one.

So one is turned into two. A block with nothing in it goes on the edge, the arguments move on to the second half, and both halves are now uncritical: the first goes to a block with one predecessor and the second leaves a block with one successor. Which of the two the moves end up in is the allocator’s answer and not this one’s, and either is correct.

§What it leaves behind

An empty block, which is a jump to the next thing unless the layout puts it where it falls through. That is a cost, and it is why an edge with nothing to carry is left alone: there are no moves to find a place for, so splitting it would buy a jump and nothing else.

Functions§

critical
Splits every critical edge that carries values, and gives back how many it split.