Ryan M. Lefever
2008-Apr-30 18:10 UTC
[LLVMdev] optimization assumes malloc return is non-null
Consider the following c code: #include <stdlib.h> int main(int argc, char** argv){ if(malloc(sizeof(int)) == NULL){ return 0; } else{ return 1; } } When I compile it with -O3, it produces the following bytecode: define i32 @main(i32 %argc, i8** %argv) { entry: ret i32 1 } Is this an error? It should be possible for malloc to return NULL, if it can not allocate more space. In fact, some programs should be able to gracefully handle such situations. Regards, Ryan
Jonathan S. Shapiro
2008-Apr-30 18:23 UTC
[LLVMdev] optimization assumes malloc return is non-null
For C code this is unquestionably a bug. On Wed, 2008-04-30 at 13:10 -0500, Ryan M. Lefever wrote:> Consider the following c code: > > #include <stdlib.h> > > int main(int argc, char** argv){ > if(malloc(sizeof(int)) == NULL){ return 0; } > else{ return 1; } > } > > > When I compile it with -O3, it produces the following bytecode: > > define i32 @main(i32 %argc, i8** %argv) { > entry: > ret i32 1 > } > > Is this an error? It should be possible for malloc to return NULL, if > it can not allocate more space. In fact, some programs should be able > to gracefully handle such situations. > > Regards, > Ryan > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
David Vandevoorde
2008-Apr-30 18:29 UTC
[LLVMdev] optimization assumes malloc return is non-null
On Apr 30, 2008, at 2:10 PM, Ryan M. Lefever wrote:> Consider the following c code: > > #include <stdlib.h> > > int main(int argc, char** argv){ > if(malloc(sizeof(int)) == NULL){ return 0; } > else{ return 1; } > } > > > When I compile it with -O3, it produces the following bytecode: > > define i32 @main(i32 %argc, i8** %argv) { > entry: > ret i32 1 > } > > Is this an error? It should be possible for malloc to return NULL, if > it can not allocate more space. In fact, some programs should be able > to gracefully handle such situations.It's an allowable program transformation because a call to malloc is not in itself a side effect. See e.g. 5.1.2.3 in the C standard. Daveed
Jonathan S. Shapiro
2008-Apr-30 18:47 UTC
[LLVMdev] optimization assumes malloc return is non-null
Daveed: Perhaps I am looking at the wrong version of the specification. Section 5.1.2.3 appears to refer to objects having volatile-qualified type. The type of malloc() is not volatile qualified in the standard library definition. In general, calls to procedures that are outside the current unit of compilation are presumed to involve side effects performed in the body of the external procedure (at least in the absence of annotation). Can you say what version of the standard you are referencing, and (just so I know) why section 5.1.2.3 makes a call to malloc() different from any other procedure call with respect to side effects? Thanks Jonathan On Wed, 2008-04-30 at 14:29 -0400, David Vandevoorde wrote:> On Apr 30, 2008, at 2:10 PM, Ryan M. Lefever wrote: > > Consider the following c code: > > > > #include <stdlib.h> > > > > int main(int argc, char** argv){ > > if(malloc(sizeof(int)) == NULL){ return 0; } > > else{ return 1; } > > } > > > > > > When I compile it with -O3, it produces the following bytecode: > > > > define i32 @main(i32 %argc, i8** %argv) { > > entry: > > ret i32 1 > > } > > > > Is this an error? It should be possible for malloc to return NULL, if > > it can not allocate more space. In fact, some programs should be able > > to gracefully handle such situations. > > It's an allowable program transformation because a call to malloc is > not in itself a side effect. See e.g. 5.1.2.3 in the C standard. > > Daveed > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Chris Lattner
2008-May-01 02:21 UTC
[LLVMdev] optimization assumes malloc return is non-null
On Wed, 30 Apr 2008, Ryan M. Lefever wrote:> Consider the following c code: > #include <stdlib.h> > int main(int argc, char** argv){ > if(malloc(sizeof(int)) == NULL){ return 0; } > else{ return 1; } > } > > > When I compile it with -O3, it produces the following bytecode: > > define i32 @main(i32 %argc, i8** %argv) { > entry: > ret i32 1 > } > > Is this an error? It should be possible for malloc to return NULL, if > it can not allocate more space. In fact, some programs should be able > to gracefully handle such situations.LLVM should not (and does not, afaik) assume the malloc succeeds in general. If LLVM is able to eliminate all users of the malloc assuming the malloc succeeded (as in this case), then it is safe to assume the malloc returned success. -Chris -- http://nondot.org/sabre/ http://llvm.org/
David Greene
2008-May-01 17:00 UTC
[LLVMdev] optimization assumes malloc return is non-null
On Wednesday 30 April 2008 21:21, Chris Lattner wrote:> If LLVM is able to eliminate all users of the malloc assuming the > malloc succeeded (as in this case), then it is safe to assume the malloc > returned success.Ah, I missed this bit. I didn't see that the result of malloc was not used outside the if test. But is the if test considered a "use?" If so, it's a use in the context of success or failure, so how can LLVM assume success? Your argument seems circular: 1. LLVM can't assume malloc success 2. If, assuming malloc success, LLVM can eliminate all uses, the malloc becomes dead. 3. LLVM can eliminate the dead malloc. 4. Since the malloc was eliminated under assumption of success, the if test becomes dead code and we can assume the malloc succeeded. Perhaps the trouble is that your statement, "If LLVM is able to eliminate all users of the malloc assuming the malloc succeeded," is ambiguous. Do you mean that LLVM assumes the malloc succeeded and then tries to eliminate all users by making use of that assumption or that it tries to eliminate all users that are in a context where malloc is assumed to have succeeded (for example the "else" of a check for malloc failure)? If the former, it's a circular argument, if the latter, then what about the use in the if test, which is in a context where we don't know whether the malloc succeeded or not? Just trying to get some clarity. -Dave
Maybe Matching Threads
- [LLVMdev] optimization assumes malloc return is non-null
- [LLVMdev] optimization assumes malloc return is non-null
- [LLVMdev] optimization assumes malloc return is non-null
- [LLVMdev] optimization assumes malloc return is non-null
- [LLVMdev] optimization assumes malloc return is non-null