[llvm-dev] Hoisting a guarded division instruction causes division-by-zero

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[llvm-dev] Hoisting a guarded division instruction causes division-by-zero

Alberto Barbaro via llvm-dev
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


_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Reply | Threaded
Open this post in threaded view
|

Re: [llvm-dev] Hoisting a guarded division instruction causes division-by-zero

Alberto Barbaro via llvm-dev

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 <[hidden email]> On Behalf Of Alexey Zhikhartsev via llvm-dev
Sent: Tuesday, December 4, 2018 2:00 PM
To: [hidden email]
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


_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev