GC_thread_deregister_foreign (void * data)
{
  short int D.6711;
  int D.6712;
  int D.6713;
  int D.6716;
  long unsigned int D.6719;
  struct GC_Thread_Rep * me;

  me = data;
  D.6711 = me->flags;
  D.6712 = (int) D.6711;
  D.6713 = D.6712 & 8;
  if (D.6713 != 0) goto <D.6714>; else goto <D.6715>;
  <D.6714>:
  D.6716 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6716 != 0) goto <D.6717>; else goto <D.6718>;
  <D.6717>:
  GC_lock ();
  <D.6718>:
  GC_destroy_thread_local (me);
  D.6719 = me->id;
  GC_delete_gc_thread (D.6719, me);
  pthread_mutex_unlock (&GC_allocate_ml);
  <D.6715>:
}


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

  keys_initialized.0 = keys_initialized;
  if (keys_initialized.0 == 0) goto <D.6721>; else goto <D.6722>;
  <D.6721>:
  D.6723 = pthread_key_create (&GC_thread_key, GC_thread_deregister_foreign);
  if (D.6723 != 0) goto <D.6724>; else goto <D.6725>;
  <D.6724>:
  GC_abort ("Failed to create key for local allocator");
  <D.6725>:
  keys_initialized = 1;
  <D.6722>:
  GC_thread_key.1 = GC_thread_key;
  D.6727 = GC_setspecific (GC_thread_key.1, p);
  if (D.6727 != 0) goto <D.6728>; else goto <D.6729>;
  <D.6728>:
  GC_abort ("Failed to set thread specific allocation pointers");
  <D.6729>:
  i = 1;
  goto <D.6403>;
  <D.6402>:
  p->ptrfree_freelists[i] = 1B;
  p->normal_freelists[i] = 1B;
  p->gcj_freelists[i] = 1B;
  i = i + 1;
  <D.6403>:
  if (i <= 64) goto <D.6402>; else goto <D.6404>;
  <D.6404>:
  p->ptrfree_freelists[0] = &size_zero_object;
  p->normal_freelists[0] = &size_zero_object;
  p->gcj_freelists[0] = -1B;
}


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

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


GC_destroy_thread_local (struct GC_Thread_Rep * p)
{
  char *[65] * D.6732;
  char *[65] * D.6733;
  char *[65] * D.6734;
  char * * GC_gcjobjfreelist.2;

  D.6732 = &p->ptrfree_freelists;
  return_freelists (D.6732, &GC_arrays._aobjfreelist);
  D.6733 = &p->normal_freelists;
  return_freelists (D.6733, &GC_arrays._objfreelist);
  D.6734 = &p->gcj_freelists;
  GC_gcjobjfreelist.2 = GC_gcjobjfreelist;
  return_freelists (D.6734, GC_gcjobjfreelist.2);
}


return_freelists (char * * fl, char * * gfl)
{
  long unsigned int D.6736;
  long unsigned int D.6737;
  long unsigned int q.3;
  long unsigned int D.6741;
  char * * D.6742;
  char * D.6743;
  char * * D.6747;
  char * D.6748;
  int i;
  char * q;
  char * * qptr;
  size_t nwords;

  i = 1;
  goto <D.6386>;
  <D.6385>:
  nwords = (size_t) i;
  D.6736 = (long unsigned int) i;
  D.6737 = D.6736 * 8;
  qptr = fl + D.6737;
  q = *qptr;
  q.3 = (long unsigned int) q;
  if (q.3 > 4095) goto <D.6739>; else goto <D.6740>;
  <D.6739>:
  D.6741 = nwords * 8;
  D.6742 = gfl + D.6741;
  D.6743 = *D.6742;
  if (D.6743 == 0B) goto <D.6744>; else goto <D.6745>;
  <D.6744>:
  D.6741 = nwords * 8;
  D.6742 = gfl + D.6741;
  *D.6742 = q;
  goto <D.6746>;
  <D.6745>:
  goto <D.6383>;
  <D.6382>:
  qptr = q;
  q = *qptr;
  <D.6383>:
  q.3 = (long unsigned int) q;
  if (q.3 > 4095) goto <D.6382>; else goto <D.6384>;
  <D.6384>:
  D.6741 = nwords * 8;
  D.6742 = gfl + D.6741;
  D.6743 = *D.6742;
  *qptr = D.6743;
  D.6741 = nwords * 8;
  D.6742 = gfl + D.6741;
  D.6736 = (long unsigned int) i;
  D.6737 = D.6736 * 8;
  D.6747 = fl + D.6737;
  D.6748 = *D.6747;
  *D.6742 = D.6748;
  <D.6746>:
  <D.6740>:
  D.6736 = (long unsigned int) i;
  D.6737 = D.6736 * 8;
  D.6747 = fl + D.6737;
  *D.6747 = 4096B;
  i = i + 1;
  <D.6386>:
  if (i <= 64) goto <D.6385>; else goto <D.6387>;
  <D.6387>:
}


GC_local_malloc (size_t bytes)
{
  int GC_all_interior_pointers.4;
  long unsigned int D.6750;
  long unsigned int D.6751;
  _Bool D.6752;
  long int D.6753;
  long int D.6754;
  void * D.6757;
  long unsigned int D.6758;
  long unsigned int D.6759;
  char *[65] * D.6760;
  long unsigned int D.6761;
  long unsigned int D.6762;
  long unsigned int my_entry.5;
  _Bool D.6764;
  long int D.6765;
  long int D.6766;
  long unsigned int D.6769;
  sizetype D.6772;
  sizetype D.6773;
  char * D.6774;
  int D.6775;
  int D.6776;
  char * D.6777;
  void * (*<T40d>) (size_t) GC_oom_fn.6;

  GC_all_interior_pointers.4 = GC_all_interior_pointers;
  D.6750 = (long unsigned int) GC_all_interior_pointers.4;
  D.6751 = D.6750 + bytes;
  D.6752 = D.6751 > 512;
  D.6753 = (long int) D.6752;
  D.6754 = __builtin_expect (D.6753, 0);
  if (D.6754 != 0) goto <D.6755>; else goto <D.6756>;
  <D.6755>:
  D.6757 = GC_malloc (bytes);
  return D.6757;
  <D.6756>:
  {
    int index;
    char * * my_fl;
    char * my_entry;
    void * tsd;

    GC_all_interior_pointers.4 = GC_all_interior_pointers;
    D.6750 = (long unsigned int) GC_all_interior_pointers.4;
    D.6751 = D.6750 + bytes;
    D.6758 = D.6751 + 7;
    D.6759 = D.6758 / 8;
    index = (int) D.6759;
    tsd = GC_thread_tls;
    D.6760 = &MEM[(struct GC_Thread_Rep *)tsd].normal_freelists;
    D.6761 = (long unsigned int) index;
    D.6762 = D.6761 * 8;
    my_fl = D.6760 + D.6762;
    my_entry = *my_fl;
    my_entry.5 = (long unsigned int) my_entry;
    D.6764 = my_entry.5 > 4095;
    D.6765 = (long int) D.6764;
    D.6766 = __builtin_expect (D.6765, 1);
    if (D.6766 != 0) goto <D.6767>; else goto <D.6768>;
    <D.6767>:
    {
      char * next;
      void * result;

      next = MEM[(char * *)my_entry];
      result = my_entry;
      *my_fl = next;
      MEM[(char * *)my_entry] = 0B;
      D.6757 = result;
      return D.6757;
    }
    <D.6768>:
    my_entry.5 = (long unsigned int) my_entry;
    D.6769 = my_entry.5 + 18446744073709551615;
    if (D.6769 <= 511) goto <D.6770>; else goto <D.6771>;
    <D.6770>:
    D.6772 = (sizetype) index;
    D.6773 = D.6772 + 1;
    D.6774 = my_entry + D.6773;
    *my_fl = D.6774;
    D.6757 = GC_malloc (bytes);
    return D.6757;
    <D.6771>:
    D.6775 = index * 8;
    GC_all_interior_pointers.4 = GC_all_interior_pointers;
    D.6776 = D.6775 - GC_all_interior_pointers.4;
    GC_generic_malloc_many (D.6776, 1, my_fl);
    D.6777 = *my_fl;
    if (D.6777 == 0B) goto <D.6778>; else goto <D.6779>;
    <D.6778>:
    GC_oom_fn.6 = GC_oom_fn;
    D.6757 = GC_oom_fn.6 (bytes);
    return D.6757;
    <D.6779>:
    D.6757 = GC_local_malloc (bytes);
    return D.6757;
  }
}


GC_local_malloc_atomic (size_t bytes)
{
  int GC_all_interior_pointers.7;
  long unsigned int D.6783;
  long unsigned int D.6784;
  _Bool D.6785;
  long int D.6786;
  long int D.6787;
  void * D.6790;
  long unsigned int D.6791;
  long unsigned int D.6792;
  void * GC_thread_tls.8;
  char *[65] * D.6794;
  long unsigned int D.6795;
  long unsigned int D.6796;
  long unsigned int my_entry.9;
  _Bool D.6798;
  long int D.6799;
  long int D.6800;
  char * D.6803;
  long unsigned int D.6804;
  sizetype D.6807;
  sizetype D.6808;
  char * D.6809;
  int D.6810;
  int D.6811;
  char * D.6812;
  void * (*<T40d>) (size_t) GC_oom_fn.10;

  GC_all_interior_pointers.7 = GC_all_interior_pointers;
  D.6783 = (long unsigned int) GC_all_interior_pointers.7;
  D.6784 = D.6783 + bytes;
  D.6785 = D.6784 > 512;
  D.6786 = (long int) D.6785;
  D.6787 = __builtin_expect (D.6786, 0);
  if (D.6787 != 0) goto <D.6788>; else goto <D.6789>;
  <D.6788>:
  D.6790 = GC_malloc_atomic (bytes);
  return D.6790;
  <D.6789>:
  {
    int index;
    char * * my_fl;
    char * my_entry;

    GC_all_interior_pointers.7 = GC_all_interior_pointers;
    D.6783 = (long unsigned int) GC_all_interior_pointers.7;
    D.6784 = D.6783 + bytes;
    D.6791 = D.6784 + 7;
    D.6792 = D.6791 / 8;
    index = (int) D.6792;
    GC_thread_tls.8 = GC_thread_tls;
    D.6794 = &MEM[(struct GC_Thread_Rep *)GC_thread_tls.8].ptrfree_freelists;
    D.6795 = (long unsigned int) index;
    D.6796 = D.6795 * 8;
    my_fl = D.6794 + D.6796;
    my_entry = *my_fl;
    my_entry.9 = (long unsigned int) my_entry;
    D.6798 = my_entry.9 > 4095;
    D.6799 = (long int) D.6798;
    D.6800 = __builtin_expect (D.6799, 1);
    if (D.6800 != 0) goto <D.6801>; else goto <D.6802>;
    <D.6801>:
    {
      void * result;

      result = my_entry;
      D.6803 = MEM[(char * *)my_entry];
      *my_fl = D.6803;
      D.6790 = result;
      return D.6790;
    }
    <D.6802>:
    my_entry.9 = (long unsigned int) my_entry;
    D.6804 = my_entry.9 + 18446744073709551615;
    if (D.6804 <= 511) goto <D.6805>; else goto <D.6806>;
    <D.6805>:
    D.6807 = (sizetype) index;
    D.6808 = D.6807 + 1;
    D.6809 = my_entry + D.6808;
    *my_fl = D.6809;
    D.6790 = GC_malloc_atomic (bytes);
    return D.6790;
    <D.6806>:
    D.6810 = index * 8;
    GC_all_interior_pointers.7 = GC_all_interior_pointers;
    D.6811 = D.6810 - GC_all_interior_pointers.7;
    GC_generic_malloc_many (D.6811, 0, my_fl);
    D.6812 = *my_fl;
    if (D.6812 == 0B) goto <D.6813>; else goto <D.6814>;
    <D.6813>:
    GC_oom_fn.10 = GC_oom_fn;
    D.6790 = GC_oom_fn.10 (bytes);
    return D.6790;
    <D.6814>:
    D.6790 = GC_local_malloc_atomic (bytes);
    return D.6790;
  }
}


GC_local_gcj_malloc (size_t bytes, void * ptr_to_struct_containing_descr)
{
  int GC_all_interior_pointers.11;
  long unsigned int D.6818;
  long unsigned int D.6819;
  _Bool D.6820;
  long int D.6821;
  long int D.6822;
  void * D.6825;
  long unsigned int D.6826;
  long unsigned int D.6827;
  void * GC_thread_tls.12;
  char *[65] * D.6829;
  long unsigned int D.6830;
  long unsigned int D.6831;
  long unsigned int my_entry.13;
  _Bool D.6833;
  long int D.6834;
  long int D.6835;
  char * D.6838;
  long unsigned int D.6839;
  int GC_incremental.14;
  sizetype D.6845;
  sizetype D.6846;
  char * D.6847;
  int D.6848;
  int D.6849;
  int GC_gcj_kind.15;
  char * D.6851;
  void * (*<T40d>) (size_t) GC_oom_fn.16;

  GC_all_interior_pointers.11 = GC_all_interior_pointers;
  D.6818 = (long unsigned int) GC_all_interior_pointers.11;
  D.6819 = D.6818 + bytes;
  D.6820 = D.6819 > 512;
  D.6821 = (long int) D.6820;
  D.6822 = __builtin_expect (D.6821, 0);
  if (D.6822 != 0) goto <D.6823>; else goto <D.6824>;
  <D.6823>:
  D.6825 = GC_gcj_malloc (bytes, ptr_to_struct_containing_descr);
  return D.6825;
  <D.6824>:
  {
    int index;
    char * * my_fl;
    char * my_entry;

    GC_all_interior_pointers.11 = GC_all_interior_pointers;
    D.6818 = (long unsigned int) GC_all_interior_pointers.11;
    D.6819 = D.6818 + bytes;
    D.6826 = D.6819 + 7;
    D.6827 = D.6826 / 8;
    index = (int) D.6827;
    GC_thread_tls.12 = GC_thread_tls;
    D.6829 = &MEM[(struct GC_Thread_Rep *)GC_thread_tls.12].gcj_freelists;
    D.6830 = (long unsigned int) index;
    D.6831 = D.6830 * 8;
    my_fl = D.6829 + D.6831;
    my_entry = *my_fl;
    my_entry.13 = (long unsigned int) my_entry;
    D.6833 = my_entry.13 > 4095;
    D.6834 = (long int) D.6833;
    D.6835 = __builtin_expect (D.6834, 1);
    if (D.6835 != 0) goto <D.6836>; else goto <D.6837>;
    <D.6836>:
    {
      void * result;

      result = my_entry;
      D.6838 = MEM[(char * *)my_entry];
      MEM[(char * volatile *)my_fl] = D.6838;
      MEM[(void * volatile *)result] = ptr_to_struct_containing_descr;
      D.6825 = result;
      return D.6825;
    }
    <D.6837>:
    my_entry.13 = (long unsigned int) my_entry;
    D.6839 = my_entry.13 + 18446744073709551615;
    if (D.6839 <= 511) goto <D.6840>; else goto <D.6841>;
    <D.6840>:
    GC_incremental.14 = GC_incremental;
    if (GC_incremental.14 == 0) goto <D.6843>; else goto <D.6844>;
    <D.6843>:
    D.6845 = (sizetype) index;
    D.6846 = D.6845 + 1;
    D.6847 = my_entry + D.6846;
    *my_fl = D.6847;
    <D.6844>:
    D.6825 = GC_gcj_malloc (bytes, ptr_to_struct_containing_descr);
    return D.6825;
    <D.6841>:
    D.6848 = index * 8;
    GC_all_interior_pointers.11 = GC_all_interior_pointers;
    D.6849 = D.6848 - GC_all_interior_pointers.11;
    GC_gcj_kind.15 = GC_gcj_kind;
    GC_generic_malloc_many (D.6849, GC_gcj_kind.15, my_fl);
    D.6851 = *my_fl;
    if (D.6851 == 0B) goto <D.6852>; else goto <D.6853>;
    <D.6852>:
    GC_oom_fn.16 = GC_oom_fn;
    D.6825 = GC_oom_fn.16 (bytes);
    return D.6825;
    <D.6853>:
    D.6825 = GC_local_gcj_malloc (bytes, ptr_to_struct_containing_descr);
    return D.6825;
  }
}


