Alexey Zhikhartsev via llvm-dev
2018-Dec-04 22:00 UTC
[llvm-dev] Hoisting a guarded division instruction causes division-by-zero
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20181204/35cddaaf/attachment.html>
via llvm-dev
2018-Dec-05 20:56 UTC
[llvm-dev] Hoisting a guarded division instruction causes division-by-zero
Hi Alex,
I've been looking into int div-by-0 issues that look similar, but
they've lead me to bugs in SCEV, rather than LICM. So chances are, they
aren't related to your issue. But just in case, I thought I'd point
them out to you.
The issues I've been looking at are PR30806 and PR38697. r347934 is a fix
committed last week for PR30806. And there is a patch up for review
(https://reviews.llvm.org/D55232) for PR38697.
If you haven't tried a modern revision (that includes r347934), you might
want to see if it solves it. But given your LICM comment, I'm not
optimistic. (In fact, I've verified that at -O2, for x86_64, the division
isn't hoisted, even before the fix of r347934. So unless there is some
subtle interaction on your out-of-tree backend, this won’t help. Either way, I
figured you might want to be aware.)
Thanks,
-Warren Ristow
From: llvm-dev <llvm-dev-bounces at lists.llvm.org> On Behalf Of Alexey
Zhikhartsev via llvm-dev
Sent: Tuesday, December 4, 2018 2:00 PM
To: llvm-dev at lists.llvm.org
Subject: [llvm-dev] Hoisting a guarded division instruction causes
division-by-zero
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20181205/00631a1a/attachment.html>