Пример #1
0
Файл: fp.c Проект: fanf2/qp
static bool
next_rec(Trie *t, const char **pkey, size_t *plen, void **pval) {
	if(isbranch(t)) {
		// Recurse to find either this leaf (*pkey != NULL)
		// or the next one (*pkey == NULL).
		Tbitmap b = twigbit(t, *pkey, *plen);
		uint s, m; TWIGOFFMAX(s, m, t, b);
		for(; s < m; s++)
			if(next_rec(twig(t, s), pkey, plen, pval))
				return(true);
		return(false);
	}
	// We have found the next leaf.
	if(*pkey == NULL) {
		*pkey = t->leaf.key;
		*plen = strlen(*pkey);
		*pval = t->leaf.val;
		return(true);
	}
	// We have found this leaf, so start looking for the next one.
	if(strcmp(*pkey, t->leaf.key) == 0) {
		*pkey = NULL;
		*plen = 0;
		return(false);
	}
	// No match.
	return(false);
}
Пример #2
0
static int
ckfpuse(Prog *p, Prog *ct, Sym *fp, Sym *r)
{
	int reg;

	USED(fp);
	USED(ct);
	if(p->from.sym == r && p->as == AMOVW && (p->from.type == D_CONST || p->from.type == D_OREG) && p->reg == NREG && p->to.type == D_REG){
		reg = p->to.reg;
		for(p = p->link; p != P && p->as != ATEXT; p = p->link){
			if((p->as == ABL || p->as == ABX) && p->to.type == D_OREG && p->to.reg == reg)
				return 1;
			if(!debug['F'] && (isbranch(p) || p->as == ARET)){
				// print("%s: branch %P in %s\n", fp->name, p, ct->from.sym->name);
				return 0;
			}
			if((p->from.type == D_REG || p->from.type == D_OREG) && p->from.reg == reg){
				if(!debug['F'] && p->to.type != D_REG){
					// print("%s: store %P in %s\n", fp->name, p, ct->from.sym->name);
					return 0;
				}
				reg = p->to.reg;
			}
		}
	}
	// print("%s: no MOVW O(R), R\n", fp->name);
	return debug['F'];
}
Пример #3
0
stringbuf& operator <<(stringbuf& sb, const TransOpBase& op) {
  static const char* size_names[4] = {"b", "w", "d", ""};
  // e.g. addfp, addfv, addfd, xxx
  static const char* fptype_names[4] = {".s", ".vs", ".d", ".d"};

  bool ld = isload(op.opcode);
  bool st = isstore(op.opcode);
  bool fp = (isclass(op.opcode, OPCLASS_FP_ALU));
  bool br = isbranch(op.opcode);

  stringbuf sbname;

  sbname << nameof(op.opcode);
  if (!(opinfo[op.opcode].flagops & opNOSIZE)) sbname << (fp ? fptype_names[op.size] : size_names[op.size]);

  if (isclass(op.opcode, OPCLASS_USECOND)) sbname << ".", cond_code_names[op.cond];

  if (ld|st) {
    if (op.opcode == OP_mf) {
      static const char* mf_names[4] = {"none", "st", "ld", "all"};
      sbname << '.', mf_names[op.extshift];
    }
    sbname << ((op.cond == LDST_ALIGN_LO) ? ".lo" : (op.cond == LDST_ALIGN_HI) ? ".hi" : "");
  } else if ((op.opcode == OP_mask) || (op.opcode == OP_maskb)) {
    sbname << ((op.cond == 0) ? "" : (op.cond == 1) ? ".z" : (op.cond == 2) ? ".x" : ".???");
  }

  if ((ld|st) && (op.cachelevel > 0)) sbname << ".L", (char)('1' + op.cachelevel);
  if ((ld|st) && (op.locked)) sbname << ((ld) ? ".acq" : ".rel");
  if (op.internal) sbname << ".p";
  if (op.eom) sbname << ".", (op.any_flags_in_insn ? "+" : "-");

  sb << padstring((char*)sbname, -12), " ", arch_reg_names[op.rd];
  if ((op.rd < ARCHREG_COUNT) & (!op.final_arch_in_insn)) sb << ".t";

  sb << " = ";
  if (ld|st) sb << "[";
  sb << arch_reg_names[op.ra];
  if (op.rb == REG_imm) {
    if (abs(op.rbimm) <= 32768) sb << ",", op.rbimm; else sb << ",", (void*)op.rbimm;
  } else {
    sb << ",", arch_reg_names[op.rb];
  }
  if (ld|st) sb << "]";
  if ((op.opcode == OP_mask) | (op.opcode == OP_maskb)) {
    MaskControlInfo mci(op.rcimm);
    int sh = (op.opcode == OP_maskb) ? 3 : 0;
    sb << ",[ms=", (mci.info.ms >> sh), " mc=", (mci.info.mc >> sh), " ds=", (mci.info.ds >> sh), "]";
  } else {
Пример #4
0
static void
size_rec(Trie *t, uint d, size_t *rsize, size_t *rdepth, size_t *rleaves) {
	*rsize += sizeof(*t);
	if(isbranch(t)) {
		for(uint i = 0; i < 64; i++) {
			uint64_t b = twigbit(i);
			if(hastwig(t, b))
				size_rec(twig(t, twigoff(t, b)), d+1,
					 rsize, rdepth, rleaves);
		}
	} else {
		*rdepth += d;
		*rleaves += 1;
	}
}
Пример #5
0
Файл: fp.c Проект: fanf2/qp
bool
Tgetkv(Tbl *tbl, const char *key, size_t len, const char **pkey, void **pval) {
	if(tbl == NULL)
		return(false);
	Trie *t = &tbl->root;
	while(isbranch(t)) {
		__builtin_prefetch(t->branch.twigs);
		Tbitmap b = twigbit(t, key, len);
		if(!hastwig(t, b))
			return(false);
		t = twig(t, twigoff(t, b));
	}
	if(strcmp(key, t->leaf.key) != 0)
		return(false);
	*pkey = t->leaf.key;
	*pval = t->leaf.val;
	return(true);
}
Пример #6
0
static void
dump_rec(Trie *t, int d) {
	if(isbranch(t)) {
		printf("Tdump%*s branch %p\n", d, "", t);
		for(uint i = 0; i < 64; i++) {
			uint64_t b = twigbit(i);
			if(hastwig(t, b)) {
				printf("Tdump%*s twig %d\n", d, "", i);
				dump_rec(twig(t, twigoff(t, b)), d+1);
			}
		}
	} else {
		printf("Tdump%*s leaf %p\n", d, "", t);
		printf("Tdump%*s leaf key %p %s\n", d, "",
		       t->leaf.key, t->leaf.key);
		printf("Tdump%*s leaf val %p\n", d, "",
		       t->leaf.val);
	}
}
/* Partition quadruples into basic blocks. */
void partition(context* ctx, intermediate* icode)
{
	int i;
	for (i=0; i<icode->nextslot; i++)
		icode->quadruples[i].isleader = 0;
	for (i=0; i<ctx->sbt.nextslot; i++)	/* first statement is leader */
		if (ctx->sbt.table[i].isfunction)
			icode->quadruples[ctx->sbt.table[i].firstquad].isleader = 1;
	for (i=0; i<icode->nextslot; i++)
	{
		if (isbranch(&icode->quadruples[i]))	/* branch target is leader */
			icode->quadruples[icode->quadruples[i].opdest.entity.entity.ival].isleader = 1;
		/* branch follower is leader */
		if (isbbranch(&icode->quadruples[i]) && i+1<icode->nextslot)
		{
			icode->quadruples[i].isleader = 1;
			icode->quadruples[i+1].isleader = 1;
		}
	}
}
Пример #8
0
Файл: fp.c Проект: fanf2/qp
Tbl *
Tdelkv(Tbl *tbl, const char *key, size_t len, const char **pkey, void **pval) {
	if(tbl == NULL)
		return(NULL);
	Trie *t = &tbl->root, *p = NULL;
	Tbitmap b = 0;
	while(isbranch(t)) {
		__builtin_prefetch(t->branch.twigs);
		b = twigbit(t, key, len);
		if(!hastwig(t, b))
			return(tbl);
		p = t; t = twig(t, twigoff(t, b));
	}
	if(strcmp(key, t->leaf.key) != 0)
		return(tbl);
	*pkey = t->leaf.key;
	*pval = t->leaf.val;
	if(p == NULL) {
		free(tbl);
		return(NULL);
	}
	t = p; p = NULL; // Becuase t is the usual name
	uint s, m; TWIGOFFMAX(s, m, t, b);
	if(m == 2) {
		// Move the other twig to the parent branch.
		Trie *twigs = t->branch.twigs;
		*t = *twig(t, !s);
		free(twigs);
		return(tbl);
	}
	memmove(t->branch.twigs+s, t->branch.twigs+s+1, sizeof(Trie) * (m - s - 1));
	t->branch.bitmap &= ~b;
	// We have now correctly removed the twig from the trie, so if
	// realloc() fails we can ignore it and continue to use the
	// slightly oversized twig array.
	Trie *twigs = realloc(t->branch.twigs, sizeof(Trie) * (m - 1));
	if(twigs != NULL) t->branch.twigs = twigs;
	return(tbl);
}
Пример #9
0
static void
setfpuse(Prog *p, Sym *fp, Sym *r)
{
	int reg;

	if(p->from.sym == r && p->as == AMOVW && (p->from.type == D_CONST || p->from.type == D_OREG) && p->reg == NREG && p->to.type == D_REG){
		reg = p->to.reg;
		for(p = p->link; p != P && p->as != ATEXT; p = p->link){
			if((p->as == ABL || p->as == ABX) && p->to.type == D_OREG && p->to.reg == reg){
				fp->fnptr = 0;
				p->as = ABL;	// safe to do so
// print("simplified %s call\n", fp->name);
				break;
			}
			if(!debug['F'] && (isbranch(p) || p->as == ARET))
				diag("bad setfpuse call");
			if((p->from.type == D_REG || p->from.type == D_OREG) && p->from.reg == reg){
				if(!debug['F'] && p->to.type != D_REG)
					diag("bad setfpuse call");
				reg = p->to.reg;
			}
		}
	}
}
Пример #10
0
Файл: fp.c Проект: fanf2/qp
Tbl *
Tsetl(Tbl *tbl, const char *key, size_t len, void *val) {
	// Ensure flag bits are zero.
	if(((uint64_t)val & 1) != 0 || len > 0xFFFFFF) {
		errno = EINVAL;
		return(NULL);
	}
	if(val == NULL)
		return(Tdell(tbl, key, len));
	// First leaf in an empty tbl?
	if(tbl == NULL) {
		tbl = malloc(sizeof(*tbl));
		if(tbl == NULL) return(NULL);
		tbl->root.leaf.key = key;
		tbl->root.leaf.val = val;
		return(tbl);
	}
	Trie *t = &tbl->root;
	// Find the most similar leaf node in the trie. We will compare
	// its key with our new key to find the first differing nibble,
	// which can be at a lower index than the point at which we
	// detect a difference.
	while(isbranch(t)) {
		__builtin_prefetch(t->branch.twigs);
		Tbitmap b = twigbit(t, key, len);
		// Even if our key is missing from this branch we need to
		// keep iterating down to a leaf. It doesn't matter which
		// twig we choose since the keys are all the same up to this
		// index. Note that blindly using twigoff(t, b) can cause
		// an out-of-bounds index if it equals twigmax(t).
		uint i = hastwig(t, b) ? twigoff(t, b) : 0;
		t = twig(t, i);
	}
	// Do the keys differ, and if so, where?
	size_t i;
	uint f;
	for(i = 0; i <= len; i++) {
		f = (byte)key[i] ^ (byte)t->leaf.key[i];
		if(f != 0) goto newkey;
	}
	t->leaf.val = val;
	return(tbl);
newkey:; // We have the branch's byte index; what is its chunk index?
	size_t bit = i * 8 + __builtin_clz(f) + 8 - sizeof(uint) * 8;
	size_t qi = bit / 5;
	i = qi * 5 / 8;
	f = qi * 5 % 8 << 1 | 1;
	// re-index keys with adjusted i
	uint k1 = (byte)key[i] << 8;
	uint k2 = (byte)t->leaf.key[i] << 8;
	k1 |= (k1 ? (byte)key[i+1] : 0);
	k2 |= (k2 ? (byte)t->leaf.key[i+1] : 0);
	Tbitmap b1 = nibbit(k1, f);
	// Prepare the new leaf.
	Trie t1 = { .leaf = { .key = key, .val = val } };
	// Find where to insert a branch or grow an existing branch.
	t = &tbl->root;
	while(isbranch(t)) {
		__builtin_prefetch(t->branch.twigs);
		if(i == t->branch.index && f == t->branch.flags)
			goto growbranch;
		if(i == t->branch.index && f < t->branch.flags)
			goto newbranch;
		if(i < t->branch.index)
			goto newbranch;
		Tbitmap b = twigbit(t, key, len);
		assert(hastwig(t, b));
		t = twig(t, twigoff(t, b));
	}
newbranch:;
	Trie *twigs = malloc(sizeof(Trie) * 2);
	if(twigs == NULL) return(NULL);
	Trie t2 = *t; // Save before overwriting.
	Tbitmap b2 = nibbit(k2, f);
	t->branch.twigs = twigs;
	t->branch.flags = f;
	t->branch.index = i;
	t->branch.bitmap = b1 | b2;
	*twig(t, twigoff(t, b1)) = t1;
	*twig(t, twigoff(t, b2)) = t2;
	return(tbl);
growbranch:;
	assert(!hastwig(t, b1));
	uint s, m; TWIGOFFMAX(s, m, t, b1);
	twigs = realloc(t->branch.twigs, sizeof(Trie) * (m + 1));
	if(twigs == NULL) return(NULL);
	memmove(twigs+s+1, twigs+s, sizeof(Trie) * (m - s));
	memmove(twigs+s, &t1, sizeof(Trie));
	t->branch.twigs = twigs;
	t->branch.bitmap |= b1;
	return(tbl);
}
void translate(context* ctx, assembly* casm)
{
	int i,j,k,l,m;
	symbol *s, *t;
	intermediate* icode = ctx->prog;
	tryarr* ta;
	if (!icode) return;
	partition(ctx, icode);
	/*printquadruples(icode);*/
	for (i=0; i<icode->nextslot; i++)
	{
		icode->quadruples[i].firstinstruction = casm->nextslot;
		ctx->inleader = icode->quadruples[i].isleader;
		ctx->insord = 0;
		transquad(ctx, casm, i);
		icode->quadruples[i].lastinstruction = casm->nextslot-1;
	}
	/* Adjust branch instructions' target address. */
	for (i=0; i<casm->nextslot; i++)
		if (isbranch(&casm->instructions[i]))
		{
			j = casm->instructions[i].opdest.ival;
			casm->instructions[i].opdest.ival = icode->quadruples[j].firstinstruction;
		}
	/* Adjust functional variables. */
	for (i=0; i<ctx->funcs.nextslot; i++)
	{
			j = ctx->funcs.funcs[i].slot;
			s = lookup(ctx, &ctx->sbt, ctx->funcs.funcs[i].caller);
			k = icode->quadruples[j+s->firstquad].firstinstruction;
			l = icode->quadruples[j+s->firstquad].lastinstruction;
			if (!ishostfunction(ctx->funcs.funcs[i].callee))
			{
				t = lookup(ctx, &ctx->sbt, ctx->funcs.funcs[i].callee);
				for (m=k; m<=l; m++)
					if (casm->instructions[m].op == opLFUNC)
						casm->instructions[m].op1.ival = icode->quadruples[t->firstquad].firstinstruction;
			}
			else
				casm->instructions[k].op1.ival = (int)zen_getfunc(ctx->funcs.funcs[i].callee);
	}

	/* Adjust tryblock records for each of the functions. */
	for (i=0; i<ctx->sbt.nextslot; i++)
		if (ctx->sbt.table[i].isfunction)
		{
			if ((ta=ctx->sbt.table[i].ta) == 0)
				continue;
			for (j=0; j<ta->nextslot; j++)
			{
				ta->tr[j].first += ctx->sbt.table[i].firstquad;
				ta->tr[j].first = icode->quadruples[ta->tr[j].first].firstinstruction;
				ta->tr[j].last += ctx->sbt.table[i].firstquad;
				ta->tr[j].last = icode->quadruples[ta->tr[j].last].lastinstruction;
				ta->tr[j].catchentry += ctx->sbt.table[i].firstquad;
				ta->tr[j].catchentry = icode->quadruples[ta->tr[j].catchentry].firstinstruction;
			}
		}
	casm->stacksize = ZEN_DEFAULT_STACK_SIZE;
	/*printinstructions(casm);*/
}
Пример #12
0
noeud* ttos_unres_rooted(int** ttree, int nbotu, int nbbi, char** nom, double* lgbi_init, double* lgbp, double fracroot1, int l1, char** list1, int l2, char** list2, double** lgbi_pt){

  noeud *tabnd, nd1, nd2, nd3;
  int i, j, k, *kill_bi, min, rang_min, ** sorted, *nbfeuille, *fils, nbfils, cpt, *remain;
  double arg6, *lgbi;
  branche* br_list;

int mo1=-1;


  tabnd=(noeud*)check_alloc(2*nbotu, sizeof(noeud));
  kill_bi=(int*)check_alloc(nbbi, sizeof(int));
  remain=(int*)check_alloc(nbbi, sizeof(int));
  if(lgbi_init)
    lgbi=(double*)check_alloc(nbbi, sizeof(double));
  else lgbi=NULL;
  sorted=(int**)check_alloc(nbotu, sizeof(int*));
  for(i=0;i<nbotu;i++)
    sorted[i]=(int*)check_alloc(nbbi, sizeof(int));
  nbfeuille=(int*)check_alloc(nbbi, sizeof(int));
  fils=(int*)check_alloc(2*nbotu, sizeof(int));
  br_list=(branche*)check_alloc(2*nbotu-3, sizeof(branche));
  for(i=0;i<2*nbotu-3;i++){
    br_list[i]=(branche)check_alloc(1, sizeof(struct branche));
    br_list[i]->bout1=NULL;
  }

 
 		/* SORT BRANCHES , REFRESH TREE */

  for(i=0;i<nbbi;i++){
    nbfeuille[i]=0;
    for(j=0;j<nbotu;j++)
      if(ttree[j][i]==1) nbfeuille[i]++;
    if(nbfeuille[i]>nbotu/2){
      nbfeuille[i]=nbotu-nbfeuille[i];
      for(j=0;j<nbotu;j++) ttree[j][i]=1-ttree[j][i];
    }
  }

  for(i=0;i<nbbi;i++) kill_bi[i]=0;

  for(i=0;i<nbbi;i++){
    min=nbotu+1; rang_min=-1;
    for(j=0;j<nbbi;j++){
      if(nbfeuille[j]<min && kill_bi[j]==0){
	min=nbfeuille[j];
	rang_min=j;
      }
    }
    for(j=0;j<nbotu;j++) sorted[j][i]=ttree[j][rang_min];
    if(lgbi_init){ lgbi[i]=lgbi_init[rang_min]; remain[i]=rang_min; }
    kill_bi[rang_min]=1;
  }

   
  
 		/* CREATE NBOTU TERMINAL NODES */

  for(i=0;i<nbotu;i++){
    if(lgbp==NULL) arg6=-1.0; else arg6=lgbp[i];
    tabnd[i]=create_node(NULL, NULL, NULL, 0., 0., arg6, 0., 0., 1., nom[i]);
  }


  		/* CREATE NBBI ALIVE INTERNAL NODES + A FEW NONALIVE ONES*/

  cpt=0;
  for(i=0;i<nbbi;i++){

    		/* find and record sons */
    nbfils=0;
    for(j=0;j<nbbi;j++) kill_bi[j]=0;
    for(j=0;j<nbotu;j++){
      if(sorted[j][i]==1){
	for(k=i-1;k>=0;k--){
	  if(sorted[j][k]==1){
   	    if(kill_bi[k]) break;
/* internal son node (possible index : nbotu, nbotu+1, ..., nbotu+nbbi-1) */
	    nbfils++;
	    fils[nbfils-1]=nbotu+k;
	    kill_bi[k]=1;
	    break;
	  }
	}
	if(k==-1){
/* terminal son node (possible index : 0, 1, ..., nbotu-1) */
	  nbfils++;
	  fils[nbfils-1]=j;
	}
      }
    }
    if(nbfils<2) {
      printf("Bad tree:\n");
      printf("%d sons found for branch %d in sorted tree\n", nbfils, i);
      /* debug_printree(sorted, nbotu, nbbi);*/
      exit(EXIT_FAILURE);
    }

		/* create node(s) */

    if(lgbi==NULL) arg6=-1.0; else arg6=lgbi[i];

    if(nbfils==2){
      nd1=tabnd[fils[0]];
      nd2=tabnd[fils[1]];
      tabnd[nbotu+i]=create_node(nd1, nd2, NULL, nd1->l3, nd2->l3, arg6, 1., 1., 1., NULL);
      nd1->v3=nd2->v3=tabnd[nbotu+i]; 
      if(lgbi_pt) lgbi_pt[remain[i]]=&(tabnd[nbotu+i]->l3);
    }
    else{
      nd1=tabnd[fils[0]]; nd2=tabnd[fils[1]];
      tabnd[nbotu+nbbi+cpt]=create_node(nd1, nd2, NULL, nd1->l3, nd2->l3, -1., 1., 1., 0., NULL);
      nd1->v3=nd2->v3=tabnd[nbotu+nbbi+cpt]; 
      cpt++;
      for(j=0;j<nbfils-3;j++){
	nd1=tabnd[fils[j+2]]; nd2=tabnd[nbotu+nbbi+cpt-1];
	tabnd[nbotu+nbbi+cpt]=create_node(nd1, nd2, NULL, nd1->l3, nd2->l3, -1., 1., 0., 0., NULL);
	nd1->v3=nd2->v3=tabnd[nbotu+nbbi+cpt]; 
	cpt++;
      }
      nd1=tabnd[fils[nbfils-1]]; nd2=tabnd[nbotu+nbbi+cpt-1];
      tabnd[nbotu+i]=create_node(nd1, nd2, NULL, nd1->l3, nd2->l3, arg6, 1., 0., 1., NULL);
      nd1->v3=nd2->v3=tabnd[nbotu+i]; 
    }


  }



		/* JOIN HANGING NODES */

  nbfils=0;
  for(i=0;i<nbotu+nbbi+cpt;i++){
    if(tabnd[i]->v3==NULL){
      fils[nbfils]=i;
      nbfils++;
    }
  }

 
  if(nbfils<3){
    printf("Bad tree 2\n");
    exit(EXIT_FAILURE);
  }

  if(nbfils==3){
    nd1=tabnd[fils[0]];
    nd2=tabnd[fils[1]];
    nd3=tabnd[fils[2]];
    tabnd[nbotu+nbbi+cpt]=create_node(nd1, nd2, nd3, nd1->l3, nd2->l3, nd3->l3, 1., 1., 1., NULL);
    nd1->v3=nd2->v3=nd3->v3=tabnd[nbotu+nbbi+cpt];
  }

  if(nbfils>3){
    nd1=tabnd[fils[0]]; nd2=tabnd[fils[1]];
    tabnd[nbotu+nbbi+cpt]=create_node(nd1, nd2, NULL, nd1->l3, nd2->l3, -1., 1., 1., 0., NULL);
    nd1->v3=nd2->v3=tabnd[nbotu+nbbi+cpt];
    cpt++;
    for(i=0;i<nbfils-4;i++){
      nd1=tabnd[fils[i+2]]; nd2=tabnd[nbotu+nbbi+cpt-1];
      tabnd[nbotu+nbbi+cpt]=create_node(nd1, nd2, NULL, nd1->l3, nd2->l3, -1., 1., 0., 0., NULL);
      nd1->v3=nd2->v3=tabnd[nbotu+nbbi+cpt];
      cpt++;
    }
    nd1=tabnd[fils[nbfils-2]]; nd2=tabnd[fils[nbfils-1]]; nd3=tabnd[nbotu+nbbi+cpt-1];
    tabnd[nbotu+nbbi+cpt]=create_node(nd1, nd2, nd3, nd1->l3, nd2->l3, nd3->l3, 1., 1., 0., NULL);
    nd1->v3=nd2->v3=nd3->v3=tabnd[nbotu+nbbi+cpt];
  }
 		/* ROOT */



  root=create_node(NULL, NULL, NULL, -1., -1., -1., 1., 1., 0., "ROOT");

  makelistbr_unrooted(NULL, tabnd[0], br_list, NULL, 2*nbotu-3);


  for(i=0;i<2*nbotu-3;i++){
    if(isbranch(br_list[i], l1, list1, l2, list2)==1){
      root_s(br_list[i], fracroot1);
      break;
    }
    if(isbranch(br_list[i], l1, list1, l2, list2)==2){
      root_s(br_list[i], 1.-fracroot1);
      break;
    }
  }
  if(i==2*nbotu-3) printf("Erreur racinage\n");

  organize_tree(NULL, root);


  free(kill_bi);
  if(lgbi_init) free(lgbi);
  for(i=0;i<nbotu;i++) free(sorted[i]);
  free(sorted);
  free(nbfeuille); free(fils);
  for(i=0;i<2*nbotu-3;i++) free(br_list[i]);
  free(br_list);
  free(remain);


  return(tabnd);
}