GC_local_gcj_fast_malloc (size_t lw, void * ptr_to_struct_containing_descr)
{
  void * GC_thread_tls.17;
  char *[65] * D.6857;
  long unsigned int D.6858;
  long unsigned int my_entry.18;
  _Bool D.6860;
  long int D.6861;
  long int D.6862;
  char * D.6865;
  void * D.6866;
  long unsigned int D.6867;
  int GC_incremental.19;
  sizetype D.6873;
  char * D.6874;
  int GC_all_interior_pointers.20;
  long unsigned int D.6876;
  long unsigned int D.6877;
  int GC_gcj_kind.21;
  char * D.6879;
  void * (*<T40d>) (size_t) GC_oom_fn.22;
  char * * my_fl;
  char * my_entry;

  GC_thread_tls.17 = GC_thread_tls;
  D.6857 = &MEM[(struct GC_Thread_Rep *)GC_thread_tls.17].gcj_freelists;
  D.6858 = lw * 8;
  my_fl = D.6857 + D.6858;
  my_entry = *my_fl;
  my_entry.18 = (long unsigned int) my_entry;
  D.6860 = my_entry.18 > 4095;
  D.6861 = (long int) D.6860;
  D.6862 = __builtin_expect (D.6861, 1);
  if (D.6862 != 0) goto <D.6863>; else goto <D.6864>;
  <D.6863>:
  {
    void * result;

    result = my_entry;
    D.6865 = MEM[(char * *)my_entry];
    MEM[(char * volatile *)my_fl] = D.6865;
    MEM[(void * volatile *)result] = ptr_to_struct_containing_descr;
    D.6866 = result;
    return D.6866;
  }
  <D.6864>:
  my_entry.18 = (long unsigned int) my_entry;
  D.6867 = my_entry.18 + 18446744073709551615;
  if (D.6867 <= 511) goto <D.6868>; else goto <D.6869>;
  <D.6868>:
  GC_incremental.19 = GC_incremental;
  if (GC_incremental.19 == 0) goto <D.6871>; else goto <D.6872>;
  <D.6871>:
  D.6873 = lw + 1;
  D.6874 = my_entry + D.6873;
  *my_fl = D.6874;
  <D.6872>:
  D.6866 = GC_gcj_fast_malloc (lw, ptr_to_struct_containing_descr);
  return D.6866;
  <D.6869>:
  D.6858 = lw * 8;
  GC_all_interior_pointers.20 = GC_all_interior_pointers;
  D.6876 = (long unsigned int) GC_all_interior_pointers.20;
  D.6877 = D.6858 - D.6876;
  GC_gcj_kind.21 = GC_gcj_kind;
  GC_generic_malloc_many (D.6877, GC_gcj_kind.21, my_fl);
  D.6879 = *my_fl;
  if (D.6879 == 0B) goto <D.6880>; else goto <D.6881>;
  <D.6880>:
  GC_oom_fn.22 = GC_oom_fn;
  D.6858 = lw * 8;
  GC_all_interior_pointers.20 = GC_all_interior_pointers;
  D.6876 = (long unsigned int) GC_all_interior_pointers.20;
  D.6877 = D.6858 - D.6876;
  D.6866 = GC_oom_fn.22 (D.6877);
  return D.6866;
  <D.6881>:
  D.6866 = GC_local_gcj_fast_malloc (lw, ptr_to_struct_containing_descr);
  return D.6866;
}


GC_mark_thread (void * id)
{
  long unsigned int id.23;
  char * D.6885;
  long unsigned int GC_mark_no.24;
  long unsigned int D.6890;
  word my_mark_no;

  my_mark_no = 0;
  id.23 = (long unsigned int) id;
  D.6885 = GC_approx_sp ();
  marker_sp[id.23] = D.6885;
  <D.6472>:
  GC_mark_no.24 = GC_mark_no;
  if (my_mark_no < GC_mark_no.24) goto <D.6886>; else goto <D.6889>;
  <D.6889>:
  GC_mark_no.24 = GC_mark_no;
  D.6890 = GC_mark_no.24 + 2;
  if (D.6890 < my_mark_no) goto <D.6886>; else goto <D.6887>;
  <D.6886>:
  my_mark_no = GC_mark_no;
  <D.6887>:
  GC_help_marker (my_mark_no);
  my_mark_no = my_mark_no + 1;
  goto <D.6472>;
}


GC_push_thread_structures ()
{
  char * D.6891;
  unsigned char * D.6892;
  unsigned char * D.6893;
  char * D.6894;

  D.6891 = &GC_threads + 1024;
  GC_push_all (&GC_threads, D.6891);
  D.6892 = get_gc_thread_key_addr ();
  D.6893 = get_gc_thread_key_addr ();
  D.6894 = D.6893 + 8;
  GC_push_all (D.6892, D.6894);
}


__attribute__((noinline))
get_gc_thread_key_addr ()
{
  unsigned char * D.6895;

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


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

  i = 0;
  goto <D.6504>;
  <D.6503>:
  p = GC_threads[i];
  goto <D.6501>;
  <D.6500>:
  j = 1;
  goto <D.6498>;
  <D.6497>:
  q = p->ptrfree_freelists[j];
  q.25 = (long unsigned int) q;
  if (q.25 > 4096) goto <D.6898>; else goto <D.6899>;
  <D.6898>:
  GC_set_fl_marks (q);
  <D.6899>:
  q = p->normal_freelists[j];
  q.25 = (long unsigned int) q;
  if (q.25 > 4096) goto <D.6900>; else goto <D.6901>;
  <D.6900>:
  GC_set_fl_marks (q);
  <D.6901>:
  q = p->gcj_freelists[j];
  q.25 = (long unsigned int) q;
  if (q.25 > 4096) goto <D.6902>; else goto <D.6903>;
  <D.6902>:
  GC_set_fl_marks (q);
  <D.6903>:
  j = j + 1;
  <D.6498>:
  if (j <= 64) goto <D.6497>; else goto <D.6499>;
  <D.6499>:
  p = p->next;
  <D.6501>:
  if (p != 0B) goto <D.6500>; else goto <D.6502>;
  <D.6502>:
  i = i + 1;
  <D.6504>:
  if (i <= 127) goto <D.6503>; else goto <D.6505>;
  <D.6505>:
}


GC_new_thread (pthread_t id)
{
  int D.6904;
  int first_thread_used.26;
  struct GC_Thread_Rep * D.6911;
  struct GC_Thread_Rep * D.6912;
  int hv;
  struct GC_Thread_Rep * result;
  static GC_bool first_thread_used = 0;

  D.6904 = (int) id;
  hv = D.6904 & 127;
  first_thread_used.26 = first_thread_used;
  if (first_thread_used.26 == 0) goto <D.6906>; else goto <D.6907>;
  <D.6906>:
  result = &first_thread;
  first_thread_used = 1;
  goto <D.6908>;
  <D.6907>:
  result = GC_generic_malloc_inner (1656, 1);
  <D.6908>:
  if (result == 0B) goto <D.6909>; else goto <D.6910>;
  <D.6909>:
  D.6911 = 0B;
  return D.6911;
  <D.6910>:
  result->id = id;
  D.6912 = GC_threads[hv];
  result->next = D.6912;
  GC_threads[hv] = result;
  D.6911 = result;
  return D.6911;
}


