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?

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