GC_thread_deregister_foreign (void * data)
{
  short int D.6278;
  int D.6279;
  int D.6280;
  int D.6283;
  long unsigned int D.6286;
  struct GC_Thread_Rep * me;

  me = data;
  D.6278 = me->flags;
  D.6279 = (int) D.6278;
  D.6280 = D.6279 & 8;
  if (D.6280 != 0) goto <D.6281>; else goto <D.6282>;
  <D.6281>:
  D.6283 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6283 != 0) goto <D.6284>; else goto <D.6285>;
  <D.6284>:
  GC_lock ();
  <D.6285>:
  GC_destroy_thread_local (me);
  D.6286 = me->id;
  GC_delete_gc_thread (D.6286, me);
  pthread_mutex_unlock (&GC_allocate_ml);
  <D.6282>:
}


GC_init_thread_local (struct GC_Thread_Rep * p)
{
  int keys_initialized.0;
  int D.6290;
  unsigned int GC_thread_key.1;
  int D.6294;
  int i;

  keys_initialized.0 = keys_initialized;
  if (keys_initialized.0 == 0) goto <D.6288>; else goto <D.6289>;
  <D.6288>:
  D.6290 = pthread_key_create (&GC_thread_key, GC_thread_deregister_foreign);
  if (D.6290 != 0) goto <D.6291>; else goto <D.6292>;
  <D.6291>:
  GC_abort ("Failed to create key for local allocator");
  <D.6292>:
  keys_initialized = 1;
  <D.6289>:
  GC_thread_key.1 = GC_thread_key;
  D.6294 = GC_setspecific (GC_thread_key.1, p);
  if (D.6294 != 0) goto <D.6295>; else goto <D.6296>;
  <D.6295>:
  GC_abort ("Failed to set thread specific allocation pointers");
  <D.6296>:
  i = 1;
  goto <D.5970>;
  <D.5969>:
  p->ptrfree_freelists[i] = 1B;
  p->normal_freelists[i] = 1B;
  p->gcj_freelists[i] = 1B;
  i = i + 1;
  <D.5970>:
  if (i <= 64) goto <D.5969>; else goto <D.5971>;
  <D.5971>:
  p->ptrfree_freelists[0] = &size_zero_object;
  p->normal_freelists[0] = &size_zero_object;
  p->gcj_freelists[0] = 4294967295B;
}


GC_setspecific (GC_key_t key, void * value)
{
  int D.6297;

  GC_thread_tls = value;
  D.6297 = pthread_setspecific (key, value);
  return D.6297;
}


GC_destroy_thread_local (struct GC_Thread_Rep * p)
{
  char *[65] * D.6299;
  char *[65] * D.6300;
  char * * GC_gcjobjfreelist.2;
  char *[65] * D.6302;

  D.6299 = &p->ptrfree_freelists;
  return_freelists (D.6299, &GC_arrays._aobjfreelist);
  D.6300 = &p->normal_freelists;
  return_freelists (D.6300, &GC_arrays._objfreelist);
  GC_gcjobjfreelist.2 = GC_gcjobjfreelist;
  D.6302 = &p->gcj_freelists;
  return_freelists (D.6302, GC_gcjobjfreelist.2);
}


return_freelists (char * * fl, char * * gfl)
{
  unsigned int i.3;
  unsigned int D.6304;
  long unsigned int q.4;
  unsigned int D.6308;
  char * * D.6309;
  char * D.6310;
  char * * D.6314;
  char * D.6315;
  int i;
  char * q;
  char * * qptr;
  size_t nwords;

  i = 1;
  goto <D.5953>;
  <D.5952>:
  i.3 = (unsigned int) i;
  nwords = i.3 * 2;
  i.3 = (unsigned int) i;
  D.6304 = i.3 * 4;
  qptr = fl + D.6304;
  q = *qptr;
  q.4 = (long unsigned int) q;
  if (q.4 > 4095) goto <D.6306>; else goto <D.6307>;
  <D.6306>:
  D.6308 = nwords * 4;
  D.6309 = gfl + D.6308;
  D.6310 = *D.6309;
  if (D.6310 == 0B) goto <D.6311>; else goto <D.6312>;
  <D.6311>:
  D.6308 = nwords * 4;
  D.6309 = gfl + D.6308;
  *D.6309 = q;
  goto <D.6313>;
  <D.6312>:
  goto <D.5950>;
  <D.5949>:
  qptr = q;
  q = *qptr;
  <D.5950>:
  q.4 = (long unsigned int) q;
  if (q.4 > 4095) goto <D.5949>; else goto <D.5951>;
  <D.5951>:
  D.6308 = nwords * 4;
  D.6309 = gfl + D.6308;
  D.6310 = *D.6309;
  *qptr = D.6310;
  D.6308 = nwords * 4;
  D.6309 = gfl + D.6308;
  i.3 = (unsigned int) i;
  D.6304 = i.3 * 4;
  D.6314 = fl + D.6304;
  D.6315 = *D.6314;
  *D.6309 = D.6315;
  <D.6313>:
  <D.6307>:
  i.3 = (unsigned int) i;
  D.6304 = i.3 * 4;
  D.6314 = fl + D.6304;
  *D.6314 = 4096B;
  i = i + 1;
  <D.5953>:
  if (i <= 64) goto <D.5952>; else goto <D.5954>;
  <D.5954>:
}


GC_local_malloc (size_t bytes)
{
  int GC_all_interior_pointers.5;
  unsigned int GC_all_interior_pointers.6;
  unsigned int D.6318;
  _Bool D.6319;
  long int D.6320;
  long int D.6321;
  void * D.6324;
  unsigned int D.6325;
  unsigned int D.6326;
  sizetype index.7;
  long unsigned int my_entry.8;
  _Bool D.6329;
  long int D.6330;
  long int D.6331;
  long unsigned int D.6334;
  sizetype D.6337;
  char * D.6338;
  int D.6339;
  int D.6340;
  char * D.6341;
  void * (*<T2bb>) (size_t) GC_oom_fn.9;

  GC_all_interior_pointers.5 = GC_all_interior_pointers;
  GC_all_interior_pointers.6 = (unsigned int) GC_all_interior_pointers.5;
  D.6318 = bytes + GC_all_interior_pointers.6;
  D.6319 = D.6318 > 512;
  D.6320 = (long int) D.6319;
  D.6321 = __builtin_expect (D.6320, 0);
  if (D.6321 != 0) goto <D.6322>; else goto <D.6323>;
  <D.6322>:
  D.6324 = GC_malloc (bytes);
  return D.6324;
  <D.6323>:
  {
    int index;
    char * * my_fl;
    char * my_entry;
    void * tsd;

    GC_all_interior_pointers.5 = GC_all_interior_pointers;
    GC_all_interior_pointers.6 = (unsigned int) GC_all_interior_pointers.5;
    D.6318 = bytes + GC_all_interior_pointers.6;
    D.6325 = D.6318 + 7;
    D.6326 = D.6325 / 8;
    index = (int) D.6326;
    tsd = GC_thread_tls;
    index.7 = (sizetype) index;
    my_fl = &MEM[(struct GC_Thread_Rep *)tsd].normal_freelists[index.7];
    my_entry = *my_fl;
    my_entry.8 = (long unsigned int) my_entry;
    D.6329 = my_entry.8 > 4095;
    D.6330 = (long int) D.6329;
    D.6331 = __builtin_expect (D.6330, 1);
    if (D.6331 != 0) goto <D.6332>; else goto <D.6333>;
    <D.6332>:
    {
      char * next;
      void * result;

      next = MEM[(char * *)my_entry];
      result = my_entry;
      *my_fl = next;
      MEM[(char * *)my_entry] = 0B;
      D.6324 = result;
      return D.6324;
    }
    <D.6333>:
    my_entry.8 = (long unsigned int) my_entry;
    D.6334 = my_entry.8 + 4294967295;
    if (D.6334 <= 511) goto <D.6335>; else goto <D.6336>;
    <D.6335>:
    index.7 = (sizetype) index;
    D.6337 = index.7 + 1;
    D.6338 = my_entry + D.6337;
    *my_fl = D.6338;
    D.6324 = GC_malloc (bytes);
    return D.6324;
    <D.6336>:
    D.6339 = index * 8;
    GC_all_interior_pointers.5 = GC_all_interior_pointers;
    D.6340 = D.6339 - GC_all_interior_pointers.5;
    GC_generic_malloc_many (D.6340, 1, my_fl);
    D.6341 = *my_fl;
    if (D.6341 == 0B) goto <D.6342>; else goto <D.6343>;
    <D.6342>:
    GC_oom_fn.9 = GC_oom_fn;
    D.6324 = GC_oom_fn.9 (bytes);
    return D.6324;
    <D.6343>:
    D.6324 = GC_local_malloc (bytes);
    return D.6324;
  }
}


