The Mercury language (http://www.mercury.csse.unimelb.edu.au/) does one better. It can use the fact that multiplication is associative to automatically transform the non-tail-recursive function into the tail-recursive form.
Wow, I didn't know this. It's such a great feature, they really should advertise it more.
(Examining assembler output shows that a naïve implementation of fact() also gets the autovectorization treatment as well as a fair bit of loop unrolling. Very impressive.)