[llvm-dev] unsigned operations with negative numbers
Alexandre Isoard via llvm-dev
llvm-dev at lists.llvm.org
Mon Jul 31 07:40:39 PDT 2017
On Mon, Jul 31, 2017 at 9:56 AM, Anastasiya Ruzhanskaya via llvm-dev <
llvm-dev at lists.llvm.org> wrote:
> I want to know, if I can always assume that when I do unsigned operations
> udiv, urem
> I will get the both operands converted to unsigned values?
Signed-ness in LLVM is not stored into the integer, it is left to
interpretation to the instruction that use them.
udiv / urem will interpret both their operands as unsigned integer. (and
the behavior is straight forward)
sdiv / srem will interpret both their operands as signed integers stored
with 2's complement. (and the behavior match the "crappy" behavior of C)
> with under optimized version of code I sometimes receive these lines:
> unsigned a = 123;
> int b = -2;
> int c = a / b;
> -> %1 = udiv i32 123, -2
> and get the result 0. Will it always be zero?
Yes. We decided that LLVM IR, when printed for human consumption, would
print literal constants as signed integers.
Here it is -2, but it actually means 4294967294. This number is indubitably
bigger than 123.
udiv i32 -2, -2
udiv i32 -1, -2
Are the only ones that will return a non null result, in both cases the
result will be 1.
or is it undefined? Somewhere I have read that it may produce garbage.
> will it be zero in this case : %1 = udiv i32 -123, 2?
%1 = udiv i32 -123, 2 = udiv i32 4294967173, 2 = 2147483586
> However, when I set only the result as unsigned, then :
> int a = 123;
> int b = -2;
> unsigned int c = a / b;
> -> %1 = sdiv i32 123, -2
> the result seems to be correct. So one operand (not the result variable)
> needs to be unsigned in order the result was unsigned too?
That is a C semantic. From what I remember, if one of the operand is
unsigned, then the computation will be unsigned.
The return value type does not influence the type of the operation. But it
might introduce a final cast.
> What should I expect from sign of the operand if I get the line:
> %1 = udiv i32 %a.o, 2. Can it in this case be negative. Or this situation
> is only the result of under optimization and zero value is ok?
The result cannot be "negative". Because negative numbers start with a 1,
and a udiv by 2 is equal to a logical shift right by 1 bit, which introduce
a 0 as first bit.
Which means that if a later operand interpret %1 as a signed integer, it
will still be a positive value. It can be zero if %a.o is 0 or 1.
Note that if %a.o was produced by a "signed" operation, and you see the
result as a negative number, %a.o can grow in size (because the number will
now become positive if interpreted as signed number).
> These questions may be related mostly to c, but still, perhaps llvm has
> some additional rules that I didn't find. The general thing I wanted to
> know what to expect from sign of value when I get urem/udiv ops in final
It depends what you mean by "sign of value". Again, in llvm, integer data
do not have a sign. You will see that there is no sign-cast instruction.
Some instruction like add/sub/mul/etc... are sign-oblivious and do not need
to distinguish between signed/unsigned kind.
While udiv/sdiv, urem/srem, etc... are different depending if you take into
account a signed-ness of their operands or not.
In LLVM, sign of numbers interpreted as signed values follow 2's
complement. (0 is positive, and there the number of maximum absolute value
is negative and do not have a positive equivalent, which is annoying when
considering signed division by -1).
> Thank you in advance for the answer.
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the llvm-dev