GC_local_malloc_atomic (size_t bytes)
{
  int GC_all_interior_pointers.10;
  unsigned int GC_all_interior_pointers.11;
  unsigned int D.6348;
  _Bool D.6349;
  long int D.6350;
  long int D.6351;
  void * D.6354;
  unsigned int D.6355;
  unsigned int D.6356;
  void * GC_thread_tls.12;
  sizetype index.13;
  long unsigned int my_entry.14;
  _Bool D.6360;
  long int D.6361;
  long int D.6362;
  char * D.6365;
  long unsigned int D.6366;
  sizetype D.6369;
  char * D.6370;
  int D.6371;
  int D.6372;
  char * D.6373;
  void * (*<T2bb>) (size_t) GC_oom_fn.15;

  GC_all_interior_pointers.10 = GC_all_interior_pointers;
  GC_all_interior_pointers.11 = (unsigned int) GC_all_interior_pointers.10;
  D.6348 = bytes + GC_all_interior_pointers.11;
  D.6349 = D.6348 > 512;
  D.6350 = (long int) D.6349;
  D.6351 = __builtin_expect (D.6350, 0);
  if (D.6351 != 0) goto <D.6352>; else goto <D.6353>;
  <D.6352>:
  D.6354 = GC_malloc_atomic (bytes);
  return D.6354;
  <D.6353>:
  {
    int index;
    char * * my_fl;
    char * my_entry;

    GC_all_interior_pointers.10 = GC_all_interior_pointers;
    GC_all_interior_pointers.11 = (unsigned int) GC_all_interior_pointers.10;
    D.6348 = bytes + GC_all_interior_pointers.11;
    D.6355 = D.6348 + 7;
    D.6356 = D.6355 / 8;
    index = (int) D.6356;
    GC_thread_tls.12 = GC_thread_tls;
    index.13 = (sizetype) index;
    my_fl = &MEM[(struct GC_Thread_Rep *)GC_thread_tls.12].ptrfree_freelists[index.13];
    my_entry = *my_fl;
    my_entry.14 = (long unsigned int) my_entry;
    D.6360 = my_entry.14 > 4095;
    D.6361 = (long int) D.6360;
    D.6362 = __builtin_expect (D.6361, 1);
    if (D.6362 != 0) goto <D.6363>; else goto <D.6364>;
    <D.6363>:
    {
      void * result;

      result = my_entry;
      D.6365 = MEM[(char * *)my_entry];
      *my_fl = D.6365;
      D.6354 = result;
      return D.6354;
    }
    <D.6364>:
    my_entry.14 = (long unsigned int) my_entry;
    D.6366 = my_entry.14 + 4294967295;
    if (D.6366 <= 511) goto <D.6367>; else goto <D.6368>;
    <D.6367>:
    index.13 = (sizetype) index;
    D.6369 = index.13 + 1;
    D.6370 = my_entry + D.6369;
    *my_fl = D.6370;
    D.6354 = GC_malloc_atomic (bytes);
    return D.6354;
    <D.6368>:
    D.6371 = index * 8;
    GC_all_interior_pointers.10 = GC_all_interior_pointers;
    D.6372 = D.6371 - GC_all_interior_pointers.10;
    GC_generic_malloc_many (D.6372, 0, my_fl);
    D.6373 = *my_fl;
    if (D.6373 == 0B) goto <D.6374>; else goto <D.6375>;
    <D.6374>:
    GC_oom_fn.15 = GC_oom_fn;
    D.6354 = GC_oom_fn.15 (bytes);
    return D.6354;
    <D.6375>:
    D.6354 = GC_local_malloc_atomic (bytes);
    return D.6354;
  }
}


GC_local_gcj_malloc (size_t bytes, void * ptr_to_struct_containing_descr)
{
  int GC_all_interior_pointers.16;
  unsigned int GC_all_interior_pointers.17;
  unsigned int D.6380;
  _Bool D.6381;
  long int D.6382;
  long int D.6383;
  void * D.6386;
  unsigned int D.6387;
  unsigned int D.6388;
  void * GC_thread_tls.18;
  sizetype index.19;
  long unsigned int my_entry.20;
  _Bool D.6392;
  long int D.6393;
  long int D.6394;
  char * D.6397;
  long unsigned int D.6398;
  int GC_incremental.21;
  sizetype D.6404;
  char * D.6405;
  int GC_gcj_kind.22;
  int D.6407;
  int D.6408;
  char * D.6409;
  void * (*<T2bb>) (size_t) GC_oom_fn.23;

  GC_all_interior_pointers.16 = GC_all_interior_pointers;
  GC_all_interior_pointers.17 = (unsigned int) GC_all_interior_pointers.16;
  D.6380 = bytes + GC_all_interior_pointers.17;
  D.6381 = D.6380 > 512;
  D.6382 = (long int) D.6381;
  D.6383 = __builtin_expect (D.6382, 0);
  if (D.6383 != 0) goto <D.6384>; else goto <D.6385>;
  <D.6384>:
  D.6386 = GC_gcj_malloc (bytes, ptr_to_struct_containing_descr);
  return D.6386;
  <D.6385>:
  {
    int index;
    char * * my_fl;
    char * my_entry;

    GC_all_interior_pointers.16 = GC_all_interior_pointers;
    GC_all_interior_pointers.17 = (unsigned int) GC_all_interior_pointers.16;
    D.6380 = bytes + GC_all_interior_pointers.17;
    D.6387 = D.6380 + 7;
    D.6388 = D.6387 / 8;
    index = (int) D.6388;
    GC_thread_tls.18 = GC_thread_tls;
    index.19 = (sizetype) index;
    my_fl = &MEM[(struct GC_Thread_Rep *)GC_thread_tls.18].gcj_freelists[index.19];
    my_entry = *my_fl;
    my_entry.20 = (long unsigned int) my_entry;
    D.6392 = my_entry.20 > 4095;
    D.6393 = (long int) D.6392;
    D.6394 = __builtin_expect (D.6393, 1);
    if (D.6394 != 0) goto <D.6395>; else goto <D.6396>;
    <D.6395>:
    {
      void * result;

      result = my_entry;
      D.6397 = MEM[(char * *)my_entry];
      MEM[(char * volatile *)my_fl] = D.6397;
      MEM[(void * volatile *)result] = ptr_to_struct_containing_descr;
      D.6386 = result;
      return D.6386;
    }
    <D.6396>:
    my_entry.20 = (long unsigned int) my_entry;
    D.6398 = my_entry.20 + 4294967295;
    if (D.6398 <= 511) goto <D.6399>; else goto <D.6400>;
    <D.6399>:
    GC_incremental.21 = GC_incremental;
    if (GC_incremental.21 == 0) goto <D.6402>; else goto <D.6403>;
    <D.6402>:
    index.19 = (sizetype) index;
    D.6404 = index.19 + 1;
    D.6405 = my_entry + D.6404;
    *my_fl = D.6405;
    <D.6403>:
    D.6386 = GC_gcj_malloc (bytes, ptr_to_struct_containing_descr);
    return D.6386;
    <D.6400>:
    GC_gcj_kind.22 = GC_gcj_kind;
    D.6407 = index * 8;
    GC_all_interior_pointers.16 = GC_all_interior_pointers;
    D.6408 = D.6407 - GC_all_interior_pointers.16;
    GC_generic_malloc_many (D.6408, GC_gcj_kind.22, my_fl);
    D.6409 = *my_fl;
    if (D.6409 == 0B) goto <D.6410>; else goto <D.6411>;
    <D.6410>:
    GC_oom_fn.23 = GC_oom_fn;
    D.6386 = GC_oom_fn.23 (bytes);
    return D.6386;
    <D.6411>:
    D.6386 = GC_local_gcj_malloc (bytes, ptr_to_struct_containing_descr);
    return D.6386;
  }
}


