Sat May 8 21:25:41 EDT 2010
I've changed the fold to a 2-pass fold. For each expression, the last
node is renamed to be the output. Problem is that this isn't always
possible, i.e. if output nodes are not unique, some name sharing needs
Icredible how there is so much tension between explicit and implicit
outputs. Both have advantages and disadvantages, and there are some
corner cases in the explicit output case case.
The current implementation for named outputs also feels quite ad-hoc.
Think about this. Maybe outputs should be assigned explicitly to
intermediate nodes. And symmetrically, the same should be done with
I'm trying to find something that has a solid base. It looks like
input/output _copy_ is the most general. Copy elimination can then be
an optimization that works in some cases.
I.e. for pure risc machines, if the ins and outs are memory, they need
to be copied to registers anyway. Otoh, this is something that's
easier to perform on the caller side.
So what to do with copy nodes?
Conclusion really seems to be that this is far from a sound
representation.. Maye I should stop worrying about these details and
pick one: let's make all nodes internal, and use explicit in/out
Solution: the Bindings type now has two constructors: Op and Assign,
where Op is register to register, and Assign transports in/out to/from
Can it be made fully load/store?
Ok, seems to work. Also added distinction between Op, Input, Output
so all input, output and tmps can be straightforwardly identified.
Maybe they don't even need to be part of the datastructure.
Alright: full circle: combinint Ai, Term, Procedure, Flatten, Complex
*DFL> compile f0
in: in0, in2, in1, in3
out: out0, out1
temp: tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10
[tmp0] <- [in0]
[tmp1] <- [in2]
[tmp2] <- mul[in0, in2]
[tmp3] <- [in1]
[tmp4] <- [in3]
[tmp5] <- mul[in1, in3]
[tmp6] <- negate[tmp5]
[tmp7] <- add[tmp2, tmp6]
[out0] <- [tmp7]
[tmp8] <- mul[in0, in3]
[tmp9] <- mul[in1, in2]
[tmp10] <- add[tmp8, tmp9]
[out1] <- [tmp10]
Shuffling around a bit, the representation can be abstracted over
inputs and outputs like this:
-- Compile to linkable code.
compileIO :: (Show a) => ([Term a] -> [Term a]) -> [String] -> [String] -> Procedure
compileIO f is os = compileTIO tmps is os f
This gives the functional representation as desired. I think from
here things should go a bit more smoothly.