static void
fill_hash_bucket (void)
{
  basic_block bb;
  rtx insn;
  void **slot;
  p_hash_bucket bucket;
  struct hash_bucket_def tmp_bucket;
  p_hash_elem elem;
  unsigned long insn_idx;

  insn_idx = 0;
  FOR_EACH_BB (bb)
    {
      FOR_BB_INSNS_REVERSE (bb, insn)
        {
          if (!ABSTRACTABLE_INSN_P (insn))
            continue;

          /* Compute hash value for INSN.  */
          tmp_bucket.hash = compute_hash (insn);

          /* Select the hash group.  */
          bucket = (p_hash_bucket) htab_find (hash_buckets, &tmp_bucket);

          if (!bucket)
            {
              /* Create a new hash group.  */
              bucket = (p_hash_bucket) xcalloc (1,
                                        sizeof (struct hash_bucket_def));
              bucket->hash = tmp_bucket.hash;
              bucket->seq_candidates = NULL;

              slot = htab_find_slot (hash_buckets, &tmp_bucket, INSERT);
              *slot = bucket;
            }

          /* Create new list for storing sequence candidates.  */
          if (!bucket->seq_candidates)
              bucket->seq_candidates = htab_create (HASH_INIT,
                                                    htab_hash_elem,
                                                    htab_eq_elem,
                                                    htab_del_elem);

          elem = (p_hash_elem) xcalloc (1, sizeof (struct hash_elem_def));
          elem->insn = insn;
          elem->idx = insn_idx;
          elem->length = get_attr_length (insn);

          /* Insert INSN into BUCKET hash bucket.  */
          slot = htab_find_slot (bucket->seq_candidates, elem, INSERT);
          *slot = elem;

          insn_idx++;
        }
    }
}
Exemple #2
0
static tree
TB_up_expr (tree node)
{
  tree res;
  if (node == NULL_TREE)
    return NULL_TREE;

  res = (tree) htab_find (TB_up_ht, node);
  return res;
}
Exemple #3
0
int
mf_marked_p (tree t)
{
  void *entry;

  if (marked_trees == NULL)
    return 0;

  entry = htab_find (marked_trees, t);
  return (entry != NULL);
}
static int
compute_rtx_cost (rtx insn)
{
  struct hash_bucket_def tmp_bucket;
  p_hash_bucket bucket;
  struct hash_elem_def tmp_elem;
  p_hash_elem elem = NULL;
  int cost = -1;

  /* Compute hash value for INSN.  */
  tmp_bucket.hash = compute_hash (insn);

  /* Select the hash group.  */
  bucket = (p_hash_bucket) htab_find (hash_buckets, &tmp_bucket);

  if (bucket)
  {
    tmp_elem.insn = insn;

    /* Select the insn.  */
    elem = (p_hash_elem) htab_find (bucket->seq_candidates, &tmp_elem);

    /* If INSN is parsed the cost will be the cached length.  */
    if (elem)
      cost = elem->length;
  }

  /* If we can't parse the INSN cost will be the instruction length.  */
  if (cost == -1)
  {
    cost = get_attr_length (insn);

    /* Cache the length.  */
    if (elem)
      elem->length = cost;
  }

  /* If we can't get an accurate estimate for a complex instruction,
     assume that it has the same cost as a single fast instruction.  */
  return cost != 0 ? cost : COSTS_N_INSNS (1);
}
Exemple #5
0
static void
read_name (char *str, FILE *infile)
{
  char *p;
  int c;

  c = read_skip_spaces (infile);

  p = str;
  while (1)
    {
      if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r')
	break;
      if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
	  || c == '(' || c == '[')
	{
	  ungetc (c, infile);
	  break;
	}
      *p++ = c;
      c = getc (infile);
    }
  if (p == str)
    fatal_with_file_and_line (infile, "missing name or number");
  if (c == '\n')
    read_rtx_lineno++;

  *p = 0;

  if (md_constants)
    {
      /* Do constant expansion.  */
      struct md_constant *def;

      p = str;
      do
	{
	  struct md_constant tmp_def;

	  tmp_def.name = p;
	  def = htab_find (md_constants, &tmp_def);
	  if (def)
	    p = def->value;
	} while (def);
      if (p != str)
	strcpy (str, p);
    }
}
Exemple #6
0
int parse_labels(tvm_program_t* p, const char*** tokens)
{
	int i, num_instructions = 0;
	for(i = 0; tokens[i]; i++)
	{
		int token_idx, valid_instruction = 0;
		for(token_idx = 0; token_idx < MAX_TOKENS; token_idx++)
		{
			char* label_delimiter;

			/* If the token is empty, or non-existent, skip it */
			if(!tokens[i][token_idx]) continue;

			/* Figure out if the source line we're on contains a valid instruction */
			if(instr_to_opcode(tokens[i][token_idx]) != -1) valid_instruction = 1;

			/* Figure out if the token we're dealing with has a label delimiter */
			label_delimiter = strchr(tokens[i][token_idx], ':');

			if(label_delimiter != NULL)
			{
				*label_delimiter = 0;

				/* If the label is "start," set the program to begin there */
				if(strcmp(tokens[i][token_idx], "start") == 0) p->start = num_instructions;

				/* Check if the label already exists */
				if(htab_find(p->label_htab, tokens[i][token_idx]) != -1)
				{
					printf("Label '%s' defined twice\n", tokens[i][token_idx]);
					return 1;
				}
				else
				{
					/* Add that f****r to the hash table with the corresponding instruction index */
					htab_add(p->label_htab, tokens[i][token_idx], num_instructions);
				}

				continue;
			}
		}

		if(valid_instruction) num_instructions++;
	}

	return 0;
}
static void
error_symbol_once (struct compile_c_instance *context,
		   const struct symbol *sym)
{
  struct symbol_error search;
  struct symbol_error *err;
  char *message;

  if (context->symbol_err_map == NULL)
    return;

  search.sym = sym;
  err = htab_find (context->symbol_err_map, &search);
  if (err == NULL || err->message == NULL)
    return;

  message = err->message;
  err->message = NULL;
  make_cleanup (xfree, message);
  error (_("%s"), message);
}
Exemple #8
0
int parse_instructions(tvm_program_t *p, const char ***tokens, tvm_memory_t *pMemory)
{
	int line_idx;
	for(line_idx = 0; tokens[line_idx]; line_idx++)
	{
		p->instr = (int *)realloc(p->instr, sizeof(int) * (line_idx + 2));
		p->instr[line_idx] = 0;

		p->args = (int ***)realloc(p->args, sizeof(int **) * (line_idx + 2));
		p->args[line_idx] = (int **)calloc(MAX_ARGS, sizeof(int *));

		int token_idx;
		for(token_idx = 0; token_idx < MAX_TOKENS; token_idx++)
		{
			int opcode = 0;

			/* Skip empty tokens */
			if(!tokens[line_idx][token_idx]) continue;

			opcode = instr_to_opcode(tokens[line_idx][token_idx]);

			/* If it *isn't* an opcode, skip trying to parse arguments */
			if(opcode == -1) continue;

			int i, instr_idx = 0, num_instr = p->num_instructions;
			p->instr[p->num_instructions++] = opcode;

			for(i = ++token_idx; i < (token_idx + 2); ++i)
			{
				if(!tokens[line_idx][i] || strlen(tokens[line_idx][i]) <= 0) continue;

				char *newline = strchr(tokens[line_idx][i], '\n');
				if(newline) *newline = 0;

				/* Check to see if the token specifies a register */
				int *pRegister = token_to_register(tokens[line_idx][i], pMemory);
				if(pRegister)
				{
					p->args[num_instr][i - token_idx] = pRegister;
					continue;
				}

				/* Check to see whether the token specifies an address */
				if(tokens[line_idx][i][0] == '[')
				{
					char *end_symbol = strchr(tokens[line_idx][i], ']');
					if(end_symbol)
					{
						*end_symbol = 0;
						p->args[num_instr][i - token_idx] = &((int *)pMemory->mem_space)[tvm_parse_value(tokens[line_idx][i] + 1)];

						continue;
					}
				}

				/* Check if the argument is a label */
				instr_idx = htab_find(p->label_htab, tokens[line_idx][i]);

				if(instr_idx >= 0)
				{
					p->args[num_instr][i - token_idx] = tvm_add_value(p, instr_idx);
					continue;
				}

				/* F**k it, parse it as a value */
				p->args[num_instr][i - token_idx] = tvm_add_value(p, tvm_parse_value(tokens[line_idx][i]));
			}
		}
	}

	p->args[line_idx] = NULL;
	p->instr[line_idx] = -0x1;

	return 0;
}
Exemple #9
0
int tvm_preprocess(char *src, int *src_len, tvm_htab_t *defines)
{
	char* pp_directive_delimiter = NULL;
	if((pp_directive_delimiter = strstr(src, "%include")))
	{
		char *strbegin = pp_directive_delimiter, *strend = strchr(strbegin, '\n');

		if(!strend || !strbegin)  return 0;

		int linelen = strend - strbegin;
		char* temp_str = calloc(linelen + 1, sizeof(char));
		memcpy(temp_str, strbegin, linelen);

		char *filename = (strchr(temp_str, ' ') + 1);

		FILE* pFile = tvm_fopen(filename, ".vm", "r");
		if(!pFile)
		{
			printf("Unable to open file \"%s\"\n", filename);
			return -1;
		}

		free(temp_str);

		size_t addition_len = tvm_flength(pFile);
		char *addition_str = calloc(addition_len, sizeof(char));
		tvm_fcopy(addition_str, addition_len, pFile);
		fclose(pFile);

		size_t first_block_len = (strbegin - src);
		size_t second_block_len = ((src + *src_len) - strend);
		size_t new_src_len = (first_block_len + addition_len + second_block_len);

		src = (char *)realloc((char *)src, sizeof(char) * new_src_len);
		src[new_src_len] = 0;

		memmove(&src[first_block_len + addition_len], strend, second_block_len);
		memcpy(&src[first_block_len], addition_str, addition_len);

		// F****n' hack
		for(int i = 0; i < new_src_len; i++) if(src[i] == 0) src[i] = ' ';

		*src_len = strlen(src);
		return 1;
	}
	else if((pp_directive_delimiter = strstr(src, "%define ")))
	{
		char *begin = pp_directive_delimiter;
		char *end = strchr(begin, '\n');

		if(!end) return 0;

		int offset = strlen("%define ");

		if(begin + offset >= end)
		{
			printf("Define missing arguments.\n");
			return -1;
		}

		int length = (end - (begin + offset));
		char tempstr[length + 1];
		memset(tempstr, 0, length + 1);
		memcpy(tempstr, begin + offset, length);

		char *keystr = tempstr;
		char *valstr = strchr(tempstr, ' ');

		/* If there is a value, seperate the key and value
		   with a null character. */
		if(valstr)
		{
			*valstr = 0;
			valstr += 1;
		}

		if(!keystr || !valstr)
		{
			printf("Define missing arguments.\n");
			return -1;
		}

		if(htab_find(defines, keystr) < 0)
			htab_add_ref(defines, keystr, valstr, strlen(valstr) + 1);
		else
		{
			printf("Multiple definitions for %s.\n", keystr);
			return -1;
		}

		/* Remove the define line so it is not processed again. */
		size_t new_length = *src_len - (end - begin);
		size_t first_block_len = begin - src;
		size_t second_block_len = (src + *src_len) - end;

		memmove(&src[first_block_len], end, second_block_len);

		src = realloc(src, sizeof(char) * new_length);
		*src_len = new_length;

		return 1;
	}

	return 0;

}
Exemple #10
0
void parse_instruction(tvm_program_t* p, const char** tokens, tvm_memory_t* pMemory)
{
	int token_idx;
	for(token_idx = 0; token_idx < MAX_TOKENS; token_idx++)
	{
		int opcode = 0;

		/* Skip empty tokens */
		if(!tokens[token_idx]) continue;

		opcode = instr_to_opcode(tokens[token_idx]);

		/* If it *is* an opcode, parse the arguments */
		if(opcode != -1)
		{
			int i, instr_idx = 0, num_instr = p->num_instructions;
			p->instr[p->num_instructions++] = opcode;

			for(i = ++token_idx; i < (token_idx + 2); ++i)
			{
				char* newline;
				if(!tokens[i] || strlen(tokens[i]) <= 0) continue;

				newline = strchr(tokens[i], '\n');
				if(newline) *newline = 0;

				/* Check to see if the token specifies a register */
				int* pRegister = token_to_register(tokens[i], pMemory);
				if(pRegister)
				{
					p->args[num_instr][i - token_idx] = pRegister;
					continue;
				}

				/* Check to see whether the token specifies an address */
				if(tokens[i][0] == '[')
				{
					char* end_symbol = strchr(tokens[i], ']');
					if(end_symbol)
					{
						*end_symbol = 0;
						p->args[num_instr][i - token_idx] = &((int*)pMemory->mem_space)[tvm_parse_value(tokens[i] + 1)];

						continue;
					}
				}

				/* Check if the argument is a label */
				instr_idx = htab_find(p->label_htab, tokens[i]);

				if(instr_idx >= 0)
				{
					p->args[num_instr][i - token_idx] = tvm_add_value(p, instr_idx);
					continue;
				}

				/* F**k it, parse it as a value */
				p->args[num_instr][i - token_idx] = tvm_add_value(p, tvm_parse_value(tokens[i]));
			}
		}
	}
}
/* Read the documentation file with name IN_FNAME, perform substitutions
   to incorporate informtion from hook_array, and emit the result on stdout.
   Hooks defined with DEFHOOK / DEFHOOKPOD are emitted at the place of a
   matching @hook in the input file; if there is no matching @hook, the
   hook is emitted after the hook that precedes it in target.def .
   Usually, the emitted hook documentation starts with the hook
   signature, followed by the string from the doc field.
   The documentation is bracketed in @deftypefn / @deftypevr and a matching
   @end.
   While emitting the doc field, @Fcode is translated to @code, and an
   @findex entry is added to the affected paragraph.
   If the doc field starts with '*', the leading '*' is stripped, and the doc
   field is otherwise emitted unaltered; no function signature/
   @deftypefn/deftypevr/@end is emitted.
   In particular, a doc field of "*" means not to emit any ocumentation for
   this target.def / hook_array entry at all (there might be documentation
   for this hook in the file named IN_FNAME, though).
   A doc field of 0 is used to append the hook signature after the previous
   hook's signture, so that one description can be used for a group of hooks.
   When the doc field is "", @deftypefn/@deftypevr and the hook signature
   is emitted, but not the matching @end.  This allows all the free-form
   documentation to be placed in IN_FNAME, to work around GPL/GFDL
   licensing incompatibility issues.  */