GC_delete_thread (pthread_t id)
{
  int D.6914;
  long unsigned int D.6915;
  int D.6916;
  struct GC_Thread_Rep * D.6919;
  int hv;
  register struct GC_Thread_Rep * p;
  register struct GC_Thread_Rep * prev;

  D.6914 = (int) id;
  hv = D.6914 & 127;
  p = GC_threads[hv];
  prev = 0B;
  goto <D.6520>;
  <D.6519>:
  prev = p;
  p = p->next;
  <D.6520>:
  D.6915 = p->id;
  D.6916 = pthread_equal (D.6915, id);
  if (D.6916 == 0) goto <D.6519>; else goto <D.6521>;
  <D.6521>:
  if (prev == 0B) goto <D.6917>; else goto <D.6918>;
  <D.6917>:
  D.6919 = p->next;
  GC_threads[hv] = D.6919;
  goto <D.6920>;
  <D.6918>:
  D.6919 = p->next;
  prev->next = D.6919;
  <D.6920>:
  GC_free_inner (p);
}


__attribute__((__gnu_inline__, const, __leaf__, __nothrow__))
pthread_equal (pthread_t __thread1, pthread_t __thread2)
{
  int D.6921;
  _Bool D.6922;

  D.6922 = __thread1 == __thread2;
  D.6921 = (int) D.6922;
  return D.6921;
}


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

  D.6924 = (int) id;
  hv = D.6924 & 127;
  p = GC_threads[hv];
  prev = 0B;
  goto <D.6530>;
  <D.6529>:
  prev = p;
  p = p->next;
  <D.6530>:
  if (p != gc_id) goto <D.6529>; else goto <D.6531>;
  <D.6531>:
  if (prev == 0B) goto <D.6925>; else goto <D.6926>;
  <D.6925>:
  D.6927 = p->next;
  GC_threads[hv] = D.6927;
  goto <D.6928>;
  <D.6926>:
  D.6927 = p->next;
  prev->next = D.6927;
  <D.6928>:
  GC_free_inner (p);
}


GC_lookup_thread (pthread_t id)
{
  int D.6929;
  long unsigned int D.6931;
  int D.6932;
  struct GC_Thread_Rep * D.6933;
  int hv;
  register struct GC_Thread_Rep * p;

  D.6929 = (int) id;
  hv = D.6929 & 127;
  p = GC_threads[hv];
  goto <D.6538>;
  <D.6537>:
  p = p->next;
  <D.6538>:
  if (p != 0B) goto <D.6930>; else goto <D.6539>;
  <D.6930>:
  D.6931 = p->id;
  D.6932 = pthread_equal (D.6931, id);
  if (D.6932 == 0) goto <D.6537>; else goto <D.6539>;
  <D.6539>:
  D.6933 = p;
  return D.6933;
}


GC_thread_is_registered ()
{
  int D.6935;
  long unsigned int D.6938;
  int D.6939;
  _Bool D.6940;
  void * ptr;

  D.6935 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6935 != 0) goto <D.6936>; else goto <D.6937>;
  <D.6936>:
  GC_lock ();
  <D.6937>:
  D.6938 = pthread_self ();
  ptr = GC_lookup_thread (D.6938);
  pthread_mutex_unlock (&GC_allocate_ml);
  D.6940 = ptr != 0B;
  D.6939 = (int) D.6940;
  return D.6939;
}


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

  D.6942 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.6942 != 0) goto <D.6943>; else goto <D.6944>;
  <D.6943>:
  GC_lock ();
  <D.6944>:
  D.6945 = pthread_self ();
  thread = GC_lookup_thread (D.6945);
  if (thread != 0B) goto <D.6946>; else goto <D.6947>;
  <D.6946>:
  thread->stack = stack;
  thread->stack_size = stack_size;
  thread->altstack = altstack;
  thread->altstack_size = altstack_size;
  goto <D.6948>;
  <D.6947>:
  D.6945 = pthread_self ();
  main_pthread_self = D.6945;
  main_stack = stack;
  main_stack_size = stack_size;
  main_altstack = altstack;
  main_altstack_size = altstack_size;
  <D.6948>:
  pthread_mutex_unlock (&GC_allocate_ml);
}


GC_get_nprocs ()
{
  long int D.6952;
  void (*<T490>) (char *, GC_word) GC_current_warn_proc.27;
  int D.6954;
  char D.6955;
  long unsigned int D.6958;
  char D.6959;
  long unsigned int D.6962;
  char D.6963;
  long unsigned int D.6966;
  char D.6967;
  sizetype D.6970;
  const char * D.6971;
  long unsigned int D.6972;
  int D.6975;
  long unsigned int D.6976;
  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.6949>; else goto <D.6951>;
      <D.6951>:
      D.6952 = read (f, &stat_buf, 4096);
      len = (size_t) D.6952;
      if (len <= 99) goto <D.6949>; else goto <D.6950>;
      <D.6949>:
      GC_current_warn_proc.27 = GC_current_warn_proc;
      GC_current_warn_proc.27 ("GC Warning: Couldn\'t read /proc/stat\n", 0);
      D.6954 = -1;
      return D.6954;
      <D.6950>:
      i = 0;
      goto <D.6560>;
      <D.6559>:
      D.6955 = stat_buf[i];
      if (D.6955 == 10) goto <D.6956>; else goto <D.6957>;
      <D.6956>:
      D.6958 = i + 1;
      D.6959 = stat_buf[D.6958];
      if (D.6959 == 99) goto <D.6960>; else goto <D.6961>;
      <D.6960>:
      D.6962 = i + 2;
      D.6963 = stat_buf[D.6962];
      if (D.6963 == 112) goto <D.6964>; else goto <D.6965>;
      <D.6964>:
      D.6966 = i + 3;
      D.6967 = stat_buf[D.6966];
      if (D.6967 == 117) goto <D.6968>; else goto <D.6969>;
      <D.6968>:
      {
        int cpu_no;

        D.6970 = i + 4;
        D.6971 = &stat_buf + D.6970;
        cpu_no = atoi (D.6971);
        D.6972 = (long unsigned int) cpu_no;
        if (D.6972 >= result) goto <D.6973>; else goto <D.6974>;
        <D.6973>:
        D.6975 = cpu_no + 1;
        result = (word) D.6975;
        <D.6974>:
      }
      <D.6969>:
      <D.6965>:
      <D.6961>:
      <D.6957>:
      i = i + 1;
      <D.6560>:
      D.6976 = len + 18446744073709551516;
      if (D.6976 > i) goto <D.6559>; else goto <D.6561>;
      <D.6561>:
      close (f);
      D.6954 = (int) result;
      return D.6954;
    }
  finally
    {
      stat_buf = {CLOBBER};
    }
}


__attribute__((__artificial__, __gnu_inline__, __always_inline__))
open (const char * __path, int __oflag)
{
  int D.6979;
  int D.6982;
  int D.6987;
  int D.6989;
  int D.6990;
  int D.6993;
  int D.6994;

  D.6979 = __builtin_va_arg_pack_len ();
  if (D.6979 > 1) goto <D.6980>; else goto <D.6981>;
  <D.6980>:
  __open_too_many_args ();
  <D.6981>:
  D.6982 = __builtin_constant_p (__oflag);
  if (D.6982 != 0) goto <D.6983>; else goto <D.6984>;
  <D.6983>:
  D.6987 = __oflag & 64;
  if (D.6987 != 0) goto <D.6985>; else goto <D.6988>;
  <D.6988>:
  D.6989 = __oflag & 4259840;
  if (D.6989 == 4259840) goto <D.6985>; else goto <D.6986>;
  <D.6985>:
  D.6990 = __builtin_va_arg_pack_len ();
  if (D.6990 <= 0) goto <D.6991>; else goto <D.6992>;
  <D.6991>:
  __open_missing_mode ();
  D.6993 = __open_2 (__path, __oflag);
  return D.6993;
  <D.6992>:
  <D.6986>:
  D.6993 = __open_alias (__path, __oflag, __builtin_va_arg_pack ());
  return D.6993;
  <D.6984>:
  D.6994 = __builtin_va_arg_pack_len ();
  if (D.6994 <= 0) goto <D.6995>; else goto <D.6996>;
  <D.6995>:
  D.6993 = __open_2 (__path, __oflag);
  return D.6993;
  <D.6996>:
  D.6993 = __open_alias (__path, __oflag, __builtin_va_arg_pack ());
  return D.6993;
}


