Mill Computing, Inc. Forums The Mill Architecture Control flow divergence and The Belt Reply To: Control flow divergence and The Belt

Ivan Godard
Keymaster
Post count: 629

The ISA documentation on the site is woefully out of date and we have no volunteer to resume the work on it; please accept my apologies. Here’s a conAsm fragment (from the printf() function as it happens) that shows carrying branches in use:

    eql(b4 %46, 108) %435 ^0,
    eql(b4 %46, 104) %434 ^0,
    brtrs(b0 %434, "printf$17_75", b5 %51) ^0,
    brfls(b1 %435, "printf$17_9", b8 %48/460, b10 %50/461) ^0,
    brs("printf$17_75", b2 %399) ^0,
    rd(w(128)) %399 ^263;

You see that the two branches to ebb $17_75 are carrying two different arguments, %51 for one and %399 for the other.

Ebbs don’t really “produce results”, except in the sense that they contain store operations that update memory. I think you mean more a notion of liveness or in-flight operands, those produced by an operation but that have not yet been consumed by all consumers. Live operands are initially created on the belt, and are consumed from the belt. If at any point there are more simultaneously live operands than fit in the fixed capacity of the belt (16 positions on a Silver, from which the above fragment was drawn) then the code must spill the excess, initially to scratchpad and ultimately, if scratch itself fills up, to memory. The specializer uses heuristics to decide which operands to spill. Spill and fill are a fact of life for any machine because there are always codes that exceed local resource constraints, although the compiler algorithms to do spilling are very different on a belt machine than on a general register machine.

Spilling is also done in a few other situations. For example, if an operand is created in one ebb and not consumed until much later after a long chain of branches then it is better code to spill it at point of production and fill it at point of consumption than to pass it along across many value-carrying branches.