GC_local_gcj_fast_malloc (size_t lw, void * ptr_to_struct_containing_descr)
{
  void * GC_thread_tls.24;
  long unsigned int my_entry.25;
  _Bool D.6416;
  long int D.6417;
  long int D.6418;
  char * D.6421;
  void * D.6422;
  long unsigned int D.6423;
  int GC_incremental.26;
  sizetype D.6429;
  char * D.6430;
  int GC_gcj_kind.27;
  unsigned int D.6432;
  int GC_all_interior_pointers.28;
  unsigned int GC_all_interior_pointers.29;
  unsigned int D.6435;
  char * D.6436;
  void * (*<T2bb>) (size_t) GC_oom_fn.30;
  char * * my_fl;
  char * my_entry;

  GC_thread_tls.24 = GC_thread_tls;
  my_fl = &MEM[(struct GC_Thread_Rep *)GC_thread_tls.24].gcj_freelists[lw];
  my_entry = *my_fl;
  my_entry.25 = (long unsigned int) my_entry;
  D.6416 = my_entry.25 > 4095;
  D.6417 = (long int) D.6416;
  D.6418 = __builtin_expect (D.6417, 1);
  if (D.6418 != 0) goto <D.6419>; else goto <D.6420>;
  <D.6419>:
  {
    void * result;

    result = my_entry;
    D.6421 = MEM[(char * *)my_entry];
    MEM[(char * volatile *)my_fl] = D.6421;
    MEM[(void * volatile *)result] = ptr_to_struct_containing_descr;
    D.6422 = result;
    return D.6422;
  }
  <D.6420>:
  my_entry.25 = (long unsigned int) my_entry;
  D.6423 = my_entry.25 + 4294967295;
  if (D.6423 <= 511) goto <D.6424>; else goto <D.6425>;
  <D.6424>:
  GC_incremental.26 = GC_incremental;
  if (GC_incremental.26 == 0) goto <D.6427>; else goto <D.6428>;
  <D.6427>:
  D.6429 = lw + 1;
  D.6430 = my_entry + D.6429;
  *my_fl = D.6430;
  <D.6428>:
  D.6422 = GC_gcj_fast_malloc (lw, ptr_to_struct_containing_descr);
  return D.6422;
  <D.6425>:
  GC_gcj_kind.27 = GC_gcj_kind;
  D.6432 = lw * 8;
  GC_all_interior_pointers.28 = GC_all_interior_pointers;
  GC_all_interior_pointers.29 = (unsigned int) GC_all_interior_pointers.28;
  D.6435 = D.6432 - GC_all_interior_pointers.29;
  GC_generic_malloc_many (D.6435, GC_gcj_kind.27, my_fl);
  D.6436 = *my_fl;
  if (D.6436 == 0B) goto <D.6437>; else goto <D.6438>;
  <D.6437>:
  GC_oom_fn.30 = GC_oom_fn;
  D.6432 = lw * 8;
  GC_all_interior_pointers.28 = GC_all_interior_pointers;
  GC_all_interior_pointers.29 = (unsigned int) GC_all_interior_pointers.28;
  D.6435 = D.6432 - GC_all_interior_pointers.29;
  D.6422 = GC_oom_fn.30 (D.6435);
  return D.6422;
  <D.6438>:
  D.6422 = GC_local_gcj_fast_malloc (lw, ptr_to_struct_containing_descr);
  return D.6422;
}


GC_mark_thread (void * id)
{
  long unsigned int id.31;
  char * D.6442;
  long unsigned int GC_mark_no.32;
  long unsigned int D.6447;
  word my_mark_no;

  my_mark_no = 0;
  id.31 = (long unsigned int) id;
  D.6442 = GC_approx_sp ();
  marker_sp[id.31] = D.6442;
  <D.6039>:
  GC_mark_no.32 = GC_mark_no;
  if (my_mark_no < GC_mark_no.32) goto <D.6443>; else goto <D.6446>;
  <D.6446>:
  GC_mark_no.32 = GC_mark_no;
  D.6447 = GC_mark_no.32 + 2;
  if (D.6447 < my_mark_no) goto <D.6443>; else goto <D.6444>;
  <D.6443>:
  my_mark_no = GC_mark_no;
  <D.6444>:
  GC_help_marker (my_mark_no);
  my_mark_no = my_mark_no + 1;
  goto <D.6039>;
}


GC_push_thread_structures ()
{
  unsigned char * D.6448;
  char * D.6449;
  unsigned char * D.6450;

  GC_push_all (&GC_threads, &MEM[(void *)&GC_threads + 512B]);
  D.6448 = get_gc_thread_key_addr ();
  D.6449 = D.6448 + 4;
  D.6450 = get_gc_thread_key_addr ();
  GC_push_all (D.6450, D.6449);
}


get_gc_thread_key_addr ()
{
  unsigned char * D.6451;

  D.6451 = &GC_thread_key;
  return D.6451;
}


GC_mark_thread_local_free_lists ()
{
  long unsigned int q.33;
  int i;
  int j;
  struct GC_Thread_Rep * p;
  char * q;

  i = 0;
  goto <D.6071>;
  <D.6070>:
  p = GC_threads[i];
  goto <D.6068>;
  <D.6067>:
  j = 1;
  goto <D.6065>;
  <D.6064>:
  q = p->ptrfree_freelists[j];
  q.33 = (long unsigned int) q;
  if (q.33 > 4096) goto <D.6454>; else goto <D.6455>;
  <D.6454>:
  GC_set_fl_marks (q);
  <D.6455>:
  q = p->normal_freelists[j];
  q.33 = (long unsigned int) q;
  if (q.33 > 4096) goto <D.6456>; else goto <D.6457>;
  <D.6456>:
  GC_set_fl_marks (q);
  <D.6457>:
  q = p->gcj_freelists[j];
  q.33 = (long unsigned int) q;
  if (q.33 > 4096) goto <D.6458>; else goto <D.6459>;
  <D.6458>:
  GC_set_fl_marks (q);
  <D.6459>:
  j = j + 1;
  <D.6065>:
  if (j <= 64) goto <D.6064>; else goto <D.6066>;
  <D.6066>:
  p = p->next;
  <D.6068>:
  if (p != 0B) goto <D.6067>; else goto <D.6069>;
  <D.6069>:
  i = i + 1;
  <D.6071>:
  if (i <= 127) goto <D.6070>; else goto <D.6072>;
  <D.6072>:
}


GC_new_thread (pthread_t id)
{
  int id.34;
  int first_thread_used.35;
  struct GC_Thread_Rep * D.6467;
  struct GC_Thread_Rep * D.6468;
  int hv;
  struct GC_Thread_Rep * result;
  static GC_bool first_thread_used = 0;

  id.34 = (int) id;
  hv = id.34 & 127;
  first_thread_used.35 = first_thread_used;
  if (first_thread_used.35 == 0) goto <D.6462>; else goto <D.6463>;
  <D.6462>:
  result = &first_thread;
  first_thread_used = 1;
  goto <D.6464>;
  <D.6463>:
  result = GC_generic_malloc_inner (828, 1);
  <D.6464>:
  if (result == 0B) goto <D.6465>; else goto <D.6466>;
  <D.6465>:
  D.6467 = 0B;
  return D.6467;
  <D.6466>:
  result->id = id;
  D.6468 = GC_threads[hv];
  result->next = D.6468;
  GC_threads[hv] = result;
  D.6467 = result;
  return D.6467;
}


GC_delete_thread (pthread_t id)
{
  int id.36;
  long unsigned int D.6471;
  int D.6472;
  struct GC_Thread_Rep * D.6475;
  int hv;
  register struct GC_Thread_Rep * p;
  register struct GC_Thread_Rep * prev;

  id.36 = (int) id;
  hv = id.36 & 127;
  p = GC_threads[hv];
  prev = 0B;
  goto <D.6087>;
  <D.6086>:
  prev = p;
  p = p->next;
  <D.6087>:
  D.6471 = p->id;
  D.6472 = pthread_equal (D.6471, id);
  if (D.6472 == 0) goto <D.6086>; else goto <D.6088>;
  <D.6088>:
  if (prev == 0B) goto <D.6473>; else goto <D.6474>;
  <D.6473>:
  D.6475 = p->next;
  GC_threads[hv] = D.6475;
  goto <D.6476>;
  <D.6474>:
  D.6475 = p->next;
  prev->next = D.6475;
  <D.6476>:
  GC_free_inner (p);
}


pthread_equal (pthread_t __thread1, pthread_t __thread2)
{
  int D.6477;
  _Bool D.6478;

  D.6478 = __thread1 == __thread2;
  D.6477 = (int) D.6478;
  return D.6477;
}


GC_delete_gc_thread (pthread_t id, struct GC_Thread_Rep * gc_id)
{
  int id.37;
  struct GC_Thread_Rep * D.6483;
  int hv;
  register struct GC_Thread_Rep * p;
  register struct GC_Thread_Rep * prev;

  id.37 = (int) id;
  hv = id.37 & 127;
  p = GC_threads[hv];
  prev = 0B;
  goto <D.6097>;
  <D.6096>:
  prev = p;
  p = p->next;
  <D.6097>:
  if (p != gc_id) goto <D.6096>; else goto <D.6098>;
  <D.6098>:
  if (prev == 0B) goto <D.6481>; else goto <D.6482>;
  <D.6481>:
  D.6483 = p->next;
  GC_threads[hv] = D.6483;
  goto <D.6484>;
  <D.6482>:
  D.6483 = p->next;
  prev->next = D.6483;
  <D.6484>:
  GC_free_inner (p);
}


GC_lookup_thread (pthread_t id)
{
  int id.38;
  long unsigned int D.6487;
  int D.6488;
  struct GC_Thread_Rep * D.6489;
  int hv;
  register struct GC_Thread_Rep * p;

  id.38 = (int) id;
  hv = id.38 & 127;
  p = GC_threads[hv];
  goto <D.6105>;
  <D.6104>:
  p = p->next;
  <D.6105>:
  if (p != 0B) goto <D.6486>; else goto <D.6106>;
  <D.6486>:
  D.6487 = p->id;
  D.6488 = pthread_equal (D.6487, id);
  if (D.6488 == 0) goto <D.6104>; else goto <D.6106>;
  <D.6106>:
  D.6489 = p;
  return D.6489;
}


GC_thread_is_registered ()
{
  int D.6491;
  long unsigned int D.6494;
  int D.6495;
  _Bool D.6496;
  void * ptr;

  D.6491 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6491 != 0) goto <D.6492>; else goto <D.6493>;
  <D.6492>:
  GC_lock ();
  <D.6493>:
  D.6494 = pthread_self ();
  ptr = GC_lookup_thread (D.6494);
  pthread_mutex_unlock (&GC_allocate_ml);
  D.6496 = ptr != 0B;
  D.6495 = (int) D.6496;
  return D.6495;
}


GC_register_altstack (void * stack, int stack_size, void * altstack, int altstack_size)
{
  int D.6498;
  long unsigned int main_pthread_self.39;
  struct GC_Thread_Rep * thread;

  D.6498 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6498 != 0) goto <D.6499>; else goto <D.6500>;
  <D.6499>:
  GC_lock ();
  <D.6500>:
  main_pthread_self.39 = pthread_self ();
  thread = GC_lookup_thread (main_pthread_self.39);
  if (thread != 0B) goto <D.6502>; else goto <D.6503>;
  <D.6502>:
  thread->stack = stack;
  thread->stack_size = stack_size;
  thread->altstack = altstack;
  thread->altstack_size = altstack_size;
  goto <D.6504>;
  <D.6503>:
  main_pthread_self.39 = pthread_self ();
  main_pthread_self = main_pthread_self.39;
  main_stack = stack;
  main_stack_size = stack_size;
  main_altstack = altstack;
  main_altstack_size = altstack_size;
  <D.6504>:
  pthread_mutex_unlock (&GC_allocate_ml);
}


GC_get_nprocs ()
{
  int D.6508;
  void (*<T33e>) (char *, GC_word) GC_current_warn_proc.40;
  int D.6510;
  char D.6511;
  unsigned int D.6514;
  char D.6515;
  unsigned int D.6518;
  char D.6519;
  unsigned int D.6522;
  char D.6523;
  sizetype D.6526;
  const char * D.6527;
  long unsigned int cpu_no.41;
  int D.6531;
  unsigned int D.6532;
  char stat_buf[4096];
  int f;
  word result;
  size_t i;
  size_t len;

  try
    {
      result = 1;
      len = 0;
      f = open ("/proc/stat", 0);
      if (f < 0) goto <D.6505>; else goto <D.6507>;
      <D.6507>:
      D.6508 = read (f, &stat_buf, 4096);
      len = (size_t) D.6508;
      if (len <= 99) goto <D.6505>; else goto <D.6506>;
      <D.6505>:
      GC_current_warn_proc.40 = GC_current_warn_proc;
      GC_current_warn_proc.40 ("GC Warning: Couldn\'t read /proc/stat\n", 0);
      D.6510 = -1;
      return D.6510;
      <D.6506>:
      i = 0;
      goto <D.6127>;
      <D.6126>:
      D.6511 = stat_buf[i];
      if (D.6511 == 10) goto <D.6512>; else goto <D.6513>;
      <D.6512>:
      D.6514 = i + 1;
      D.6515 = stat_buf[D.6514];
      if (D.6515 == 99) goto <D.6516>; else goto <D.6517>;
      <D.6516>:
      D.6518 = i + 2;
      D.6519 = stat_buf[D.6518];
      if (D.6519 == 112) goto <D.6520>; else goto <D.6521>;
      <D.6520>:
      D.6522 = i + 3;
      D.6523 = stat_buf[D.6522];
      if (D.6523 == 117) goto <D.6524>; else goto <D.6525>;
      <D.6524>:
      {
        int cpu_no;

        D.6526 = i + 4;
        D.6527 = &stat_buf + D.6526;
        cpu_no = atoi (D.6527);
        cpu_no.41 = (long unsigned int) cpu_no;
        if (cpu_no.41 >= result) goto <D.6529>; else goto <D.6530>;
        <D.6529>:
        D.6531 = cpu_no + 1;
        result = (word) D.6531;
        <D.6530>:
      }
      <D.6525>:
      <D.6521>:
      <D.6517>:
      <D.6513>:
      i = i + 1;
      <D.6127>:
      D.6532 = len + 4294967196;
      if (D.6532 > i) goto <D.6126>; else goto <D.6128>;
      <D.6128>:
      close (f);
      D.6510 = (int) result;
      return D.6510;
    }
  finally
    {
      stat_buf = {CLOBBER};
    }
}


open (const char * __path, int __oflag)
{
  int D.6535;
  int D.6538;
  int D.6543;
  int D.6545;
  int D.6546;
  int D.6549;
  int D.6550;

  D.6535 = __builtin_va_arg_pack_len ();
  if (D.6535 > 1) goto <D.6536>; else goto <D.6537>;
  <D.6536>:
  __open_too_many_args ();
  <D.6537>:
  D.6538 = __builtin_constant_p (__oflag);
  if (D.6538 != 0) goto <D.6539>; else goto <D.6540>;
  <D.6539>:
  D.6543 = __oflag & 64;
  if (D.6543 != 0) goto <D.6541>; else goto <D.6544>;
  <D.6544>:
  D.6545 = __oflag & 4259840;
  if (D.6545 == 4259840) goto <D.6541>; else goto <D.6542>;
  <D.6541>:
  D.6546 = __builtin_va_arg_pack_len ();
  if (D.6546 <= 0) goto <D.6547>; else goto <D.6548>;
  <D.6547>:
  __open_missing_mode ();
  D.6549 = __open_2 (__path, __oflag);
  return D.6549;
  <D.6548>:
  <D.6542>:
  D.6549 = __open_alias (__path, __oflag, __builtin_va_arg_pack ());
  return D.6549;
  <D.6540>:
  D.6550 = __builtin_va_arg_pack_len ();
  if (D.6550 <= 0) goto <D.6551>; else goto <D.6552>;
  <D.6551>:
  D.6549 = __open_2 (__path, __oflag);
  return D.6549;
  <D.6552>:
  D.6549 = __open_alias (__path, __oflag, __builtin_va_arg_pack ());
  return D.6549;
}