__attribute__((__artificial__, __gnu_inline__, __always_inline__))
read (int __fd, void * __buf, size_t __nbytes)
{
  long unsigned int D.6998;
  int D.7001;
  ssize_t D.7004;
  long unsigned int D.7005;
  long unsigned int D.7006;
  long unsigned int D.7009;

  D.6998 = __builtin_object_size (__buf, 0);
  if (D.6998 != 18446744073709551615) goto <D.6999>; else goto <D.7000>;
  <D.6999>:
  D.7001 = __builtin_constant_p (__nbytes);
  if (D.7001 == 0) goto <D.7002>; else goto <D.7003>;
  <D.7002>:
  D.7005 = __builtin_object_size (__buf, 0);
  D.7004 = __read_chk (__fd, __buf, __nbytes, D.7005);
  return D.7004;
  <D.7003>:
  D.7006 = __builtin_object_size (__buf, 0);
  if (D.7006 < __nbytes) goto <D.7007>; else goto <D.7008>;
  <D.7007>:
  D.7009 = __builtin_object_size (__buf, 0);
  D.7004 = __read_chk_warn (__fd, __buf, __nbytes, D.7009);
  return D.7004;
  <D.7008>:
  <D.7000>:
  D.7004 = __read_alias (__fd, __buf, __nbytes);
  return D.7004;
}


__attribute__((__gnu_inline__, __pure__, __leaf__, __nothrow__))
atoi (const char * __nptr)
{
  int D.7011;
  long int D.7012;

  D.7012 = strtol (__nptr, 0B, 10);
  D.7011 = (int) D.7012;
  return D.7011;
}


GC_wait_for_gc_completion (GC_bool wait_for_all)
{
  int GC_incremental.28;
  int D.7017;
  long unsigned int GC_gc_no.29;
  int D.7021;
  int D.7025;
  long unsigned int D.7028;

  GC_incremental.28 = GC_incremental;
  if (GC_incremental.28 != 0) goto <D.7015>; else goto <D.7016>;
  <D.7015>:
  D.7017 = GC_collection_in_progress ();
  if (D.7017 != 0) goto <D.7018>; else goto <D.7019>;
  <D.7018>:
  {
    int old_gc_no;

    GC_gc_no.29 = GC_gc_no;
    old_gc_no = (int) GC_gc_no.29;
    goto <D.6568>;
    <D.6567>:
    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.7021 = pthread_mutex_trylock (&GC_allocate_ml);
    if (D.7021 != 0) goto <D.7022>; else goto <D.7023>;
    <D.7022>:
    GC_lock ();
    <D.7023>:
    <D.6568>:
    GC_incremental.28 = GC_incremental;
    if (GC_incremental.28 != 0) goto <D.7024>; else goto <D.6569>;
    <D.7024>:
    D.7025 = GC_collection_in_progress ();
    if (D.7025 != 0) goto <D.7026>; else goto <D.6569>;
    <D.7026>:
    if (wait_for_all != 0) goto <D.6567>; else goto <D.7027>;
    <D.7027>:
    D.7028 = (long unsigned int) old_gc_no;
    GC_gc_no.29 = GC_gc_no;
    if (D.7028 == GC_gc_no.29) goto <D.6567>; else goto <D.6569>;
    <D.6569>:
  }
  <D.7019>:
  <D.7016>:
}


GC_thr_init ()
{
  int GC_thr_initialized.30;
  long unsigned int D.7032;
  long unsigned int main_pthread_self.31;
  void * main_stack.32;
  int main_stack_size.33;
  void * main_altstack.34;
  int main_altstack_size.35;
  int D.7042;
  long int D.7043;
  long int GC_nprocs.36;
  int D.7047;
  long int D.7048;
  void (*<T490>) (char *, GC_word) GC_current_warn_proc.37;
  long unsigned int GC_nprocs.38;
  int D.7056;
  long int D.7057;
  long int GC_markers.39;
  int GC_print_stats.40;
  int GC_parallel.41;
  int dummy;
  struct GC_Thread_Rep * t;

  try
    {
      GC_thr_initialized.30 = GC_thr_initialized;
      if (GC_thr_initialized.30 != 0) goto <D.7030>; else goto <D.7031>;
      <D.7030>:
      return;
      <D.7031>:
      GC_thr_initialized = 1;
      D.7032 = pthread_self ();
      t = GC_new_thread (D.7032);
      t->stop_info.stack_ptr = &dummy;
      t->flags = 6;
      D.7032 = pthread_self ();
      main_pthread_self.31 = main_pthread_self;
      if (D.7032 == main_pthread_self.31) goto <D.7034>; else goto <D.7035>;
      <D.7034>:
      main_stack.32 = main_stack;
      t->stack = main_stack.32;
      main_stack_size.33 = main_stack_size;
      t->stack_size = main_stack_size.33;
      main_altstack.34 = main_altstack;
      t->altstack = main_altstack.34;
      main_altstack_size.35 = main_altstack_size;
      t->altstack_size = main_altstack_size.35;
      <D.7035>:
      GC_stop_init ();
      {
        char * nprocs_string;

        nprocs_string = getenv ("GC_NPROCS");
        GC_nprocs = -1;
        if (nprocs_string != 0B) goto <D.7040>; else goto <D.7041>;
        <D.7040>:
        D.7042 = atoi (nprocs_string);
        D.7043 = (long int) D.7042;
        GC_nprocs = D.7043;
        <D.7041>:
      }
      GC_nprocs.36 = GC_nprocs;
      if (GC_nprocs.36 <= 0) goto <D.7045>; else goto <D.7046>;
      <D.7045>:
      D.7047 = GC_get_nprocs ();
      D.7048 = (long int) D.7047;
      GC_nprocs = D.7048;
      <D.7046>:
      GC_nprocs.36 = GC_nprocs;
      if (GC_nprocs.36 <= 0) goto <D.7049>; else goto <D.7050>;
      <D.7049>:
      GC_current_warn_proc.37 = GC_current_warn_proc;
      GC_nprocs.36 = GC_nprocs;
      GC_nprocs.38 = (long unsigned int) GC_nprocs.36;
      GC_current_warn_proc.37 ("GC Warning: GC_get_nprocs() returned %ld\n", GC_nprocs.38);
      GC_nprocs = 2;
      GC_markers = 1;
      goto <D.7053>;
      <D.7050>:
      {
        char * markers_string;

        markers_string = getenv ("GC_MARKERS");
        if (markers_string != 0B) goto <D.7054>; else goto <D.7055>;
        <D.7054>:
        D.7056 = atoi (markers_string);
        D.7057 = (long int) D.7056;
        GC_markers = D.7057;
        goto <D.7058>;
        <D.7055>:
        GC_nprocs.36 = GC_nprocs;
        GC_markers = GC_nprocs.36;
        GC_markers.39 = GC_markers;
        if (GC_markers.39 > 16) goto <D.7060>; else goto <D.7061>;
        <D.7060>:
        GC_markers = 16;
        <D.7061>:
        <D.7058>:
      }
      <D.7053>:
      GC_print_stats.40 = GC_print_stats;
      if (GC_print_stats.40 != 0) goto <D.7063>; else goto <D.7064>;
      <D.7063>:
      GC_nprocs.36 = GC_nprocs;
      GC_markers.39 = GC_markers;
      GC_printf ("Number of processors = %ld, number of marker threads = %ld\n", GC_nprocs.36, GC_markers.39, 0, 0, 0, 0);
      <D.7064>:
      GC_markers.39 = GC_markers;
      if (GC_markers.39 == 1) goto <D.7065>; else goto <D.7066>;
      <D.7065>:
      GC_parallel = 0;
      GC_print_stats.40 = GC_print_stats;
      if (GC_print_stats.40 != 0) goto <D.7067>; else goto <D.7068>;
      <D.7067>:
      GC_printf ("Single marker thread, turning off parallel marking\n", 0, 0, 0, 0, 0, 0);
      <D.7068>:
      goto <D.7069>;
      <D.7066>:
      GC_parallel = 1;
      GC_time_limit = 999999;
      <D.7069>:
      GC_parallel.41 = GC_parallel;
      if (GC_parallel.41 != 0) goto <D.7071>; else goto <D.7072>;
      <D.7071>:
      start_mark_threads ();
      <D.7072>:
    }
  finally
    {
      dummy = {CLOBBER};
    }
}


