I don't know what the difference between running "directly on the CPU" and "compiling to some kind of native code" is. If you mean that the Web page delivers raw machine code to the browser, that describes NaCl, not PNaCl.
Regardless, it is incorrect that asm.js is first interpreted before being compiled. asm.js is compiled ahead of time exactly as PNaCl is.
This doesn't sound right. It's a subset of javascript, you are still shipping javascript to the browser... which is then parsed and then jitted in said browser. Which is an extra step above bitcode, where you just jit it as is. Albeit it's specifically crafted to be easier to optimize but it is still javascript that you are sending to the browser.
I feel like someone is trying too hard to make javascript into something it isn't and shouldn't be. Javascript does it's thing pretty well, why is there no room for other tools in the toolbox?
The contents of Bitcode/Reader/ in LLVM are about 3,000 lines of code alone, and that does not include the definition of LLVM data structures, the validator, etc.
Regardless, it is incorrect that asm.js is first interpreted before being compiled. asm.js is compiled ahead of time exactly as PNaCl is.