read (int __fd, void * __buf, size_t __nbytes)
{
  unsigned int D.6554;
  int D.6557;
  ssize_t D.6560;
  unsigned int D.6561;
  unsigned int D.6562;
  unsigned int D.6565;

  D.6554 = __builtin_object_size (__buf, 0);
  if (D.6554 != 4294967295) goto <D.6555>; else goto <D.6556>;
  <D.6555>:
  D.6557 = __builtin_constant_p (__nbytes);
  if (D.6557 == 0) goto <D.6558>; else goto <D.6559>;
  <D.6558>:
  D.6561 = __builtin_object_size (__buf, 0);
  D.6560 = __read_chk (__fd, __buf, __nbytes, D.6561);
  return D.6560;
  <D.6559>:
  D.6562 = __builtin_object_size (__buf, 0);
  if (D.6562 < __nbytes) goto <D.6563>; else goto <D.6564>;
  <D.6563>:
  D.6565 = __builtin_object_size (__buf, 0);
  D.6560 = __read_chk_warn (__fd, __buf, __nbytes, D.6565);
  return D.6560;
  <D.6564>:
  <D.6556>:
  D.6560 = __read_alias (__fd, __buf, __nbytes);
  return D.6560;
}


atoi (const char * __nptr)
{
  int D.6567;

  D.6567 = strtol (__nptr, 0B, 10);
  return D.6567;
}


GC_wait_for_gc_completion (GC_bool wait_for_all)
{
  int GC_incremental.42;
  int D.6572;
  long unsigned int GC_gc_no.43;
  int D.6576;
  int D.6580;
  long unsigned int old_gc_no.44;

  GC_incremental.42 = GC_incremental;
  if (GC_incremental.42 != 0) goto <D.6570>; else goto <D.6571>;
  <D.6570>:
  D.6572 = GC_collection_in_progress ();
  if (D.6572 != 0) goto <D.6573>; else goto <D.6574>;
  <D.6573>:
  {
    int old_gc_no;

    GC_gc_no.43 = GC_gc_no;
    old_gc_no = (int) GC_gc_no.43;
    goto <D.6135>;
    <D.6134>:
    GC_collecting = 1;
    GC_in_thread_creation = 1;
    GC_collect_a_little_inner (1);
    GC_in_thread_creation = 0;
    GC_collecting = 0;
    pthread_mutex_unlock (&GC_allocate_ml);
    sched_yield ();
    D.6576 = pthread_mutex_trylock (&GC_allocate_ml);
    if (D.6576 != 0) goto <D.6577>; else goto <D.6578>;
    <D.6577>:
    GC_lock ();
    <D.6578>:
    <D.6135>:
    GC_incremental.42 = GC_incremental;
    if (GC_incremental.42 != 0) goto <D.6579>; else goto <D.6136>;
    <D.6579>:
    D.6580 = GC_collection_in_progress ();
    if (D.6580 != 0) goto <D.6581>; else goto <D.6136>;
    <D.6581>:
    if (wait_for_all != 0) goto <D.6134>; else goto <D.6582>;
    <D.6582>:
    old_gc_no.44 = (long unsigned int) old_gc_no;
    GC_gc_no.43 = GC_gc_no;
    if (old_gc_no.44 == GC_gc_no.43) goto <D.6134>; else goto <D.6136>;
    <D.6136>:
  }
  <D.6574>:
  <D.6571>:
}


GC_thr_init ()
{
  int GC_thr_initialized.45;
  long unsigned int D.6587;
  long unsigned int main_pthread_self.46;
  void * main_stack.47;
  int main_stack_size.48;
  void * main_altstack.49;
  int main_altstack_size.50;
  int GC_nprocs.51;
  long int GC_nprocs.52;
  int GC_nprocs.53;
  void (*<T33e>) (char *, GC_word) GC_current_warn_proc.54;
  long unsigned int GC_nprocs.55;
  int GC_markers.56;
  long int GC_markers.57;
  int GC_print_stats.58;
  int GC_parallel.59;
  int dummy;
  struct GC_Thread_Rep * t;

  try
    {
      GC_thr_initialized.45 = GC_thr_initialized;
      if (GC_thr_initialized.45 != 0) goto <D.6585>; else goto <D.6586>;
      <D.6585>:
      return;
      <D.6586>:
      GC_thr_initialized = 1;
      D.6587 = pthread_self ();
      t = GC_new_thread (D.6587);
      t->stop_info.stack_ptr = &dummy;
      t->flags = 6;
      D.6587 = pthread_self ();
      main_pthread_self.46 = main_pthread_self;
      if (D.6587 == main_pthread_self.46) goto <D.6589>; else goto <D.6590>;
      <D.6589>:
      main_stack.47 = main_stack;
      t->stack = main_stack.47;
      main_stack_size.48 = main_stack_size;
      t->stack_size = main_stack_size.48;
      main_altstack.49 = main_altstack;
      t->altstack = main_altstack.49;
      main_altstack_size.50 = main_altstack_size;
      t->altstack_size = main_altstack_size.50;
      <D.6590>:
      GC_stop_init ();
      {
        char * nprocs_string;

        nprocs_string = getenv ("GC_NPROCS");
        GC_nprocs = -1;
        if (nprocs_string != 0B) goto <D.6595>; else goto <D.6596>;
        <D.6595>:
        GC_nprocs.51 = atoi (nprocs_string);
        GC_nprocs = GC_nprocs.51;
        <D.6596>:
      }
      GC_nprocs.52 = GC_nprocs;
      if (GC_nprocs.52 <= 0) goto <D.6599>; else goto <D.6600>;
      <D.6599>:
      GC_nprocs.53 = GC_get_nprocs ();
      GC_nprocs = GC_nprocs.53;
      <D.6600>:
      GC_nprocs.52 = GC_nprocs;
      if (GC_nprocs.52 <= 0) goto <D.6602>; else goto <D.6603>;
      <D.6602>:
      GC_current_warn_proc.54 = GC_current_warn_proc;
      GC_nprocs.52 = GC_nprocs;
      GC_nprocs.55 = (long unsigned int) GC_nprocs.52;
      GC_current_warn_proc.54 ("GC Warning: GC_get_nprocs() returned %ld\n", GC_nprocs.55);
      GC_nprocs = 2;
      GC_markers = 1;
      goto <D.6606>;
      <D.6603>:
      {
        char * markers_string;

        markers_string = getenv ("GC_MARKERS");
        if (markers_string != 0B) goto <D.6607>; else goto <D.6608>;
        <D.6607>:
        GC_markers.56 = atoi (markers_string);
        GC_markers = GC_markers.56;
        goto <D.6610>;
        <D.6608>:
        GC_nprocs.52 = GC_nprocs;
        GC_markers = GC_nprocs.52;
        GC_markers.57 = GC_markers;
        if (GC_markers.57 > 16) goto <D.6612>; else goto <D.6613>;
        <D.6612>:
        GC_markers = 16;
        <D.6613>:
        <D.6610>:
      }
      <D.6606>:
      GC_print_stats.58 = GC_print_stats;
      if (GC_print_stats.58 != 0) goto <D.6615>; else goto <D.6616>;
      <D.6615>:
      GC_markers.57 = GC_markers;
      GC_nprocs.52 = GC_nprocs;
      GC_printf ("Number of processors = %ld, number of marker threads = %ld\n", GC_nprocs.52, GC_markers.57, 0, 0, 0, 0);
      <D.6616>:
      GC_markers.57 = GC_markers;
      if (GC_markers.57 == 1) goto <D.6617>; else goto <D.6618>;
      <D.6617>:
      GC_parallel = 0;
      GC_print_stats.58 = GC_print_stats;
      if (GC_print_stats.58 != 0) goto <D.6619>; else goto <D.6620>;
      <D.6619>:
      GC_printf ("Single marker thread, turning off parallel marking\n", 0, 0, 0, 0, 0, 0);
      <D.6620>:
      goto <D.6621>;
      <D.6618>:
      GC_parallel = 1;
      GC_time_limit = 999999;
      <D.6621>:
      GC_parallel.59 = GC_parallel;
      if (GC_parallel.59 != 0) goto <D.6623>; else goto <D.6624>;
      <D.6623>:
      start_mark_threads ();
      <D.6624>:
    }
  finally
    {
      dummy = {CLOBBER};
    }
}


