Hey guys, I'm learning that LLVM does not preserve faults during constant folding. I realize that this is an architecture dependent problem, but I'm not sure if it's safe to constant fold away a fault on x86-64. A little testcase: #include <stdio.h> int foo(int j, int d) { return j / d ; } int bar (int k, int d) { return foo(k + 1, d); } int main( void ) { int r = bar(5, 0); printf( " r = %d\n", r); } At execution, on an x86-64 processor, this optimized code should fault with a divide-by-zero. At -O2, LLVM 3.1 folds the divide by zero into a constant load. This is, of course, undefined by the C standard, so the folding makes sense on that front. But on x86-64, I don't think this is okay. On x86-64, an integer divide by zero is non-maskable, meaning it will always trap and has no result of any type. My first question is, what's the rationale behind not preserving faults on constant integer folding? Second, is this a bug? With my current understanding, this is most definitely a bug for me on x86-64. But, I'm wondering if there is a hole in my understanding. Thanks in advance, Cameron -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130405/2a299492/attachment.html>
On 4/5/2013 1:23 PM, Cameron McInally wrote:> Hey guys, > > I'm learning that LLVM does not preserve faults during constant > folding. I realize that this is an architecture dependent problem, but > I'm not sure if it's safe to constant fold away a fault on x86-64. > > A little testcase: > > #include <stdio.h> > > int foo(int j, int d) { > return j / d ; > } > > int bar (int k, int d) { > return foo(k + 1, d); > } > > int main( void ) { > int r = bar(5, 0); > printf( " r = %d\n", r); > } > > At execution, on an x86-64 processor, this optimized code should fault > with a divide-by-zero. At -O2, LLVM 3.1 folds the divide by zero into > a constant load. This is, of course, undefined by the C standard, so > the folding makes sense on that front. But on x86-64, I don't think > this is okay. On x86-64, an integer divide by zero is non-maskable, > meaning it will always trap and has no result of any type.Per C and C++, integer division by 0 is undefined. That means, if it happens, the compiler is free to do whatever it wants. It is perfectly legal for LLVM to define r to be, say, 42 in this code; it is not required to preserve the fact that the idiv instruction on x86 and x86-64 will trap. -- Joshua Cranmer Thunderbird and DXR developer Source code archæologist
On 5 April 2013 19:40, Joshua Cranmer 🐧 <Pidgeot18 at gmail.com> wrote:> Per C and C++, integer division by 0 is undefined. That means, if it > happens, the compiler is free to do whatever it wants. It is perfectly > legal for LLVM to define r to be, say, 42 in this code; it is not required > to preserve the fact that the idiv instruction on x86 and x86-64 will trap. >Undefined behaviour aside, would be good to have a warning, I think. Does the static analyser have something like it? cheers, --renato -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130405/34f9ccd8/attachment.html>
On Fri, Apr 5, 2013 at 2:40 PM, Joshua Cranmer 🐧 <Pidgeot18 at gmail.com>wrote: ...> Per C and C++, integer division by 0 is undefined. That means, if it > happens, the compiler is free to do whatever it wants. It is perfectly > legal for LLVM to define r to be, say, 42 in this code; it is not required > to preserve the fact that the idiv instruction on x86 and x86-64 will trap.This is quite a conundrum to me. Yes, I agree with you on the C/C++ Standards interpretation. However, the x86-64 expectations are orthogonal. I find that other compilers, including GCC, will trap by default at high optimization levels on x86-64 for this test case. Hardly scientific, but every other compiler on our machines issues a trap. We take safety seriously in our compiler. Our other components go to great lengths not to constant fold an integer division by zero. We would also like LLVM to do the same. Are there others in the community who feel this way? I can envision an option which preserves faults during constant folding. E.g. an integer version of -enable-unsafe-fp-math or gfortran's -ffpe-trap. More accurately, this hypothetical option would suppress the folding of unsafe integer expressions altogether. Would an option such as this benefit the community at large? To be complete, I've also explored the idea of generating a __builtin_trap() call for such expressions before the IR level. However, I have not yet convinced myself that this will generate the same fault as the actual sdiv/udiv instruction would. Things to do. -Cameron -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130405/ddc211b4/attachment.html>