freenode/#clasp - IRC Chatlog
Search
14:30:38
Bike
array-row-major-index is a little weird to optimize. i guess i can just expand it into "if the array is a vector and there's only one argument, return the argument, otherwise full call"
14:37:52
Bike
i'd like to expand aref into row-major-aref of array-row-major-index, and not call the latter
14:41:12
Bike
we also have a lisp definition of array-row-major-index in addition to a C++ one, and the lisp one is uniformly slower
14:41:48
beach
I would think the array reference would most often be in a loop, and part or all of the computation for row-major index would be loop invariant.
14:46:56
Bike
since array-row-major-index can take any number of indices, the full version basically has to be a loop over them (or from 0 upto the array rank).
14:49:21
Bike
and i think with inlining we could only pick off a few specific cases, because we can't expand into an infinite number of "is the rank 0? is the rank 1? is the rank 2?" etc
14:51:24
Bike
well, as currently written in clasp the loop is actually over the indices as a list, so we'd need to know the length of the list is constant to do it that way.
14:53:22
Bike
okay, then to do that we need to put in some branch we can resolve at compile time, like a type check.
14:54:58
Bike
or do you mean that we would rewrite a-r-m-i so that it would do different things based on the, oh, okay.
14:55:33
Bike
so i was thinking you meant you'd have like (defun array-rank (array) (typecase array ((array * 0) 0) ((array * 1) 1) ...))
14:59:18
beach
I don't think that would be necessary. It would typically be a loop-invariant value anyway.
14:59:47
Bike
okay, i mean, i understand overall that it should work for any rank and that we should unroll the loop and all, but i don't understand how to actually write this with how cleavir usually does things.
15:00:26
Bike
for one, we presently ignore type declarations of rank. of course we can change that, but then what do we do with it? our only tool right now is typeq, which we cannot do infinitely.
15:01:36
beach
I guess I should study how deftransform works. I don't know how it works right now nor how it is used.
15:02:46
Bike
SBCL has something like HIR in that it's an explicit control flow graph. some of the details are different, of course, but i don't think any of them are relevant
15:03:50
Bike
as it's proceeding with optimization, it can get to a combination node, and then that node has a "deftransform". the "deftransform" is a lisp function that receives information about the function and its arguments as its arguments
15:04:39
Bike
and it returns, i think, a lisp lambda expression, which is then compiled, and used as the function being called at the node
15:05:33
Bike
so, a very simple example would be we have (deftransform array-rank (array) (if (known-array-type-with-rank-p array) `(lambda (array) (declare (ignore array)) ,(known-array-type-rank array)) (do-not-transform)))
15:06:00
Bike
(also i think there's sugar so that if you return a general form instead of a lambda expression it wraps it in a lambda expression for you)
15:08:11
beach
The most severe one being that, if this were to be done in HIR, we would need to consult the compilation environment, which disappeared at the AST level.
15:12:38
beach
Anyway, array rank represents an interesting class of problems. It would be worth some of my time to give it some thought.
15:14:04
Bike
i've hit some... difficulties, with inline definitions for a few other things. mostly just loops like that, but there are a few places i'd rather not be restricted to source-level constantp.
15:14:52
Bike
type arguments to map and coerce, for example. i don't want to miss an opportunity to avoid a full call involving subtypep because somebody once-only'd
15:16:08
Bike
i actually had sort of the same problem with sequence functions (and :key and :test) but changing inlining as we discussed should fix that
15:21:02
Bike
like, in macros you use once-only, so you might end up with a macroexpansion such as (let ((#:g192 'list)) (coerce x #:g192))
15:22:05
Bike
so if you have a compiler macro on COERCE to turn that into (%coerce-to-list x), it has to know that #:g192 is constant, which it doesn't from the source
18:23:17
Bike
"!!! Mismatch in irc-store between val type #<TYPE i32> and destination type #<TYPE {}*>
18:25:10
drmeister
You are trying to store an i32 in a memory location that has been defined {}* . You can only write i32 into i32*
18:28:17
Bike
yeah, i was trying to index into a ext:byte32 array, so it does (%store (%load (%inttoptr whatever cmp::%i32*%)) [an output])
18:44:13
drmeister
uintptr_t is the correct type. It's an i64 (on x86_64) unsigned integer that contains as many bits as a pointer.
18:44:39
drmeister
https://github.com/drmeister/clasp/blob/dev/src/lisp/kernel/cmp/cmpintrinsics.lsp#L1145
18:46:57
Bike
which i assumed was because the variable i was trying to store into was a T** not an i32*
18:47:09
drmeister
This: "!!! Mismatch in irc-store between val type #<TYPE i32> and destination type #<TYPE {}*>
18:51:03
Bike
it doesn't. it expects that you can put unboxed values and boxed values in the same location.
19:52:56
drmeister
That would associate the closure returned from the cc_enclose call with the outer closure and allow me to look up the associated llvm-ir functions.
20:02:10
drmeister
What I want to do is associate the closure that comes out of the top level function call with the llvm functions that were generated while compiling the top level form.