Tuesday, May 16, 2006

Factor 0.82 now available

Factor 0.82 is now available. This release brings an overhauled compiler and various other improvements.

Thursday, May 11, 2006

Factor 0.82 almost ready

I'm tying up some loose ends in the register allocator, and updating the AMD64 compiler backend. Factor 0.82 should be out in a few days. Apart from the compiler overhaul, this release only brings a few minor improvements and bug fixes.

My plans for 0.83 include:
  • Major improvements to the UI
  • Compiler internals documentation
  • Possibly the new array quotation interpreter, and phasing out cons cells
  • Getting Factor running on Mac Intel

Going back and forth between UI and compiler work for each release seems to be the pattern for the last few releases. In 0.84, I will probably once again work on the compiler, and implement complex float intrinsics using SSE2 and AltiVec, as well as some new dataflow and template optimizations I've been planning out.

Tuesday, May 09, 2006

Cool Common Lisp project

It appears as if more and more people are building really neat applications using McCLIM, such as cl-wav-synth. Not bad for an interpreted AI language from the 50s only used by academics whose sole datatype is the list, as some seem to think anyway :-)

Floating point intrinsics working on PowerPC

The compiler now inlines machine code for floating point operations instead of calling the runtime. This results in a performance improvement on my 2.5 Ghz PowerPC G5:
BenchmarkBeforeAfter
Mandelbrot10.55.4
Raytracer61.141

Here are the x86 results (Pentium 4 1.8 GHz):
BenchmarkBeforeAfter
Mandelbrot8.74.3
Raytracer44.333.2

The Before column is 0.81, the After column is 0.82, and times are in seconds.
Yes, a five year old box beats my brand new G5, but I suspect this is because my compiler doesn't do instruction scheduling.
Bigger gains will come as the higher levels of the compiler improve, resulting in more inlining.

Thursday, May 04, 2006

Java 6 last release to support PowerPC macs?

So while I've been considering dropping support for x86 CPUs older than 5 years (and I decided I won't do it, and just offer two boot images for x86 instead), Apple released a Java 6 beta for Intel macs a few days ago, indicating it will follow suit with a PowerPC version soon. However the word is that this will be the last release to support PowerPC macs. Just goes to show that "write once run anywhere(tm)(R)(C)" is a marketing myth, and indeed Java is one of the least portable languages out there.

Wednesday, May 03, 2006

Is SSE2 mainstream?

The SSE2 extensions to the x86 architecture debuted when the Pentium 4 was released. SSE is a vector processing extension which only dealt with single-precision floats. SSE2 supports double-precision floats. What this means is that as of the Pentium 4, the x86 finally has a sane FPU architecture (the x87 is horrible to program for; it is stack-based, but only has a depth of 7 cells so you get the disadvantages of registers together with the disadvantages of a stack).

What I'm wondering is how widespread Pentium 4 (and above) chips are, and if the x86 backend of the Factor compiler should require SSE2 for floating point operations.

If you have thoughts, share them in the comments. Most likely, nobody will respond, and I will go ahead with my evil plan to drop support for Pentium III chips and older :-)

Monday, May 01, 2006

Assembler templates

I've finished updating the PowerPC and x86 backends for the new compiler design, and new boot images are up. AMD64 will have to wait a few days.

If you study the compiler source, you will find many calls to the words with-template and define-intrinsic; the former is called during code generation time to load inputs from the stack to registers, and store registers back to the stack. The latter associates a word with a compiler intrinsic quotation which passes the specified arguments to with-template.

Here is a typical definition:
: generate-fixnum-mod
#! PowerPC doesn't have a MOD instruction; so we compute
#! x-(x/y)*y. Puts the result in "s" operand.
"s" operand "r" operand "y" operand MULLW
"s" operand "s" operand "x" operand SUBF ;

\ fixnum-mod [
! divide x by y, store result in x
"r" operand "x" operand "y" operand DIVW
generate-fixnum-mod
] H{
{ +input { { f "x" } { f "y" } } }
{ +scratch { { f "r" } { f "s" } } }
{ +output { "s" } }
} define-intrinsic

This looks like a macro assembler; the operands "x", "y", "r" and "s" are assigned at compile time, and used to generate an assembly segment involving various instructions, such as MULLW and SUBF.

The complete list of specifiers which can be passed as keys in the hashtable there is as follows:
  • +input - an array of pairs, where each pair is of the form { vreg string }; the string is an operand name, and the vreg is either an integer or f (meaning any free register can be assigned). The with-template form compiles code to load objects from the stack into the input registers
  • +scratch - this specifier is of the same format as +input, except here the registers are untouched. The body of the template can use them for any purpose, including outputs.
  • +output - a list of previously-assigned operand names holding values which should be moved to the stack. Registers allocated by +input and +scratch can be listed here.
  • +scratch - a list of previously-assigned operand names whose contents should not be assumed to have remained constant after the template finishes executing. Usually a template does not modify its inputs; however if it does, they must be listed here to avoid miscompiling code.

I'm going to implement a few assorted cleanups and optimizations now, and then move on to floating point intrinsics, which should provide a nice performance boost.