start_mark_threads ()
{
  long int GC_markers.60;
  void (*<T33e>) (char *, GC_word) GC_current_warn_proc.61;
  int D.6632;
  int D.6635;
  int GC_print_stats.62;
  long int D.6641;
  void * i.63;
  unsigned int D.6643;
  pthread_t * D.6644;
  int D.6645;
  int * D.6648;
  int D.6649;
  long unsigned int D.6650;
  long unsigned int D.6651;
  unsigned int i;
  union pthread_attr_t attr;

  try
    {
      GC_markers.60 = GC_markers;
      if (GC_markers.60 > 16) goto <D.6629>; else goto <D.6630>;
      <D.6629>:
      GC_current_warn_proc.61 = GC_current_warn_proc;
      GC_current_warn_proc.61 ("GC Warning: Limiting number of mark threads\n", 0);
      GC_markers = 16;
      <D.6630>:
      D.6632 = pthread_attr_init (&attr);
      if (D.6632 != 0) goto <D.6633>; else goto <D.6634>;
      <D.6633>:
      GC_abort ("pthread_attr_init failed");
      <D.6634>:
      D.6635 = pthread_attr_setdetachstate (&attr, 1);
      if (D.6635 != 0) goto <D.6636>; else goto <D.6637>;
      <D.6636>:
      GC_abort ("pthread_attr_setdetachstate failed");
      <D.6637>:
      GC_print_stats.62 = GC_print_stats;
      if (GC_print_stats.62 != 0) goto <D.6639>; else goto <D.6640>;
      <D.6639>:
      GC_markers.60 = GC_markers;
      D.6641 = GC_markers.60 + -1;
      GC_printf ("Starting %ld marker threads\n", D.6641, 0, 0, 0, 0, 0);
      <D.6640>:
      i = 0;
      goto <D.6047>;
      <D.6046>:
      i.63 = (void *) i;
      D.6643 = i * 4;
      D.6644 = &GC_mark_threads + D.6643;
      D.6645 = pthread_create (D.6644, &attr, GC_mark_thread, i.63);
      if (D.6645 != 0) goto <D.6646>; else goto <D.6647>;
      <D.6646>:
      GC_current_warn_proc.61 = GC_current_warn_proc;
      D.6648 = __errno_location ();
      D.6649 = *D.6648;
      D.6650 = (long unsigned int) D.6649;
      GC_current_warn_proc.61 ("GC Warning: Marker thread creation failed, errno = %ld.\n", D.6650);
      <D.6647>:
      i = i + 1;
      <D.6047>:
      GC_markers.60 = GC_markers;
      D.6641 = GC_markers.60 + -1;
      D.6651 = (long unsigned int) D.6641;
      if (D.6651 > i) goto <D.6046>; else goto <D.6048>;
      <D.6048>:
    }
  finally
    {
      attr = {CLOBBER};
    }
}


GC_init_parallel ()
{
  int parallel_initialized.64;
  int GC_is_initialized.65;
  int D.6658;
  long unsigned int D.6661;
  struct GC_Thread_Rep * D.6662;

  parallel_initialized.64 = parallel_initialized;
  if (parallel_initialized.64 != 0) goto <D.6653>; else goto <D.6654>;
  <D.6653>:
  return;
  <D.6654>:
  parallel_initialized = 1;
  GC_is_initialized.65 = GC_is_initialized;
  if (GC_is_initialized.65 == 0) goto <D.6656>; else goto <D.6657>;
  <D.6656>:
  GC_init ();
  <D.6657>:
  D.6658 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6658 != 0) goto <D.6659>; else goto <D.6660>;
  <D.6659>:
  GC_lock ();
  <D.6660>:
  D.6661 = pthread_self ();
  D.6662 = GC_lookup_thread (D.6661);
  GC_init_thread_local (D.6662);
  pthread_mutex_unlock (&GC_allocate_ml);
}


GC_pthread_sigmask (int how, const struct sigset_t * set, struct sigset_t * oset)
{
  _Bool D.6666;
  _Bool D.6667;
  _Bool D.6668;
  int D.6671;
  struct sigset_t fudged_set;

  try
    {
      if (set != 0B) goto <D.6664>; else goto <D.6665>;
      <D.6664>:
      D.6666 = how == 0;
      D.6667 = how == 2;
      D.6668 = D.6666 | D.6667;
      if (D.6668 != 0) goto <D.6669>; else goto <D.6670>;
      <D.6669>:
      fudged_set = *set;
      sigdelset (&fudged_set, 30);
      set = &fudged_set;
      <D.6670>:
      <D.6665>:
      D.6671 = pthread_sigmask (how, set, oset);
      return D.6671;
    }
  finally
    {
      fudged_set = {CLOBBER};
    }
}


GC_start_blocking ()
{
  int D.6674;
  long unsigned int D.6677;
  char * D.6678;
  char * D.6679;
  char * D.6680;
  struct GC_Thread_Rep * me;

  D.6674 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6674 != 0) goto <D.6675>; else goto <D.6676>;
  <D.6675>:
  GC_lock ();
  <D.6676>:
  D.6677 = pthread_self ();
  me = GC_lookup_thread (D.6677);
  D.6678 = GC_approx_sp ();
  me->stop_info.stack_ptr = D.6678;
  D.6679 = me->stop_info.stack_ptr;
  D.6680 = D.6679 + 4294967168;
  me->stop_info.stack_ptr = D.6680;
  me->thread_blocked = 1;
  pthread_mutex_unlock (&GC_allocate_ml);
}


GC_end_blocking ()
{
  int D.6681;
  long unsigned int D.6684;
  struct GC_Thread_Rep * me;

  D.6681 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6681 != 0) goto <D.6682>; else goto <D.6683>;
  <D.6682>:
  GC_lock ();
  <D.6683>:
  D.6684 = pthread_self ();
  me = GC_lookup_thread (D.6684);
  me->thread_blocked = 0;
  pthread_mutex_unlock (&GC_allocate_ml);
}


GC_sleep (unsigned int seconds)
{
  unsigned int D.6685;
  int D.6686;
  int result;

  GC_start_blocking ();
  D.6685 = sleep (seconds);
  result = (int) D.6685;
  GC_end_blocking ();
  D.6686 = result;
  return D.6686;
}


GC_thread_exit_proc (void * arg)
{
  int D.6688;
  long unsigned int D.6691;
  short int D.6692;
  int D.6693;
  int D.6694;
  unsigned int GC_thread_key.66;
  int D.6698;
  short int D.6702;
  struct GC_Thread_Rep * me;

  D.6688 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6688 != 0) goto <D.6689>; else goto <D.6690>;
  <D.6689>:
  GC_lock ();
  <D.6690>:
  D.6691 = pthread_self ();
  me = GC_lookup_thread (D.6691);
  GC_destroy_thread_local (me);
  D.6692 = me->flags;
  D.6693 = (int) D.6692;
  D.6694 = D.6693 & 2;
  if (D.6694 != 0) goto <D.6695>; else goto <D.6696>;
  <D.6695>:
  GC_thread_key.66 = GC_thread_key;
  D.6698 = GC_setspecific (GC_thread_key.66, 0B);
  if (D.6698 != 0) goto <D.6699>; else goto <D.6700>;
  <D.6699>:
  GC_abort ("Failed to set thread specific allocation pointers");
  <D.6700>:
  D.6691 = pthread_self ();
  GC_delete_thread (D.6691);
  goto <D.6701>;
  <D.6696>:
  D.6692 = me->flags;
  D.6702 = D.6692 | 1;
  me->flags = D.6702;
  <D.6701>:
  GC_wait_for_gc_completion (0);
  pthread_mutex_unlock (&GC_allocate_ml);
}