start_mark_threads ()
{
  long int GC_markers.42;
  void (*<T490>) (char *, GC_word) GC_current_warn_proc.43;
  int D.7080;
  int D.7083;
  int GC_print_stats.44;
  long int D.7089;
  long unsigned int D.7090;
  long unsigned int D.7091;
  pthread_t * D.7092;
  void * D.7093;
  int D.7094;
  int * D.7097;
  int D.7098;
  long unsigned int D.7099;
  long int D.7100;
  unsigned int i;
  union pthread_attr_t attr;

  try
    {
      GC_markers.42 = GC_markers;
      if (GC_markers.42 > 16) goto <D.7077>; else goto <D.7078>;
      <D.7077>:
      GC_current_warn_proc.43 = GC_current_warn_proc;
      GC_current_warn_proc.43 ("GC Warning: Limiting number of mark threads\n", 0);
      GC_markers = 16;
      <D.7078>:
      D.7080 = pthread_attr_init (&attr);
      if (D.7080 != 0) goto <D.7081>; else goto <D.7082>;
      <D.7081>:
      GC_abort ("pthread_attr_init failed");
      <D.7082>:
      D.7083 = pthread_attr_setdetachstate (&attr, 1);
      if (D.7083 != 0) goto <D.7084>; else goto <D.7085>;
      <D.7084>:
      GC_abort ("pthread_attr_setdetachstate failed");
      <D.7085>:
      GC_print_stats.44 = GC_print_stats;
      if (GC_print_stats.44 != 0) goto <D.7087>; else goto <D.7088>;
      <D.7087>:
      GC_markers.42 = GC_markers;
      D.7089 = GC_markers.42 + -1;
      GC_printf ("Starting %ld marker threads\n", D.7089, 0, 0, 0, 0, 0);
      <D.7088>:
      i = 0;
      goto <D.6480>;
      <D.6479>:
      D.7090 = (long unsigned int) i;
      D.7091 = D.7090 * 8;
      D.7092 = &GC_mark_threads + D.7091;
      D.7090 = (long unsigned int) i;
      D.7093 = (void *) D.7090;
      D.7094 = pthread_create (D.7092, &attr, GC_mark_thread, D.7093);
      if (D.7094 != 0) goto <D.7095>; else goto <D.7096>;
      <D.7095>:
      GC_current_warn_proc.43 = GC_current_warn_proc;
      D.7097 = __errno_location ();
      D.7098 = *D.7097;
      D.7099 = (long unsigned int) D.7098;
      GC_current_warn_proc.43 ("GC Warning: Marker thread creation failed, errno = %ld.\n", D.7099);
      <D.7096>:
      i = i + 1;
      <D.6480>:
      D.7100 = (long int) i;
      GC_markers.42 = GC_markers;
      D.7089 = GC_markers.42 + -1;
      if (D.7100 < D.7089) goto <D.6479>; else goto <D.6481>;
      <D.6481>:
    }
  finally
    {
      attr = {CLOBBER};
    }
}


GC_init_parallel ()
{
  int parallel_initialized.45;
  int GC_is_initialized.46;
  int D.7107;
  long unsigned int D.7110;
  struct GC_Thread_Rep * D.7111;

  parallel_initialized.45 = parallel_initialized;
  if (parallel_initialized.45 != 0) goto <D.7102>; else goto <D.7103>;
  <D.7102>:
  return;
  <D.7103>:
  parallel_initialized = 1;
  GC_is_initialized.46 = GC_is_initialized;
  if (GC_is_initialized.46 == 0) goto <D.7105>; else goto <D.7106>;
  <D.7105>:
  GC_init ();
  <D.7106>:
  D.7107 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7107 != 0) goto <D.7108>; else goto <D.7109>;
  <D.7108>:
  GC_lock ();
  <D.7109>:
  D.7110 = pthread_self ();
  D.7111 = GC_lookup_thread (D.7110);
  GC_init_thread_local (D.7111);
  pthread_mutex_unlock (&GC_allocate_ml);
}


GC_pthread_sigmask (int how, const struct sigset_t * set, struct sigset_t * oset)
{
  int D.7118;
  struct sigset_t fudged_set;

  try
    {
      if (set != 0B) goto <D.7115>; else goto <D.7116>;
      <D.7115>:
      if (how == 0) goto <D.7113>; else goto <D.7117>;
      <D.7117>:
      if (how == 2) goto <D.7113>; else goto <D.7114>;
      <D.7113>:
      fudged_set = *set;
      sigdelset (&fudged_set, 30);
      set = &fudged_set;
      <D.7114>:
      <D.7116>:
      D.7118 = pthread_sigmask (how, set, oset);
      return D.7118;
    }
  finally
    {
      fudged_set = {CLOBBER};
    }
}


GC_start_blocking ()
{
  int D.7121;
  long unsigned int D.7124;
  char * D.7125;
  char * D.7126;
  char * D.7127;
  struct GC_Thread_Rep * me;

  D.7121 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7121 != 0) goto <D.7122>; else goto <D.7123>;
  <D.7122>:
  GC_lock ();
  <D.7123>:
  D.7124 = pthread_self ();
  me = GC_lookup_thread (D.7124);
  D.7125 = GC_approx_sp ();
  me->stop_info.stack_ptr = D.7125;
  D.7126 = me->stop_info.stack_ptr;
  D.7127 = D.7126 + 18446744073709551488;
  me->stop_info.stack_ptr = D.7127;
  me->thread_blocked = 1;
  pthread_mutex_unlock (&GC_allocate_ml);
}


GC_end_blocking ()
{
  int D.7128;
  long unsigned int D.7131;
  struct GC_Thread_Rep * me;

  D.7128 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7128 != 0) goto <D.7129>; else goto <D.7130>;
  <D.7129>:
  GC_lock ();
  <D.7130>:
  D.7131 = pthread_self ();
  me = GC_lookup_thread (D.7131);
  me->thread_blocked = 0;
  pthread_mutex_unlock (&GC_allocate_ml);
}


GC_sleep (unsigned int seconds)
{
  unsigned int D.7132;
  int D.7133;
  int result;

  GC_start_blocking ();
  D.7132 = sleep (seconds);
  result = (int) D.7132;
  GC_end_blocking ();
  D.7133 = result;
  return D.7133;
}


GC_thread_exit_proc (void * arg)
{
  int D.7135;
  long unsigned int D.7138;
  short int D.7139;
  int D.7140;
  int D.7141;
  unsigned int GC_thread_key.47;
  int D.7145;
  short int D.7149;
  struct GC_Thread_Rep * me;

  D.7135 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7135 != 0) goto <D.7136>; else goto <D.7137>;
  <D.7136>:
  GC_lock ();
  <D.7137>:
  D.7138 = pthread_self ();
  me = GC_lookup_thread (D.7138);
  GC_destroy_thread_local (me);
  D.7139 = me->flags;
  D.7140 = (int) D.7139;
  D.7141 = D.7140 & 2;
  if (D.7141 != 0) goto <D.7142>; else goto <D.7143>;
  <D.7142>:
  GC_thread_key.47 = GC_thread_key;
  D.7145 = GC_setspecific (GC_thread_key.47, 0B);
  if (D.7145 != 0) goto <D.7146>; else goto <D.7147>;
  <D.7146>:
  GC_abort ("Failed to set thread specific allocation pointers");
  <D.7147>:
  D.7138 = pthread_self ();
  GC_delete_thread (D.7138);
  goto <D.7148>;
  <D.7143>:
  D.7139 = me->flags;
  D.7149 = D.7139 | 1;
  me->flags = D.7149;
  <D.7148>:
  GC_wait_for_gc_completion (0);
  pthread_mutex_unlock (&GC_allocate_ml);
}


