This code is essentially from an LTP test ( http://ltp.sourceforge.net/ <http://ltp.sourceforge.net/> ). #include <stdlib.h> int main() { void *curr; do { curr = malloc(1); } while (curr); return 0; } If you compile it with no optimization, it will keep the malloc calls. If you compile it with -O2, it will create an infinite loop, i.e. assuming that malloc always returns a non zero result and the result is not used. ~/llvmpb/install/bin/clang loop.c -O2 -S .file "loop.c" .text .globl main .align 16, 0x90 .type main, at function main: # @main .cfi_startproc # BB#0: # %entry .align 16, 0x90 .LBB0_1: # %do.body # =>This Inner Loop Header: Depth=1 jmp .LBB0_1 .Ltmp0: .size main, .Ltmp0-main .cfi_endproc .section ".note.GNU-stack","", at progbits -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121001/98dfdbb2/attachment.html>
On 1 October 2012 18:34, reed kotler <rkotler at mips.com> wrote:> This code is essentially from an LTP test ( http://ltp.sourceforge.net/). > > > #include <stdlib.h> > > int main() { > void *curr; > > do { > curr = malloc(1); > } while (curr); > > return 0; > > } > > If you compile it with no optimization, it will keep the malloc calls. > > If you compile it with -O2, it will create an infinite loop, i.e. assuming > that malloc always returns a non zero result and the result is not used. >As far as I know, this optimization is legal. Fix the test with a volatile pointer: int main() { volatile char *curr; do { curr = malloc(1); int i = *curr; (void)i; } while (curr); return 0; } which produces: pushq %rax .Ltmp1: movl $1, %edi callq malloc movb (%rax), %cl testq %rax, %rax jne .LBB0_1 # BB#2: # %do.end xorl %eax, %eax popq %rdx ret Oh how people don't appreciate the luxury of having an infinite memory machine! Nick ~/llvmpb/install/bin/clang loop.c -O2 -S> > .file "loop.c" > .text > .globl main > .align 16, 0x90 > .type main, at function > main: # @main > .cfi_startproc > # BB#0: # %entry > .align 16, 0x90 > .LBB0_1: # %do.body > # =>This Inner Loop Header: Depth=1 > jmp .LBB0_1 > .Ltmp0: > .size main, .Ltmp0-main > .cfi_endproc > > > .section ".note.GNU-stack","", at progbits > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121001/c986b9bf/attachment.html>
On 2 Oct 2012, at 03:40, Nick Lewycky wrote:> As far as I know, this optimization is legal. Fix the test with a volatile pointer:Why would that be required? malloc() is defined by the standard to return a pointer that is distinct from any other valid pointer, or NULL. Any optimisation that makes any assumptions about its next value is invalid.> int main() { > volatile char *curr; > > do { > curr = malloc(1); > int i = *curr;This, in particular, looks very wrong. If curr is void, then you are dereferencing an invalid pointer, and so you are doing something undefined. In fact, this version of the code is completely free to elide the conditional loop, because by dereferencing the pointer you are asserting that it is not NULL (or, at least, that if it is then after this point the program is in an undefined state and so any behaviour is legal) and so it is completely free to generate the code that it in fact does generate without this test. So here we have another bug, because the testq in your output is redundant after the movb. David
>>>>> On Mon, 1 Oct 2012 19:40:58 -0700, Nick Lewycky <nlewycky at google.com> said:> On 1 October 2012 18:34, reed kotler <rkotler at mips.com> wrote: > This code is essentially from an LTP test ( > http://ltp.sourceforge.net/ ). > #include <stdlib.h> > int main() { void *curr; > do { curr = malloc(1); } while (curr); > return 0; > } > If you compile it with no optimization, it will keep the > malloc calls. > If you compile it with -O2, it will create an infinite > loop, i.e. assuming that malloc always returns a non zero > result and the result is not used. Nick> As far as I know, this optimization is legal. Well, indeed the result is used by the while and we have a control dependence on the future execution. The termination or not of the program is a side effect from the user perspective. [...] Nick> Oh how people don't appreciate the luxury of having an Nick> infinite memory machine! You have also a potentially infinite loop, which is another kind of luxury. More boring, especially on the end. :-) Even if you have a lazy allocation as with the default libC on Linux that allocates the memory pages only on demand, the memory will blow up just because the malloc() library itself has to track the allocations for a potential future free(). Of course, if you have an infinite memory, you can avoid implementing free() or your interprocedural analysis may prove you do not call free() in your program. :-) This makes me feel uncomfortable to have this kind of optimizations with too many hypothesis on the run-time, even if it addresses domains not well captured by the norm... How to know about the real target? It may be another allocation library, some LD_PRELOAD hack to insert memory verification code or at the end the code is to be run inside a tool like valgrind to track this very malloc() bug that would be hidden by this optimization... :-( Just to give an example from another compiler, in the PIPS source-to-source compiler the side effect of malloc() is taken into account by registering a write effect on an abstract location which is tested later by some optimization phases to avoid too much liberal optimizations, like the one above. Anyway, this is an interesting limit case to discuss tonight at the LLVM Bay-area Social. :-) -- Ronan KERYELL |\/ Phone: +1 408 658 9453 SILKAN Wild Systems |/) 4962 El Camino Real #201 K Ronan.Keryell at silkan.com Los Altos, CA 94022 |\ skype:keryell USA | \ http://silkan.com
On 10/1/2012 9:40 PM, Nick Lewycky wrote:> > As far as I know, this optimization is legal.It's not legal. 1. malloc is not known to always return a non-null pointer. 2. malloc has side-effects and hence cannot be eliminated. -K -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation