diff --git a/libgomp/allocator.c b/libgomp/allocator.c
index 9fcfc4ea5c6bb80d6013c6e80672af0abcdb3cf8..dce600f5bd7442334b9ff0690594753babea4fff 100644
--- a/libgomp/allocator.c
+++ b/libgomp/allocator.c
@@ -30,6 +30,7 @@
 #define _GNU_SOURCE
 #include "libgomp.h"
 #include <stdlib.h>
+#include <string.h>
 
 #define omp_max_predefined_alloc omp_thread_mem_alloc
 
@@ -205,18 +206,19 @@ omp_destroy_allocator (omp_allocator_handle_t allocator)
 ialias (omp_init_allocator)
 ialias (omp_destroy_allocator)
 
-static void *
+void *
 omp_aligned_alloc (size_t alignment, size_t size,
 		   omp_allocator_handle_t allocator)
 {
   struct omp_allocator_data *allocator_data;
-  size_t new_size;
+  size_t new_size, new_alignment;
   void *ptr, *ret;
 
   if (__builtin_expect (size == 0, 0))
     return NULL;
 
 retry:
+  new_alignment = alignment;
   if (allocator == omp_null_allocator)
     {
       struct gomp_thread *thr = gomp_thread ();
@@ -228,19 +230,19 @@ retry:
   if (allocator > omp_max_predefined_alloc)
     {
       allocator_data = (struct omp_allocator_data *) allocator;
-      if (alignment < allocator_data->alignment)
-	alignment = allocator_data->alignment;
+      if (new_alignment < allocator_data->alignment)
+	new_alignment = allocator_data->alignment;
     }
   else
     {
       allocator_data = NULL;
-      if (alignment < sizeof (void *))
-	alignment = sizeof (void *);
+      if (new_alignment < sizeof (void *))
+	new_alignment = sizeof (void *);
     }
 
   new_size = sizeof (struct omp_mem_header);
-  if (alignment > sizeof (void *))
-    new_size += alignment - sizeof (void *);
+  if (new_alignment > sizeof (void *))
+    new_size += new_alignment - sizeof (void *);
   if (__builtin_add_overflow (size, new_size, &new_size))
     goto fail;
 
@@ -300,10 +302,11 @@ retry:
 	goto fail;
     }
 
-  if (alignment > sizeof (void *))
+  if (new_alignment > sizeof (void *))
     ret = (void *) (((uintptr_t) ptr
 		     + sizeof (struct omp_mem_header)
-		     + alignment - sizeof (void *)) & ~(alignment - 1));
+		     + new_alignment - sizeof (void *))
+		    & ~(new_alignment - 1));
   else
     ret = (char *) ptr + sizeof (struct omp_mem_header);
   ((struct omp_mem_header *) ret)[-1].ptr = ptr;