GC_pthread_join (pthread_t thread, void * * retval)
{
  int D.6703;
  int D.6708;
  int D.6711;
  int result;
  struct GC_Thread_Rep * thread_gc_id;

  D.6703 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6703 != 0) goto <D.6704>; else goto <D.6705>;
  <D.6704>:
  GC_lock ();
  <D.6705>:
  thread_gc_id = GC_lookup_thread (thread);
  pthread_mutex_unlock (&GC_allocate_ml);
  result = pthread_join (thread, retval);
  if (result == 0) goto <D.6706>; else goto <D.6707>;
  <D.6706>:
  D.6708 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6708 != 0) goto <D.6709>; else goto <D.6710>;
  <D.6709>:
  GC_lock ();
  <D.6710>:
  GC_delete_gc_thread (thread, thread_gc_id);
  pthread_mutex_unlock (&GC_allocate_ml);
  <D.6707>:
  D.6711 = result;
  return D.6711;
}


GC_pthread_detach (pthread_t thread)
{
  int D.6713;
  int D.6718;
  short int D.6721;
  short int D.6722;
  int D.6723;
  int D.6724;
  int D.6727;
  int result;
  struct GC_Thread_Rep * thread_gc_id;

  D.6713 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6713 != 0) goto <D.6714>; else goto <D.6715>;
  <D.6714>:
  GC_lock ();
  <D.6715>:
  thread_gc_id = GC_lookup_thread (thread);
  pthread_mutex_unlock (&GC_allocate_ml);
  result = pthread_detach (thread);
  if (result == 0) goto <D.6716>; else goto <D.6717>;
  <D.6716>:
  D.6718 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6718 != 0) goto <D.6719>; else goto <D.6720>;
  <D.6719>:
  GC_lock ();
  <D.6720>:
  D.6721 = thread_gc_id->flags;
  D.6722 = D.6721 | 2;
  thread_gc_id->flags = D.6722;
  D.6721 = thread_gc_id->flags;
  D.6723 = (int) D.6721;
  D.6724 = D.6723 & 1;
  if (D.6724 != 0) goto <D.6725>; else goto <D.6726>;
  <D.6725>:
  GC_delete_gc_thread (thread, thread_gc_id);
  <D.6726>:
  pthread_mutex_unlock (&GC_allocate_ml);
  <D.6717>:
  D.6727 = result;
  return D.6727;
}


GC_start_routine_head (void * arg, void * base_addr, void * (*ThreadStartFn) (void *) * start, void * * start_arg)
{
  int D.6729;
  long unsigned int D.6732;
  short int D.6733;
  long unsigned int GC_page_size.67;
  long unsigned int base_addr.68;
  long unsigned int D.6736;
  long unsigned int D.6737;
  long unsigned int D.6738;
  long unsigned int D.6739;
  char * D.6740;
  char * D.6741;
  char * D.6742;
  void * (*<T348>) (void *) D.6745;
  void * D.6748;
  long unsigned int D.6749;
  union sem_t * D.6752;
  int D.6753;
  void * D.6756;
  struct start_info * si;
  void * result;
  struct GC_Thread_Rep * me;
  pthread_t my_pthread;

  si = arg;
  my_pthread = pthread_self ();
  D.6729 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6729 != 0) goto <D.6730>; else goto <D.6731>;
  <D.6730>:
  GC_lock ();
  <D.6731>:
  GC_in_thread_creation = 1;
  me = GC_new_thread (my_pthread);
  GC_in_thread_creation = 0;
  me->stop_info.stack_ptr = 0B;
  D.6732 = si->flags;
  D.6733 = (short int) D.6732;
  me->flags = D.6733;
  GC_page_size.67 = GC_page_size;
  base_addr.68 = (long unsigned int) base_addr;
  D.6736 = GC_page_size.67 + base_addr.68;
  D.6737 = D.6736 + 4294967295;
  GC_page_size.67 = GC_page_size;
  D.6738 = -GC_page_size.67;
  D.6739 = D.6737 & D.6738;
  D.6740 = (char *) D.6739;
  me->stack_end = D.6740;
  D.6741 = me->stack_end;
  D.6742 = D.6741 + 4294967280;
  me->stop_info.stack_ptr = D.6742;
  pthread_mutex_unlock (&GC_allocate_ml);
  if (start != 0B) goto <D.6743>; else goto <D.6744>;
  <D.6743>:
  D.6745 = si->start_routine;
  *start = D.6745;
  <D.6744>:
  if (start_arg != 0B) goto <D.6746>; else goto <D.6747>;
  <D.6746>:
  D.6748 = si->arg;
  *start_arg = D.6748;
  <D.6747>:
  D.6732 = si->flags;
  D.6749 = D.6732 & 8;
  if (D.6749 == 0) goto <D.6750>; else goto <D.6751>;
  <D.6750>:
  D.6752 = &si->registered;
  sem_post (D.6752);
  <D.6751>:
  D.6753 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6753 != 0) goto <D.6754>; else goto <D.6755>;
  <D.6754>:
  GC_lock ();
  <D.6755>:
  GC_init_thread_local (me);
  pthread_mutex_unlock (&GC_allocate_ml);
  D.6756 = me;
  return D.6756;
}


GC_thread_register_foreign (void * base_addr)
{
  int parallel_initialized.69;
  int D.6761;
  int GC_thr_initialized.70;
  int D.6767;
  _Bool D.6768;
  struct start_info si;
  struct GC_Thread_Rep * me;

  try
    {
      si = {};
      si.flags = 8;
      parallel_initialized.69 = parallel_initialized;
      if (parallel_initialized.69 == 0) goto <D.6759>; else goto <D.6760>;
      <D.6759>:
      GC_init_parallel ();
      <D.6760>:
      D.6761 = pthread_mutex_trylock (&GC_allocate_ml);
      if (D.6761 != 0) goto <D.6762>; else goto <D.6763>;
      <D.6762>:
      GC_lock ();
      <D.6763>:
      GC_thr_initialized.70 = GC_thr_initialized;
      if (GC_thr_initialized.70 == 0) goto <D.6765>; else goto <D.6766>;
      <D.6765>:
      GC_thr_init ();
      <D.6766>:
      pthread_mutex_unlock (&GC_allocate_ml);
      me = GC_start_routine_head (&si, base_addr, 0B, 0B);
      D.6768 = me != 0B;
      D.6767 = (int) D.6768;
      return D.6767;
    }
  finally
    {
      si = {CLOBBER};
    }
}


GC_start_routine (void * arg)
{
  long int D.6771;
  void * (*<T348>) (void *) start.71;
  void * start_arg.72;
  void * D.6778;
  int dummy;
  struct start_info * si;
  void * result;
  struct GC_Thread_Rep * me;
  void * (*ThreadStartFn) (void *) start;
  void * start_arg;

  try
    {
      si = arg;
      me = GC_start_routine_head (arg, &dummy, &start, &start_arg);
      {
        struct __pthread_unwind_buf_t __cancel_buf;
        void (*<Tbf>) (void *) __cancel_routine;
        void * __cancel_arg;
        int __not_first_call;

        try
          {
            __cancel_routine = GC_thread_exit_proc;
            __cancel_arg = 0B;
            __not_first_call = __sigsetjmp (&__cancel_buf.__cancel_jmp_buf, 0);
            D.6771 = __builtin_expect (__not_first_call, 0);
            if (D.6771 != 0) goto <D.6772>; else goto <D.6773>;
            <D.6772>:
            __cancel_routine (__cancel_arg);
            __pthread_unwind_next (&__cancel_buf);
            <D.6773>:
            __pthread_register_cancel (&__cancel_buf);
            start.71 = start;
            start_arg.72 = start_arg;
            result = start.71 (start_arg.72);
            me->status = result;
            __pthread_unregister_cancel (&__cancel_buf);
            if (1 != 0) goto <D.6776>; else goto <D.6777>;
            <D.6776>:
            __cancel_routine (__cancel_arg);
            <D.6777>:
          }
        finally
          {
            __cancel_buf = {CLOBBER};
          }
      }
      D.6778 = result;
      return D.6778;
    }
  finally
    {
      dummy = {CLOBBER};
      start = {CLOBBER};
      start_arg = {CLOBBER};
    }
}


