Why LLVM IR does not distinguish signed and unsigned multiplication?

I see that LLVM IR has udiv and div instruction but only has mul instruction.

So how does the backend know whether translate this mul in IR into a signed multiplication (mul) or unsigned multiplication (imul) in machine code?

There is no difference between signed multiplication and unsigned multiplication, if you’re multiplying iN * iN → iN, so the choice is completely arbitrary.

However, the instructions you are talking about don’t do that, but instead do an iN * iN → i2N wide multiplication instruction. In the list of instruction kinds LLVM has for lowering, you’ll notice that there are indeed signed and unsigned variants of the wide multiply: llvm-project/ISDOpcodes.h at main · llvm/llvm-project · GitHub, so when it is necessary to do a wide multiply, the lowering will know which one to pick. LLVM IR itself doesn’t have a native wide multiply intrinsic, but the pattern-match of mul (sext/zext a) will trigger lowering to a wide multiply, and there are cases (such as division by a small constant) where wide multiplies are generated from other constructs.

Note that for division and remainder, the two operations are not equivalent on iN for both signed and unsigned numbers, so they need to have a version for each sign.

1 Like