Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LLVM/Clang special case for allocators

If you have the following code in "alloc.c":

typedef __typeof__(sizeof(int)) size_t;

extern void *calloc (size_t __nmemb, size_t __size)
  __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) ;
extern void free (void *__ptr) __attribute__ ((__nothrow__ ));

struct _astruct {
  int l;
};


int main() {
  struct _astruct *f = (struct _astruct*)calloc(1, sizeof(struct _astruct));
  f->l = 99;
  int x = f->l;
  free(f);
  return x;
}

(I know that's not the preferred way to declare calloc/free, but it's for simplicity of output below.)

Then you run "clang -O3 -S -emit-llvm alloc.c" with Clang/LLVM 3.3, you get:

; ModuleID = 'alloc.c'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: nounwind readnone uwtable
define i32 @main() #0 {
entry:
  ret i32 99
}

attributes #0 = { nounwind readnone uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }

You can see that it has eliminated the call to calloc altogether. Awesome. In general, though, a compiler can't eliminate calls to functions that it does not have the source to (there may be side-effects). So it seems that Clang has special case code for calloc/free. This is supported by the fact that if you chanage all occurrences to "calloc" in the code to be "_calloc", the "allocation" comes back.

So my question is, is there any way to tell Clang/LLVM that a particular function is an "allocation only" function? Perhaps some annotation I could put on the definition of one of my own functions that would allow LLVM to optimize away allocations just as it can for calloc/malloc.

like image 270
laslowh Avatar asked Oct 13 '13 23:10

laslowh


1 Answers

is there any way to tell Clang/LLVM that a particular function is an "allocation only" function?

Nope. As you have correctly stated, in the general case it's only possible to eliminate a call if the compiler has access to its implementation*. The support for calloc is hard-coded in LLVM (see LLVM's "MemoryBuiltins" and "TargetLibraryInfo" classes), which is how the call was eliminated in your example.

There are no attributes that signal to the compiler that a certain function will only attempt to allocate memory.


*: well it may be possible if the function is marked to have absolutely no possible side effects, but there's currently no way to mark something like this in LLVM, see this related discussion; and in any case a function that allocates memory can certainly have side effects.

like image 188
Oak Avatar answered Nov 08 '22 08:11

Oak