David, Here is the definition accepted by Hal of what we’re doing> 1. Sometimes there are abstraction penalties in C++ code > 2. That can be optimized away after template instantiation, function inlining, etc > 3. When they for example exhibit this pattern > if (A) { > stuff; > } else { > other stuff including “undefined behavior”; > } > 4. Where the compiler assumes “undefined behavior” doesn’t actually happen because > In the C language standard it is the users responsibility to avoid it > 5. Therefore in this example the compiler can a) delete the else-clause > b) delete the if-cond, c) assume A is true and propagate that informationWe are actively deleting undefined behavior, and the question is why given that doing so potentially masks a real source code bug. At the very least deleting undefined behavior should not be the default. Peter Lawrence.> On Jul 12, 2017, at 2:24 AM, David Chisnall <David.Chisnall at cl.cam.ac.uk> wrote: > > On 10 Jul 2017, at 19:36, Peter Lawrence via llvm-dev <llvm-dev at lists.llvm.org> wrote: >> >> why should we ever optimize / delete any UB at all ? > > No one has addressed this yet, which may be why you are still under the impression that it’s under discussion. You seem to have some misconceptions about UB. There are two major reasons for UB in a language such as C: > > 1. The safe version may be prohibitively expensive on some architectures. For example, division by zero will give a trap on some architectures or an unspecified value on others. If the C specification stated that it gave an unspecified value, then on architectures that trap every division would have to be wrapped in a branch that tested if the divisor was zero and branched over the divide instruction if so. This would lead to very inefficient code on these architectures, so the C standard says that anything is allowed to happen. > > 2. Some properties are effectively impossible to verify statically[1]. For example, it is undefined behaviour in C to use a pointer to a deallocated object[2]. If C required well-defined behaviour here then it would effectively be mandating some form of garbage collector: you’d need to either find all pointers to an object and null them on free, or you’d need to mark the object, check the mark on every load, and not reuse the memory until later. This would be unacceptable overhead for a C implementation. A lot of other things are in this category. > > Many things are a mixture of these. Most optimisations that rely on undefined behaviour are not saying ‘aha, we’ve spotted that the program invokes undefined behaviour, we can replace the whole thing with a trap instruction!’, they’re saying ‘this program does either X or Y, X would be undefined behaviour and so we can assume that it does Y’. Not being able to do the latter would mean that they’d need to insert run-time checks each time, which would negate the optimisation and *in well-written code would never be hit*. > > The cases where the compiler can statically prove that undefined behaviour is present are comparatively rare. > > David > > [1] Note: Some of these are possible with whole-program analysis, so if you’re happy without shared libraries and with week-long compile times then it’s possible. > > [2] The wording of this actually means that it’s impossible to implement malloc() in ISO C, because as soon as the pointer has been passed to free then it becomes invalid and using it to put the object on a free list invokes undefined behaviour.
Chandler Carruth via llvm-dev
2017-Jul-13 21:15 UTC
[llvm-dev] GEP with a null pointer base
On Thu, Jul 13, 2017 at 5:13 PM Peter Lawrence via llvm-dev < llvm-dev at lists.llvm.org> wrote:> David, > Here is the definition accepted by Hal of what we’re doing > > > 1. Sometimes there are abstraction penalties in C++ code > > 2. That can be optimized away after template instantiation, function > inlining, etc > > 3. When they for example exhibit this pattern > > if (A) { > > stuff; > > } else { > > other stuff including “undefined behavior”; > > } > > 4. Where the compiler assumes “undefined behavior” doesn’t actually > happen because > > In the C language standard it is the users responsibility to avoid it > > 5. Therefore in this example the compiler can a) delete the else-clause > > b) delete the if-cond, c) assume A is true and propagate that > information > > > > We are actively deleting undefined behavior, and the question is why > given that doing so potentially masks a real source code bug. > At the very least deleting undefined behavior should not be the default. >You are asserting this (again), but others have clearly stated that they disagree. David gave detailed and clear reasons why. Continuing to re-state positions is not productive. -Chandler -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170713/be2c95ed/attachment.html>
2017-07-12 11:17 GMT-07:00 Peter Lawrence via llvm-dev < llvm-dev at lists.llvm.org>:> David, > Here is the definition accepted by Hal of what we’re doing > > > 1. Sometimes there are abstraction penalties in C++ code > > 2. That can be optimized away after template instantiation, function > inlining, etc > > 3. When they for example exhibit this pattern > > if (A) { > > stuff; > > } else { > > other stuff including “undefined behavior”; > > } > > 4. Where the compiler assumes “undefined behavior” doesn’t actually > happen because > > In the C language standard it is the users responsibility to avoid it > > 5. Therefore in this example the compiler can a) delete the else-clause > > b) delete the if-cond, c) assume A is true and propagate that > information > > > > We are actively deleting undefined behavior, and the question is why > given that doing so potentially masks a real source code bug. > At the very least deleting undefined behavior should not be the default. >I don't believe it is the default today: optimizations aren't turned on unless you opt-in. -- Mehdi -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170713/daa92db7/attachment.html>
Chandler, The only thing David made clear that wasn’t already clear is that he believes UB to be “comparatively rare”, which is in agreement with what Hal already said which is that he does not expect deleting UB will be of benefit to for example SPEC benchmarks. Given that it is “comparatively rare”, why all the effort to delete it ? And why make deleting it the default rather than warning about it ? Peter> On Jul 13, 2017, at 2:15 PM, Chandler Carruth <chandlerc at gmail.com> wrote: > > On Thu, Jul 13, 2017 at 5:13 PM Peter Lawrence via llvm-dev <llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>> wrote: > David, > Here is the definition accepted by Hal of what we’re doing > > > 1. Sometimes there are abstraction penalties in C++ code > > 2. That can be optimized away after template instantiation, function inlining, etc > > 3. When they for example exhibit this pattern > > if (A) { > > stuff; > > } else { > > other stuff including “undefined behavior”; > > } > > 4. Where the compiler assumes “undefined behavior” doesn’t actually happen because > > In the C language standard it is the users responsibility to avoid it > > 5. Therefore in this example the compiler can a) delete the else-clause > > b) delete the if-cond, c) assume A is true and propagate that information > > > > We are actively deleting undefined behavior, and the question is why > given that doing so potentially masks a real source code bug. > At the very least deleting undefined behavior should not be the default. > > You are asserting this (again), but others have clearly stated that they disagree. David gave detailed and clear reasons why. Continuing to re-state positions is not productive. > > -Chandler-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170719/867bf94f/attachment.html>