1-bit integer is tricky in different dialects sometimes. E.g., there is no
arithmetic instructions on 1-bit integer in SPIR-V, i.e., spv.IMul %0, %1 : i1
is not valid. Instead, spv.LogicalAnd %0, %1 : i1 is valid. Creating the op
directly makes lowering easier because we don't need to match a complicated
pattern like !(!lhs && !rhs). Also, this matches the semantic better.
Also add assertions on inputs.