How doesn't llvm generate IR for logical negate operation

How can I generate LLVM IR for both logical NEG (!)? For example, if I have Int32Ty a,

For the bitwise NEG(~):

c = ~a ;

I can use the following API from LLVM:

BinaryOperator *neg = BinaryOperator::CreateNeg(nbits, "bitwiseNEG", insertBefore);

How, if I want to generate logical NEG:

c = !a;

what should I do for this?


LLVM doesn’t have a “logical neg” (or “not”) operator. That’s a C thing. Do a compare against 0 to create an i1 result, then zero extend the i1 to the size of integer result you want.

Thanks, Bruce. So, what is the easiest way to check if there is any bit set to 1 in a vector type? I used bitcast instruction to cast it into “iN” first and them compare iN to 0. Do you have a better way to do it? Thanks again.

Sure, if you actually just want an i1 saying whether or not at least one bit is set to 1, then comparing against 0 is the right thing.

That should end up generating a unary TST instruction on ISAs that have one.

Yes, but my point is that there would be some overhead to do cast the vectortype to an integerNty. Is there any good way to check not all of these N bits in the vectortype are 0s?

I suppose that depends on your CPU. Do you even have a CPU that supports operations on as packed bits in vector registers?

I see. My CPU is a general Core i7 Ivy bridge CPU.

In that case, I’m pretty sure that if you use in LLVM IR then the generated code will use 8 bits in the vector registers for each i1, which is probably not what you want.

But hopefully someone who actually knows this stuff will come along shortly…

Yes. That’s something I am worried about. But anyway, I will try it first and see what’s going on in the assembly. I will keep you posted if it works. I would appreciate if some who knows this…

It seemed that it finally generated a “vucomisd” instruction for the two <2 x double> operands.

BTW, is it possible to load a float point data to all the entries of an SSE/AVX register? In other words, how can generate IR in LLVM to work like instrinsics _mm_load_ps1(double const* addr) or _mm_load_pd1(double const* addr)?