freenode/#clasp - IRC Chatlog
Search
14:43:30
Bike
karlosz: am i seeing correctly that as of yet, local calls still always return multiple values?
15:11:31
Bike
seems like it should be pretty easy to merge duplicate code just before a branch merge but we'd hit llvm's problem with multiple source infos
15:14:23
Bike
note to self do change the runtime so that unwind return values are sent through the exception object so we can save some multiple value save load stupidity
15:21:10
Bike
with known values, we could probably allocate stack space in the outer function, and stick the stack pointer in the continuation so the inner functions can mutate directly with those weird intrinsics
15:31:51
Bike
I suppose we could heap allocate space for the multiple values, unwind passing a pointer to that space, extract the values, and then free the space
16:13:34
drmeister
We should plan to improve clasp's compiler performance by a factor of 5 in four stages, with each stage increasing performance by 50%.
16:19:19
drmeister
I misspoke - not what they are doing - but this showed up in Hacker News: https://news.ycombinator.com/item?id=24837309
16:20:10
drmeister
To be fair - they used an equivalence symbol but I couldn't figure out how to generate it.
16:21:38
drmeister
There is some good advice in that post "Enhance compiler to generate superior machine code." We should be doing this!
16:22:35
drmeister
Good - because if you were degrading the compiler to generate lousy code I'd say stop and do this other thing.
16:37:52
Bike
like, if we have (if cond (done thing) (loop ... finally (return (done thing2)))), we can rewrite it as (done (if cond thing1 (loop ... finally (return thing2)))), but then the source location of the call to done is ambiguous
16:48:55
karlosz
Bike: you are quite right that i did not do anything special with return value conventions with local calls
16:50:07
karlosz
it would be really nice if we could do fast returns, but it seems involved given llvm. maybe you have a better idea how to do it?
16:50:21
karlosz
i don't think this really requires cleavir changes, this is purely a backend thing.
16:51:21
Bike
i figure local-call might have separate outputs to indicate it returns two object values, or whatever
16:51:46
Bike
since erasing multiple-to-fixed and fixed-to-multiple in the backend would be kind of annoying
16:54:08
Bike
i mean, i think it's fine, but the only transform we do with it now is deleting a f->m m->f when interpolating
16:54:36
Bike
i figured returni would take multiple inputs, and local-call would take multiple outputs, and for correcntess they'd have to correspond
16:54:40
karlosz
it would be great if the backend could choose the representation, or at least not in BIR, kinda like how the calling convention is chosen in the backend
16:59:15
Bike
cleavir2 doesn't have mv locations at all, but instead it assumes there's a global mv location, which is modified by the corresponding instructions
17:01:31
Bike
what i'm imagining is that we'd start out with a given function ending with f->m, and the calls to it having an m->f after them (if that's how they're used)
17:01:52
Bike
and ideally it would work similarly with cast instructions, so that local calls could return unboxed floats directly and such
17:18:31
Bike
of course if a client doesn't want to set up that kind of thing they can just not run the transforms
17:19:57
Bike
actually i guess calls in general should have outputs, it's possible a client wants global functions that return unboxed values or whatever, presumably from transformations
17:22:47
karlosz
well the alternative is to punt all multiple values representation choices into the backend, like Python does
17:23:11
karlosz
the reason why i don't see a pure BIR way of implementing this is that the choice to allocate external entry points is currently in the backend
17:24:01
karlosz
Python's "transfers" are just always annotated with ctypes that have the unknown values or fixed values information represented via (VALUES ... &OPTIONAL) etc... you know, the standard CL representation for that sort of thing
17:24:30
karlosz
so that could also be a good fit for us because it allows client independence for how to represent those things besides "don't run these transforms"
17:25:14
karlosz
the other reason to punt the choices into the backend is as you allude to, we can have known global functions do spicy return stuff
17:25:37
karlosz
in general we can't assume the representation that BIR currently has of always returning unknown values
17:26:30
karlosz
another advantage is that you don't need to do low level casting of values in BIR itself, so you save some dumb stuff like having to do F->M and M->F
17:27:12
karlosz
i found a couple cases where they didn't get removed because a merge block got created and a phi blocked the optimization
17:27:40
karlosz
we couldn't have done this in HIR because HIR didn't have the concept of splitting variables and transfers
17:28:00
karlosz
obviously lexical variables can't hold multiple values, and transfers are really the only thing that can
17:28:45
karlosz
plus, Python does a trick to make single value return really fast, that is purely a backend choice thing. thats impossible to represent in BIR
17:30:55
karlosz
so we might want to rethink multiple values in general if we want *all* the possible backend optimizations
18:03:01
Bike
it's true that leaving this at the lower level might be good. i'll put some thought into it
18:04:37
karlosz
also we might need to rethink it anyway because this was left over from hir when there was no concept of transfers or lexical variables
18:05:34
karlosz
what i will say is that we definitely should handle mvprog1 the way we are handling it and not the way python does which is a disaster
18:06:04
karlosz
that is, introducing a dynenv action to indicate the extent of the multiple values being kept
18:07:31
karlosz
imo they made the mistake in python of not indicating mvprog1 extent with dynamic environments like they do with tagbody or block, and they needed an entire new stack simulation pass to reconstruct how the multiple values should get popped off the stack which has caused endless multiple values bugs for them
18:56:17
Bike
as for multiple values, after my walk i'm thinking it would be good to change how it works to leave it for later, but also i'm kind of sick of rewriting ast-to-bir every week so i'm going to put it off until we have more transforms
18:56:45
Bike
so now i'm thinking about that again instead. thinking i should change environment stuff so that in addition to a type there's also a believe-this-unconditionally marker
18:56:59
Bike
so we can handle user ftypes, but also like CL function ftypes that we don't want to check
18:58:20
Bike
well, my system now is that regular THE becomes an unconditionally believed type, but if types are checked it's preceded by a test, so believing that is fine
19:13:36
Bike
but then it would be convvenient to know what variables are around, so it would be good for pcv to be early
19:13:49
Bike
but if pcv is early that info needs to be maintained, and if an unwind is cleaned up it needs to deal with things
19:27:09
karlosz
pcv should be a bir post pass because its basically impossible to maintain the variables set
19:44:51
karlosz
Bike: dead code issue from yesterday fixed and pushed. you might want to take a look at how i did it. i think the main thing you were missing is the invariant that a block should only be owned by one function uniquely
21:37:26
Bike
the function copier needs to know, in general, which variables are closed over, so that it doesn't copy them
21:38:40
karlosz
whihc is why it can basically be the very lsat thing that ever happens because nothing else should care
21:38:58
karlosz
its basically impossible to delete a variable from an environment transitively, so it has to go last
22:07:46
Bike
like if you have nil in source code it will actually be a bir:constant with constant-value nil
22:08:02
Bike
also i remembered the actual problem: if you copy (lambda (x) (lambda () x)) you need to copy the inner function since the variable is copied