GC_pthread_join (pthread_t thread, void * * retval)
{
  int D.7150;
  int D.7155;
  int D.7158;
  int result;
  struct GC_Thread_Rep * thread_gc_id;

  D.7150 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7150 != 0) goto <D.7151>; else goto <D.7152>;
  <D.7151>:
  GC_lock ();
  <D.7152>:
  thread_gc_id = GC_lookup_thread (thread);
  pthread_mutex_unlock (&GC_allocate_ml);
  result = pthread_join (thread, retval);
  if (result == 0) goto <D.7153>; else goto <D.7154>;
  <D.7153>:
  D.7155 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7155 != 0) goto <D.7156>; else goto <D.7157>;
  <D.7156>:
  GC_lock ();
  <D.7157>:
  GC_delete_gc_thread (thread, thread_gc_id);
  pthread_mutex_unlock (&GC_allocate_ml);
  <D.7154>:
  D.7158 = result;
  return D.7158;
}


GC_pthread_detach (pthread_t thread)
{
  int D.7160;
  int D.7165;
  short int D.7168;
  short int D.7169;
  int D.7170;
  int D.7171;
  int D.7174;
  int result;
  struct GC_Thread_Rep * thread_gc_id;

  D.7160 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7160 != 0) goto <D.7161>; else goto <D.7162>;
  <D.7161>:
  GC_lock ();
  <D.7162>:
  thread_gc_id = GC_lookup_thread (thread);
  pthread_mutex_unlock (&GC_allocate_ml);
  result = pthread_detach (thread);
  if (result == 0) goto <D.7163>; else goto <D.7164>;
  <D.7163>:
  D.7165 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7165 != 0) goto <D.7166>; else goto <D.7167>;
  <D.7166>:
  GC_lock ();
  <D.7167>:
  D.7168 = thread_gc_id->flags;
  D.7169 = D.7168 | 2;
  thread_gc_id->flags = D.7169;
  D.7168 = thread_gc_id->flags;
  D.7170 = (int) D.7168;
  D.7171 = D.7170 & 1;
  if (D.7171 != 0) goto <D.7172>; else goto <D.7173>;
  <D.7172>:
  GC_delete_gc_thread (thread, thread_gc_id);
  <D.7173>:
  pthread_mutex_unlock (&GC_allocate_ml);
  <D.7164>:
  D.7174 = result;
  return D.7174;
}


GC_start_routine_head (void * arg, void * base_addr, void * (*ThreadStartFn) (void *) * start, void * * start_arg)
{
  int D.7176;
  long unsigned int D.7179;
  short int D.7180;
  long unsigned int GC_page_size.48;
  long unsigned int base_addr.49;
  long unsigned int D.7183;
  long unsigned int D.7184;
  long unsigned int D.7185;
  long unsigned int D.7186;
  char * D.7187;
  char * D.7188;
  char * D.7189;
  void * (*<T49a>) (void *) D.7192;
  void * D.7195;
  long unsigned int D.7196;
  union sem_t * D.7199;
  int D.7200;
  void * D.7203;
  struct start_info * si;
  void * result;
  struct GC_Thread_Rep * me;
  pthread_t my_pthread;

  si = arg;
  my_pthread = pthread_self ();
  D.7176 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7176 != 0) goto <D.7177>; else goto <D.7178>;
  <D.7177>:
  GC_lock ();
  <D.7178>:
  GC_in_thread_creation = 1;
  me = GC_new_thread (my_pthread);
  GC_in_thread_creation = 0;
  me->stop_info.stack_ptr = 0B;
  D.7179 = si->flags;
  D.7180 = (short int) D.7179;
  me->flags = D.7180;
  GC_page_size.48 = GC_page_size;
  base_addr.49 = (long unsigned int) base_addr;
  D.7183 = GC_page_size.48 + base_addr.49;
  D.7184 = D.7183 + 18446744073709551615;
  GC_page_size.48 = GC_page_size;
  D.7185 = -GC_page_size.48;
  D.7186 = D.7184 & D.7185;
  D.7187 = (char *) D.7186;
  me->stack_end = D.7187;
  D.7188 = me->stack_end;
  D.7189 = D.7188 + 18446744073709551600;
  me->stop_info.stack_ptr = D.7189;
  pthread_mutex_unlock (&GC_allocate_ml);
  if (start != 0B) goto <D.7190>; else goto <D.7191>;
  <D.7190>:
  D.7192 = si->start_routine;
  *start = D.7192;
  <D.7191>:
  if (start_arg != 0B) goto <D.7193>; else goto <D.7194>;
  <D.7193>:
  D.7195 = si->arg;
  *start_arg = D.7195;
  <D.7194>:
  D.7179 = si->flags;
  D.7196 = D.7179 & 8;
  if (D.7196 == 0) goto <D.7197>; else goto <D.7198>;
  <D.7197>:
  D.7199 = &si->registered;
  sem_post (D.7199);
  <D.7198>:
  D.7200 = pthread_mutex_trylock (&GC_allocate_ml);
  if (D.7200 != 0) goto <D.7201>; else goto <D.7202>;
  <D.7201>:
  GC_lock ();
  <D.7202>:
  GC_init_thread_local (me);
  pthread_mutex_unlock (&GC_allocate_ml);
  D.7203 = me;
  return D.7203;
}


GC_thread_register_foreign (void * base_addr)
{
  int parallel_initialized.50;
  int D.7208;
  int GC_thr_initialized.51;
  int D.7214;
  _Bool D.7215;
  struct start_info si;
  struct GC_Thread_Rep * me;

  try
    {
      si = {};
      si.flags = 8;
      parallel_initialized.50 = parallel_initialized;
      if (parallel_initialized.50 == 0) goto <D.7206>; else goto <D.7207>;
      <D.7206>:
      GC_init_parallel ();
      <D.7207>:
      D.7208 = pthread_mutex_trylock (&GC_allocate_ml);
      if (D.7208 != 0) goto <D.7209>; else goto <D.7210>;
      <D.7209>:
      GC_lock ();
      <D.7210>:
      GC_thr_initialized.51 = GC_thr_initialized;
      if (GC_thr_initialized.51 == 0) goto <D.7212>; else goto <D.7213>;
      <D.7212>:
      GC_thr_init ();
      <D.7213>:
      pthread_mutex_unlock (&GC_allocate_ml);
      me = GC_start_routine_head (&si, base_addr, 0B, 0B);
      D.7215 = me != 0B;
      D.7214 = (int) D.7215;
      return D.7214;
    }
  finally
    {
      si = {CLOBBER};
    }
}


GC_start_routine (void * arg)
{
  long int D.7218;
  long int D.7219;
  void * (*<T49a>) (void *) start.52;
  void * start_arg.53;
  void * D.7226;
  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 (*<Tc6>) (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.7218 = (long int) __not_first_call;
            D.7219 = __builtin_expect (D.7218, 0);
            if (D.7219 != 0) goto <D.7220>; else goto <D.7221>;
            <D.7220>:
            __cancel_routine (__cancel_arg);
            __pthread_unwind_next (&__cancel_buf);
            <D.7221>:
            __pthread_register_cancel (&__cancel_buf);
            start.52 = start;
            start_arg.53 = start_arg;
            result = start.52 (start_arg.53);
            me->status = result;
            __pthread_unregister_cancel (&__cancel_buf);
            if (1 != 0) goto <D.7224>; else goto <D.7225>;
            <D.7224>:
            __cancel_routine (__cancel_arg);
            <D.7225>:
          }
        finally
          {
            __cancel_buf = {CLOBBER};
          }
      }
      D.7226 = result;
      return D.7226;
    }
  finally
    {
      dummy = {CLOBBER};
      start = {CLOBBER};
      start_arg = {CLOBBER};
    }
}