GC_pthread_create (pthread_t * new_thread, const union pthread_attr_t * attr, void * (*<T348>) (void *) start_routine, void * arg)
{
  int D.6783;
  int parallel_initialized.73;
  int D.6791;
  union sem_t * D.6792;
  int D.6793;
  int GC_thr_initialized.74;
  int detachstate.75;
  int * D.6807;
  int D.6808;
  int D.6811;
  int D.6812;
  int result;
  int detachstate;
  word my_flags;
  struct start_info * si;

  try
    {
      my_flags = 0;
      D.6783 = pthread_mutex_trylock (&GC_allocate_ml);
      if (D.6783 != 0) goto <D.6784>; else goto <D.6785>;
      <D.6784>:
      GC_lock ();
      <D.6785>:
      si = GC_generic_malloc_inner (28, 1);
      pthread_mutex_unlock (&GC_allocate_ml);
      parallel_initialized.73 = parallel_initialized;
      if (parallel_initialized.73 == 0) goto <D.6787>; else goto <D.6788>;
      <D.6787>:
      GC_init_parallel ();
      <D.6788>:
      if (si == 0B) goto <D.6789>; else goto <D.6790>;
      <D.6789>:
      D.6791 = 12;
      return D.6791;
      <D.6790>:
      D.6792 = &si->registered;
      sem_init (D.6792, 0, 0);
      si->start_routine = start_routine;
      si->arg = arg;
      D.6793 = pthread_mutex_trylock (&GC_allocate_ml);
      if (D.6793 != 0) goto <D.6794>; else goto <D.6795>;
      <D.6794>:
      GC_lock ();
      <D.6795>:
      GC_thr_initialized.74 = GC_thr_initialized;
      if (GC_thr_initialized.74 == 0) goto <D.6797>; else goto <D.6798>;
      <D.6797>:
      GC_thr_init ();
      <D.6798>:
      if (attr == 0B) goto <D.6799>; else goto <D.6800>;
      <D.6799>:
      detachstate = 0;
      goto <D.6801>;
      <D.6800>:
      pthread_attr_getdetachstate (attr, &detachstate);
      <D.6801>:
      detachstate.75 = detachstate;
      if (detachstate.75 == 1) goto <D.6803>; else goto <D.6804>;
      <D.6803>:
      my_flags = my_flags | 2;
      <D.6804>:
      si->flags = my_flags;
      pthread_mutex_unlock (&GC_allocate_ml);
      result = pthread_create (new_thread, attr, GC_start_routine, si);
      if (result == 0) goto <D.6805>; else goto <D.6806>;
      <D.6805>:
      goto <D.6228>;
      <D.6227>:
      D.6807 = __errno_location ();
      D.6808 = *D.6807;
      if (D.6808 != 4) goto <D.6809>; else goto <D.6810>;
      <D.6809>:
      GC_abort ("sem_wait failed");
      <D.6810>:
      <D.6228>:
      D.6792 = &si->registered;
      D.6811 = sem_wait (D.6792);
      if (D.6811 != 0) goto <D.6227>; else goto <D.6229>;
      <D.6229>:
      <D.6806>:
      D.6792 = &si->registered;
      sem_destroy (D.6792);
      D.6812 = pthread_mutex_trylock (&GC_allocate_ml);
      if (D.6812 != 0) goto <D.6813>; else goto <D.6814>;
      <D.6813>:
      GC_lock ();
      <D.6814>:
      GC_free_inner (si);
      pthread_mutex_unlock (&GC_allocate_ml);
      D.6791 = result;
      return D.6791;
    }
  finally
    {
      detachstate = {CLOBBER};
    }
}


GC_pause ()
{
  int i;

  i = 0;
  goto <D.6234>;
  <D.6233>:
  __asm__ __volatile__(" " :  :  : "memory");
  i = i + 1;
  <D.6234>:
  if (i <= 9) goto <D.6233>; else goto <D.6235>;
  <D.6235>:
}


GC_generic_lock (union pthread_mutex_t * lock)
{
  int D.6817;
  long unsigned int GC_unlocked_count.76;
  long unsigned int GC_unlocked_count.77;
  int D.6822;
  long unsigned int GC_spin_count.78;
  long unsigned int GC_spin_count.79;
  long unsigned int GC_block_count.80;
  long unsigned int GC_block_count.81;
  unsigned int pause_length;
  unsigned int i;

  pause_length = 1;
  D.6817 = pthread_mutex_trylock (lock);
  if (D.6817 == 0) goto <D.6818>; else goto <D.6819>;
  <D.6818>:
  GC_unlocked_count.76 = GC_unlocked_count;
  GC_unlocked_count.77 = GC_unlocked_count.76 + 1;
  GC_unlocked_count = GC_unlocked_count.77;
  return;
  <D.6819>:
  goto <D.6253>;
  <D.6252>:
  i = 0;
  goto <D.6246>;
  <D.6245>:
  GC_pause ();
  i = i + 1;
  <D.6246>:
  if (i < pause_length) goto <D.6245>; else goto <D.6247>;
  <D.6247>:
  D.6822 = pthread_mutex_trylock (lock);
  switch (D.6822) <default: <D.6251>, case 0: <D.6248>, case 16: <D.6249>>
  <D.6248>:
  GC_spin_count.78 = GC_spin_count;
  GC_spin_count.79 = GC_spin_count.78 + 1;
  GC_spin_count = GC_spin_count.79;
  return;
  <D.6249>:
  goto <D.6250>;
  <D.6251>:
  GC_abort ("Unexpected error from pthread_mutex_trylock");
  <D.6250>:
  pause_length = pause_length << 1;
  <D.6253>:
  if (pause_length <= 128) goto <D.6252>; else goto <D.6254>;
  <D.6254>:
  GC_block_count.80 = GC_block_count;
  GC_block_count.81 = GC_block_count.80 + 1;
  GC_block_count = GC_block_count.81;
  pthread_mutex_lock (lock);
}


GC_lock ()
{
  long int GC_nprocs.82;
  int GC_collecting.83;

  GC_nprocs.82 = GC_nprocs;
  if (GC_nprocs.82 == 1) goto <D.6829>; else goto <D.6833>;
  <D.6833>:
  GC_collecting.83 = GC_collecting;
  if (GC_collecting.83 != 0) goto <D.6829>; else goto <D.6830>;
  <D.6829>:
  pthread_mutex_lock (&GC_allocate_ml);
  goto <D.6831>;
  <D.6830>:
  GC_generic_lock (&GC_allocate_ml);
  <D.6831>:
}


GC_acquire_mark_lock ()
{
  GC_generic_lock (&mark_mutex);
}


GC_release_mark_lock ()
{
  int D.6835;

  D.6835 = pthread_mutex_unlock (&mark_mutex);
  if (D.6835 != 0) goto <D.6836>; else goto <D.6837>;
  <D.6836>:
  GC_abort ("pthread_mutex_unlock failed");
  <D.6837>:
}


GC_wait_builder ()
{
  int D.6838;

  D.6838 = pthread_cond_wait (&builder_cv, &mark_mutex);
  if (D.6838 != 0) goto <D.6839>; else goto <D.6840>;
  <D.6839>:
  GC_abort ("pthread_cond_wait failed");
  <D.6840>:
}


GC_wait_for_reclaim ()
{
  long unsigned int GC_fl_builder_count.84;

  GC_acquire_mark_lock ();
  goto <D.6268>;
  <D.6267>:
  GC_wait_builder ();
  <D.6268>:
  GC_fl_builder_count.84 = GC_fl_builder_count;
  if (GC_fl_builder_count.84 != 0) goto <D.6267>; else goto <D.6269>;
  <D.6269>:
  GC_release_mark_lock ();
}


GC_notify_all_builder ()
{
  int D.6842;

  D.6842 = pthread_cond_broadcast (&builder_cv);
  if (D.6842 != 0) goto <D.6843>; else goto <D.6844>;
  <D.6843>:
  GC_abort ("pthread_cond_broadcast failed");
  <D.6844>:
}


GC_wait_marker ()
{
  int D.6845;

  D.6845 = pthread_cond_wait (&mark_cv, &mark_mutex);
  if (D.6845 != 0) goto <D.6846>; else goto <D.6847>;
  <D.6846>:
  GC_abort ("pthread_cond_wait failed");
  <D.6847>:
}


GC_notify_all_marker ()
{
  int D.6848;

  D.6848 = pthread_cond_broadcast (&mark_cv);
  if (D.6848 != 0) goto <D.6849>; else goto <D.6850>;
  <D.6849>:
  GC_abort ("pthread_cond_broadcast failed");
  <D.6850>:
}