@@ -317,7 +320,7 @@ fail:
       switch (allocator_data->fallback)
 	{
 	case omp_atv_default_mem_fb:
-	  if (alignment > sizeof (void *)
+	  if ((new_alignment > sizeof (void *) && new_alignment > alignment)
 	      || (allocator_data
 		  && allocator_data->pool_size < ~(uintptr_t) 0))
 	    {
@@ -326,7 +329,7 @@ fail:
 	    }
 	  /* Otherwise, we've already performed default mem allocation
 	     and if that failed, it won't succeed again (unless it was
-	     intermitent.  Return NULL then, as that is the fallback.  */
+	     intermittent.  Return NULL then, as that is the fallback.  */
 	  break;
 	case omp_atv_null_fb:
 	  break;
@@ -342,10 +345,12 @@ fail:
   return NULL;
 }
 
+ialias (omp_aligned_alloc)
+
 void *
 omp_alloc (size_t size, omp_allocator_handle_t allocator)
 {
-  return omp_aligned_alloc (1, size, allocator);
+  return ialias_call (omp_aligned_alloc) (1, size, allocator);
 }
 
 /* Like omp_aligned_alloc, but apply on top of that:
@@ -355,8 +360,9 @@ omp_alloc (size_t size, omp_allocator_handle_t allocator)
 void *
 GOMP_alloc (size_t alignment, size_t size, uintptr_t allocator)
 {
-  void *ret = omp_aligned_alloc (alignment, size,
-				 (omp_allocator_handle_t) allocator);
+  void *ret
+    = ialias_call (omp_aligned_alloc) (alignment, size,
+				       (omp_allocator_handle_t) allocator);
   if (__builtin_expect (ret == NULL, 0) && size)
     gomp_fatal ("Out of memory allocating %lu bytes",
 		(unsigned long) size);
@@ -396,5 +402,365 @@ ialias (omp_free)
 void
 GOMP_free (void *ptr, uintptr_t allocator)
 {
-  return omp_free (ptr, (omp_allocator_handle_t) allocator);
+  return ialias_call (omp_free) (ptr, (omp_allocator_handle_t) allocator);
+}
+
+void *
+omp_aligned_calloc (size_t alignment, size_t nmemb, size_t size,
+		    omp_allocator_handle_t allocator)
+{
+  struct omp_allocator_data *allocator_data;
+  size_t new_size, size_temp, new_alignment;
+  void *ptr, *ret;
+
+  if (__builtin_expect (size == 0 || nmemb == 0, 0))
+    return NULL;
+
+retry:
+  new_alignment = alignment;
+  if (allocator == omp_null_allocator)
+    {
+      struct gomp_thread *thr = gomp_thread ();
+      if (thr->ts.def_allocator == omp_null_allocator)
+	thr->ts.def_allocator = gomp_def_allocator;
+      allocator = (omp_allocator_handle_t) thr->ts.def_allocator;
+    }
+
+  if (allocator > omp_max_predefined_alloc)
+    {
+      allocator_data = (struct omp_allocator_data *) allocator;
+      if (new_alignment < allocator_data->alignment)
+	new_alignment = allocator_data->alignment;
+    }
+  else
+    {
+      allocator_data = NULL;
+      if (new_alignment < sizeof (void *))
+	new_alignment = sizeof (void *);
+    }
+
+  new_size = sizeof (struct omp_mem_header);
+  if (new_alignment > sizeof (void *))
+    new_size += new_alignment - sizeof (void *);
+  if (__builtin_mul_overflow (size, nmemb, &size_temp))
+    goto fail;
+  if (__builtin_add_overflow (size_temp, new_size, &new_size))
+    goto fail;
+
+  if (__builtin_expect (allocator_data
+			&& allocator_data->pool_size < ~(uintptr_t) 0, 0))
+    {
+      uintptr_t used_pool_size;
+      if (new_size > allocator_data->pool_size)
+	goto fail;
+#ifdef HAVE_SYNC_BUILTINS
+      used_pool_size = __atomic_load_n (&allocator_data->used_pool_size,
+					MEMMODEL_RELAXED);
+      do
+	{
+	  uintptr_t new_pool_size;
+	  if (__builtin_add_overflow (used_pool_size, new_size,
+				      &new_pool_size)
+	      || new_pool_size > allocator_data->pool_size)
+	    goto fail;
+	  if (__atomic_compare_exchange_n (&allocator_data->used_pool_size,
+					   &used_pool_size, new_pool_size,
+					   true, MEMMODEL_RELAXED,
+					   MEMMODEL_RELAXED))
+	    break;
+	}
+      while (1);
+#else
+      gomp_mutex_lock (&allocator_data->lock);
+      if (__builtin_add_overflow (allocator_data->used_pool_size, new_size,
+				  &used_pool_size)
+	  || used_pool_size > allocator_data->pool_size)
+	{
+	  gomp_mutex_unlock (&allocator_data->lock);
+	  goto fail;
+	}
+      allocator_data->used_pool_size = used_pool_size;
+      gomp_mutex_unlock (&allocator_data->lock);
+#endif
+      ptr = calloc (1, new_size);
+      if (ptr == NULL)
+	{
+#ifdef HAVE_SYNC_BUILTINS
+	  __atomic_add_fetch (&allocator_data->used_pool_size, -new_size,
+			      MEMMODEL_RELAXED);
+#else
+	  gomp_mutex_lock (&allocator_data->lock);
+	  allocator_data->used_pool_size -= new_size;
+	  gomp_mutex_unlock (&allocator_data->lock);
+#endif
+	  goto fail;
+	}
+    }
+  else
+    {
+      ptr = calloc (1, new_size);
+      if (ptr == NULL)
+	goto fail;
+    }
+
+  if (new_alignment > sizeof (void *))
+    ret = (void *) (((uintptr_t) ptr
+		     + sizeof (struct omp_mem_header)
+		     + new_alignment - sizeof (void *))
+		    & ~(new_alignment - 1));
+  else
+    ret = (char *) ptr + sizeof (struct omp_mem_header);
+  ((struct omp_mem_header *) ret)[-1].ptr = ptr;
+  ((struct omp_mem_header *) ret)[-1].size = new_size;
+  ((struct omp_mem_header *) ret)[-1].allocator = allocator;
+  return ret;
+
+fail:
+  if (allocator_data)
+    {
+      switch (allocator_data->fallback)
+	{
+	case omp_atv_default_mem_fb:
+	  if ((new_alignment > sizeof (void *) && new_alignment > alignment)
+	      || (allocator_data
+		  && allocator_data->pool_size < ~(uintptr_t) 0))
+	    {
+	      allocator = omp_default_mem_alloc;
+	      goto retry;
+	    }
+	  /* Otherwise, we've already performed default mem allocation
+	     and if that failed, it won't succeed again (unless it was
+	     intermittent.  Return NULL then, as that is the fallback.  */
+	  break;
+	case omp_atv_null_fb:
+	  break;
+	default:
+	case omp_atv_abort_fb:
+	  gomp_fatal ("Out of memory allocating %lu bytes",
+		      (unsigned long) (size * nmemb));
+	case omp_atv_allocator_fb:
+	  allocator = allocator_data->fb_data;
+	  goto retry;
+	}
+    }
+  return NULL;
+}
+
+ialias (omp_aligned_calloc)
+
+void *
+omp_calloc (size_t nmemb, size_t size, omp_allocator_handle_t allocator)
+{
+  return ialias_call (omp_aligned_calloc) (1, nmemb, size, allocator);
+}
+
+void *
+omp_realloc (void *ptr, size_t size, omp_allocator_handle_t allocator,
+	     omp_allocator_handle_t free_allocator)
+{
+  struct omp_allocator_data *allocator_data, *free_allocator_data;
+  size_t new_size, old_size, new_alignment, old_alignment;
+  void *new_ptr, *ret;
+  struct omp_mem_header *data;
+
+  if (__builtin_expect (ptr == NULL, 0))
+    return ialias_call (omp_aligned_alloc) (1, size, allocator);
+
+  if (__builtin_expect (size == 0, 0))
+    {
+      ialias_call (omp_free) (ptr, free_allocator);
+      return NULL;
+    }
+
+  data = &((struct omp_mem_header *) ptr)[-1];
+  free_allocator = data->allocator;
+
+retry:
+  new_alignment = sizeof (void *);
+  if (allocator == omp_null_allocator)
+    allocator = free_allocator;
+
+  if (allocator > omp_max_predefined_alloc)
+    {
+      allocator_data = (struct omp_allocator_data *) allocator;
+      if (new_alignment < allocator_data->alignment)
+	new_alignment = allocator_data->alignment;
+    }
+  else
+    allocator_data = NULL;
+  if (free_allocator > omp_max_predefined_alloc)
+    free_allocator_data = (struct omp_allocator_data *) free_allocator;
+  else
+    free_allocator_data = NULL;
+  old_alignment = (uintptr_t) ptr - (uintptr_t) (data->ptr);
+
+  new_size = sizeof (struct omp_mem_header);
+  if (new_alignment > sizeof (void *))
+    new_size += new_alignment - sizeof (void *);
+  if (__builtin_add_overflow (size, new_size, &new_size))
+    goto fail;
+  old_size = data->size;
+
+  if (__builtin_expect (allocator_data
+			&& allocator_data->pool_size < ~(uintptr_t) 0, 0))
+    {
+      uintptr_t used_pool_size;
+      size_t prev_size = 0;
+      /* Check if we can use realloc.  Don't use it if extra alignment
+	 was used previously or newly, because realloc might return a pointer
+	 with different alignment and then we'd need to memmove the data
+	 again.  */
+      if (free_allocator_data
+	  && free_allocator_data == allocator_data
+	  && new_alignment == sizeof (void *)
+	  && old_alignment == sizeof (struct omp_mem_header))
+	prev_size = old_size;
+      if (new_size > prev_size
+	  && new_size - prev_size > allocator_data->pool_size)
+	goto fail;
+#ifdef HAVE_SYNC_BUILTINS
+      used_pool_size = __atomic_load_n (&allocator_data->used_pool_size,
+					MEMMODEL_RELAXED);
+      do
+	{
+	  uintptr_t new_pool_size;
+	  if (new_size > prev_size)
+	    {
+	      if (__builtin_add_overflow (used_pool_size, new_size - prev_size,
+					  &new_pool_size)
+		  || new_pool_size > allocator_data->pool_size)
+		goto fail;
+	    }
+	  else
+	    new_pool_size = used_pool_size + new_size - prev_size;
+	  if (__atomic_compare_exchange_n (&allocator_data->used_pool_size,
+					   &used_pool_size, new_pool_size,
+					   true, MEMMODEL_RELAXED,
+					   MEMMODEL_RELAXED))
+	    break;
+	}
+      while (1);
+#else
+      gomp_mutex_lock (&allocator_data->lock);
+      if (new_size > prev_size)
+	{
+	  if (__builtin_add_overflow (allocator_data->used_pool_size,
+				      new_size - prev_size,
+				      &used_pool_size)
+	      || used_pool_size > allocator_data->pool_size)
+	    {
+	      gomp_mutex_unlock (&allocator_data->lock);
+	      goto fail;
+	    }
+	}
+      else
+	used_pool_size = (allocator_data->used_pool_size
+			  + new_size - prev_size);
+      allocator_data->used_pool_size = used_pool_size;
+      gomp_mutex_unlock (&allocator_data->lock);
+#endif
+      if (prev_size)
+	new_ptr = realloc (data->ptr, new_size);
+      else
+	new_ptr = malloc (new_size);
+      if (new_ptr == NULL)
+	{
+#ifdef HAVE_SYNC_BUILTINS
+	  __atomic_add_fetch (&allocator_data->used_pool_size,
+			      prev_size - new_size,
+			      MEMMODEL_RELAXED);
+#else
+	  gomp_mutex_lock (&allocator_data->lock);
+	  allocator_data->used_pool_size -= new_size - prev_size;
+	  gomp_mutex_unlock (&allocator_data->lock);
+#endif
+	  goto fail;
+	}
+      else if (prev_size)
+	{
+	  ret = (char *) new_ptr + sizeof (struct omp_mem_header);
+	  ((struct omp_mem_header *) ret)[-1].ptr = new_ptr;
+	  ((struct omp_mem_header *) ret)[-1].size = new_size;
+	  ((struct omp_mem_header *) ret)[-1].allocator = allocator;
+	  return ret;
+	}
+    }
+  else if (new_alignment == sizeof (void *)
+	   && old_alignment == sizeof (struct omp_mem_header)
+	   && (free_allocator_data == NULL
+	       || free_allocator_data->pool_size == ~(uintptr_t) 0))
+    {
+      new_ptr = realloc (data->ptr, new_size);
+      if (new_ptr == NULL)
+	goto fail;
+      ret = (char *) new_ptr + sizeof (struct omp_mem_header);
+      ((struct omp_mem_header *) ret)[-1].ptr = new_ptr;
+      ((struct omp_mem_header *) ret)[-1].size = new_size;
+      ((struct omp_mem_header *) ret)[-1].allocator = allocator;
+      return ret;
+    }
+  else
+    {
+      new_ptr = malloc (new_size);
+      if (new_ptr == NULL)
+	goto fail;
+    }
+
+  if (new_alignment > sizeof (void *))
+    ret = (void *) (((uintptr_t) new_ptr
+		     + sizeof (struct omp_mem_header)
+		     + new_alignment - sizeof (void *))
+		    & ~(new_alignment - 1));
+  else
+    ret = (char *) new_ptr + sizeof (struct omp_mem_header);
+  ((struct omp_mem_header *) ret)[-1].ptr = new_ptr;
+  ((struct omp_mem_header *) ret)[-1].size = new_size;
+  ((struct omp_mem_header *) ret)[-1].allocator = allocator;
+  if (old_size - old_alignment < size)
+    size = old_size - old_alignment;
+  memcpy (ret, ptr, size);
+  if (__builtin_expect (free_allocator_data
+			&& free_allocator_data->pool_size < ~(uintptr_t) 0, 0))
+    {
+#ifdef HAVE_SYNC_BUILTINS
+      __atomic_add_fetch (&free_allocator_data->used_pool_size, -data->size,
+			  MEMMODEL_RELAXED);
+#else
+      gomp_mutex_lock (&free_allocator_data->lock);
+      free_allocator_data->used_pool_size -= data->size;
+      gomp_mutex_unlock (&free_allocator_data->lock);
+#endif
+    }
+  free (data->ptr);
+  return ret;
+
+fail:
+  if (allocator_data)
+    {
+      switch (allocator_data->fallback)
+	{
+	case omp_atv_default_mem_fb:
+	  if (new_alignment > sizeof (void *)
+	      || (allocator_data
+		  && allocator_data->pool_size < ~(uintptr_t) 0))
+	    {
+	      allocator = omp_default_mem_alloc;
+	      goto retry;
+	    }
+	  /* Otherwise, we've already performed default mem allocation
+	     and if that failed, it won't succeed again (unless it was
+	     intermittent.  Return NULL then, as that is the fallback.  */
+	  break;
+	case omp_atv_null_fb:
+	  break;
+	default:
+	case omp_atv_abort_fb:
+	  gomp_fatal ("Out of memory allocating %lu bytes",
+		      (unsigned long) size);
+	case omp_atv_allocator_fb:
+	  allocator = allocator_data->fb_data;
+	  goto retry;
+	}
+    }
+  return NULL;
 }
diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map
index e0c813c2716d824d7bf0aa1c5694ad29e00fe585..460a7a4a34bee53f6c9e140ab690c5de374de0e3 100644
--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map
@@ -203,6 +203,10 @@ OMP_5.0.2 {
   global:
 	omp_get_device_num;
 	omp_get_device_num_;
+	omp_aligned_alloc;
+	omp_calloc;
+	omp_aligned_calloc;
+	omp_realloc;
 } OMP_5.0.1;
 
 OMP_5.1 {
diff --git a/libgomp/omp.h.in b/libgomp/omp.h.in
index 314f964f8413d381c87953d4af54d552254d4468..e39988e7cbd34cc715c9c042c24533a1c44ec9e2 100644
--- a/libgomp/omp.h.in
+++ b/libgomp/omp.h.in
@@ -295,12 +295,31 @@ extern omp_allocator_handle_t omp_init_allocator (omp_memspace_handle_t,
 extern void omp_destroy_allocator (omp_allocator_handle_t) __GOMP_NOTHROW;
 extern void omp_set_default_allocator (omp_allocator_handle_t) __GOMP_NOTHROW;
 extern omp_allocator_handle_t omp_get_default_allocator (void) __GOMP_NOTHROW;
-extern void *omp_alloc (__SIZE_TYPE__,
-			omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR)
-  __GOMP_NOTHROW __attribute__((__malloc__, __alloc_size__ (1)));
 extern void omp_free (void *,
 		      omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR)
   __GOMP_NOTHROW;
+extern void *omp_alloc (__SIZE_TYPE__,
+			omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR)
+  __GOMP_NOTHROW __attribute__((__malloc__, __malloc__ (omp_free),
+				__alloc_size__ (1)));
+extern void *omp_aligned_alloc (__SIZE_TYPE__, __SIZE_TYPE__,
+				omp_allocator_handle_t
+				__GOMP_DEFAULT_NULL_ALLOCATOR)
+  __GOMP_NOTHROW __attribute__((__malloc__, __malloc__ (omp_free),
+				__alloc_size__ (2)));
+extern void *omp_calloc (__SIZE_TYPE__, __SIZE_TYPE__,
+			 omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR)
+  __GOMP_NOTHROW __attribute__((__malloc__, __malloc__ (omp_free),
+				__alloc_size__ (1, 2)));
+extern void *omp_aligned_calloc (__SIZE_TYPE__, __SIZE_TYPE__, __SIZE_TYPE__,
+				 omp_allocator_handle_t
+				 __GOMP_DEFAULT_NULL_ALLOCATOR)
+  __GOMP_NOTHROW __attribute__((__malloc__, __malloc__ (omp_free),
+				__alloc_size__ (2, 3)));
+extern void *omp_realloc (void *, __SIZE_TYPE__,
+			  omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR,
+			  omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR)
+  __GOMP_NOTHROW __attribute__((__malloc__ (omp_free), __alloc_size__ (2)));
 
 extern void omp_display_env (int) __GOMP_NOTHROW;
 
diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-4.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-4.c
index 841e1bcc201bad73844aaa98245a3cfeff09895c..67ba1cda083969c01559689090df182905c61c05 100644
--- a/libgomp/testsuite/libgomp.c-c++-common/alloc-4.c
+++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-4.c
@@ -12,12 +12,30 @@ main ()
 
   if (omp_alloc (0, omp_null_allocator) != NULL)
     abort ();
+  if (omp_aligned_alloc (64, 0, omp_null_allocator) != NULL)
+    abort ();
+  if (omp_calloc (0, 0, omp_null_allocator) != NULL
+      || omp_calloc (32, 0, omp_null_allocator) != NULL
+      || omp_calloc (0, 64, omp_null_allocator) != NULL)
+    abort ();
+  if (omp_aligned_calloc (32, 0, 0, omp_null_allocator) != NULL
+      || omp_aligned_calloc (64, 32, 0, omp_null_allocator) != NULL
+      || omp_aligned_calloc (16, 0, 64, omp_null_allocator) != NULL)
+    abort ();
   a = omp_init_allocator (omp_default_mem_space, 2, traits);
   if (a != omp_null_allocator)
     {
       if (omp_alloc (0, a) != NULL
 	  || omp_alloc (0, a) != NULL
-	  || omp_alloc (0, a) != NULL)
+	  || omp_alloc (0, a) != NULL
+	  || omp_aligned_alloc (16, 0, a) != NULL
+	  || omp_aligned_alloc (128, 0, a) != NULL
+	  || omp_calloc (0, 0, a) != NULL
+	  || omp_calloc (32, 0, a) != NULL
+	  || omp_calloc (0, 64, a) != NULL
+	  || omp_aligned_calloc (32, 0, 0, a) != NULL
+	  || omp_aligned_calloc (64, 32, 0, a) != NULL
+	  || omp_aligned_calloc (16, 0, 64, a) != NULL)
 	abort ();
       omp_destroy_allocator (a);
     }
diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-5.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-5.c
new file mode 100644
index 0000000000000000000000000000000000000000..8b4a489a92bdc469f479e55b495d499a3edd3962
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-5.c
@@ -0,0 +1,159 @@
+#include <omp.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+const omp_alloctrait_t traits2[]
+= { { omp_atk_alignment, 16 },
+    { omp_atk_sync_hint, omp_atv_default },
+    { omp_atk_access, omp_atv_default },
+    { omp_atk_pool_size, 1024 },
+    { omp_atk_fallback, omp_atv_default_mem_fb },
+    { omp_atk_partition, omp_atv_environment } };
+omp_alloctrait_t traits3[]
+= { { omp_atk_sync_hint, omp_atv_uncontended },
+    { omp_atk_alignment, 32 },
+    { omp_atk_access, omp_atv_all },
+    { omp_atk_pool_size, 512 },
+    { omp_atk_fallback, omp_atv_allocator_fb },
+    { omp_atk_fb_data, 0 },
+    { omp_atk_partition, omp_atv_default } };
+const omp_alloctrait_t traits4[]
+= { { omp_atk_alignment, 128 },
+    { omp_atk_pool_size, 1024 },
+    { omp_atk_fallback, omp_atv_null_fb } };
+
+int
+main ()
+{
+  int *volatile p = (int *) omp_aligned_alloc (sizeof (int), 3 * sizeof (int), omp_default_mem_alloc);
+  int *volatile q;
+  int *volatile r;
+  omp_alloctrait_t traits[3]
+    = { { omp_atk_alignment, 64 },
+	{ omp_atk_fallback, omp_atv_null_fb },
+	{ omp_atk_pool_size, 4096 } };
+  omp_allocator_handle_t a, a2;
+
+  if ((((uintptr_t) p) % __alignof (int)) != 0)
+    abort ();
+  p[0] = 1;
+  p[1] = 2;
+  p[2] = 3;
+  omp_free (p, omp_default_mem_alloc);
+  p = (int *) omp_aligned_alloc (2 * sizeof (int), 2 * sizeof (int), omp_default_mem_alloc);
+  if ((((uintptr_t) p) % (2 * sizeof (int))) != 0)
+    abort ();
+  p[0] = 1;
+  p[1] = 2;
+  omp_free (p, omp_null_allocator);
+  omp_set_default_allocator (omp_default_mem_alloc);
+  p = (int *) omp_aligned_alloc (1, sizeof (int), omp_null_allocator);
+  if ((((uintptr_t) p) % __alignof (int)) != 0)
+    abort ();
+  p[0] = 3;
+  omp_free (p, omp_get_default_allocator ());
+
+  a = omp_init_allocator (omp_default_mem_space, 3, traits);
+  if (a == omp_null_allocator)
+    abort ();
+  p = (int *) omp_aligned_alloc (32, 3072, a);
+  if ((((uintptr_t) p) % 64) != 0)
+    abort ();
+  p[0] = 1;
+  p[3071 / sizeof (int)] = 2;
+  if (omp_aligned_alloc (8, 3072, a) != NULL)
+    abort ();
+  omp_free (p, a);
+  p = (int *) omp_aligned_alloc (128, 3072, a);
+  if ((((uintptr_t) p) % 128) != 0)
+    abort ();
+  p[0] = 3;
+  p[3071 / sizeof (int)] = 4;
+  omp_free (p, omp_null_allocator);
+  omp_set_default_allocator (a);
+  if (omp_get_default_allocator () != a)
+    abort ();
+  p = (int *) omp_aligned_alloc (64, 3072, omp_null_allocator);
+  if (omp_aligned_alloc (8, 3072, omp_null_allocator) != NULL)
+    abort ();
+  omp_free (p, a);
+  omp_destroy_allocator (a);
+
+  a = omp_init_allocator (omp_default_mem_space,
+			  sizeof (traits2) / sizeof (traits2[0]),
+			  traits2);
+  if (a == omp_null_allocator)
+    abort ();
+  if (traits3[5].key != omp_atk_fb_data)
+    abort ();
+  traits3[5].value = (uintptr_t) a;
+  a2 = omp_init_allocator (omp_default_mem_space,
+			   sizeof (traits3) / sizeof (traits3[0]),
+			   traits3);
+  if (a2 == omp_null_allocator)
+    abort ();
+  p = (int *) omp_aligned_alloc (4, 420, a2);
+  if ((((uintptr_t) p) % 32) != 0)
+    abort ();
+  p[0] = 5;
+  p[419 / sizeof (int)] = 6;
+  q = (int *) omp_aligned_alloc (8, 768, a2);
+  if ((((uintptr_t) q) % 16) != 0)
+    abort ();
+  q[0] = 7;
+  q[767 / sizeof (int)] = 8;
+  r = (int *) omp_aligned_alloc (8, 512, a2);
+  if ((((uintptr_t) r) % 8) != 0)
+    abort ();
+  r[0] = 9;
+  r[511 / sizeof (int)] = 10;
+  omp_free (p, omp_null_allocator);
+  omp_free (q, a2);
+  omp_free (r, omp_null_allocator);
+  omp_destroy_allocator (a2);
+  omp_destroy_allocator (a);
+
+  a = omp_init_allocator (omp_default_mem_space,
+			  sizeof (traits4) / sizeof (traits4[0]),
+			  traits4);
+  if (a == omp_null_allocator)
+    abort ();
+  if (traits3[5].key != omp_atk_fb_data)
+    abort ();
+  traits3[5].value = (uintptr_t) a;
+  a2 = omp_init_allocator (omp_default_mem_space,
+			   sizeof (traits3) / sizeof (traits3[0]),
+			   traits3);
+  if (a2 == omp_null_allocator)
+    abort ();
+  omp_set_default_allocator (a2);
+#ifdef __cplusplus
+  p = static_cast <int *> (omp_aligned_alloc (4, 420));
+#else
+  p = (int *) omp_aligned_alloc (4, 420, omp_null_allocator);
+#endif
+  if ((((uintptr_t) p) % 32) != 0)
+    abort ();
+  p[0] = 5;
+  p[419 / sizeof (int)] = 6;
+  q = (int *) omp_aligned_alloc (64, 768, omp_null_allocator);
+  if ((((uintptr_t) q) % 128) != 0)
+    abort ();
+  q[0] = 7;
+  q[767 / sizeof (int)] = 8;
+  if (omp_aligned_alloc (8, 768, omp_null_allocator) != NULL)
+    abort ();
+#ifdef __cplusplus
+  omp_free (p);
+  omp_free (q);
+  omp_free (NULL);
+#else
+  omp_free (p, omp_null_allocator);
+  omp_free (q, omp_null_allocator);
+  omp_free (NULL, omp_null_allocator);
+#endif
+  omp_free (NULL, omp_null_allocator);
+  omp_destroy_allocator (a2);
+  omp_destroy_allocator (a);
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-6.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-6.c
new file mode 100644
index 0000000000000000000000000000000000000000..be571b7ecea6af8c863c95ca7ecd4ed94d45615e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-6.c
@@ -0,0 +1,58 @@
+#include <omp.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+const omp_alloctrait_t traits[]
+= { { omp_atk_alignment, 16 },
+    { omp_atk_sync_hint, omp_atv_default },
+    { omp_atk_access, omp_atv_default },
+    { omp_atk_fallback, omp_atv_default_mem_fb },
+    { omp_atk_partition, omp_atv_environment } };
+
+int
+main ()
+{
+  omp_allocator_handle_t a;
+  void *p, *q;
+  volatile size_t large_sz;
+
+  a = omp_init_allocator (omp_default_mem_space,
+			  sizeof (traits) / sizeof (traits[0]),
+			  traits);
+  if (a == omp_null_allocator)
+    abort ();
+  p = omp_alloc (2048, a);
+  if ((((uintptr_t) p) % 16) != 0)
+    abort ();
+  large_sz = ~(size_t) 1023;
+  q = omp_alloc (large_sz, a);
+  if (q != NULL)
+    abort ();
+  q = omp_aligned_alloc (32, large_sz, a);
+  if (q != NULL)
+    abort ();
+  q = omp_calloc (large_sz / 4, 4, a);
+  if (q != NULL)
+    abort ();
+  q = omp_aligned_calloc (1, 2, large_sz / 2, a);
+  if (q != NULL)
+    abort ();
+  omp_free (p, a);
+  large_sz = ~(size_t) 0;
+  large_sz >>= 1;
+  large_sz += 1;
+  if (omp_calloc (2, large_sz, a) != NULL)
+    abort ();
+  if (omp_calloc (large_sz, 1024, a) != NULL)
+    abort ();
+  if (omp_calloc (large_sz, large_sz, a) != NULL)
+    abort ();
+  if (omp_aligned_calloc (16, 2, large_sz, a) != NULL)
+    abort ();
+  if (omp_aligned_calloc (32, large_sz, 1024, a) != NULL)
+    abort ();
+  if (omp_aligned_calloc (64, large_sz, large_sz, a) != NULL)
+    abort ();
+  omp_destroy_allocator (a);
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-7.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-7.c
new file mode 100644
index 0000000000000000000000000000000000000000..d66e25ac7d61cca225e22fca54594c1750921c9e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-7.c
@@ -0,0 +1,182 @@
+#include <omp.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+const omp_alloctrait_t traits2[]
+= { { omp_atk_alignment, 16 },
+    { omp_atk_sync_hint, omp_atv_default },
+    { omp_atk_access, omp_atv_default },
+    { omp_atk_pool_size, 1024 },
+    { omp_atk_fallback, omp_atv_default_mem_fb },
+    { omp_atk_partition, omp_atv_environment } };
+omp_alloctrait_t traits3[]
+= { { omp_atk_sync_hint, omp_atv_uncontended },
+    { omp_atk_alignment, 32 },
+    { omp_atk_access, omp_atv_all },
+    { omp_atk_pool_size, 512 },
+    { omp_atk_fallback, omp_atv_allocator_fb },
+    { omp_atk_fb_data, 0 },
+    { omp_atk_partition, omp_atv_default } };
+const omp_alloctrait_t traits4[]
+= { { omp_atk_alignment, 128 },
+    { omp_atk_pool_size, 1024 },
+    { omp_atk_fallback, omp_atv_null_fb } };
+
+int
+main ()
+{
+  int *volatile p = (int *) omp_calloc (3, sizeof (int), omp_default_mem_alloc);
+  int *volatile q;
+  int *volatile r;
+  int i;
+  omp_alloctrait_t traits[3]
+    = { { omp_atk_alignment, 64 },
+	{ omp_atk_fallback, omp_atv_null_fb },
+	{ omp_atk_pool_size, 4096 } };
+  omp_allocator_handle_t a, a2;
+
+  if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0] || p[1] || p[2])
+    abort ();
+  p[0] = 1;
+  p[1] = 2;
+  p[2] = 3;
+  omp_free (p, omp_default_mem_alloc);
+  p = (int *) omp_calloc (2, sizeof (int), omp_default_mem_alloc);
+  if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0] || p[1])
+    abort ();
+  p[0] = 1;
+  p[1] = 2;
+  omp_free (p, omp_null_allocator);
+  omp_set_default_allocator (omp_default_mem_alloc);
+  p = (int *) omp_calloc (1, sizeof (int), omp_null_allocator);
+  if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0])
+    abort ();
+  p[0] = 3;
+  omp_free (p, omp_get_default_allocator ());
+
+  a = omp_init_allocator (omp_default_mem_space, 3, traits);
+  if (a == omp_null_allocator)
+    abort ();
+  p = (int *) omp_calloc (3, 1024, a);
+  if ((((uintptr_t) p) % 64) != 0)
+    abort ();
+  for (i = 0; i < 3072 / sizeof (int); i++)
+    if (p[i])
+      abort ();
+  p[0] = 1;
+  p[3071 / sizeof (int)] = 2;
+  if (omp_calloc (1024, 3, a) != NULL)
+    abort ();
+  omp_free (p, a);
+  p = (int *) omp_calloc (512, 6, a);
+  for (i = 0; i < 3072 / sizeof (int); i++)
+    if (p[i])
+      abort ();
+  p[0] = 3;
+  p[3071 / sizeof (int)] = 4;
+  omp_free (p, omp_null_allocator);
+  omp_set_default_allocator (a);
+  if (omp_get_default_allocator () != a)
+    abort ();
+  p = (int *) omp_calloc (12, 256, omp_null_allocator);
+  for (i = 0; i < 3072 / sizeof (int); i++)
+    if (p[i])
+      abort ();
+  if (omp_calloc (128, 24, omp_null_allocator) != NULL)
+    abort ();
+  omp_free (p, a);
+  omp_destroy_allocator (a);
+
+  a = omp_init_allocator (omp_default_mem_space,
+			  sizeof (traits2) / sizeof (traits2[0]),
+			  traits2);
+  if (a == omp_null_allocator)
+    abort ();
+  if (traits3[5].key != omp_atk_fb_data)
+    abort ();
+  traits3[5].value = (uintptr_t) a;
+  a2 = omp_init_allocator (omp_default_mem_space,
+			   sizeof (traits3) / sizeof (traits3[0]),
+			   traits3);
+  if (a2 == omp_null_allocator)
+    abort ();
+  p = (int *) omp_calloc (10, 42, a2);
+  for (i = 0; i < 420 / sizeof (int); i++)
+    if (p[i])
+      abort ();
+  if ((((uintptr_t) p) % 32) != 0)
+    abort ();
+  p[0] = 5;
+  p[419 / sizeof (int)] = 6;
+  q = (int *) omp_calloc (24, 32, a2);
+  if ((((uintptr_t) q) % 16) != 0)
+    abort ();
+  for (i = 0; i < 768 / sizeof (int); i++)
+    if (q[i])
+      abort ();
+  q[0] = 7;
+  q[767 / sizeof (int)] = 8;
+  r = (int *) omp_calloc (128, 4, a2);
+  if ((((uintptr_t) r) % __alignof (int)) != 0)
+    abort ();
+  for (i = 0; i < 512 / sizeof (int); i++)
+    if (r[i])
+      abort ();
+  r[0] = 9;
+  r[511 / sizeof (int)] = 10;
+  omp_free (p, omp_null_allocator);
+  omp_free (q, a2);
+  omp_free (r, omp_null_allocator);
+  omp_destroy_allocator (a2);
+  omp_destroy_allocator (a);
+
+  a = omp_init_allocator (omp_default_mem_space,
+			  sizeof (traits4) / sizeof (traits4[0]),
+			  traits4);
+  if (a == omp_null_allocator)
+    abort ();
+  if (traits3[5].key != omp_atk_fb_data)
+    abort ();
+  traits3[5].value = (uintptr_t) a;
+  a2 = omp_init_allocator (omp_default_mem_space,
+			   sizeof (traits3) / sizeof (traits3[0]),
+			   traits3);
+  if (a2 == omp_null_allocator)
+    abort ();
+  omp_set_default_allocator (a2);
+#ifdef __cplusplus
+  p = static_cast <int *> (omp_calloc (42, 10));
+#else
+  p = (int *) omp_calloc (42, 10, omp_null_allocator);
+#endif
+  if ((((uintptr_t) p) % 32) != 0)
+    abort ();
+  for (i = 0; i < 420 / sizeof (int); i++)
+    if (p[i])
+      abort ();
+  p[0] = 5;
+  p[419 / sizeof (int)] = 6;
+  q = (int *) omp_calloc (32, 24, omp_null_allocator);
+  if ((((uintptr_t) q) % 128) != 0)
+    abort ();
+  for (i = 0; i < 768 / sizeof (int); i++)
+    if (q[i])
+      abort ();
+  q[0] = 7;
+  q[767 / sizeof (int)] = 8;
+  if (omp_calloc (24, 32, omp_null_allocator) != NULL)
+    abort ();
+#ifdef __cplusplus
+  omp_free (p);
+  omp_free (q);
+  omp_free (NULL);
+#else
+  omp_free (p, omp_null_allocator);
+  omp_free (q, omp_null_allocator);
+  omp_free (NULL, omp_null_allocator);
+#endif
+  omp_free (NULL, omp_null_allocator);
+  omp_destroy_allocator (a2);
+  omp_destroy_allocator (a);
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-8.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-8.c
new file mode 100644
index 0000000000000000000000000000000000000000..bd4e08a6f9182a3116e1f59e3a5ca5fbbe625cc5
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-8.c
@@ -0,0 +1,184 @@
+#include <omp.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+const omp_alloctrait_t traits2[]
+= { { omp_atk_alignment, 16 },
+    { omp_atk_sync_hint, omp_atv_default },
+    { omp_atk_access, omp_atv_default },
+    { omp_atk_pool_size, 1024 },
+    { omp_atk_fallback, omp_atv_default_mem_fb },
+    { omp_atk_partition, omp_atv_environment } };
+omp_alloctrait_t traits3[]
+= { { omp_atk_sync_hint, omp_atv_uncontended },
+    { omp_atk_alignment, 32 },
+    { omp_atk_access, omp_atv_all },
+    { omp_atk_pool_size, 512 },
+    { omp_atk_fallback, omp_atv_allocator_fb },
+    { omp_atk_fb_data, 0 },
+    { omp_atk_partition, omp_atv_default } };
+const omp_alloctrait_t traits4[]
+= { { omp_atk_alignment, 128 },
+    { omp_atk_pool_size, 1024 },
+    { omp_atk_fallback, omp_atv_null_fb } };
+
+int
+main ()
+{
+  int *volatile p = (int *) omp_aligned_calloc (sizeof (int), 3, sizeof (int), omp_default_mem_alloc);
+  int *volatile q;
+  int *volatile r;
+  int i;
+  omp_alloctrait_t traits[3]
+    = { { omp_atk_alignment, 64 },
+	{ omp_atk_fallback, omp_atv_null_fb },
+	{ omp_atk_pool_size, 4096 } };
+  omp_allocator_handle_t a, a2;
+
+  if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0] || p[1] || p[2])
+    abort ();
+  p[0] = 1;
+  p[1] = 2;
+  p[2] = 3;
+  omp_free (p, omp_default_mem_alloc);
+  p = (int *) omp_aligned_calloc (2 * sizeof (int), 1, 2 * sizeof (int), omp_default_mem_alloc);
+  if ((((uintptr_t) p) % (2 * sizeof (int))) != 0 || p[0] || p[1])
+    abort ();
+  p[0] = 1;
+  p[1] = 2;
+  omp_free (p, omp_null_allocator);
+  omp_set_default_allocator (omp_default_mem_alloc);
+  p = (int *) omp_aligned_calloc (1, 1, sizeof (int), omp_null_allocator);
+  if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0])
+    abort ();
+  p[0] = 3;
+  omp_free (p, omp_get_default_allocator ());
+
+  a = omp_init_allocator (omp_default_mem_space, 3, traits);
+  if (a == omp_null_allocator)
+    abort ();
+  p = (int *) omp_aligned_calloc (32, 3, 1024, a);
+  if ((((uintptr_t) p) % 64) != 0)
+    abort ();
+  for (i = 0; i < 3072 / sizeof (int); i++)
+    if (p[i])
+      abort ();
+  p[0] = 1;
+  p[3071 / sizeof (int)] = 2;
+  if (omp_aligned_calloc (8, 192, 16, a) != NULL)
+    abort ();
+  omp_free (p, a);
+  p = (int *) omp_aligned_calloc (128, 6, 512, a);
+  if ((((uintptr_t) p) % 128) != 0)
+    abort ();
+  for (i = 0; i < 3072 / sizeof (int); i++)
+    if (p[i])
+      abort ();
+  p[0] = 3;
+  p[3071 / sizeof (int)] = 4;
+  omp_free (p, omp_null_allocator);
+  omp_set_default_allocator (a);
+  if (omp_get_default_allocator () != a)
+    abort ();
+  p = (int *) omp_aligned_calloc (64, 12, 256, omp_null_allocator);
+  for (i = 0; i < 3072 / sizeof (int); i++)
+    if (p[i])
+      abort ();
+  if (omp_aligned_calloc (8, 128, 24, omp_null_allocator) != NULL)
+    abort ();
+  omp_free (p, a);
+  omp_destroy_allocator (a);
+
+  a = omp_init_allocator (omp_default_mem_space,
+			  sizeof (traits2) / sizeof (traits2[0]),
+			  traits2);
+  if (a == omp_null_allocator)
+    abort ();
+  if (traits3[5].key != omp_atk_fb_data)
+    abort ();
+  traits3[5].value = (uintptr_t) a;
+  a2 = omp_init_allocator (omp_default_mem_space,
+			   sizeof (traits3) / sizeof (traits3[0]),
+			   traits3);
+  if (a2 == omp_null_allocator)
+    abort ();
+  p = (int *) omp_aligned_calloc (4, 5, 84, a2);
+  for (i = 0; i < 420 / sizeof (int); i++)
+    if (p[i])
+      abort ();
+  if ((((uintptr_t) p) % 32) != 0)
+    abort ();
+  p[0] = 5;
+  p[419 / sizeof (int)] = 6;
+  q = (int *) omp_aligned_calloc (8, 24, 32, a2);
+  if ((((uintptr_t) q) % 16) != 0)
+    abort ();
+  for (i = 0; i < 768 / sizeof (int); i++)
+    if (q[i])
+      abort ();
+  q[0] = 7;
+  q[767 / sizeof (int)] = 8;
+  r = (int *) omp_aligned_calloc (8, 64, 8, a2);
+  if ((((uintptr_t) r) % 8) != 0)
+    abort ();
+  for (i = 0; i < 512 / sizeof (int); i++)
+    if (r[i])
+      abort ();
+  r[0] = 9;
+  r[511 / sizeof (int)] = 10;
+  omp_free (p, omp_null_allocator);
+  omp_free (q, a2);
+  omp_free (r, omp_null_allocator);
+  omp_destroy_allocator (a2);
+  omp_destroy_allocator (a);
+
+  a = omp_init_allocator (omp_default_mem_space,
+			  sizeof (traits4) / sizeof (traits4[0]),
+			  traits4);
+  if (a == omp_null_allocator)
+    abort ();
+  if (traits3[5].key != omp_atk_fb_data)
+    abort ();
+  traits3[5].value = (uintptr_t) a;
+  a2 = omp_init_allocator (omp_default_mem_space,
+			   sizeof (traits3) / sizeof (traits3[0]),
+			   traits3);
+  if (a2 == omp_null_allocator)
+    abort ();
+  omp_set_default_allocator (a2);
+#ifdef __cplusplus
+  p = static_cast <int *> (omp_aligned_calloc (4, 21, 20));
+#else
+  p = (int *) omp_aligned_calloc (4, 21, 20, omp_null_allocator);
+#endif
+  if ((((uintptr_t) p) % 32) != 0)
+    abort ();
+  for (i = 0; i < 420 / sizeof (int); i++)
+    if (p[i])
+      abort ();
+  p[0] = 5;
+  p[419 / sizeof (int)] = 6;
+  q = (int *) omp_aligned_calloc (64, 12, 64, omp_null_allocator);
+  if ((((uintptr_t) q) % 128) != 0)
+    abort ();
+  for (i = 0; i < 768 / sizeof (int); i++)
+    if (q[i])
+      abort ();
+  q[0] = 7;
+  q[767 / sizeof (int)] = 8;
+  if (omp_aligned_calloc (8, 24, 32, omp_null_allocator) != NULL)
+    abort ();
+#ifdef __cplusplus
+  omp_free (p);
+  omp_free (q);
+  omp_free (NULL);
+#else
+  omp_free (p, omp_null_allocator);
+  omp_free (q, omp_null_allocator);
+  omp_free (NULL, omp_null_allocator);
+#endif
+  omp_free (NULL, omp_null_allocator);
+  omp_destroy_allocator (a2);
+  omp_destroy_allocator (a);
+  return 0;
+}