For our out-of-tree backend, Machine LICM hoists the division instruction out of the following loop:
int foo(int n, int dividend, int divisor) {
int a = 0;
while (n–) {
if (divisor != 0) {
a += dividend / divisor;
}
}
return a;
}
However, the division instruction causes a hardware exception when the divisor is zero, so there’s a discrepancy between the actual and expected behaviours.
The most straightforward solution that declares the division instruction with hasSideEffects=1 has a significant downside: unnecessary order edges between division instructions and any other instructions that have unmodelled side effects; these edges hinder instruction scheduling. Although, I see that the X86 division instruction has unmodelled side-effects, it is not surprising, since instruction scheduling is not that important for out-of-order processors.
Another solution is to introduce a new flag to MachineInstr, e.g., isDiv (similar to isAdd or mayLoad). Then, the MachineLICM pass will have to check for this flag when it looks for loop invariants. Are there significant downsides to this, or is there a better solution? I would appreciate your thoughts.
Unfortunately, I cannot provide assembly code for our out-of-tree target, for which I apologize. I tried to reproduce the problem for the PowerPC backend: the division is hoisted but it seems that Power division instruction (divw) does not trap, so there is no problem there (but my knowledge of PPC is very limited).
Best,
Alex