freenode/#clasp - IRC Chatlog
Search
15:18:57
Shinmera
Testing for cons first seems better for branching anyway since it would succeed in most cases, right?
15:21:00
beach
Shinmera: But, yeah, branch prediction should make the test come out the same way most of the time.
15:21:57
Bike
the HIR for the unsafe "fast" version seems to only call eq and eql. not that it should actually call either, but still
15:22:31
Bike
as many as four pointless assignments in a row. i hope meister was right when he said llvm eliminates those
15:23:47
beach
EQL is tricky to get rid of. Maybe (OR (EQ .. ..) (FULL-EQL .. ..)) is a good compromise.
15:24:35
Bike
but yes, i could compile-file it and disassemble the bitcode, i guess. but i think there's something built into clasp
15:26:07
Bike
beach: (defun eql (o1 o2) (cond ((typeq o1 number) (if (typeq o2 number) (number-eql o1 o2) nil)) ((typeq o2 character) (if (typeq o2 character) (char= o1 o2) nil)) (t (eq o1 o2)))) is what i had in mind
15:30:39
Bike
actually for full inference you'd probably want to check both without an order. it's not really well expressed as an inline definition
15:32:56
Shinmera
I'm not 100%, but if I remember correctly characters are tagged words in clasp, so you'll get lucky with those too.
15:34:26
Bike
i guess i can just do (define-compiler-macro eql (o1 o2) `(or (eq ,o1 ,o2) (locally (notinline eql) (eql ,o1 ,o2)))
15:36:00
beach
There are a lot of cases that might be worthwhile, for example heap objects that are not EQ are not EQL. Same thing for fixnums and characters.
15:36:47
Bike
the way compiler macros work is, if the compiler macro returns the whole, exactly, it's not expanded again
15:37:22
Bike
mhm. requiring the notinline to be there makes sense to me though, it would be weird to require a, like, database of previously expanded forms
15:38:19
beach
(cond ((eq x y) t) ((or (heap-objectp x) (characterp x) (fixnump x)) nil) (t (full-eql x y))) is what I suggest.
15:40:49
Bike
how about, (cond ((eq x y) t) ((typeq x (not (or character number))) nil) (t (full-eql x y)))
15:42:14
Bike
hm, but then if x is known to be a symbol, say, you'd end up with (if (eq x y) t nil)... well i guess that's another case for boolean elimination
15:53:09
Bike
and it looks like llvm does eliminate redundant assignments... all this landing pad crap still bothers me, though
16:26:08
Bike
when any function returns there's this snippet that runs to change what function is on top of the stack for backtrace purposes
16:39:00
Bike
okay, so i wrote an assoc in terms of primops, so i don't need to worry about boolean elimination or type inference or anything
16:39:34
Bike
for a test, regular assoc took 1.218s. this assoc took 1.544s. if i changed the primop assoc to use primop:eq instead of calling eql, 0.617s
16:41:26
drmeister
Build a list of things that need inlining. I need to get through Monday and then I can assist.
16:43:40
Bike
i've tried to understand how to make those primitive things usable from clasp, for inline definitions, and failed
16:45:46
drmeister
(1) From either a cleavir xxx-instruction or a bclasp codegen-xxx function (or both) call a function that generates llvm-ir directly - this works in COMPILE and COMPILE-FILE code
16:46:18
drmeister
(2) Write a C++ intrinsic and put it in intrinsics.cc. That gets inlined using llvm inlining and only works with COMPILE-FILE code.
16:48:38
Bike
in other news, i tried a few things replacing (eq x y) with (if (primop:eq x y) t nil), and it saves over half the time even without boolean elimination
16:51:16
drmeister
I thought I generated more code for the eql test in fastgf - but I adopted a hybrid approach to get things up and running.
16:51:47
drmeister
That inlines an EQ test and if that fails punts and calls cc_eql - that will be inlined in COMPILE-FILE'd code.
17:03:08
drmeister
cc_eql doesn't currently do the EQ test because that is in the generated code - but it could be made to do that.
17:03:49
drmeister
Also, it returns 1 or 0 based on the result - it needs to return <something> or NIL correct?
17:14:36
drmeister
I deferred to tx.unsafe_single_float()==ty.unsafe_single_float() because I wasn't sure.
17:22:07
Bike
this actually seems fine to me. i'll do like (declaim (inline eql)) (defun eql (x y) (or (eq x y) (whatever "cc_eql" x y)))
21:18:19
drmeister
at child.on_msg (http://0.0.0.0:8888/nbextensions/nglview-js-widgets/index.js?v=20170714202205:893:42)
22:45:45
Bike
so: i think there's a lot of room for microoptimization of basic library functions, and that i can do that most effectively if i have a typeq that isn't extremely slow
22:49:22
Bike
...and those optimizations will probably make everything a bit faster, though it's harder to gauge that impact
22:51:59
drmeister
(TYPEQ x y) where y is 'fixnum 'single-float 'character - those are just (fixnump x), (single-float-p x), (characterp x) respectively
22:53:03
Bike
if possible i'd rather not call a function at all. (or call an intrinsic that will get inlined later, i guess.)
22:55:35
drmeister
That gets turned into this for boehm/mps builds: https://github.com/drmeister/clasp/blob/dev/src/main/clasp_gc.cc#L2131
22:56:34
drmeister
I think there is a boehmdc feature - or something like that - if not, I'll add it.
22:57:57
drmeister
What we need are access to the integer ranges for the header value and a hash table that associates type specifiers (all symbols) with the header value or value range.
23:01:22
drmeister
We are about to migrate to my parents place - so I'll be out of contact for about 1-2 hours.
23:02:27
drmeister
I can give you a fast TYPEQ with a couple of hours work and a rerun of the static analyzer.
23:04:57
Bike
compiling down typeq is probably going to be more ocmplicated in the future, too, but without a primitive interface there's not much that can be done
23:07:56
Bike
because type checks will have to be moved around and done in relation to each other, i think
0:31:17
drmeister
There is currently no typeq-instruction - that is because they are being translated to typep calls - correct?
0:41:17
drmeister
I mean, the stamp values are integers that start at 1 and go up by 1 - they are shifted into position in the header value in the upper 60 bits.
0:42:03
drmeister
I can build the table so that I incorporate the flag and tag into the value ranges and then just compare header values to the value ranges in the table.
0:45:18
drmeister
The test for Symbol_O is here: https://github.com/drmeister/clasp/blob/dev/src/main/clasp_gc.cc#L2131
1:41:15
drmeister
I started up the static analyzer and it will generate a block of code that can be converted into SYMBOL -> header-value-range