Re: car/cdr chain optimization
Douglas Katzman via Sbcl-help <[email protected]> Mon, 3 Feb 2025 18:59:39 -0500
| Newsgroups | gmane.lisp.steel-bank.general |
|---|---|
| Message-ID | <CAOrNasyXa9dZOjOvo8-Amx2VjGWaBWJp54JWC8SnGNfy2-FYKQ@mail.gmail.com> |
The SBCL compiler is pretty much unaware of the concept of common subexpression elimination. One of my thoughts about how to really improve it to compile into LLVM IR. That idea brings with it a world of issues to resolve in order to get there, but gives a glimmer of hope toward availing ourselves of modern compiler techniques. I wanted to see what would happen if we compile a C program that is nearly equivalent to your EQ expression with type-check - does LLVM eliminate the redundant read and type-check? Indeed it does. I've attached the source and asm. The asm contains only 3 memory loads (one is disguised as a CMP in mem-to-reg form) and 2 conditional branches. See attached if you're curious. _______________________________________________ Sbcl-help mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/sbcl-help
silly.s
(application/octet-stream, 910 B) - not displayed
silly.c
(application/octet-stream, 830 B)
extern void lose(char *fmt, ...) __attribute__ ((noreturn));
typedef unsigned long lispobj;
struct cons {
lispobj car;
lispobj cdr;
};
static inline int consp(lispobj x) { return (((int)x - 7) & 15) == 0; }
#define predict_consp(x) __builtin_expect(consp(x),1)
static inline lispobj get_car(lispobj x) { return ((struct cons*)(x-7))->car; }
static inline lispobj get_cdr(lispobj x) { return ((struct cons*)(x-7))->cdr; }
static inline lispobj checking_car(lispobj x) {
if (predict_consp(x)) return get_car(x); else lose("not a cons: %p", (void*)x);
}
static inline lispobj checking_cdr(lispobj x) {
if (predict_consp(x)) return get_cdr(x); else lose("not a cons: %p", (void*)x);
}
char foopred(lispobj x) {
if (checking_car(checking_cdr(x)) ==
checking_cdr(checking_cdr(x))) return 'y'; else return 'n';
}