GC_pthread_create (pthread_t * new_thread, const union pthread_attr_t * attr, void * (*<T49a>) (void *) start_routine, void * arg)
{
  int D.7231;
  int parallel_initialized.54;
  int D.7239;
  union sem_t * D.7240;
  int D.7241;
  int GC_thr_initialized.55;
  int detachstate.56;
  int * D.7255;
  int D.7256;
  int D.7259;
  int D.7260;
  int result;
  int detachstate;
  word my_flags;
  struct start_info * si;

  try
    {
      my_flags = 0;
      D.7231 = pthread_mutex_trylock (&GC_allocate_ml);
      if (D.7231 != 0) goto <D.7232>; else goto <D.7233>;
      <D.7232>:
      GC_lock ();
      <D.7233>:
      si = GC_generic_malloc_inner (56, 1);
      pthread_mutex_unlock (&GC_allocate_ml);
      parallel_initialized.54 = parallel_initialized;
      if (parallel_initialized.54 == 0) goto <D.7235>; else goto <D.7236>;
      <D.7235>:
      GC_init_parallel ();
      <D.7236>:
      if (si == 0B) goto <D.7237>; else goto <D.7238>;
      <D.7237>:
      D.7239 = 12;
      return D.7239;
      <D.7238>:
      D.7240 = &si->registered;
      sem_init (D.7240, 0, 0);
      si->start_routine = start_routine;
      si->arg = arg;
      D.7241 = pthread_mutex_trylock (&GC_allocate_ml);
      if (D.7241 != 0) goto <D.7242>; else goto <D.7243>;
      <D.7242>:
      GC_lock ();
      <D.7243>:
      GC_thr_initialized.55 = GC_thr_initialized;
      if (GC_thr_initialized.55 == 0) goto <D.7245>; else goto <D.7246>;
      <D.7245>:
      GC_thr_init ();
      <D.7246>:
      if (attr == 0B) goto <D.7247>; else goto <D.7248>;
      <D.7247>:
      detachstate = 0;
      goto <D.7249>;
      <D.7248>:
      pthread_attr_getdetachstate (attr, &detachstate);
      <D.7249>:
      detachstate.56 = detachstate;
      if (detachstate.56 == 1) goto <D.7251>; else goto <D.7252>;
      <D.7251>:
      my_flags = my_flags | 2;
      <D.7252>:
      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.7253>; else goto <D.7254>;
      <D.7253>:
      goto <D.6661>;
      <D.6660>:
      D.7255 = __errno_location ();
      D.7256 = *D.7255;
      if (D.7256 != 4) goto <D.7257>; else goto <D.7258>;
      <D.7257>:
      GC_abort ("sem_wait failed");
      <D.7258>:
      <D.6661>:
      D.7240 = &si->registered;
      D.7259 = sem_wait (D.7240);
      if (D.7259 != 0) goto <D.6660>; else goto <D.6662>;
      <D.6662>:
      <D.7254>:
      D.7240 = &si->registered;
      sem_destroy (D.7240);
      D.7260 = pthread_mutex_trylock (&GC_allocate_ml);
      if (D.7260 != 0) goto <D.7261>; else goto <D.7262>;
      <D.7261>:
      GC_lock ();
      <D.7262>:
      GC_free_inner (si);
      pthread_mutex_unlock (&GC_allocate_ml);
      D.7239 = result;
      return D.7239;
    }
  finally
    {
      detachstate = {CLOBBER};
    }
}


GC_pause ()
{
  int i;

  i = 0;
  goto <D.6667>;
  <D.6666>:
  __asm__ __volatile__(" " :  :  : "memory");
  i = i + 1;
  <D.6667>:
  if (i <= 9) goto <D.6666>; else goto <D.6668>;
  <D.6668>:
}


GC_generic_lock (union pthread_mutex_t * lock)
{
  int D.7265;
  long unsigned int GC_unlocked_count.57;
  long unsigned int D.7269;
  int D.7270;
  long unsigned int GC_spin_count.58;
  long unsigned int D.7272;
  long unsigned int GC_block_count.59;
  long unsigned int D.7274;
  unsigned int pause_length;
  unsigned int i;

  pause_length = 1;
  D.7265 = pthread_mutex_trylock (lock);
  if (D.7265 == 0) goto <D.7266>; else goto <D.7267>;
  <D.7266>:
  GC_unlocked_count.57 = GC_unlocked_count;
  D.7269 = GC_unlocked_count.57 + 1;
  GC_unlocked_count = D.7269;
  return;
  <D.7267>:
  goto <D.6686>;
  <D.6685>:
  i = 0;
  goto <D.6679>;
  <D.6678>:
  GC_pause ();
  i = i + 1;
  <D.6679>:
  if (i < pause_length) goto <D.6678>; else goto <D.6680>;
  <D.6680>:
  D.7270 = pthread_mutex_trylock (lock);
  switch (D.7270) <default: <D.6684>, case 0: <D.6681>, case 16: <D.6682>>
  <D.6681>:
  GC_spin_count.58 = GC_spin_count;
  D.7272 = GC_spin_count.58 + 1;
  GC_spin_count = D.7272;
  return;
  <D.6682>:
  goto <D.6683>;
  <D.6684>:
  GC_abort ("Unexpected error from pthread_mutex_trylock");
  <D.6683>:
  pause_length = pause_length << 1;
  <D.6686>:
  if (pause_length <= 128) goto <D.6685>; else goto <D.6687>;
  <D.6687>:
  GC_block_count.59 = GC_block_count;
  D.7274 = GC_block_count.59 + 1;
  GC_block_count = D.7274;
  pthread_mutex_lock (lock);
}


GC_lock ()
{
  long int GC_nprocs.60;
  int GC_collecting.61;

  GC_nprocs.60 = GC_nprocs;
  if (GC_nprocs.60 == 1) goto <D.7277>; else goto <D.7281>;
  <D.7281>:
  GC_collecting.61 = GC_collecting;
  if (GC_collecting.61 != 0) goto <D.7277>; else goto <D.7278>;
  <D.7277>:
  pthread_mutex_lock (&GC_allocate_ml);
  goto <D.7279>;
  <D.7278>:
  GC_generic_lock (&GC_allocate_ml);
  <D.7279>:
}


GC_acquire_mark_lock ()
{
  GC_generic_lock (&mark_mutex);
}


GC_release_mark_lock ()
{
  int D.7283;

  D.7283 = pthread_mutex_unlock (&mark_mutex);
  if (D.7283 != 0) goto <D.7284>; else goto <D.7285>;
  <D.7284>:
  GC_abort ("pthread_mutex_unlock failed");
  <D.7285>:
}


GC_wait_builder ()
{
  int D.7286;

  D.7286 = pthread_cond_wait (&builder_cv, &mark_mutex);
  if (D.7286 != 0) goto <D.7287>; else goto <D.7288>;
  <D.7287>:
  GC_abort ("pthread_cond_wait failed");
  <D.7288>:
}


GC_wait_for_reclaim ()
{
  long unsigned int GC_fl_builder_count.62;

  GC_acquire_mark_lock ();
  goto <D.6701>;
  <D.6700>:
  GC_wait_builder ();
  <D.6701>:
  GC_fl_builder_count.62 = GC_fl_builder_count;
  if (GC_fl_builder_count.62 != 0) goto <D.6700>; else goto <D.6702>;
  <D.6702>:
  GC_release_mark_lock ();
}


GC_notify_all_builder ()
{
  int D.7290;

  D.7290 = pthread_cond_broadcast (&builder_cv);
  if (D.7290 != 0) goto <D.7291>; else goto <D.7292>;
  <D.7291>:
  GC_abort ("pthread_cond_broadcast failed");
  <D.7292>:
}


GC_wait_marker ()
{
  int D.7293;

  D.7293 = pthread_cond_wait (&mark_cv, &mark_mutex);
  if (D.7293 != 0) goto <D.7294>; else goto <D.7295>;
  <D.7294>:
  GC_abort ("pthread_cond_wait failed");
  <D.7295>:
}


GC_notify_all_marker ()
{
  int D.7296;

  D.7296 = pthread_cond_broadcast (&mark_cv);
  if (D.7296 != 0) goto <D.7297>; else goto <D.7298>;
  <D.7297>:
  GC_abort ("pthread_cond_broadcast failed");
  <D.7298>:
}


