Hi Nick,> The attribute you're looking for, "delete if result is unused" doesn't > exist in LLVM. I've considered it in the past, but the truth is that > most of the time I want to eliminate dead malloc's, they *do* have a > use: the matching free. At some point I expect I'm going to teach LLVM > to remove dead malloc+free / new+delete / new[]+delete[] pairings, but I > haven't gotten around to it yet. Teaching it to kill an allocation with > no uses at all will be dead simple too.LLVM already removes malloc+(perhaps compare with null)+free. Ciao, Duncan.
Duncan Sands wrote:> Hi Nick, > >> The attribute you're looking for, "delete if result is unused" doesn't >> exist in LLVM. I've considered it in the past, but the truth is that >> most of the time I want to eliminate dead malloc's, they *do* have a >> use: the matching free. At some point I expect I'm going to teach LLVM >> to remove dead malloc+free / new+delete / new[]+delete[] pairings, but I >> haven't gotten around to it yet. Teaching it to kill an allocation with >> no uses at all will be dead simple too. > > LLVM already removes malloc+(perhaps compare with null)+free.What? declare noalias i8* @malloc() nounwind declare void @free(i8* nocapture) nounwind define i8 @test() { %A = call i8* @malloc() call void @free(i8* %A) ret i8 undef } doesn't optimize at all. While we're at it, we also don't get: declare noalias i8* @malloc() nounwind define i8 @test() { %A = call i8* @malloc() %B = load i8* %A ret i8 %B } either, though that's fixable by inserting llvm.lifetime.start right after the malloc. Nick
Hi Nick,>>> The attribute you're looking for, "delete if result is unused" doesn't >>> exist in LLVM. I've considered it in the past, but the truth is that >>> most of the time I want to eliminate dead malloc's, they *do* have a >>> use: the matching free. At some point I expect I'm going to teach LLVM >>> to remove dead malloc+free / new+delete / new[]+delete[] pairings, but I >>> haven't gotten around to it yet. Teaching it to kill an allocation with >>> no uses at all will be dead simple too. >> >> LLVM already removes malloc+(perhaps compare with null)+free. > > What? > > declare noalias i8* @malloc() nounwind > declare void @free(i8* nocapture) nounwind > define i8 @test() { > %A = call i8* @malloc()^ malloc with wrong signature> call void @free(i8* %A) > ret i8 undef > } > > doesn't optimize at all. While we're at it, we also don't get: > > declare noalias i8* @malloc() nounwind > define i8 @test() { > %A = call i8* @malloc() > %B = load i8* %A > ret i8 %B > } > > either, though that's fixable by inserting llvm.lifetime.start right > after the malloc.Take a look at: Instruction *InstCombiner::visitMalloc(Instruction &MI) { // If we have a malloc call which is only used in any amount of comparisons // to null and free calls, delete the calls and replace the comparisons with // true or false as appropriate. if (IsOnlyNullComparedAndFreed(MI)) { ... Ciao, Duncan.