Improve optimizations for boolean values

LLVM doesn't handle i1 value in allocas/memory very well and skips a number of optimizations if it hits it. So we have to do the same thing that Clang does, using i1 for SSA values, but storing i8 in memory.

Fixes #15203.
Regarding the range asserts for char, those didn't seem all that useful here, the value is just passed on to another function. Not much potential for optzns unless the wrapped function gets inlined. Not sure how common that is, and after all, it wasn't using the range assert before either :-)