http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53082
Bug #: 53082 Summary: local malloc/free optimization Classification: Unclassified Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end AssignedTo: unassig...@gcc.gnu.org ReportedBy: xinlian...@gmail.com Malloc/free pairs sometimes are used in a way that behaves like a stack memory. The optimizer should recognize the pattern and take advantage of it. For instance if the memory is not escaped, dead stores to the memory can be removed. In extreme case, the malloc/free pair can be completely removed. For instance: for (i = 0; i < 100; i++) { int *s = (int*) malloc (sizeof(int)); *s = 10; free (s); } This code can be completely removed (which LLVM does). The above can be considered as a benchmarking optimization -- see the one appended (objinst.c in LLVM's benchmark suite). The following more advanced optimization (which as far as I know only HP compiler does) can also be done: coalescing multiple malloc calls into one alloca call, and eliminating the free calls. The memory can be escaped. for (...) { int *s1 = malloc (...); int *s2 = malloc (...); int *s3 = malloc (...); ... free(s1); free(s2); free(s3); } ==> for (...) { int s = alloca (...); s1 = s; s2 = s+ .. s3 = s+ .. ... } // objinst.c /* -*- mode: c -*- * $Id: objinst.c 36673 2007-05-03 16:55:46Z laurov $ * http://www.bagley.org/~doug/shootout/ */ #include <stdio.h> #include <stdlib.h> enum {false, true}; #define TOGGLE \ char state; \ char (*value)(struct Toggle *); \ struct Toggle *(*activate)(struct Toggle *) #define DESTROY free typedef struct Toggle { TOGGLE; } Toggle; char toggle_value(Toggle *this) { return(this->state); } Toggle *toggle_activate(Toggle *this) { this->state = !this->state; return(this); } Toggle *init_Toggle(Toggle *this, char start_state) { this->state = start_state; this->value = toggle_value; this->activate = toggle_activate; return(this); } Toggle *new_Toggle(char start_state) { Toggle *this = (Toggle *)malloc(sizeof(Toggle)); return(init_Toggle(this, start_state)); } typedef struct NthToggle { Toggle base; int count_max; int counter; } NthToggle; NthToggle *nth_toggle_activate(NthToggle *this) { if (++this->counter >= this->count_max) { this->base.state = !this->base.state; this->counter = 0; } return(this); } NthToggle *init_NthToggle(NthToggle *this, int max_count) { this->count_max = max_count; this->counter = 0; this->base.activate = (Toggle *(*)(Toggle *))nth_toggle_activate; return(this); } NthToggle *new_NthToggle(char start_state, int max_count) { NthToggle *this = (NthToggle *)malloc(sizeof(NthToggle)); this = (NthToggle *)init_Toggle((Toggle *)this, start_state); return(init_NthToggle(this, max_count)); } int main(int argc, char *argv[]) { #ifdef SMALL_PROBLEM_SIZE #define LENGTH 7000000 #else #define LENGTH 70000000 #endif int i, n = ((argc == 2) ? atoi(argv[1]) : LENGTH); Toggle *tog; NthToggle *ntog; tog = new_Toggle(true); for (i=0; i<5; i++) { puts((tog->activate(tog)->value(tog)) ? "true" : "false"); } DESTROY(tog); for (i=0; i<n; i++) { tog = new_Toggle(true); DESTROY(tog); } puts(""); ntog = new_NthToggle(true, 3); for (i=0; i<8; i++) { const char *Msg; if (ntog->base.activate((Toggle*)ntog)->value((Toggle*)ntog)) Msg = "true"; else Msg = "false"; puts(Msg); } DESTROY(ntog); for (i=0; i<n; i++) { ntog = new_NthToggle(true, 3); DESTROY(ntog); } return 0; }