> Dale Johannesen wrote: >> Paul Schlie wrote: >>> Dale Johannesen wrote: >>>> Marius Wachtler wrote: >>>> ... >>>> The call to address 0 gets removed. >>>> >>>> define i32 @t(i32 %a) noreturn nounwind readnone { >>>> entry: >>>> unreachable >>>> } >>>> >>>> How can I prevent that the call is removed, without making the >>>> function addr volatile? >>>> Does anyone know which optimization removes it? >>> >>> Calling 0 is undefined behavior; the optimizer is within its >>> rights to remove this. Why do you want to call 0? >> >> Although a C translation unit may arguably not assign a >> correspondingly defined function as having a pointer value >> (address) comparing equal to ((void *) 0); > > Nothing arguable about it, see C99 6.3.2.3- yes agreed, however:>> it's not clear that the standard forbids the invocation of such a >> function > > No such function can exist. I don't think the standard forbids you > to call 0, but it makes calling 0 undefined behavior ("behavior, upon > use of a nonportable or erroneous program construct or of erroneous > data"), since there can't possibly be a valid function there.- also yes, however ((void *) 0) need not have a storage representation being equivalent to ((int) 0), as for example may be represented as being equivalent to ((int) -1) if desired (as may even be desirable in some circumstances); in which circumstance striping calls to "0" would arguably be wrong to broadly do. Although more practically as:>> nor does it seem like a good idea to silently strip any such >> invocations especially if allowed to be specified; as to do so >> would seemingly only mask potentially legitimate problems, and/or >> prevent that intended from being performed although potentially >> relying on an undefined behavior. >> >> (As for example, it's not hard to imagine that it may be desirable >> to allow a machine which may trap such calls to do, and/or to allow >> the invocation of some otherwise specified behavior although >> considered undefined by standard itself.) > > In general, a C compiler is not the right tool to use for > functionality outside the C language, so I'm not inclined to be > sympathetic to this line of reasoning.- I presume you mean things like supporting inline assembly and a multitude of other other useful extensions which correspondingly have no have no well defined behavior? (a rhetorical question) I understand you position, just simply don't agree that supporting extensions which are useful and which do not violate the standard are worthy of being broadly rejected, unless their specified undefined behavior may be usefully capitalized upon to justify some more useful optimization; however as stripping calls to "0", does not seem very useful to anyone in practice, such calls may be more usefully preserved possibly in combination with a useful non-portable warning. Merely IMHO.
There's another point that hasn't been raised yet here, which is that the undefinedness of calling (void*) 0 is a property of C, not necessarily of the LLVM abstract language. I think you can make an excellent case that the standard optimizations should not be enforcing C language semantics, or at least should allow such optimizations to be disabled. Case in point — calls/loads/stores to null may be undefined behavior in C, but they're certainly not undefined behavior in (say) Java. There's a well- known implementation trick in JVMs where you optimistically emit code assuming non-null objects, and then you install signal handlers to raise exceptions in the cases where you're wrong. Now, obviously that trick is going to have implications for the optimizers beyond "don't mark null stores as unreachable" , but even so, it really shouldn't be totally precluded by widespread assumptions of C semantics. John.
2009/6/10 John McCall <rjmccall at apple.com>> There's another point that hasn't been raised yet here, which is that > the > undefinedness of calling (void*) 0 is a property of C, not necessarily > of > the LLVM abstract language. I think you can make an excellent case that > the standard optimizations should not be enforcing C language semantics, > or at least should allow such optimizations to be disabled.All sorts of optimizations rely on this, whether as simple as eliminating comparisons of alloca against null to knowing that two malloc'd pointers can never alias (what if malloc returns null? if null is valid then you can store data there...). Case in point — calls/loads/stores to null may be undefined behavior> in C, > but they're certainly not undefined behavior in (say) Java. There's a > well- > known implementation trick in JVMs where you optimistically emit code > assuming non-null objects, and then you install signal handlers to raise > exceptions in the cases where you're wrong. Now, obviously that trick > is going to have implications for the optimizers beyond "don't mark null > stores as unreachable" , but even so, it really shouldn't be totally > precluded > by widespread assumptions of C semantics.The current workaround is to use an alternate address space for your pointers. At some point we may extend the load/store/call instructions to specify their exact semantics similarly to the integer overflow proposal ( http://nondot.org/sabre/LLVMNotes/IntegerOverflow.txt ). Nick -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20090610/7f12b536/attachment.html>
On Jun 10, 2009, at 12:25 PM, John McCall wrote:> There's another point that hasn't been raised yet here, which is that > the > undefinedness of calling (void*) 0 is a property of C, not necessarily > of > the LLVM abstract language. I think you can make an excellent case > that > the standard optimizations should not be enforcing C language > semantics, > or at least should allow such optimizations to be disabled.For the default address space, LLVM IR *should* currently treat load/ store to null as an undefined operation. To support Java-style "potentially trapping" load/store, we need something like this: http://nondot.org/sabre/LLVMNotes/ExceptionHandlingChanges.txt -Chris
Reasonably Related Threads
- [LLVMdev] Call to address 0 gets removed
- [LLVMdev] Call to address 0 gets removed
- [LLVMdev] Call to address 0 gets removed
- [LLVMdev] Is LLVM expressive enough to represent asynchronous exceptions?
- [LLVMdev] Is LLVM expressive enough to represent asynchronous exceptions?