static void
emit_documentation (const char *in_fname)
{
  int i, j;
  char buf[1000];
  htab_t start_hooks = htab_create (99, s_hook_hash, s_hook_eq_p, (htab_del) 0);
  FILE *f;
  bool found_start = false;

  /* Enter all the start hooks in start_hooks.  */
  f = fopen (in_fname, "r");
  if (!f)
    {
      perror ("");
      fatal ("Couldn't open input file");
    }
  while (fscanf (f, "%*[^@]"), buf[0] = '\0',
	 fscanf (f, "@%5[^ \n]", buf) != EOF)
    {
      void **p;
      struct s_hook *shp;

      if (strcmp (buf, "hook") != 0)
	continue;
      buf[0] = '\0';
      fscanf (f, "%999s", buf);
      shp = XNEW (struct s_hook);
      shp->name = upstrdup (buf);
      shp->pos = -1;
      p = htab_find_slot (start_hooks, shp, INSERT);
      if (*p != HTAB_EMPTY_ENTRY)
	fatal ("Duplicate placement for hook %s\n", shp->name);
      *(struct s_hook **) p = shp;
    }
  fclose (f);
  /* For each hook in hook_array, if it is a start hook, store its position.  */
  for (i = 0; i < (int) (sizeof hook_array / sizeof hook_array[0]); i++)
    {
      struct s_hook sh, *shp;
      void *p;

      if (!hook_array[i].doc || strcmp (hook_array[i].doc, "*") == 0)
	continue;
      sh.name = upstrdup (hook_array[i].name);
      p = htab_find (start_hooks, &sh);
      if (p)
	{
	  shp = (struct s_hook *) p;
	  if (shp->pos >= 0)
	    fatal ("Duplicate hook %s\n", sh.name);
	  shp->pos = i;
	  found_start = true;
	}
      else if (!found_start)
	fatal ("No place specified to document hook %s\n", sh.name);
      free (sh.name);
    }
  /* Copy input file to stdout, substituting @hook directives with the
     corresponding hook documentation sequences.  */
  f = fopen (in_fname, "r");
  if (!f)
    {
      perror ("");
      fatal ("Couldn't open input file");
    }
  for (;;)
    {
      struct s_hook sh, *shp;
      int c = getc (f);
      char *name;

      if (c == EOF)
	break;
      if (c != '@')
	{
	  putchar (c);
	  continue;
	}
      buf[0] = '\0';
      fscanf (f, "%5[^ \n]", buf);
      if (strcmp (buf, "hook") != 0)
	{
	  printf ("@%s", buf);
	  continue;
	}
      fscanf (f, "%999s", buf);
      sh.name = name = upstrdup (buf);
      shp = (struct s_hook *) htab_find (start_hooks, &sh);
      if (!shp || shp->pos < 0)
	fatal ("No documentation for hook %s\n", sh.name);
      i = shp->pos;
      do
	{
	  const char *q, *e;
	  const char *deftype;
	  const char *doc, *fcode, *p_end;

	  /* A leading '*' means to output the documentation string without
	     further processing.  */
	  if (*hook_array[i].doc == '*')
	    printf ("%s", hook_array[i].doc + 1);
	  else
	    {
	      if (i != shp->pos)
		printf ("\n\n");
	      emit_findices (hook_array[i].doc, name);

	      /* Print header.  Function-valued hooks have a parameter list, 
		 unlike POD-valued ones.  */
	      deftype = hook_array[i].param ? "deftypefn" : "deftypevr";
	      printf ("@%s {%s} ", deftype, hook_array[i].docname);
	      if (strchr (hook_array[i].type, ' '))
		printf ("{%s}", hook_array[i].type);
	      else
		printf ("%s", hook_array[i].type);
	      printf (" %s", name);
	      if (hook_array[i].param)
		{
		  /* Print the parameter list, with the parameter names
		     enclosed in @var{}.  */
		  printf (" ");
		  for (q = hook_array[i].param; (e = strpbrk (q, " *,)"));
		       q = e + 1)
		    /* Type names like 'int' are followed by a space, sometimes
		       also by '*'.  'void' should appear only in "(void)".  */
		    if (*e == ' ' || *e == '*' || *q == '(')
		      printf ("%.*s", (int) (e - q + 1), q);
		    else
		      printf ("@var{%.*s}%c", (int) (e - q), q, *e);
		}
	      /* POD-valued hooks sometimes come in groups with common
		 documentation.*/
	      for (j = i + 1;
		   j < (int) (sizeof hook_array / sizeof hook_array[0])
		   && hook_array[j].doc == 0 && hook_array[j].type; j++)
		{
		  char *namex = upstrdup (hook_array[j].name);

		  printf ("\n@%sx {%s} {%s} %s",
			  deftype, hook_array[j].docname,
			  hook_array[j].type, namex);
		}
	      if (hook_array[i].doc[0])
		{
		  printf ("\n");
		  /* Print each documentation paragraph in turn.  */
		  for (doc = hook_array[i].doc; *doc; doc = p_end)
		    {
		      /* Find paragraph end.  */
		      p_end = strstr (doc, "\n\n");
		      p_end = (p_end ? p_end + 2 : doc + strlen (doc));
		      /* Print paragraph, emitting @Fcode as @code.  */
		      for (; (fcode = strstr (doc, "@Fcode{")) && fcode < p_end;
			   doc = fcode + 2)
			printf ("%.*s@", (int) (fcode - doc), doc);
		      printf ("%.*s", (int) (p_end - doc), doc);
		      /* Emit function indices for next paragraph.  */
		      emit_findices (p_end, name);
		    }
		  printf ("\n@end %s", deftype);
		}
	    }
	  if (++i >= (int) (sizeof hook_array / sizeof hook_array[0])
	      || !hook_array[i].doc)
	    break;
	  free (name);
	  sh.name = name = upstrdup (hook_array[i].name);
	}
      while (!htab_find (start_hooks, &sh));
      free (name);
    }
}
Exemple #12
0
void
gomp_task_maybe_wait_for_dependencies (void **depend)
{
  struct gomp_thread *thr = gomp_thread ();
  struct gomp_task *task = thr->task;
  struct gomp_team *team = thr->ts.team;
  struct gomp_task_depend_entry elem, *ent = NULL;
  struct gomp_taskwait taskwait;
  struct gomp_task *last_parent_depends_on = NULL;
  size_t ndepend = (uintptr_t) depend[0];
  size_t nout = (uintptr_t) depend[1];
  size_t i;
  size_t num_awaited = 0;
  struct gomp_task *child_task = NULL;
  struct gomp_task *to_free = NULL;
  int do_wake = 0;

  gomp_mutex_lock (&team->task_lock);
  for (i = 0; i < ndepend; i++)
    {
      elem.addr = depend[i + 2];
      ent = htab_find (task->depend_hash, &elem);
      for (; ent; ent = ent->next)
	if (i >= nout && ent->is_in)
	  continue;
	else
	  {
	    struct gomp_task *tsk = ent->task;
	    if (!tsk->parent_depends_on)
	      {
		tsk->parent_depends_on = true;
		++num_awaited;
		/* If a task we need to wait for is not already
		   running and is ready to be scheduled, move it to
		   front, so that we run it as soon as possible.

		   We rearrange the children queue such that all
		   parent_depends_on tasks are first, and
		   last_parent_depends_on points to the last such task
		   we rearranged.  For example, given the following
		   children where PD[123] are the parent_depends_on
		   tasks:

			task->children
			|
			V
			C1 -> C2 -> C3 -> PD1 -> PD2 -> PD3 -> C4

		   We rearrange such that:

			task->children
			|	       +--- last_parent_depends_on
			|	       |
			V	       V
			PD1 -> PD2 -> PD3 -> C1 -> C2 -> C3 -> C4
		*/

		if (tsk->num_dependees == 0 && tsk->kind == GOMP_TASK_WAITING)
		  {
		    if (last_parent_depends_on)
		      {
			tsk->prev_child->next_child = tsk->next_child;
			tsk->next_child->prev_child = tsk->prev_child;
			tsk->prev_child = last_parent_depends_on;
			tsk->next_child = last_parent_depends_on->next_child;
			tsk->prev_child->next_child = tsk;
			tsk->next_child->prev_child = tsk;
		      }
		    else if (tsk != task->children)
		      {
			tsk->prev_child->next_child = tsk->next_child;
			tsk->next_child->prev_child = tsk->prev_child;
			tsk->prev_child = task->children->prev_child;
			tsk->next_child = task->children;
			task->children = tsk;
			tsk->prev_child->next_child = tsk;
			tsk->next_child->prev_child = tsk;
		      }
		    last_parent_depends_on = tsk;
		  }
	      }
	  }
    }
  if (num_awaited == 0)
    {
      gomp_mutex_unlock (&team->task_lock);
      return;
    }

  memset (&taskwait, 0, sizeof (taskwait));
  taskwait.n_depend = num_awaited;
  taskwait.last_parent_depends_on = last_parent_depends_on;
  gomp_sem_init (&taskwait.taskwait_sem, 0);
  task->taskwait = &taskwait;

  while (1)
    {
      bool cancelled = false;
      if (taskwait.n_depend == 0)
	{
	  task->taskwait = NULL;
	  gomp_mutex_unlock (&team->task_lock);
	  if (to_free)
	    {
	      gomp_finish_task (to_free);
	      free (to_free);
	    }
	  gomp_sem_destroy (&taskwait.taskwait_sem);
	  return;
	}
      if (task->children->kind == GOMP_TASK_WAITING)
	{
	  child_task = task->children;
	  cancelled
	    = gomp_task_run_pre (child_task, task, team);
	  if (__builtin_expect (cancelled, 0))
	    {
	      if (to_free)
		{
		  gomp_finish_task (to_free);
		  free (to_free);
		  to_free = NULL;
		}
	      goto finish_cancelled;
	    }
	}
      else
	/* All tasks we are waiting for are already running
	   in other threads.  Wait for them.  */
	taskwait.in_depend_wait = true;
      gomp_mutex_unlock (&team->task_lock);
      if (do_wake)
	{
	  gomp_team_barrier_wake (&team->barrier, do_wake);
	  do_wake = 0;
	}
      if (to_free)
	{
	  gomp_finish_task (to_free);
	  free (to_free);
	  to_free = NULL;
	}
      if (child_task)
	{
	  thr->task = child_task;
	  child_task->fn (child_task->fn_data);
	  thr->task = task;
	}
      else
	gomp_sem_wait (&taskwait.taskwait_sem);
      gomp_mutex_lock (&team->task_lock);
      if (child_task)
	{
	 finish_cancelled:;
	  size_t new_tasks
	    = gomp_task_run_post_handle_depend (child_task, team);
	  if (child_task->parent_depends_on)
	    --taskwait.n_depend;

	  /* Remove child_task from sibling list.  */
	  child_task->prev_child->next_child = child_task->next_child;
	  child_task->next_child->prev_child = child_task->prev_child;
	  if (task->children == child_task)
	    {
	      if (child_task->next_child != child_task)
		task->children = child_task->next_child;
	      else
		task->children = NULL;
	    }

	  gomp_clear_parent (child_task->children);
	  gomp_task_run_post_remove_taskgroup (child_task);
	  to_free = child_task;
	  child_task = NULL;
	  team->task_count--;
	  if (new_tasks > 1)
	    {
	      do_wake = team->nthreads - team->task_running_count
			- !task->in_tied_task;
	      if (do_wake > new_tasks)
		do_wake = new_tasks;
	    }
	}
    }
}