Index: runtime/CMakeLists.txt
===================================================================
--- runtime/CMakeLists.txt
+++ runtime/CMakeLists.txt
@@ -194,6 +194,7 @@
 set(LIBOMP_SRC_DIR ${LIBOMP_BASE_DIR}/src)
 set(LIBOMP_TOOLS_DIR ${LIBOMP_BASE_DIR}/tools)
 set(LIBOMP_INC_DIR ${LIBOMP_SRC_DIR}/include/${LIBOMP_OMP_VERSION})
+set(LIBOMP_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
 
 # Enabling Fortran if it is needed
 if(${LIBOMP_FORTRAN_MODULES})
@@ -308,4 +309,5 @@
 endif()
 
 add_subdirectory(src)
+add_subdirectory(test)
 
Index: runtime/src/CMakeLists.txt
===================================================================
--- runtime/src/CMakeLists.txt
+++ runtime/src/CMakeLists.txt
@@ -162,6 +162,26 @@
   SKIP_BUILD_RPATH true # have Mac linker -install_name just be "-install_name libomp.dylib"
 )
 
+# Get the library's location within the build tree for the unit tester
+get_target_property(LIBOMP_LIBRARY_DIR omp LIBRARY_OUTPUT_DIRECTORY)
+if(NOT LIBOMP_LIBRARY_DIR)
+  set(LIBOMP_LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
+  set(LIBOMP_LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)
+else()
+  set(LIBOMP_LIBRARY_DIR ${LIBOMP_LIBRARY_DIR} PARENT_SCOPE)
+endif()
+
+# Add symbolic links to libomp
+if(NOT WIN32)
+  add_custom_command(TARGET omp POST_BUILD
+    COMMAND ${CMAKE_COMMAND} -E create_symlink ${LIBOMP_LIB_FILE}
+      libgomp${CMAKE_SHARED_LIBRARY_SUFFIX}
+    COMMAND ${CMAKE_COMMAND} -E create_symlink ${LIBOMP_LIB_FILE}
+      libiomp5${CMAKE_SHARED_LIBRARY_SUFFIX}
+    WORKING_DIRECTORY ${LIBOMP_LIBRARY_DIR}
+  )
+endif()
+
 # Linking command will include libraries in LIBOMP_CONFIGURED_LIBFLAGS
 libomp_get_libflags(LIBOMP_CONFIGURED_LIBFLAGS)
 target_link_libraries(omp ${LIBOMP_CONFIGURED_LIBFLAGS} ${CMAKE_DL_LIBS})
Index: runtime/test/CMakeLists.txt
===================================================================
--- /dev/null
+++ runtime/test/CMakeLists.txt
@@ -0,0 +1,69 @@
+# CMakeLists.txt file for unit testing OpenMP Library
+include(FindPythonInterp)
+if(NOT PYTHONINTERP_FOUND)
+  libomp_warning_say("Could not find Python.")
+  libomp_warning_say("The check-libomp target will not be available!")
+  return()
+endif()
+
+set(LIBOMP_TEST_CFLAGS "" CACHE STRING
+  "Extra compiler flags to send to the test compiler")
+
+if(${LIBOMP_STANDALONE_BUILD})
+  # Make sure we can use the console pool for recent cmake and ninja > 1.5
+  if(CMAKE_VERSION VERSION_LESS 3.1.20141117)
+    set(cmake_3_2_USES_TERMINAL)
+  else()
+    set(cmake_3_2_USES_TERMINAL USES_TERMINAL)
+  endif()
+  set(LIBOMP_TEST_COMPILER ${CMAKE_C_COMPILER} CACHE STRING
+    "Compiler to use for testing OpenMP library")
+  set(LIBOMP_TEST_OPENMP_FLAG -fopenmp CACHE STRING
+    "OpenMP compiler flag to use for testing OpenMP library")
+  set(LIBOMP_LLVM_LIT_EXECUTABLE "" CACHE STRING
+    "Path to llvm-lit")
+  find_program(LIT_EXECUTABLE NAMES llvm-lit ${LIBOMP_LLVM_LIT_EXECUTABLE})
+  if(NOT LIT_EXECUTABLE)
+    libomp_warning_say("Cannot find llvm-lit.")
+    libomp_warning_say("Please put llvm-lit in your PATH or set LIBOMP_LLVM_LIT_EXECUTABLE to its full path")
+    libomp_warning_say("The check-libomp target will not be available!")
+    return()
+  endif()
+  # Set lit arguments
+  # The -j 1 lets the actual tests run with the entire machine.
+  # We have one test thread that spawns the tests serially.  This allows
+  # Each test to use the entire machine.
+  set(LIBOMP_LIT_ARGS_DEFAULT "-sv --show-unsupported --show-xfail -j 1")
+  if(MSVC OR XCODE)
+    set(LIBOMP_LIT_ARGS_DEFAULT "${LIBOMP_LIT_ARGS_DEFAULT} --no-progress-bar")
+  endif()
+  set(LIBOMP_LIT_ARGS "${LIBOMP_LIT_ARGS_DEFAULT}" CACHE STRING
+    "Default options for lit")
+  separate_arguments(LIBOMP_LIT_ARGS)
+  add_custom_target(check-libomp
+    COMMAND ${LIT_EXECUTABLE} ${LIBOMP_LIT_ARGS} ${CMAKE_CURRENT_BINARY_DIR}
+    DEPENDS omp
+    COMMENT "Running libomp tests"
+    ${cmake_3_2_USES_TERMINAL}
+  )
+else()
+  # LLVM source tree build, test just-built clang
+  if(NOT MSVC)
+    set(LIBOMP_TEST_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang)
+  else()
+    set(LIBOMP_TEST_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang.exe)
+  endif()
+  set(LIBOMP_TEST_OPENMP_FLAG -fopenmp=libomp)
+  # Use add_lit_testsuite() from LLVM CMake.
+  add_lit_testsuite(check-libomp 
+    "Running libomp tests"
+    ${CMAKE_CURRENT_BINARY_DIR}
+    ARGS "-j 1"
+    DEPENDS omp
+  )
+endif()
+
+# Configure the lit.site.cfg.in file
+set(AUTO_GEN_COMMENT "## Autogenerated by libomp configuration.\n# Do not edit!")
+configure_file(lit.site.cfg.in lit.site.cfg @ONLY)
+
Index: runtime/test/api/has_openmp.c
===================================================================
--- /dev/null
+++ runtime/test/api/has_openmp.c
@@ -0,0 +1,23 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <stdlib.h>
+#include "omp_testsuite.h"
+
+int test_has_openmp()
+{
+  int rvalue = 0;
+#ifdef _OPENMP
+  rvalue = 1;
+#endif
+  return (rvalue);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+  if(!test_has_openmp()) {
+    num_failed++;
+  }
+  return num_failed;
+}
Index: runtime/test/api/omp_get_num_threads.c
===================================================================
--- /dev/null
+++ runtime/test/api/omp_get_num_threads.c
@@ -0,0 +1,39 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int test_omp_get_num_threads()
+{
+  /* checks that omp_get_num_threads is equal to the number of
+     threads */
+  int nthreads_lib;
+  int nthreads = 0;
+
+  nthreads_lib = -1;
+
+  #pragma omp parallel 
+  {
+    #pragma omp critical
+    {
+      nthreads++;
+    } /* end of critical */
+    #pragma omp single
+    { 
+      nthreads_lib = omp_get_num_threads ();
+    }  /* end of single */
+  } /* end of parallel */
+  return (nthreads == nthreads_lib);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_get_num_threads()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/api/omp_get_wtick.c
===================================================================
--- /dev/null
+++ runtime/test/api/omp_get_wtick.c
@@ -0,0 +1,24 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int test_omp_get_wtick()
+{
+  double tick;
+  tick = -1.;
+  tick = omp_get_wtick ();
+  return ((tick > 0.0) && (tick < 0.01));
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_get_wtick()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/api/omp_get_wtime.c
===================================================================
--- /dev/null
+++ runtime/test/api/omp_get_wtime.c
@@ -0,0 +1,34 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include<stdio.h>
+#include<stdlib.h>
+#include<unistd.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+int test_omp_get_wtime()
+{
+  double start;
+  double end;
+  double measured_time;
+  int wait_time = 1; 
+  start = 0;
+  end = 0;
+  start = omp_get_wtime();
+  my_sleep (wait_time); 
+  end = omp_get_wtime();
+  measured_time = end-start;
+  return ((measured_time > 0.99 * wait_time) && (measured_time < 1.01 * wait_time)) ;
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_get_wtime()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/api/omp_in_parallel.c
===================================================================
--- /dev/null
+++ runtime/test/api/omp_in_parallel.c
@@ -0,0 +1,39 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+/*
+ * Checks that false is returned when called from serial region
+ * and true is returned when called within parallel region. 
+ */
+int test_omp_in_parallel()
+{
+  int serial;
+  int isparallel;
+
+  serial = 1;
+  isparallel = 0;
+  serial = omp_in_parallel();
+
+  #pragma omp parallel
+  {
+    #pragma omp single
+    {
+      isparallel = omp_in_parallel();
+    }
+  }
+  return (!(serial) && isparallel);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_in_parallel()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/atomic/omp_atomic.c
===================================================================
--- /dev/null
+++ runtime/test/atomic/omp_atomic.c
@@ -0,0 +1,368 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t -lm && %t
+#include <stdio.h>
+#include <unistd.h>
+#include <math.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+#define DOUBLE_DIGITS 20  /* dt^DOUBLE_DIGITS */
+#define MAX_FACTOR 10
+#define KNOWN_PRODUCT 3628800  /* 10! */
+
+int test_omp_atomic()
+{
+  int sum;
+  int diff;
+  double dsum = 0;
+  double dt = 0.5;  /* base of geometric row for + and - test*/
+  double ddiff;
+  int product;
+  int x;
+  int *logics;
+  int bit_and = 1;
+  int bit_or = 0;
+  int exclusiv_bit_or = 0;
+  int j;
+  int known_sum;
+  int known_diff;
+  int known_product;
+  int result = 0;
+  int logic_and = 1;
+  int logic_or = 0;
+  double dknown_sum;
+  double rounding_error = 1.E-9;
+  double dpt, div;
+  int logicsArray[LOOPCOUNT];
+  logics = logicsArray;
+  
+  sum = 0;
+  diff = 0;
+  product = 1;
+
+  // sum of integers test
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp for
+    for (i = 1; i <= LOOPCOUNT; i++) {
+      #pragma omp atomic
+      sum += i;
+    }
+  
+  }
+  known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
+  if (known_sum != sum)
+  {
+    fprintf(stderr, 
+      "Error in sum with integers: Result was %d instead of %d.\n", 
+      sum, known_sum);
+    result++;
+  }
+  
+  // difference of integers test
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp for
+    for (i = 0; i < LOOPCOUNT; i++) {
+      #pragma omp atomic
+      diff -= i;
+    }
+  }
+  known_diff = ((LOOPCOUNT - 1) * LOOPCOUNT) / 2 * -1;
+  if (diff != known_diff)
+  {
+    fprintf (stderr,
+      "Error in difference with integers: Result was %d instead of 0.\n",
+      diff);
+    result++;
+  }
+
+  // sum of doubles test
+  dsum = 0;
+  dpt = 1;
+  for (j = 0; j < DOUBLE_DIGITS; ++j) {
+    dpt *= dt;
+  }
+  dknown_sum = (1 - dpt) / (1 -dt);
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp for
+    for (i = 0; i < DOUBLE_DIGITS; ++i) {
+      #pragma omp atomic
+      dsum += pow (dt, i);
+    }
+  }
+  if (dsum != dknown_sum && (fabs (dsum - dknown_sum) > rounding_error)) {
+    fprintf (stderr, "Error in sum with doubles: Result was %f"
+      " instead of: %f (Difference: %E)\n",
+      dsum, dknown_sum, dsum - dknown_sum);
+    result++;
+  }
+
+  // difference of doubles test
+  dpt = 1;
+  for (j = 0; j < DOUBLE_DIGITS; ++j) {
+    dpt *= dt;
+  }
+  ddiff = (1 - dpt) / (1 - dt);
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp for
+    for (i = 0; i < DOUBLE_DIGITS; ++i) {
+      #pragma omp atomic
+      ddiff -= pow (dt, i);
+    }
+  } 
+  if (fabs (ddiff) > rounding_error) {
+    fprintf (stderr,
+      "Error in difference with doubles: Result was %E instead of 0.0\n",
+      ddiff);
+    result++;
+  }
+
+  // product of integers test
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp for
+    for (i = 1; i <= MAX_FACTOR; i++) {
+      #pragma omp atomic
+      product *= i;
+    }
+  }
+  known_product = KNOWN_PRODUCT;
+  if (known_product != product) {
+    fprintf (stderr,
+      "Error in product with integers: Result was %d instead of %d\n",
+      product, known_product);
+    result++;
+  }
+
+  // division of integers test
+  product = KNOWN_PRODUCT;
+  #pragma omp parallel
+  {
+     int i;
+    #pragma omp for
+    for (i = 1; i <= MAX_FACTOR; ++i) {
+      #pragma omp atomic
+      product /= i;
+    }
+  }
+  if (product != 1) {
+    fprintf (stderr,
+      "Error in product division with integers: Result was %d"
+      " instead of 1\n",
+      product);
+    result++;
+  }
+  
+  // division of doubles test
+  div = 5.0E+5;
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp for
+    for (i = 1; i <= MAX_FACTOR; i++) {
+      #pragma omp atomic
+      div /= i;
+    }
+  }
+  if (fabs(div-0.137787) >= 1.0E-4 ) {
+    result++;
+    fprintf (stderr, "Error in division with double: Result was %f"
+      " instead of 0.137787\n", div);
+  }
+
+  // ++ test
+  x = 0;
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp for
+    for (i = 0; i < LOOPCOUNT; ++i) {
+      #pragma omp atomic
+      x++;
+    }
+  }
+  if (x != LOOPCOUNT) {
+    result++;
+    fprintf (stderr, "Error in ++\n");
+  }
+
+  // -- test
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp for
+    for (i = 0; i < LOOPCOUNT; ++i) {
+      #pragma omp atomic
+      x--;
+    }
+  }
+  if (x != 0) {
+    result++;
+    fprintf (stderr, "Error in --\n");
+  }
+
+  // bit-and test part 1
+  for (j = 0; j < LOOPCOUNT; ++j) {
+    logics[j] = 1;
+  }
+  bit_and = 1;
+  #pragma omp parallel
+  {
+     int i;
+    #pragma omp for
+    for (i = 0; i < LOOPCOUNT; ++i) {
+      #pragma omp atomic
+      bit_and &= logics[i];
+    }
+  }
+  if (!bit_and) {
+    result++;
+    fprintf (stderr, "Error in BIT AND part 1\n");
+  }
+
+  // bit-and test part 2
+  bit_and = 1;
+  logics[LOOPCOUNT / 2] = 0;
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp for
+    for (i = 0; i < LOOPCOUNT; ++i) {
+      #pragma omp atomic
+      bit_and &= logics[i];
+    }
+  }
+  if (bit_and) {
+    result++;
+    fprintf (stderr, "Error in BIT AND part 2\n");
+  }
+
+  // bit-or test part 1
+  for (j = 0; j < LOOPCOUNT; j++) {
+    logics[j] = 0;
+  }
+  bit_or = 0;
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp for
+    for (i = 0; i < LOOPCOUNT; ++i) {
+      #pragma omp atomic
+      bit_or |= logics[i];
+    }
+  }
+  if (bit_or) {
+    result++;
+    fprintf (stderr, "Error in BIT OR part 1\n");
+  }
+
+  // bit-or test part 2
+  bit_or = 0;
+  logics[LOOPCOUNT / 2] = 1;
+  #pragma omp parallel
+  {
+    
+    int i;
+    #pragma omp for
+    for (i = 0; i < LOOPCOUNT; ++i) {
+      #pragma omp atomic
+      bit_or |= logics[i];
+    }
+  }
+  if (!bit_or) {
+    result++;
+    fprintf (stderr, "Error in BIT OR part 2\n");
+  }
+
+  // bit-xor test part 1
+  for (j = 0; j < LOOPCOUNT; j++) {
+    logics[j] = 0;
+  }
+  exclusiv_bit_or = 0;
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp for
+    for (i = 0; i < LOOPCOUNT; ++i) {
+      #pragma omp atomic
+      exclusiv_bit_or ^= logics[i];
+    }
+  }
+  if (exclusiv_bit_or) {
+    result++;
+    fprintf (stderr, "Error in EXCLUSIV BIT OR part 1\n");
+  }
+
+  // bit-xor test part 2
+  exclusiv_bit_or = 0;
+  logics[LOOPCOUNT / 2] = 1;
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp for
+    for (i = 0; i < LOOPCOUNT; ++i) {
+      #pragma omp atomic
+      exclusiv_bit_or ^= logics[i];
+    }
+    
+  }
+  if (!exclusiv_bit_or) {
+    result++;
+    fprintf (stderr, "Error in EXCLUSIV BIT OR part 2\n");
+  }
+
+  // left shift test
+  x = 1;
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp for
+    for (i = 0; i < 10; ++i) {
+      #pragma omp atomic
+      x <<= 1;
+    }
+    
+  }
+  if ( x != 1024) {
+    result++;
+    fprintf (stderr, "Error in <<\n");
+    x = 1024;
+  }
+
+  // right shift test
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp for
+    for (i = 0; i < 10; ++i) {
+      #pragma omp atomic
+      x >>= 1;
+    }
+  }
+  if (x != 1) {
+    result++;
+    fprintf (stderr, "Error in >>\n");
+  }
+
+  return (result == 0);
+} // test_omp_atomic()
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_atomic()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/barrier/omp_barrier.c
===================================================================
--- /dev/null
+++ runtime/test/barrier/omp_barrier.c
@@ -0,0 +1,41 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <unistd.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+int test_omp_barrier()
+{
+  int result1;
+  int result2;
+  result1 = 0;
+  result2 = 0;
+
+  #pragma omp parallel
+  {
+    int rank;
+    rank = omp_get_thread_num ();
+    if (rank ==1) {
+      my_sleep(SLEEPTIME_LONG);
+      result2 = 3;
+    }
+    #pragma omp barrier
+    if (rank == 2) {
+      result1 = result2;
+    }
+  }
+  return (result1 == 3);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_barrier()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/critical/omp_critical.c
===================================================================
--- /dev/null
+++ runtime/test/critical/omp_critical.c
@@ -0,0 +1,39 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <unistd.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+int test_omp_critical()
+{
+  int sum;
+  int known_sum;
+
+  sum=0;
+  #pragma omp parallel
+  {
+    int mysum=0;
+    int i;
+    #pragma omp for
+    for (i = 0; i < 1000; i++)
+      mysum = mysum + i;
+
+    #pragma omp critical
+    sum = mysum +sum;
+  }
+  known_sum = 999 * 1000 / 2;
+  return (known_sum == sum);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_critical()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/flush/omp_flush.c
===================================================================
--- /dev/null
+++ runtime/test/flush/omp_flush.c
@@ -0,0 +1,46 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <unistd.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+int test_omp_flush()
+{
+  int result1;
+  int result2;
+  int dummy;
+
+  result1 = 0;
+  result2 = 0;
+
+  #pragma omp parallel
+  {
+    int rank;
+    rank = omp_get_thread_num ();
+    #pragma omp barrier
+    if (rank == 1) {
+      result2 = 3;
+      #pragma omp flush (result2)
+      dummy = result2;
+    }
+    if (rank == 0) {
+      my_sleep(SLEEPTIME_LONG);
+      #pragma omp flush (result2)
+      result1 = result2;
+    }
+  }  /* end of parallel */
+  return ((result1 == result2) && (result2 == dummy) && (result2 == 3));
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for (i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_flush()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/lit.cfg
===================================================================
--- /dev/null
+++ runtime/test/lit.cfg
@@ -0,0 +1,49 @@
+# -*- Python -*- vim: set ft=python ts=4 sw=4 expandtab tw=79:
+# Configuration file for the 'lit' test runner.
+
+import os
+import lit.formats
+
+# Tell pylint that we know config and lit_config exist somewhere.
+if 'PYLINT_IMPORT' in os.environ:
+    config = object()
+    lit_config = object()
+
+def append_dynamic_library_path(name, value, sep):
+    if name in config.environment:
+        config.environment[name] = value + sep + config.environment[name]
+    else:
+        config.environment[name] = value
+
+# name: The name of this test suite.
+config.name = 'libomp'
+
+# suffixes: A list of file extensions to treat as test files.
+config.suffixes = ['.c']
+
+# test_source_root: The root path where tests are located.
+config.test_source_root = os.path.dirname(__file__)
+
+# test_exec_root: The root object directory where output is placed
+config.test_exec_root = config.libomp_obj_root
+
+# test format
+config.test_format = lit.formats.ShTest()
+
+# Setup environment to find dynamic library at runtime
+if config.operating_system == 'Windows':
+    append_dynamic_library_path('PATH', config.library_dir, ";")
+elif config.operating_system == 'Darwin':
+    append_dynamic_library_path('DYLD_LIBRARY_PATH', config.library_dir, ":")
+else: # Unices
+    append_dynamic_library_path('LD_LIBRARY_PATH', config.library_dir, ":")
+
+# substitutions
+config.substitutions.append(("%clang", config.test_compiler))
+config.substitutions.append(("%openmp_flag", config.test_openmp_flag))
+config.substitutions.append(("%cflags", \
+    " -I " + config.test_source_root + \
+    " -I " + config.omp_header_directory + \
+    " -L \"" + config.library_dir + "\"" + \
+    config.test_extra_cflags))
+
Index: runtime/test/lit.site.cfg.in
===================================================================
--- /dev/null
+++ runtime/test/lit.site.cfg.in
@@ -0,0 +1,13 @@
+@AUTO_GEN_COMMENT@
+
+config.test_compiler = "@LIBOMP_TEST_COMPILER@"
+config.test_openmp_flag = "@LIBOMP_TEST_OPENMP_FLAG@"
+config.test_extra_cflags = "@LIBOMP_TEST_CFLAGS@"
+config.libomp_obj_root = "@CMAKE_CURRENT_BINARY_DIR@"
+config.library_dir = "@LIBOMP_LIBRARY_DIR@"
+config.omp_header_directory = "@LIBOMP_BINARY_DIR@/src"
+config.operating_system = "@CMAKE_SYSTEM_NAME@"
+
+# Let the main config do the real work.
+lit_config.load_config(config, "@LIBOMP_BASE_DIR@/test/lit.cfg")
+
Index: runtime/test/lock/omp_lock.c
===================================================================
--- /dev/null
+++ runtime/test/lock/omp_lock.c
@@ -0,0 +1,45 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+omp_lock_t lck;
+
+int test_omp_lock()
+{
+  int nr_threads_in_single = 0;
+  int result = 0;
+  int nr_iterations = 0;
+  int i;
+
+  omp_init_lock(&lck);
+  #pragma omp parallel shared(lck)
+  {
+    #pragma omp for
+    for(i = 0; i < LOOPCOUNT; i++) {
+      omp_set_lock(&lck);
+      #pragma omp flush
+      nr_threads_in_single++;
+      #pragma omp flush       
+      nr_iterations++;
+      nr_threads_in_single--;
+      result = result + nr_threads_in_single;
+      omp_unset_lock(&lck);
+    }
+  }
+  omp_destroy_lock(&lck);
+
+  return ((result == 0) && (nr_iterations == LOOPCOUNT));
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_lock()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/lock/omp_nest_lock.c
===================================================================
--- /dev/null
+++ runtime/test/lock/omp_nest_lock.c
@@ -0,0 +1,45 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+omp_nest_lock_t lck;
+
+int test_omp_nest_lock()
+{
+  int nr_threads_in_single = 0;
+  int result = 0;
+  int nr_iterations = 0;
+  int i;
+
+  omp_init_nest_lock(&lck);
+  #pragma omp parallel shared(lck)  
+  {
+    #pragma omp for
+    for(i = 0; i < LOOPCOUNT; i++) {
+      omp_set_nest_lock(&lck);
+      #pragma omp flush
+      nr_threads_in_single++;
+      #pragma omp flush       
+      nr_iterations++;
+      nr_threads_in_single--;
+      result = result + nr_threads_in_single;
+      omp_unset_nest_lock(&lck);
+    }
+  }
+  omp_destroy_nest_lock(&lck);
+
+  return ((result == 0) && (nr_iterations == LOOPCOUNT));
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_nest_lock()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/lock/omp_test_lock.c
===================================================================
--- /dev/null
+++ runtime/test/lock/omp_test_lock.c
@@ -0,0 +1,45 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+omp_lock_t lck;
+
+int test_omp_test_lock()
+{
+  int nr_threads_in_single = 0;
+  int result = 0;
+  int nr_iterations = 0;
+  int i;
+
+  omp_init_lock (&lck);
+  #pragma omp parallel shared(lck)  
+  {
+    #pragma omp for
+    for (i = 0; i < LOOPCOUNT; i++) {
+      while (!omp_test_lock (&lck))
+      {};
+      #pragma omp flush
+      nr_threads_in_single++;
+      #pragma omp flush       
+      nr_iterations++;
+      nr_threads_in_single--;
+      result = result + nr_threads_in_single;
+      omp_unset_lock (&lck);
+    }
+  }
+  omp_destroy_lock(&lck);
+  return ((result == 0) && (nr_iterations == LOOPCOUNT));
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_test_lock()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/lock/omp_test_nest_lock.c
===================================================================
--- /dev/null
+++ runtime/test/lock/omp_test_nest_lock.c
@@ -0,0 +1,47 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+static omp_nest_lock_t lck;
+
+int test_omp_test_nest_lock()
+{
+  int nr_threads_in_single = 0;
+  int result = 0;
+  int nr_iterations = 0;
+  int i;
+
+  omp_init_nest_lock (&lck);
+  #pragma omp parallel shared(lck) 
+  {
+    #pragma omp for
+    for (i = 0; i < LOOPCOUNT; i++)
+    {
+      /*omp_set_lock(&lck);*/
+      while(!omp_test_nest_lock (&lck))
+      {};
+      #pragma omp flush
+      nr_threads_in_single++;
+      #pragma omp flush       
+      nr_iterations++;
+      nr_threads_in_single--;
+      result = result + nr_threads_in_single;
+      omp_unset_nest_lock (&lck);
+    }
+  }
+  omp_destroy_nest_lock (&lck);
+  return ((result == 0) && (nr_iterations == LOOPCOUNT));
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_test_nest_lock()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/master/omp_master.c
===================================================================
--- /dev/null
+++ runtime/test/master/omp_master.c
@@ -0,0 +1,38 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int test_omp_master()
+{
+  int nthreads;
+  int executing_thread;
+
+  nthreads = 0;
+  executing_thread = -1;
+
+  #pragma omp parallel
+  {
+    #pragma omp master 
+    {
+      #pragma omp critical
+      {
+        nthreads++;
+      }
+      executing_thread = omp_get_thread_num();
+    } /* end of master*/
+  } /* end of parallel*/
+  return ((nthreads == 1) && (executing_thread == 0));
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_master()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/master/omp_master_3.c
===================================================================
--- /dev/null
+++ runtime/test/master/omp_master_3.c
@@ -0,0 +1,44 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int test_omp_master_3()
+{
+  int nthreads;
+  int executing_thread;
+  int tid_result = 0; /* counts up the number of wrong thread no. for
+               the master thread. (Must be 0) */
+  nthreads = 0;
+  executing_thread = -1;
+
+  #pragma omp parallel
+  {
+    #pragma omp master 
+    {
+      int tid = omp_get_thread_num();
+      if (tid != 0) {
+        #pragma omp critical
+        { tid_result++; }
+      }
+      #pragma omp critical
+      {
+        nthreads++;
+      }
+      executing_thread = omp_get_thread_num ();
+    } /* end of master*/
+  } /* end of parallel*/
+  return ((nthreads == 1) && (executing_thread == 0) && (tid_result == 0));
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_master_3()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/omp_my_sleep.h
===================================================================
--- /dev/null
+++ runtime/test/omp_my_sleep.h
@@ -0,0 +1,35 @@
+#ifndef MY_SLEEP_H
+#define MY_SLEEP_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/times.h> 
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+
+/*! Utility function to have a sleep function with better resolution and which only stops one thread. */
+
+static void my_sleep(double sleeptime){
+  struct timeval tv;
+  struct timezone tzp;
+  double start;
+  double real;
+  if(gettimeofday(&tv,&tzp)!=0) {
+    perror("get_time: ");
+    exit(-1);
+  }
+  start = (double)tv.tv_sec + ((double)tv.tv_usec/1000000.0);
+  real=start;
+  while( (real-start)<sleeptime){
+    if(gettimeofday(&tv,&tzp)!=0) {
+      perror("get_time: ");
+      exit(-1);
+    }
+    real = (double)tv.tv_sec + ((double)tv.tv_usec/1000000.0);
+  }
+}
+
+#endif
Index: runtime/test/omp_testsuite.h
===================================================================
--- /dev/null
+++ runtime/test/omp_testsuite.h
@@ -0,0 +1,22 @@
+/* Global headerfile of the OpenMP Testsuite */
+
+#ifndef OMP_TESTSUITE_H
+#define OMP_TESTSUITE_H
+
+#include <stdio.h>
+#include <omp.h>
+
+/* General                                                */
+/**********************************************************/
+#define LOOPCOUNT 1000 /* Number of iterations to slit amongst threads */
+#define REPETITIONS 10 /* Number of times to run each test */
+/* following times are in seconds */
+#define SLEEPTIME 0.1
+#define SLEEPTIME_LONG 0.5
+
+/* Definitions for tasks                                  */
+/**********************************************************/
+#define NUM_TASKS 25
+#define MAX_TASKS_PER_THREAD 5
+
+#endif
Index: runtime/test/parallel/omp_nested.c
===================================================================
--- /dev/null
+++ runtime/test/parallel/omp_nested.c
@@ -0,0 +1,41 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+/*
+ * Test if the compiler supports nested parallelism
+ * By Chunhua Liao, University of Houston
+ * Oct. 2005
+ */
+int test_omp_nested()
+{
+  int counter = 0;
+#ifdef _OPENMP
+  omp_set_nested(1);
+#endif
+
+  #pragma omp parallel shared(counter)
+  {
+    #pragma omp critical
+    counter++;
+    #pragma omp parallel
+    {
+      #pragma omp critical
+      counter--;
+    }
+  }
+  return (counter != 0);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_nested()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/parallel/omp_parallel_copyin.c
===================================================================
--- /dev/null
+++ runtime/test/parallel/omp_parallel_copyin.c
@@ -0,0 +1,47 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <stdlib.h>
+#include "omp_testsuite.h"
+
+static int sum1 = 789;
+#pragma omp threadprivate(sum1)
+
+int test_omp_parallel_copyin()
+{
+  int sum, num_threads;
+  int known_sum;
+
+  sum = 0;
+  sum1 = 7;
+  num_threads = 0;
+
+  #pragma omp parallel copyin(sum1)
+  {
+    /*printf("sum1=%d\n",sum1);*/
+    int i;
+    #pragma omp for 
+    for (i = 1; i < 1000; i++) {
+      sum1 = sum1 + i;
+    } /*end of for*/
+    #pragma omp critical
+    {
+      sum = sum + sum1;
+      num_threads++;
+    } /*end of critical*/
+  } /* end of parallel*/  
+  known_sum = (999 * 1000) / 2 + 7 * num_threads;
+  return (known_sum == sum);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_copyin()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/parallel/omp_parallel_default.c
===================================================================
--- /dev/null
+++ runtime/test/parallel/omp_parallel_default.c
@@ -0,0 +1,44 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <unistd.h>
+#include "omp_testsuite.h"
+
+int test_omp_parallel_default()
+{
+  int i;
+  int sum;
+  int mysum;
+  int known_sum;
+  sum =0;
+  known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2 ;
+
+  #pragma omp parallel default(shared) private(i) private(mysum)
+  {
+    mysum = 0;
+    #pragma omp for
+    for (i = 1; i <= LOOPCOUNT; i++) {
+      mysum = mysum + i;
+    } 
+    #pragma omp critical
+    {
+      sum = sum + mysum;
+    }   /* end of critical */
+  }   /* end of parallel */
+  if (known_sum != sum) {
+    fprintf(stderr, "KNOWN_SUM = %d; SUM = %d\n", known_sum, sum);
+  }
+  return (known_sum == sum);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_default()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/parallel/omp_parallel_firstprivate.c
===================================================================
--- /dev/null
+++ runtime/test/parallel/omp_parallel_firstprivate.c
@@ -0,0 +1,46 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <stdlib.h>
+#include "omp_testsuite.h"
+
+//static int sum1 = 789;
+
+int test_omp_parallel_firstprivate()
+{
+  int sum, num_threads,sum1;
+  int known_sum;
+
+  sum = 0;
+  sum1=7;
+  num_threads = 0;
+
+  #pragma omp parallel firstprivate(sum1)
+  {
+    /*printf("sum1=%d\n",sum1);*/
+    int i;
+    #pragma omp for 
+    for (i = 1; i < 1000; i++) {
+      sum1 = sum1 + i;
+    } /*end of for*/
+    #pragma omp critical
+    {
+      sum = sum + sum1;
+      num_threads++;
+    } /*end of critical*/
+  } /* end of parallel*/  
+  known_sum = (999 * 1000) / 2 + 7 * num_threads;
+  return (known_sum == sum);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_firstprivate()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/parallel/omp_parallel_if.c
===================================================================
--- /dev/null
+++ runtime/test/parallel/omp_parallel_if.c
@@ -0,0 +1,41 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <unistd.h>
+#include "omp_testsuite.h"
+
+int test_omp_parallel_if()
+{
+  int i;
+  int sum;
+  int known_sum;
+  int mysum;
+  int control=1;
+
+  sum =0;
+  known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2 ;
+  #pragma omp parallel private(i) if(control==0)
+  {
+    mysum = 0;
+    for (i = 1; i <= LOOPCOUNT; i++) {
+      mysum = mysum + i;
+    } 
+    #pragma omp critical
+    {
+      sum = sum + mysum;
+    }
+  }
+  return (known_sum == sum);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_if()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/parallel/omp_parallel_num_threads.c
===================================================================
--- /dev/null
+++ runtime/test/parallel/omp_parallel_num_threads.c
@@ -0,0 +1,46 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int test_omp_parallel_num_threads()
+{
+  int num_failed;
+  int threads;
+  int nthreads;
+  int max_threads = 0;
+
+  num_failed = 0;
+
+  /* first we check how many threads are available */
+  #pragma omp parallel
+  {
+    #pragma omp master
+    max_threads = omp_get_num_threads ();
+  }
+
+  /* we increase the number of threads from one to maximum:*/
+  for(threads = 1; threads <= max_threads; threads++) {
+    nthreads = 0;
+    #pragma omp parallel reduction(+:num_failed) num_threads(threads)
+    {
+      num_failed = num_failed + !(threads == omp_get_num_threads());
+      #pragma omp atomic
+      nthreads += 1;
+    }
+    num_failed = num_failed + !(nthreads == threads);
+  }
+  return (!num_failed);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_num_threads()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/parallel/omp_parallel_private.c
===================================================================
--- /dev/null
+++ runtime/test/parallel/omp_parallel_private.c
@@ -0,0 +1,46 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <stdlib.h>
+#include "omp_testsuite.h"
+
+//static int sum1 = 789;
+
+int test_omp_parallel_private()
+{
+  int sum, num_threads,sum1;
+  int known_sum;
+
+  sum = 0;
+  num_threads = 0;
+
+  #pragma omp parallel private(sum1)
+  {
+    int i;
+    sum1 = 7;
+    /*printf("sum1=%d\n",sum1);*/
+    #pragma omp for 
+    for (i = 1; i < 1000; i++) {
+      sum1 = sum1 + i;
+    }
+    #pragma omp critical
+    {
+      sum = sum + sum1;
+      num_threads++;
+    }
+  }
+  known_sum = (999 * 1000) / 2 + 7 * num_threads;
+  return (known_sum == sum);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_private()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/parallel/omp_parallel_reduction.c
===================================================================
--- /dev/null
+++ runtime/test/parallel/omp_parallel_reduction.c
@@ -0,0 +1,254 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t -lm && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+#define DOUBLE_DIGITS 20    /* dt^DOUBLE_DIGITS */
+#define MAX_FACTOR 10
+#define KNOWN_PRODUCT 3628800  /* 10! */
+
+int test_omp_parallel_reduction()
+{
+  int sum;
+  int known_sum;
+  double dsum;
+  double dknown_sum;
+  double dt=0.5; /* base of geometric row for + and - test*/
+  double rounding_error= 1.E-9;
+  int diff;
+  double ddiff;
+  int product;
+  int known_product;
+  int logic_and;
+  int logic_or;
+  int bit_and;
+  int bit_or;
+  int exclusiv_bit_or;
+  int logics[LOOPCOUNT];
+  int i;
+  double dpt;
+  int result;
+
+  sum =0;
+  dsum=0;
+  product=1;
+  logic_and=1;
+  logic_or=0;
+  bit_and=1;
+  bit_or=0;
+  exclusiv_bit_or=0;
+  result=0;
+  dt = 1./3.;
+  known_sum = (LOOPCOUNT*(LOOPCOUNT+1))/2;
+
+  /* Tests for integers */
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(+:sum)
+  for (i=1;i<=LOOPCOUNT;i++) {
+    sum=sum+i;
+  }
+
+  if(known_sum!=sum) {
+    result++;
+    fprintf(stderr,"Error in sum with integers: Result was %d instead of %d\n",sum,known_sum); 
+  }
+
+  diff = (LOOPCOUNT*(LOOPCOUNT+1))/2;
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(-:diff)
+  for (i=1;i<=LOOPCOUNT;++i) {
+    diff=diff-i;
+  }
+
+  if(diff != 0) {
+    result++;
+    fprintf(stderr,"Error in difference with integers: Result was %d instead of 0.\n",diff);
+  }
+
+  /* Tests for doubles */
+  dsum=0;
+  dpt=1;
+  for (i=0;i<DOUBLE_DIGITS;++i) {
+    dpt*=dt;
+  }
+  dknown_sum = (1-dpt)/(1-dt);
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(+:dsum)
+  for (i=0;i<DOUBLE_DIGITS;++i) {
+    dsum += pow(dt,i);
+  }
+
+  if( fabs(dsum-dknown_sum) > rounding_error ) {
+    result++; 
+    fprintf(stderr,"Error in sum with doubles: Result was %f instead of %f (Difference: %E)\n",dsum,dknown_sum, dsum-dknown_sum);
+  }
+
+  dpt=1;
+
+  for (i=0;i<DOUBLE_DIGITS;++i) {
+    dpt*=dt;
+  }
+  fprintf(stderr,"\n");
+  ddiff = (1-dpt)/(1-dt);
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(-:ddiff)
+  for (i=0;i<DOUBLE_DIGITS;++i) {
+    ddiff -= pow(dt,i);
+  }
+  if( fabs(ddiff) > rounding_error) {
+    result++;
+    fprintf(stderr,"Error in Difference with doubles: Result was %E instead of 0.0\n",ddiff);
+  }
+
+  /* Tests for product of integers */
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(*:product)
+  for(i=1;i<=MAX_FACTOR;i++) {
+    product *= i;
+  }
+
+  known_product = KNOWN_PRODUCT;
+  if(known_product != product) {
+    result++;
+    fprintf(stderr,"Error in Product with integers: Result was %d instead of %d\n\n",product,known_product);
+  }
+
+  /* Tests for logical and */
+  for(i=0;i<LOOPCOUNT;i++) {
+    logics[i]=1;
+  }
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(&&:logic_and)
+  for(i=0;i<LOOPCOUNT;++i) {
+    logic_and = (logic_and && logics[i]);
+  }
+  if(!logic_and) {
+    result++;
+    fprintf(stderr,"Error in logic AND part 1.\n");
+  }
+
+  logic_and = 1;
+  logics[LOOPCOUNT/2]=0;
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(&&:logic_and)
+  for(i=0;i<LOOPCOUNT;++i) {
+    logic_and = logic_and && logics[i];
+  }
+  if(logic_and) {
+    result++;
+    fprintf(stderr,"Error in logic AND part 2.\n");
+  }
+
+  /* Tests for logical or */
+  for(i=0;i<LOOPCOUNT;i++) {
+    logics[i]=0;
+  }
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(||:logic_or)
+  for(i=0;i<LOOPCOUNT;++i) {
+    logic_or = logic_or || logics[i];
+  }
+  if(logic_or) {
+    result++;
+    fprintf(stderr,"Error in logic OR part 1.\n");
+  }
+  logic_or = 0;
+  logics[LOOPCOUNT/2]=1;
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(||:logic_or)
+  for(i=0;i<LOOPCOUNT;++i) {
+    logic_or = logic_or || logics[i];
+  }
+  if(!logic_or) {
+    result++;
+    fprintf(stderr,"Error in logic OR part 2.\n");
+  }
+
+  /* Tests for bitwise and */
+  for(i=0;i<LOOPCOUNT;++i) {
+    logics[i]=1;
+  }
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(&:bit_and)
+  for(i=0;i<LOOPCOUNT;++i) {
+    bit_and = (bit_and & logics[i]);
+  }
+  if(!bit_and) {
+    result++;
+    fprintf(stderr,"Error in BIT AND part 1.\n");
+  }
+
+  bit_and = 1;
+  logics[LOOPCOUNT/2]=0;
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(&:bit_and)
+  for(i=0;i<LOOPCOUNT;++i) {
+    bit_and = bit_and & logics[i];
+  }
+  if(bit_and) {
+    result++;
+    fprintf(stderr,"Error in BIT AND part 2.\n");
+  }
+
+  for(i=0;i<LOOPCOUNT;i++) {
+    logics[i]=0;
+  }
+
+  /* Tests for bitwise or */
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(|:bit_or)
+  for(i=0;i<LOOPCOUNT;++i) {
+    bit_or = bit_or | logics[i];
+  }
+  if(bit_or) {
+    result++;
+    fprintf(stderr,"Error in BIT OR part 1\n");
+  }
+  bit_or = 0;
+  logics[LOOPCOUNT/2]=1;
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(|:bit_or)
+  for(i=0;i<LOOPCOUNT;++i) {
+    bit_or = bit_or | logics[i];
+  }
+  if(!bit_or) {
+    result++;
+    fprintf(stderr,"Error in BIT OR part 2\n");
+  }
+
+  for(i=0;i<LOOPCOUNT;i++) {
+    logics[i]=0;
+  }
+
+  /* Tests for bitwise xor */
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(^:exclusiv_bit_or)
+  for(i=0;i<LOOPCOUNT;++i) {
+    exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+  }
+  if(exclusiv_bit_or) {
+    result++;
+    fprintf(stderr,"Error in EXCLUSIV BIT OR part 1\n");
+  }
+
+  exclusiv_bit_or = 0;
+  logics[LOOPCOUNT/2]=1;
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(^:exclusiv_bit_or)
+  for(i=0;i<LOOPCOUNT;++i) {
+    exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+  }
+  if(!exclusiv_bit_or) {
+    result++;
+    fprintf(stderr,"Error in EXCLUSIV BIT OR part 2\n");
+  }
+
+  /*printf("\nResult:%d\n",result);*/
+  return (result==0);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_reduction()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/parallel/omp_parallel_shared.c
===================================================================
--- /dev/null
+++ runtime/test/parallel/omp_parallel_shared.c
@@ -0,0 +1,47 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <unistd.h>
+#include "omp_testsuite.h"
+
+int test_omp_parallel_shared()
+{
+  int i;
+  int sum;
+  int known_sum;
+
+  sum = 0;
+  known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2 ;
+
+  #pragma omp parallel private(i) shared(sum) 
+  {
+
+    int mysum = 0;
+    #pragma omp for
+    for (i = 1; i <= LOOPCOUNT; i++) {
+      mysum = mysum + i;
+    } 
+    #pragma omp critical
+    {
+      sum = sum + mysum;
+    }
+
+
+  }
+  if (known_sum != sum) {
+    fprintf(stderr, "KNOWN_SUM = %d; SUM = %d\n", known_sum, sum);
+  }
+  return (known_sum == sum);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_shared()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/tasking/omp_task.c
===================================================================
--- /dev/null
+++ runtime/test/tasking/omp_task.c
@@ -0,0 +1,52 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+int test_omp_task()
+{
+  int tids[NUM_TASKS];
+  int i;
+
+  #pragma omp parallel 
+  {
+    #pragma omp single
+    {
+      for (i = 0; i < NUM_TASKS; i++) {
+        /* First we have to store the value of the loop index in a new variable
+         * which will be private for each task because otherwise it will be overwritten
+         * if the execution of the task takes longer than the time which is needed to 
+         * enter the next step of the loop!
+         */
+        int myi;
+        myi = i;
+        #pragma omp task
+        {
+          my_sleep (SLEEPTIME);
+          tids[myi] = omp_get_thread_num();
+        } /* end of omp task */
+      } /* end of for */
+    } /* end of single */
+  } /*end of parallel */
+
+  /* Now we ckeck if more than one thread executed the tasks. */
+  for (i = 1; i < NUM_TASKS; i++) {
+    if (tids[0] != tids[i])
+      return 1;
+  }
+  return 0;
+} /* end of check_parallel_for_private */
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_task()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/tasking/omp_task_final.c
===================================================================
--- /dev/null
+++ runtime/test/tasking/omp_task_final.c
@@ -0,0 +1,58 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+int test_omp_task_final()
+{
+  int tids[NUM_TASKS];
+  int in_final[NUM_TASKS];
+  int error;
+  #pragma omp parallel 
+  {
+    #pragma omp single
+    {
+      int i;
+      for (i = 0; i < NUM_TASKS; i++) {
+        /* First we have to store the value of the loop index in a new variable
+         * which will be private for each task because otherwise it will be overwritten
+         * if the execution of the task takes longer than the time which is needed to 
+         * enter the next step of the loop!
+         */
+        int myi;
+        myi = i;
+        #pragma omp task final(i>=10) firstprivate(myi) shared(tids) shared(in_final)
+        {
+          my_sleep (SLEEPTIME);
+          tids[myi] = omp_get_thread_num();
+          in_final[myi] = omp_in_final();
+        }
+      }
+    }
+  }
+
+  /* Now we check if more than one thread executed the tasks. */
+  int i;
+  for (i = 10; i < NUM_TASKS; i++) {
+    fprintf(stderr, "tids[10] = %d , tids[%d] = %d\n", tids[10], i, tids[i]);
+    fprintf(stderr, "in_final[%d] = %d\n", i, in_final[i]);
+    if (tids[10] != tids[i])
+      error++;
+  }
+  fprintf(stderr, "\n");
+  return (error==0);
+} /* end of check_parallel_for_private */
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_task_final()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/tasking/omp_task_firstprivate.c
===================================================================
--- /dev/null
+++ runtime/test/tasking/omp_task_firstprivate.c
@@ -0,0 +1,51 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+int test_omp_task_firstprivate()
+{
+  int i;
+  int sum = 1234;
+  int known_sum;
+  int result = 0; /* counts the wrong sums from tasks */
+
+  known_sum = 1234 + (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
+
+  #pragma omp parallel
+  {
+    #pragma omp single
+    {
+      for (i = 0; i < NUM_TASKS; i++) {
+        #pragma omp task firstprivate(sum)
+        {
+          int j;
+          for (j = 0; j <= LOOPCOUNT; j++) {
+            #pragma omp flush
+            sum += j;
+          }
+
+          /* check if calculated sum was right */
+          if (sum != known_sum) {
+            #pragma omp critical 
+            { result++; }
+          }
+        } /* omp task */
+      } /* for loop */
+    } /* omp single */
+  } /* omp parallel */
+  return (result == 0);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_task_firstprivate()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/tasking/omp_task_if.c
===================================================================
--- /dev/null
+++ runtime/test/tasking/omp_task_if.c
@@ -0,0 +1,43 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+int test_omp_task_if()
+{
+  int condition_false;
+  int count;
+  int result;
+
+  count=0;
+  condition_false = (count == 1);
+  #pragma omp parallel 
+  {
+    #pragma omp single
+    {
+      #pragma omp task if (condition_false) shared(count, result)
+      {
+        my_sleep (SLEEPTIME_LONG);
+        //#pragma omp flush (count)
+        result = (0 == count);
+      } /* end of omp task */
+      count = 1;
+      //#pragma omp flush (count)
+    } /* end of single */
+  } /*end of parallel */
+  return result;
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_task_if()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/tasking/omp_task_imp_firstprivate.c
===================================================================
--- /dev/null
+++ runtime/test/tasking/omp_task_imp_firstprivate.c
@@ -0,0 +1,47 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+/* Utility function do spend some time in a loop */
+int test_omp_task_imp_firstprivate()
+{
+  int i=5;
+  int k = 0;
+  int result = 0;
+  int task_result = 1;
+  #pragma omp parallel firstprivate(i)
+  {
+    #pragma omp single
+    {
+      for (k = 0; k < NUM_TASKS; k++) {
+        #pragma omp task shared(result , task_result)
+        {
+          int j;
+          //check if i is private
+          if(i != 5)
+            task_result = 0;
+          for(j = 0; j < NUM_TASKS; j++)
+            i++;
+          //this should be firstprivate implicitly
+        }
+      }
+      #pragma omp taskwait
+      result = (task_result && i==5);
+    }
+  }
+  return result;
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_task_imp_firstprivate()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/tasking/omp_task_private.c
===================================================================
--- /dev/null
+++ runtime/test/tasking/omp_task_private.c
@@ -0,0 +1,53 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+/* Utility function do spend some time in a loop */
+int test_omp_task_private()
+{
+  int i;
+  int known_sum;
+  int sum = 0;
+  int result = 0; /* counts the wrong sums from tasks */
+
+  known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
+
+  #pragma omp parallel
+  {
+    #pragma omp single
+    {
+      for (i = 0; i < NUM_TASKS; i++) {
+        #pragma omp task private(sum) shared(result, known_sum)
+        {
+          int j;
+          //if sum is private, initialize to 0
+          sum = 0;
+          for (j = 0; j <= LOOPCOUNT; j++) {
+            #pragma omp flush
+            sum += j;
+          }
+          /* check if calculated sum was right */
+          if (sum != known_sum) {
+            #pragma omp critical 
+            result++;
+          }
+        } /* end of omp task */
+      } /* end of for */
+    } /* end of single */
+  } /* end of parallel*/
+  return (result == 0);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_task_private()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/tasking/omp_task_shared.c
===================================================================
--- /dev/null
+++ runtime/test/tasking/omp_task_shared.c
@@ -0,0 +1,41 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+/* Utility function do spend some time in a loop */
+int test_omp_task_imp_shared()
+{
+  int i;
+  int k = 0;
+  int result = 0;
+  i=0;
+
+  #pragma omp parallel
+  {
+    #pragma omp single
+    for (k = 0; k < NUM_TASKS; k++) {
+      #pragma omp task shared(i)
+      {
+        #pragma omp atomic
+        i++;
+        //this should be shared implicitly
+      }
+    }
+  }
+  result = i;
+  return ((result == NUM_TASKS));
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_task_imp_shared()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/tasking/omp_task_untied.c
===================================================================
--- /dev/null
+++ runtime/test/tasking/omp_task_untied.c
@@ -0,0 +1,67 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+int test_omp_task_untied()
+{
+  int i;
+  int count;
+  int start_tid[NUM_TASKS];
+  int current_tid[NUM_TASKS];
+
+  count = 0;
+
+  /*initialization*/
+  for (i=0; i< NUM_TASKS; i++){
+    start_tid[i]=0;
+    current_tid[i]=0;
+  }
+
+  #pragma omp parallel firstprivate(i)
+  {
+    #pragma omp single
+    {
+      for (i = 0; i < NUM_TASKS; i++) {
+        int myi = i;
+        #pragma omp task untied
+        {
+          my_sleep(SLEEPTIME);
+          start_tid[myi] = omp_get_thread_num();
+          current_tid[myi] = omp_get_thread_num();
+
+          #pragma omp taskwait
+
+          if((start_tid[myi] % 2) != 0) {
+            my_sleep(SLEEPTIME);
+            current_tid[myi] = omp_get_thread_num();
+          } else {
+            current_tid[myi] = omp_get_thread_num();
+          }
+        } /*end of omp task */
+      } /* end of for */
+    } /* end of single */
+  } /* end of parallel */
+
+  for (i=0;i<NUM_TASKS; i++) {
+    //fprintf(stderr, "start_tid[%d]=%d, current_tid[%d]=%d\n",
+     // i, start_tid[i], i , current_tid[i]);
+    if (current_tid[i] == start_tid[i])
+      count++;
+  }
+  return (count<NUM_TASKS);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_task_untied()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/tasking/omp_taskwait.c
===================================================================
--- /dev/null
+++ runtime/test/tasking/omp_taskwait.c
@@ -0,0 +1,74 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+int test_omp_taskwait()
+{
+  int result1 = 0;   /* Stores number of not finished tasks after the taskwait */
+  int result2 = 0;   /* Stores number of wrong array elements at the end */
+  int array[NUM_TASKS];
+  int i;
+
+  /* fill array */
+  for (i = 0; i < NUM_TASKS; i++) 
+    array[i] = 0;
+
+  #pragma omp parallel 
+  {
+    #pragma omp single
+    {
+      for (i = 0; i < NUM_TASKS; i++) {
+        /* First we have to store the value of the loop index in a new variable
+         * which will be private for each task because otherwise it will be overwritten
+         * if the execution of the task takes longer than the time which is needed to 
+         * enter the next step of the loop!
+         */
+        int myi;
+        myi = i;
+        #pragma omp task
+        {
+          my_sleep (SLEEPTIME);
+          array[myi] = 1;
+        } /* end of omp task */
+      } /* end of for */
+      #pragma omp taskwait
+      /* check if all tasks were finished */
+      for (i = 0; i < NUM_TASKS; i++) 
+        if (array[i] != 1)
+          result1++;
+
+      /* generate some more tasks which now shall overwrite 
+       * the values in the tids array */
+      for (i = 0; i < NUM_TASKS; i++) {
+        int myi;
+        myi = i;
+        #pragma omp task
+        {
+          array[myi] = 2;
+        } /* end of omp task */
+      } /* end of for */
+    } /* end of single */
+  } /*end of parallel */
+
+  /* final check, if all array elements contain the right values: */
+  for (i = 0; i < NUM_TASKS; i++) {
+    if (array[i] != 2)
+      result2++;
+  }
+  return ((result1 == 0) && (result2 == 0));
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_taskwait()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/tasking/omp_taskyield.c
===================================================================
--- /dev/null
+++ runtime/test/tasking/omp_taskyield.c
@@ -0,0 +1,58 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+int test_omp_taskyield()
+{
+  int i;
+  int count = 0;
+  int start_tid[NUM_TASKS];
+  int current_tid[NUM_TASKS];
+
+  for (i=0; i< NUM_TASKS; i++) {
+    start_tid[i]=0;
+    current_tid[i]=0;
+  }
+
+  #pragma omp parallel
+  {
+    #pragma omp single
+    {
+      for (i = 0; i < NUM_TASKS; i++) {
+        int myi = i;
+        #pragma omp task untied
+        {
+          my_sleep(SLEEPTIME);
+          start_tid[myi] = omp_get_thread_num();
+          #pragma omp taskyield
+          if((start_tid[myi] %2) ==0){
+            my_sleep(SLEEPTIME);
+            current_tid[myi] = omp_get_thread_num();
+          } /*end of if*/
+        } /* end of omp task */
+      } /* end of for */
+    } /* end of single */
+  } /* end of parallel */
+  for (i=0;i<NUM_TASKS; i++) {
+    //printf("start_tid[%d]=%d, current_tid[%d]=%d\n",
+      //i, start_tid[i], i , current_tid[i]);
+    if (current_tid[i] == start_tid[i])
+      count++;
+  }
+  return (count<NUM_TASKS);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_taskyield()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/threadprivate/omp_threadprivate.c
===================================================================
--- /dev/null
+++ runtime/test/threadprivate/omp_threadprivate.c
@@ -0,0 +1,102 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+/*
+ * Threadprivate is tested in 2 ways:
+ * 1. The global variable declared as threadprivate should have
+ *  local copy for each thread. Otherwise race condition and 
+ *  wrong result.
+ * 2. If the value of local copy is retained for the two adjacent
+ *  parallel regions
+ */
+#include "omp_testsuite.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+static int sum0=0;
+static int myvalue = 0;
+
+#pragma omp threadprivate(sum0)
+#pragma omp threadprivate(myvalue)
+
+int test_omp_threadprivate()
+{
+  int sum = 0;
+  int known_sum;
+  int i; 
+  int iter;
+  int *data;
+  int size;
+  int num_failed = 0;
+  int my_random;
+  omp_set_dynamic(0);
+
+  #pragma omp parallel private(i) 
+  {
+    sum0 = 0;
+    #pragma omp for 
+    for (i = 1; i <= LOOPCOUNT; i++) {
+      sum0 = sum0 + i;
+    } /*end of for*/
+    #pragma omp critical
+    {
+      sum = sum + sum0;
+    } /*end of critical */
+  } /* end of parallel */  
+  known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
+  if (known_sum != sum ) {
+    fprintf (stderr, " known_sum = %d, sum = %d\n", known_sum, sum);
+  }
+
+  /* the next parallel region is just used to get the number of threads*/
+  omp_set_dynamic(0);
+  #pragma omp parallel
+  {
+    #pragma omp master
+    {
+      size=omp_get_num_threads();
+      data=(int*) malloc(size*sizeof(int));
+    }
+  }/* end parallel*/
+
+  srand(45);
+  for (iter = 0; iter < 100; iter++) {
+    my_random = rand(); /* random number generator is 
+                 called inside serial region*/
+
+    /* the first parallel region is used to initialiye myvalue
+       and the array with my_random+rank */
+    #pragma omp parallel
+    {
+      int rank;
+      rank = omp_get_thread_num ();
+      myvalue = data[rank] = my_random + rank;
+    }
+
+    /* the second parallel region verifies that the 
+       value of "myvalue" is retained */
+    #pragma omp parallel reduction(+:num_failed)
+    {
+      int rank;
+      rank = omp_get_thread_num ();
+      num_failed = num_failed + (myvalue != data[rank]);
+      if(myvalue != data[rank]) {
+        fprintf (stderr, " myvalue = %d, data[rank]= %d\n",
+          myvalue, data[rank]);
+      }
+    }
+  }
+  free (data);
+  return (known_sum == sum) && !num_failed;
+} /* end of check_threadprivate*/
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_threadprivate()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/threadprivate/omp_threadprivate_for.c
===================================================================
--- /dev/null
+++ runtime/test/threadprivate/omp_threadprivate_for.c
@@ -0,0 +1,47 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include "omp_testsuite.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+static int i;
+#pragma omp threadprivate(i)
+
+int test_omp_threadprivate_for()
+{
+  int known_sum;
+  int sum;
+
+  known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
+  sum = 0;
+
+  #pragma omp parallel
+  {
+    int sum0 = 0;
+    #pragma omp for
+    for (i = 1; i <= LOOPCOUNT; i++) {
+      sum0 = sum0 + i;
+    }
+    #pragma omp critical
+    {
+      sum = sum + sum0;
+    }
+  } /* end of parallel */  
+
+  if (known_sum != sum ) {
+    fprintf(stderr, " known_sum = %d, sum = %d\n", known_sum, sum);
+  }
+  return (known_sum == sum);
+} /* end of check_threadprivate*/
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_threadprivate_for()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_for_collapse.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_for_collapse.c
@@ -0,0 +1,51 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+/* Utility function to check that i is increasing monotonically 
+   with each call */
+static int check_i_islarger (int i)
+{
+  static int last_i;
+  int islarger;
+  if (i==1)
+    last_i=0;
+  islarger = ((i >= last_i)&&(i - last_i<=1));
+  last_i = i;
+  return (islarger);
+}
+
+int test_omp_for_collapse()
+{
+  int is_larger = 1;
+
+  #pragma omp parallel
+  {
+    int i,j;
+    int my_islarger = 1;
+    #pragma omp for private(i,j) schedule(static,1) collapse(2) ordered
+    for (i = 1; i < 100; i++) {
+      for (j =1; j <100; j++) {
+        #pragma omp ordered
+        my_islarger = check_i_islarger(i)&&my_islarger;
+      }
+    }
+    #pragma omp critical
+    is_larger = is_larger && my_islarger;
+  }
+  return (is_larger);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_for_collapse()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_for_firstprivate.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_for_firstprivate.c
@@ -0,0 +1,55 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+int sum1;
+#pragma omp threadprivate(sum1)
+
+int test_omp_for_firstprivate()
+{
+  int sum;
+  int sum0;
+  int known_sum;
+  int threadsnum;
+
+  sum = 0;
+  sum0 = 12345;
+  sum1 = 0;
+
+  #pragma omp parallel
+  {
+    #pragma omp single
+    {
+      threadsnum=omp_get_num_threads();
+    }
+    /* sum0 = 0; */
+  
+    int i;
+    #pragma omp for firstprivate(sum0)
+    for (i = 1; i <= LOOPCOUNT; i++) {
+      sum0 = sum0 + i;
+      sum1 = sum0;
+    }  /* end of for */
+  
+    #pragma omp critical
+    {
+      sum = sum + sum1;
+    }  /* end of critical */
+  }  /* end of parallel */  
+  known_sum = 12345* threadsnum+ (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
+  return (known_sum == sum);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_for_firstprivate()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_for_lastprivate.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_for_lastprivate.c
@@ -0,0 +1,52 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+int sum0;
+#pragma omp threadprivate(sum0)
+
+int test_omp_for_lastprivate()
+{
+  int sum = 0;
+  int known_sum;
+  int i0;
+  
+  i0 = -1;
+
+  #pragma omp parallel
+  {
+    sum0 = 0;
+    {  /* Begin of orphaned block */
+      int i;
+      #pragma omp for schedule(static,7) lastprivate(i0)
+      for (i = 1; i <= LOOPCOUNT; i++) {
+        sum0 = sum0 + i;
+        i0 = i;
+      }  /* end of for */
+    }  /* end of orphaned block */
+
+    #pragma omp critical
+    {
+      sum = sum + sum0;
+    }  /* end of critical */
+  }  /* end of parallel */  
+
+  known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
+  fprintf(stderr, "known_sum = %d , sum = %d\n",known_sum,sum);
+  fprintf(stderr, "LOOPCOUNT = %d , i0 = %d\n",LOOPCOUNT,i0);
+  return ((known_sum == sum) && (i0 == LOOPCOUNT));
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for (i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_for_lastprivate()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_for_nowait.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_for_nowait.c
@@ -0,0 +1,53 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+int test_omp_for_nowait()
+{
+  int result;
+  int count;
+  int j;
+  int myarray[LOOPCOUNT];
+
+  result = 0;
+  count = 0;
+
+  #pragma omp parallel 
+  {
+    int rank;
+    int i;
+
+    rank = omp_get_thread_num();
+
+    #pragma omp for nowait 
+    for (i = 0; i < LOOPCOUNT; i++) {
+      if (i == 0) {
+        my_sleep(SLEEPTIME);
+        count = 1;
+        #pragma omp flush(count)
+      }
+    }
+    
+    #pragma omp for
+    for (i = 0; i < LOOPCOUNT; i++) {
+      #pragma omp flush(count)
+      if (count == 0)
+        result = 1;
+    }
+  }
+  return result;
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_for_nowait()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_for_ordered.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_for_ordered.c
@@ -0,0 +1,60 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+static int last_i = 0;
+
+/* Utility function to check that i is increasing monotonically 
+   with each call */
+static int check_i_islarger (int i)
+{
+  int islarger;
+  islarger = (i > last_i);
+  last_i = i;
+  return (islarger);
+}
+
+int test_omp_for_ordered()
+{
+  int sum;
+  int is_larger = 1;
+  int known_sum;
+
+  last_i = 0;
+  sum = 0;
+
+  #pragma omp parallel
+  {
+    int i;
+    int my_islarger = 1;
+    #pragma omp for schedule(static,1) ordered
+    for (i = 1; i < 100; i++) {
+      #pragma omp ordered
+      {
+        my_islarger = check_i_islarger(i) && my_islarger;
+        sum = sum + i;
+      }
+    }
+    #pragma omp critical
+    {
+      is_larger = is_larger && my_islarger;
+    }
+  }
+
+  known_sum=(99 * 100) / 2;
+  return ((known_sum == sum) && is_larger);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_for_ordered()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_for_private.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_for_private.c
@@ -0,0 +1,63 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t -lm && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+/* Utility function do spend some time in a loop */
+static void do_some_work()
+{
+  int i;
+  double sum = 0;
+  for(i = 0; i < 1000; i++){
+  sum += sqrt ((double) i);
+  }
+}
+
+int sum1;
+#pragma omp threadprivate(sum1)
+
+int test_omp_for_private()
+{
+  int sum = 0;
+  int sum0;
+  int known_sum;
+
+  sum0 = 0;  /* setting (global) sum0 = 0 */
+
+  #pragma omp parallel
+  {
+    sum1 = 0;  /* setting sum1 in each thread to 0 */
+    {  /* begin of orphaned block */
+      int i;
+      #pragma omp for private(sum0) schedule(static,1)
+      for (i = 1; i <= LOOPCOUNT; i++) {
+        sum0 = sum1;
+        #pragma omp flush
+        sum0 = sum0 + i;
+        do_some_work ();
+        #pragma omp flush
+        sum1 = sum0;
+      }
+    }  /* end of orphaned block */
+
+    #pragma omp critical
+    {
+      sum = sum + sum1;
+    }  /*end of critical*/
+  }  /* end of parallel*/  
+  known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
+  return (known_sum == sum);
+}                
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_for_private()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_for_reduction.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_for_reduction.c
@@ -0,0 +1,339 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t -lm && %t
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+#define DOUBLE_DIGITS 20  /* dt^DOUBLE_DIGITS */
+#define MAX_FACTOR 10
+#define KNOWN_PRODUCT 3628800  /* 10! */
+
+int test_omp_for_reduction ()
+{
+  double dt;
+  int sum;
+  int diff;
+  int product = 1;
+  double dsum;
+  double dknown_sum;
+  double ddiff;
+  int logic_and;
+  int logic_or;
+  int bit_and;
+  int bit_or;
+  int exclusiv_bit_or;
+  int *logics;
+  int i;
+  int known_sum;
+  int known_product;
+  double rounding_error = 1.E-9; /* over all rounding error to be
+                    ignored in the double tests */
+  double dpt;
+  int result = 0;
+  int logicsArray[LOOPCOUNT];
+
+  /* Variables for integer tests */
+  sum = 0;
+  product = 1;
+  known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
+  /* variabels for double tests */
+  dt = 1. / 3.;  /* base of geometric row for + and - test*/
+  dsum = 0.;
+  /* Variabeles for logic  tests */
+  logics = logicsArray;
+  logic_and = 1;
+  logic_or = 0;
+  /* Variabeles for bit operators tests */
+  bit_and = 1;
+  bit_or = 0;
+  /* Variables for exclusiv bit or */
+  exclusiv_bit_or = 0;
+
+  /************************************************************************/
+  /** Tests for integers                         **/
+  /************************************************************************/
+
+  /**** Testing integer addition ****/
+  #pragma omp parallel 
+  {
+    int j;
+    #pragma omp for schedule(dynamic,1) reduction(+:sum)
+    for (j = 1; j <= LOOPCOUNT; j++) {
+      sum = sum + j;
+    }
+  }
+  if (known_sum != sum) {
+    result++;
+    fprintf (stderr, "Error in sum with integers: Result was %d"
+      " instead of %d.\n", sum, known_sum); 
+  }
+
+  /**** Testing integer subtracton ****/
+  diff = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
+  #pragma omp parallel 
+  {
+    int j;
+    #pragma omp for schedule(dynamic,1) reduction(-:diff)
+    for (j = 1; j <= LOOPCOUNT; j++) {
+      diff = diff - j;
+    }
+  }
+  if (diff != 0) {
+    result++;
+    fprintf (stderr, "Error in difference with integers: Result was %d"
+      " instead of 0.\n", diff);
+  }
+
+  /**** Testing integer multiplication ****/
+  #pragma omp parallel 
+  {
+    int j;
+    #pragma omp for schedule(dynamic,1) reduction(*:product)
+    for (j = 1; j <= MAX_FACTOR; j++) {
+      product *= j;
+    }
+  }
+  known_product = KNOWN_PRODUCT;
+  if(known_product != product) {
+    result++;
+    fprintf (stderr,"Error in Product with integers: Result was %d"
+      " instead of %d\n",product,known_product);
+  }
+
+  /************************************************************************/
+  /** Tests for doubles                          **/
+  /************************************************************************/
+
+  /**** Testing double addition ****/
+  dsum = 0.;
+  dpt = 1.;
+  for (i = 0; i < DOUBLE_DIGITS; ++i) {
+    dpt *= dt;
+  }
+  dknown_sum = (1 - dpt) / (1 - dt);
+  #pragma omp parallel 
+  {
+    int j;
+    #pragma omp for schedule(dynamic,1) reduction(+:dsum)
+    for (j = 0; j < DOUBLE_DIGITS; j++) {  
+      dsum += pow (dt, j);
+    }
+  }
+  if (fabs (dsum - dknown_sum) > rounding_error) {
+    result++; 
+    fprintf (stderr, "\nError in sum with doubles: Result was %f"
+      " instead of: %f (Difference: %E)\n",
+      dsum, dknown_sum, dsum-dknown_sum);
+  }
+
+  /**** Testing double subtraction ****/
+  ddiff = (1 - dpt) / (1 - dt);
+  #pragma omp parallel 
+  {
+    int j;
+    #pragma omp for schedule(dynamic,1) reduction(-:ddiff)
+    for (j = 0; j < DOUBLE_DIGITS; ++j) {
+      ddiff -= pow (dt, j);
+    }
+  }
+  if (fabs (ddiff) > rounding_error) {
+    result++;
+    fprintf (stderr, "Error in Difference with doubles: Result was %E"
+      " instead of 0.0\n", ddiff);
+  }
+
+
+  /************************************************************************/
+  /** Tests for logical values                       **/
+  /************************************************************************/
+
+  /**** Testing logic and ****/
+  for (i = 0; i < LOOPCOUNT; i++) {
+    logics[i] = 1;
+  }
+
+  #pragma omp parallel 
+  {
+    int j;
+    #pragma omp for schedule(dynamic,1) reduction(&&:logic_and)
+    for (j = 0; j < LOOPCOUNT; ++j) {
+      logic_and = (logic_and && logics[j]);
+    }
+  }
+  if(!logic_and) {
+    result++;
+    fprintf (stderr, "Error in logic AND part 1\n");
+  }
+
+  logic_and = 1;
+  logics[LOOPCOUNT / 2] = 0;
+
+  #pragma omp parallel 
+  {
+    int j;
+    #pragma omp for schedule(dynamic,1) reduction(&&:logic_and)
+    for (j = 0; j < LOOPCOUNT; ++j) {
+      logic_and = logic_and && logics[j];
+    }
+  }
+  if(logic_and) {
+    result++;
+    fprintf (stderr, "Error in logic AND part 2\n");
+  }
+
+  /**** Testing logic or ****/
+  for (i = 0; i < LOOPCOUNT; i++) {
+    logics[i] = 0;
+  }
+
+  #pragma omp parallel 
+  {
+    int j;
+    #pragma omp for schedule(dynamic,1) reduction(||:logic_or)  
+    for (j = 0; j < LOOPCOUNT; ++j) {
+      logic_or = logic_or || logics[j];
+    }
+  }
+  if (logic_or) {
+    result++;
+    fprintf (stderr, "Error in logic OR part 1\n");
+  }
+
+  logic_or = 0;
+  logics[LOOPCOUNT / 2] = 1;
+
+  #pragma omp parallel 
+  {
+    int j;
+    #pragma omp for schedule(dynamic,1) reduction(||:logic_or)
+    for (j = 0; j < LOOPCOUNT; ++j) {
+      logic_or = logic_or || logics[j];
+    }
+  }
+  if(!logic_or) {
+    result++;
+    fprintf (stderr, "Error in logic OR part 2\n");
+  }
+
+  /************************************************************************/
+  /** Tests for bit values                         **/
+  /************************************************************************/
+
+  /**** Testing bit and ****/
+  for (i = 0; i < LOOPCOUNT; ++i) {
+    logics[i] = 1;
+  }
+
+  #pragma omp parallel 
+  {
+    int j;
+    #pragma omp for schedule(dynamic,1) reduction(&:bit_and)  
+    for (j = 0; j < LOOPCOUNT; ++j) {
+      bit_and = (bit_and & logics[j]);
+    }
+  }
+  if (!bit_and) {
+    result++;
+    fprintf (stderr, "Error in BIT AND part 1\n");
+  }
+
+  bit_and = 1;
+  logics[LOOPCOUNT / 2] = 0;
+
+  #pragma omp parallel 
+  {
+    int j;
+    #pragma omp for schedule(dynamic,1) reduction(&:bit_and)
+    for (j = 0; j < LOOPCOUNT; ++j) {
+      bit_and = bit_and & logics[j];
+    }
+  }
+  if (bit_and) {
+    result++;
+    fprintf (stderr, "Error in BIT AND part 2\n");
+  }
+
+  /**** Testing bit or ****/
+  for (i = 0; i < LOOPCOUNT; i++) {
+    logics[i] = 0;
+  }
+
+  #pragma omp parallel 
+  {
+    int j;
+    #pragma omp for schedule(dynamic,1) reduction(|:bit_or)
+    for (j = 0; j < LOOPCOUNT; ++j) {
+      bit_or = bit_or | logics[j];
+    }
+  }
+  if (bit_or) {
+    result++;
+    fprintf (stderr, "Error in BIT OR part 1\n");
+  }
+
+  bit_or = 0;
+  logics[LOOPCOUNT / 2] = 1;
+
+  #pragma omp parallel 
+  {
+    int j;
+    #pragma omp for schedule(dynamic,1) reduction(|:bit_or)
+    for (j = 0; j < LOOPCOUNT; ++j) {
+      bit_or = bit_or | logics[j];
+    }
+  }
+  if (!bit_or) {
+    result++;
+    fprintf (stderr, "Error in BIT OR part 2\n");
+  }
+
+  /**** Testing exclusive bit or ****/
+  for (i = 0; i < LOOPCOUNT; i++) {
+    logics[i] = 0;
+  }
+
+  #pragma omp parallel 
+  {
+    int j;
+    #pragma omp for schedule(dynamic,1) reduction(^:exclusiv_bit_or)
+    for (j = 0; j < LOOPCOUNT; ++j) {
+      exclusiv_bit_or = exclusiv_bit_or ^ logics[j];
+    }
+  }
+  if (exclusiv_bit_or) {
+    result++;
+    fprintf (stderr, "Error in EXCLUSIV BIT OR part 1\n");
+  }
+
+  exclusiv_bit_or = 0;
+  logics[LOOPCOUNT / 2] = 1;
+
+  #pragma omp parallel 
+  {
+    int j;
+    #pragma omp for schedule(dynamic,1) reduction(^:exclusiv_bit_or)
+    for (j = 0; j < LOOPCOUNT; ++j) {
+      exclusiv_bit_or = exclusiv_bit_or ^ logics[j];
+    }
+  }
+  if (!exclusiv_bit_or) {
+    result++;
+    fprintf (stderr, "Error in EXCLUSIV BIT OR part 2\n");
+  }
+
+  return (result == 0);
+  free (logics);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_for_reduction()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_for_schedule_auto.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_for_schedule_auto.c
@@ -0,0 +1,56 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+int sum1;
+#pragma omp threadprivate(sum1)
+
+int test_omp_for_auto()
+{
+  int sum;
+  int sum0;
+  int known_sum;
+  int threadsnum;
+
+  sum = 0;
+  sum0 = 12345;
+  sum1 = 0;
+
+  #pragma omp parallel
+  {
+    #pragma omp single
+    {
+      threadsnum=omp_get_num_threads();
+    }
+    /* sum0 = 0; */
+  
+    int i;
+    #pragma omp for firstprivate(sum0) schedule(auto)
+    for (i = 1; i <= LOOPCOUNT; i++) {
+      sum0 = sum0 + i;
+      sum1 = sum0;
+    }
+  
+    #pragma omp critical
+    {
+      sum = sum + sum1;
+    }
+  }
+
+  known_sum = 12345 * threadsnum + (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
+  return (known_sum == sum);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_for_auto()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_for_schedule_dynamic.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_for_schedule_dynamic.c
@@ -0,0 +1,91 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+/*
+ * Test for dynamic scheduling with chunk size
+ * Method: caculate how many times the iteration space is dispatched
+ *     and judge if each dispatch has the requested chunk size
+ *     unless it is the last one.
+ * It is possible for two adjacent chunks are assigned to the same thread
+ * Modified by Chunhua Liao
+ */
+#include <stdio.h>
+#include <omp.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+#define CFDMAX_SIZE 100
+const int chunk_size = 7;
+
+int test_omp_for_schedule_dynamic()
+{
+  int tid;
+  int *tids;
+  int i;
+  int tidsArray[CFDMAX_SIZE];
+  int count = 0;
+  int tmp_count = 0; /*dispatch times*/
+  int *tmp;  /*store chunk size for each dispatch*/
+  int result = 0;
+  
+  tids = tidsArray;
+
+  #pragma omp parallel private(tid) shared(tids)
+  {        /* begin of parallel */
+    int tid;
+    tid = omp_get_thread_num ();
+    #pragma omp for schedule(dynamic,chunk_size)
+    for (i = 0; i < CFDMAX_SIZE; i++) {
+      tids[i] = tid;
+    }
+  }
+
+  for (i = 0; i < CFDMAX_SIZE - 1; ++i) {
+    if (tids[i] != tids[i + 1]) {
+      count++;
+    }
+  }
+
+  tmp = (int *) malloc (sizeof (int) * (count + 1));
+  tmp[0] = 1;
+
+  for (i = 0; i < CFDMAX_SIZE - 1; ++i) {
+    if (tmp_count > count) {
+      printf ("--------------------\nTestinternal Error: List too small!!!\n--------------------\n");  /* Error handling */
+      break;
+    }
+    if (tids[i] != tids[i + 1]) {
+      tmp_count++;
+      tmp[tmp_count] = 1;
+    } else {
+      tmp[tmp_count]++;
+    }
+  }
+  /* is dynamic statement working? */
+  for (i = 0; i < count; i++) {
+    if ((tmp[i]%chunk_size)!=0) {
+      /* it is possible for 2 adjacent chunks assigned to a same thread */
+      result++;
+      fprintf(stderr,"The intermediate dispatch has wrong chunksize.\n");
+      /* result += ((tmp[i] / chunk_size) - 1); */
+    }
+  }
+  if ((tmp[count]%chunk_size)!=(CFDMAX_SIZE%chunk_size)) { 
+    result++;
+    fprintf(stderr,"the last dispatch has wrong chunksize.\n");
+  }
+  /* for (int i=0;i<count+1;++i) printf("%d\t:=\t%d\n",i+1,tmp[i]); */
+  return (result==0);
+}
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_for_schedule_dynamic()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_for_schedule_guided.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_for_schedule_guided.c
@@ -0,0 +1,218 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+
+/* Test for guided scheduling
+ * Ensure threads get chunks interleavely first
+ * Then judge the chunk sizes are decreasing to a stable value
+ * Modified by Chunhua Liao
+ * For example, 100 iteration on 2 threads, chunksize 7
+ * one line for each dispatch, 0/1 means thread id
+ * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  24
+ * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1        18
+ * 0 0 0 0 0 0 0 0 0 0 0 0 0 0            14
+ * 1 1 1 1 1 1 1 1 1 1                10
+ * 0 0 0 0 0 0 0 0                   8
+ * 1 1 1 1 1 1 1                   7
+ * 0 0 0 0 0 0 0                   7
+ * 1 1 1 1 1 1 1                   7
+ * 0 0 0 0 0                     5
+*/
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+#define CFSMAX_SIZE 1000
+#define MAX_TIME  0.005
+
+#ifdef SLEEPTIME
+#undef SLEEPTIME
+#define SLEEPTIME 0.0001
+#endif
+
+int test_omp_for_schedule_guided()
+{
+  int * tids;
+  int * chunksizes;
+  int notout;
+  int maxiter;
+  int threads;
+  int i;
+  int result;
+
+  tids = (int *) malloc (sizeof (int) * (CFSMAX_SIZE + 1));
+  maxiter = 0;
+  result = 1;
+  notout = 1;
+
+  /* Testing if enough threads are available for this check. */
+  #pragma omp parallel
+  {
+    #pragma omp single
+    {
+      threads = omp_get_num_threads();
+    }
+  }
+
+  /* ensure there are at least two threads */
+  if (threads < 2) {
+    omp_set_num_threads(2);
+    threads = 2;
+  }
+
+  /* Now the real parallel work:  
+   * Each thread will start immediately with the first chunk.
+   */
+  #pragma omp parallel shared(tids,maxiter)
+  {  /* begin of parallel */
+    double count;
+    int tid;
+    int j;
+
+    tid = omp_get_thread_num ();
+
+    #pragma omp for nowait schedule(guided)
+    for(j = 0; j < CFSMAX_SIZE; ++j) {
+      count = 0.;
+      #pragma omp flush(maxiter)
+      if (j > maxiter) {
+        #pragma omp critical
+        {
+          maxiter = j;
+        }
+      }
+      /*printf ("thread %d sleeping\n", tid);*/
+      #pragma omp flush(maxiter,notout)  
+      while (notout && (count < MAX_TIME) && (maxiter == j)) {
+        #pragma omp flush(maxiter,notout)
+        my_sleep (SLEEPTIME);
+        count += SLEEPTIME;
+#ifdef VERBOSE
+        printf(".");
+#endif
+      }
+#ifdef VERBOSE
+      if (count > 0.) printf(" waited %lf s\n", count);
+#endif
+      /*printf ("thread %d awake\n", tid);*/
+      tids[j] = tid;
+#ifdef VERBOSE
+      printf("%d finished by %d\n",j,tid);
+#endif
+    } /* end of for */
+    notout = 0;
+    #pragma omp flush(maxiter,notout)
+  } /* end of parallel */
+
+  /*******************************************************
+   * evaluation of the values              *
+   *******************************************************/
+  {
+    int determined_chunksize = 1;
+    int last_threadnr = tids[0];
+    int global_chunknr = 0;
+    int openwork = CFSMAX_SIZE;
+    int expected_chunk_size;
+    int* local_chunknr = (int*)malloc(threads * sizeof(int));
+    double c = 1;
+
+    for (i = 0; i < threads; i++)
+      local_chunknr[i] = 0;
+
+    tids[CFSMAX_SIZE] = -1;
+
+    /*
+     * determine the number of global chunks
+     */
+    // fprintf(stderr,"# global_chunknr thread local_chunknr chunksize\n");
+    for(i = 1; i <= CFSMAX_SIZE; ++i) {
+      if (last_threadnr==tids[i]) { 
+        determined_chunksize++; 
+      } else {
+        /* fprintf(stderr, "%d\t%d\t%d\t%d\n", global_chunknr,
+           last_threadnr, local_chunknr[last_threadnr], m); */
+        global_chunknr++;
+        local_chunknr[last_threadnr]++;
+        last_threadnr = tids[i];
+        determined_chunksize = 1;
+      }
+    }
+    /* now allocate the memory for saving the sizes of the global chunks */
+    chunksizes = (int*)malloc(global_chunknr * sizeof(int));
+
+    /*
+    * Evaluate the sizes of the global chunks
+    */
+    global_chunknr = 0;
+    determined_chunksize = 1;
+    last_threadnr = tids[0];    
+    for (i = 1; i <= CFSMAX_SIZE; ++i) {
+      /* If the threadnumber was the same as before increase the
+       * detected chunksize for this chunk otherwise set the detected 
+       * chunksize again to one and save the number of the next 
+       * thread in last_threadnr. 
+       */
+      if (last_threadnr == tids[i]) { 
+        determined_chunksize++; 
+      } else {
+        chunksizes[global_chunknr] = determined_chunksize;
+        global_chunknr++;
+        local_chunknr[last_threadnr]++;
+        last_threadnr = tids[i];
+        determined_chunksize = 1;
+      }
+    }
+
+#ifdef VERBOSE
+    fprintf(stderr, "found\texpected\tconstant\n");
+#endif
+
+    /* identify the constant c for the exponential 
+       decrease of the chunksize */
+    expected_chunk_size = openwork / threads;
+    c = (double) chunksizes[0] / expected_chunk_size;
+    
+    for (i = 0; i < global_chunknr; i++) {
+      /* calculate the new expected chunksize */
+      if (expected_chunk_size > 1) 
+        expected_chunk_size = c * openwork / threads;
+#ifdef VERBOSE
+      fprintf(stderr, "%8d\t%8d\t%lf\n", chunksizes[i],
+        expected_chunk_size, c * chunksizes[i]/expected_chunk_size);
+#endif
+      /* check if chunksize is inside the rounding errors */
+      if (abs (chunksizes[i] - expected_chunk_size) >= 2) {
+        result = 0;
+#ifndef VERBOSE
+        fprintf(stderr, "Chunksize differed from expected "
+          "value: %d instead of %d\n", chunksizes[i],
+          expected_chunk_size);
+        return 0;
+#endif
+      } /* end if */
+
+#ifndef VERBOSE
+      if (expected_chunk_size - chunksizes[i] < 0)
+        fprintf(stderr, "Chunksize did not decrease: %d"
+          " instead of %d\n", chunksizes[i],expected_chunk_size);
+#endif
+
+      /* calculating the remaining amount of work */
+      openwork -= chunksizes[i];
+    }  
+  }
+  return result;
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_for_schedule_guided()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_for_schedule_static.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_for_schedule_static.c
@@ -0,0 +1,155 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+#define CFSMAX_SIZE 1000
+#define MAX_TIME 0.01
+
+#ifdef SLEEPTIME
+#undef SLEEPTIME
+#define SLEEPTIME 0.0005
+#endif
+
+int test_omp_for_schedule_static()
+{
+  int threads;
+  int i,lasttid;
+  int * tids;
+  int notout;
+  int maxiter;
+  int chunk_size;
+  int counter = 0;
+  int tmp_count=1;
+  int lastthreadsstarttid = -1;
+  int result = 1;
+
+  chunk_size = 7;
+  tids = (int *) malloc (sizeof (int) * (CFSMAX_SIZE + 1));
+  notout = 1;
+  maxiter = 0;
+
+  #pragma omp parallel shared(tids,counter)
+  {  /* begin of parallel*/
+    #pragma omp single
+    {
+      threads = omp_get_num_threads ();
+    }  /* end of single */
+  }  /* end of parallel */
+
+  if (threads < 2) {
+    omp_set_num_threads(2);
+    threads = 2;
+  }
+  fprintf (stderr,"Using an internal count of %d\nUsing a specified"
+    " chunksize of %d\n", CFSMAX_SIZE, chunk_size);
+  tids[CFSMAX_SIZE] = -1;  /* setting endflag */
+  #pragma omp parallel shared(tids)
+  { /* begin of parallel */
+    double count;
+    int tid;
+    int j;
+
+    tid = omp_get_thread_num ();
+
+    #pragma omp for nowait schedule(static,chunk_size)
+    for(j = 0; j < CFSMAX_SIZE; ++j) {
+      count = 0.;
+      #pragma omp flush(maxiter)
+      if (j > maxiter) {
+        #pragma omp critical
+        {
+          maxiter = j;
+        }
+      }
+      /*printf ("thread %d sleeping\n", tid);*/
+      while (notout && (count < MAX_TIME) && (maxiter == j)) {
+        #pragma omp flush(maxiter,notout)
+        my_sleep (SLEEPTIME);
+        count += SLEEPTIME;
+        printf(".");
+      }
+#ifdef VERBOSE
+      if (count > 0.) printf(" waited %lf s\n", count);
+#endif
+      /*printf ("thread %d awake\n", tid);*/
+      tids[j] = tid;
+#ifdef VERBOSE
+      printf("%d finished by %d\n",j,tid);
+#endif
+    } /* end of for */
+    notout = 0;
+    #pragma omp flush(maxiter,notout)
+  } /* end of parallel */
+
+  /**** analysing the data in array tids ****/
+
+  lasttid = tids[0];
+  tmp_count = 0; 
+
+  for (i = 0; i < CFSMAX_SIZE + 1; ++i) {
+    /* If the work  was done by the same thread increase tmp_count by one. */
+    if (tids[i] == lasttid) {
+      tmp_count++;
+#ifdef VERBOSE
+      fprintf (stderr, "%d: %d \n", i, tids[i]);
+#endif
+      continue;
+    }
+
+    /* Check if the next thread had has the right thread number. When finding 
+     * threadnumber -1 the end should be reached. 
+     */    
+    if (tids[i] == (lasttid + 1) % threads || tids[i] == -1) {
+      /* checking for the right chunk size */
+      if (tmp_count == chunk_size) {
+        tmp_count = 1;
+        lasttid = tids[i];
+#ifdef VERBOSE
+        fprintf (stderr, "OK\n");
+#endif
+      } else {
+        /* If the chunk size was wrong, check if the end was reached */
+        if (tids[i] == -1) {
+          if (i == CFSMAX_SIZE) {
+            fprintf (stderr, "Last thread had chunk size %d\n",
+              tmp_count);
+            break;
+          } else {
+            fprintf (stderr, "ERROR: Last thread (thread with"
+              " number -1) was found before the end.\n");
+            result = 0;
+          }
+        } else {
+          fprintf (stderr, "ERROR: chunk size was %d. (assigned"
+            " was %d)\n", tmp_count, chunk_size);
+          result = 0;
+        }
+      }
+    } else {
+      fprintf(stderr, "ERROR: Found thread with number %d (should be"
+        " inbetween 0 and %d).", tids[i], threads - 1);
+      result = 0;
+    }
+#ifdef VERBOSE
+    fprintf (stderr, "%d: %d \n", i, tids[i]);
+#endif
+  }
+
+  return result;
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_for_schedule_static()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_for_schedule_static_3.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_for_schedule_static_3.c
@@ -0,0 +1,203 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+#define CFSMAX_SIZE 1000
+#define MAX_TIME 0.01
+
+#ifdef SLEEPTIME
+#undef SLEEPTIME
+#define SLEEPTIME 0.0005
+#endif
+
+#define VERBOSE 0
+
+int test_omp_for_schedule_static_3()
+{
+  int threads;
+  int i,lasttid;
+
+  int * tids;
+  int * tids2;
+  int notout;
+  int maxiter;
+  int chunk_size;
+
+  int counter = 0;
+  int tmp_count=1;
+  int lastthreadsstarttid = -1;
+  int result = 1;
+  chunk_size = 7;
+
+  tids = (int *) malloc (sizeof (int) * (CFSMAX_SIZE + 1));
+  notout = 1;
+  maxiter = 0;
+
+  #pragma omp parallel shared(tids,counter)
+  {  /* begin of parallel*/
+    #pragma omp single
+    {
+      threads = omp_get_num_threads ();
+    }  /* end of single */
+  }  /* end of parallel */
+
+  /* Ensure that at least two threads are created */
+  if (threads < 2) {
+    omp_set_num_threads(2);
+    threads = 2;
+  } 
+  fprintf (stderr,"Using an internal count of %d\nUsing a"
+    " specified chunksize of %d\n", CFSMAX_SIZE, chunk_size);
+  tids[CFSMAX_SIZE] = -1;  /* setting endflag */
+
+  #pragma omp parallel shared(tids)
+  {  /* begin of parallel */
+    double count;
+    int tid;
+    int j;
+
+    tid = omp_get_thread_num ();
+
+    #pragma omp for nowait schedule(static,chunk_size)
+    for(j = 0; j < CFSMAX_SIZE; ++j) {
+      count = 0.;
+      #pragma omp flush(maxiter)
+      if (j > maxiter) {
+        #pragma omp critical
+        {
+          maxiter = j;
+        }
+      }
+      /*printf ("thread %d sleeping\n", tid);*/
+      while (notout && (count < MAX_TIME) && (maxiter == j)) {
+        #pragma omp flush(maxiter,notout)
+        my_sleep (SLEEPTIME);
+        count += SLEEPTIME;
+        printf(".");
+      }
+#ifdef VERBOSE
+      if (count > 0.) printf(" waited %lf s\n", count);
+#endif
+      /*printf ("thread %d awake\n", tid);*/
+      tids[j] = tid;
+#ifdef VERBOSE
+      printf("%d finished by %d\n",j,tid);
+#endif
+    } /* end of omp parallel for */
+
+    notout = 0;
+    #pragma omp flush(maxiter,notout)
+  } /* end of parallel */
+
+  /**** analysing the data in array tids ****/
+
+  lasttid = tids[0];
+  tmp_count = 0; 
+
+  for (i = 0; i < CFSMAX_SIZE + 1; ++i) {
+    /* If the work  was done by the same thread 
+       increase tmp_count by one. */
+    if (tids[i] == lasttid) {
+      tmp_count++;
+#ifdef VERBOSE
+      fprintf (stderr, "%d: %d \n", i, tids[i]);
+#endif
+      continue;
+    }
+
+    /* Check if the next thread had has the right thread number. 
+     * When finding threadnumber -1 the end should be reached. 
+     */    
+    if (tids[i] == (lasttid + 1) % threads || tids[i] == -1) {
+      /* checking for the right chunk size */
+      if (tmp_count == chunk_size) {
+        tmp_count = 1;
+        lasttid = tids[i];
+#ifdef VERBOSE
+        fprintf (stderr, "OK\n");
+#endif
+      } else {
+        /* If the chunk size was wrong, check if the end was reached */
+        if (tids[i] == -1) {
+          if (i == CFSMAX_SIZE) {
+            fprintf (stderr, "Last thread had chunk size %d\n",
+              tmp_count);
+            break;
+          } else {
+            fprintf (stderr, "ERROR: Last thread (thread with"
+              " number -1) was found before the end.\n");
+            result = 0;
+          }
+        } else {
+          fprintf (stderr, "ERROR: chunk size was %d. (assigned"
+            " was %d)\n", tmp_count, chunk_size);
+          result = 0;
+        }
+      }
+    } else {
+      fprintf(stderr, "ERROR: Found thread with number %d (should be"
+        " inbetween 0 and %d).", tids[i], threads - 1);
+      result = 0;
+    }
+#ifdef VERBOSE
+    fprintf (stderr, "%d: %d \n", i, tids[i]);
+#endif
+  }
+
+  /* Now we check if several loop regions in one parallel region have the
+   * same logical assignement of chunks to threads. We use the nowait 
+   * clause to increase the probability to get an error. */
+
+  /* First we allocate some more memmory */
+  free (tids);
+  tids = (int *) malloc (sizeof (int) * LOOPCOUNT);
+  tids2 = (int *) malloc (sizeof (int) * LOOPCOUNT);
+
+  #pragma omp parallel 
+  {
+    {
+      int n;
+      #pragma omp for schedule(static) nowait
+      for (n = 0; n < LOOPCOUNT; n++) {
+        if (LOOPCOUNT == n + 1 )
+          my_sleep(SLEEPTIME);
+
+        tids[n] = omp_get_thread_num();
+      }
+    }
+    {
+      int m;
+      #pragma omp for schedule(static) nowait
+      for (m = 1; m <= LOOPCOUNT; m++) {
+        tids2[m-1] = omp_get_thread_num();
+      }
+    }
+  }
+
+  for (i = 0; i < LOOPCOUNT; i++)
+  if (tids[i] != tids2[i]) {
+    fprintf (stderr, "Chunk no. %d was assigned once to thread %d and"
+      " later to thread %d.\n", i, tids[i],tids2[i]);
+    result = 0;
+  }
+
+  free (tids);
+  free (tids2);
+  return result;
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for (i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_for_schedule_static_3()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_parallel_for_firstprivate.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_parallel_for_firstprivate.c
@@ -0,0 +1,35 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int test_omp_parallel_for_firstprivate()
+{
+  int sum ;
+  int i2;
+  int i;
+  int known_sum;
+
+  sum=0;
+  i2=3;
+
+  #pragma omp parallel for reduction(+:sum) private(i) firstprivate(i2)
+  for (i = 1; i <= LOOPCOUNT; i++) {
+    sum = sum + (i + i2);
+  }
+
+  known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2 + i2 * LOOPCOUNT;
+  return (known_sum == sum);
+} /* end of check_parallel_for_fistprivate */
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_for_firstprivate()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_parallel_for_if.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_parallel_for_if.c
@@ -0,0 +1,42 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+int test_omp_parallel_for_if()
+{
+  int known_sum;
+  int num_threads;
+  int sum, sum2;
+  int i;
+  int control;
+
+  control = 0;
+  num_threads=0;
+  sum = 0;
+  sum2 = 0;
+
+  #pragma omp parallel for private(i) if (control==1)
+  for (i=0; i <= LOOPCOUNT; i++) {
+    num_threads = omp_get_num_threads();
+    sum = sum + i;
+  }
+
+  known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
+  fprintf(stderr, "Number of threads determined by"
+    " omp_get_num_threads: %d\n", num_threads);
+  return (known_sum == sum && num_threads == 1);
+} /* end of check_parallel_for_private */
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_for_if()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_parallel_for_lastprivate.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_parallel_for_lastprivate.c
@@ -0,0 +1,37 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int test_omp_parallel_for_lastprivate()
+{
+  int sum;
+  int i;
+  int i0;
+  int known_sum;
+
+  sum =0;
+  i0 = -1;
+
+  #pragma omp parallel for reduction(+:sum) \
+    schedule(static,7) private(i) lastprivate(i0)
+  for (i = 1; i <= LOOPCOUNT; i++) {
+    sum = sum + i;
+    i0 = i;
+  } /* end of parallel for */
+
+  known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
+  return ((known_sum == sum) && (i0 == LOOPCOUNT));
+} /* end of check_parallel_for_lastprivate */
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_for_lastprivate()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_parallel_for_ordered.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_parallel_for_ordered.c
@@ -0,0 +1,64 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+static int last_i = 0;
+
+int i;
+#pragma omp threadprivate(i)
+
+/* Variable ii is used to avoid problems with a threadprivate variable used as a loop
+ * index. See test omp_threadprivate_for.
+ */
+static int ii;
+#pragma omp threadprivate(ii)
+
+/*! 
+  Utility function: returns true if the passed argument is larger than 
+  the argument of the last call of this function.
+ */
+static int check_i_islarger2(int i)
+{
+  int islarger;
+  islarger = (i > last_i);
+  last_i = i;
+  return (islarger);
+}
+
+int test_omp_parallel_for_ordered()
+{
+  int sum;
+  int is_larger;
+  int known_sum;
+  int i;
+
+  sum = 0;
+  is_larger = 1;
+  last_i = 0;
+  #pragma omp parallel for schedule(static,1) private(i) ordered
+  for (i = 1; i < 100; i++) {
+    ii = i;
+    #pragma omp ordered
+    {
+      is_larger = check_i_islarger2 (ii) && is_larger;
+      sum  = sum + ii;
+    }
+  }
+  known_sum = (99 * 100) / 2;
+  fprintf (stderr," known_sum = %d , sum = %d \n", known_sum, sum);
+  fprintf (stderr," is_larger = %d\n", is_larger);
+  return (known_sum == sum) && is_larger;
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_for_ordered()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_parallel_for_private.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_parallel_for_private.c
@@ -0,0 +1,50 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t -lm && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+/*! Utility function to spend some time in a loop */
+static void do_some_work (void)
+{
+  int i;
+  double sum = 0;
+  for(i = 0; i < 1000; i++){
+    sum += sqrt (i);
+  }
+}
+
+int test_omp_parallel_for_private()
+{
+  int sum;
+  int i;
+  int i2;
+  int known_sum;
+
+  sum =0;
+  i2=0;
+
+  #pragma omp parallel for reduction(+:sum) schedule(static,1) private(i) private(i2)
+  for (i=1;i<=LOOPCOUNT;i++)
+  {
+    i2 = i;
+    #pragma omp flush
+    do_some_work ();
+    #pragma omp flush
+    sum = sum + i2;
+  } /*end of for*/
+  known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
+  return (known_sum == sum);
+} /* end of check_parallel_for_private */
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_for_private()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/for/omp_parallel_for_reduction.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/for/omp_parallel_for_reduction.c
@@ -0,0 +1,266 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t -lm && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+#define DOUBLE_DIGITS 20    /* dt^DOUBLE_DIGITS */
+#define MAX_FACTOR 10
+#define KNOWN_PRODUCT 3628800  /* 10! */
+
+int test_omp_parallel_for_reduction()
+{
+  int sum;
+  int known_sum;
+  double dsum;
+  double dknown_sum;
+  double dt=0.5;  /* base of geometric row for + and - test*/
+  double rounding_error= 1.E-9;
+  int diff;
+  double ddiff;
+  int product;
+  int known_product;
+  int logic_and;
+  int logic_or;
+  int bit_and;
+  int bit_or;
+  int exclusiv_bit_or;
+  int logics[LOOPCOUNT];
+  int i;
+  double dpt;
+  int result;
+
+  sum =0;
+  dsum=0;
+  dt = 1./3.;
+  result = 0;
+  product = 1;
+  logic_and=1;
+  logic_or=0;
+  bit_and=1;
+  bit_or=0;
+  exclusiv_bit_or=0;
+
+  /* Tests for integers */
+  known_sum = (LOOPCOUNT*(LOOPCOUNT+1))/2;
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(+:sum)
+  for (i=1;i<=LOOPCOUNT;i++) {
+    sum=sum+i;
+  }
+  if(known_sum!=sum) {
+    result++;
+    fprintf(stderr,"Error in sum with integers: Result was %d"
+      " instead of %d\n",sum,known_sum); 
+  }
+
+  diff = (LOOPCOUNT*(LOOPCOUNT+1))/2;
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(-:diff)
+  for (i=1;i<=LOOPCOUNT;++i) {
+    diff=diff-i;
+  }
+  if(diff != 0) {
+    result++;
+    fprintf(stderr,"Error in difference with integers: Result was %d"
+      " instead of 0.\n",diff);
+  }
+
+  /* Tests for doubles */
+  dsum=0;
+  dpt=1;
+  for (i=0;i<DOUBLE_DIGITS;++i) {
+    dpt*=dt;
+  }
+  dknown_sum = (1-dpt)/(1-dt);
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(+:dsum)
+  for (i=0;i<DOUBLE_DIGITS;++i) {
+    dsum += pow(dt,i);
+  }
+  if( fabs(dsum-dknown_sum) > rounding_error ) {
+    result++; 
+    fprintf(stderr,"Error in sum with doubles: Result was %f"
+      " instead of %f (Difference: %E)\n",
+      dsum, dknown_sum, dsum-dknown_sum);
+  }
+
+  dpt=1;
+
+  for (i=0;i<DOUBLE_DIGITS;++i) {
+    dpt*=dt;
+  }
+  fprintf(stderr,"\n");
+  ddiff = (1-dpt)/(1-dt);
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(-:ddiff)
+  for (i=0;i<DOUBLE_DIGITS;++i) {
+    ddiff -= pow(dt,i);
+  }
+  if( fabs(ddiff) > rounding_error) {
+    result++;
+    fprintf(stderr,"Error in Difference with doubles: Result was %E"
+      " instead of 0.0\n",ddiff);
+  }
+
+  /* Tests for integers */
+  #pragma omp parallel for schedule(dynamic,1) private(i) reduction(*:product)
+  for(i=1;i<=MAX_FACTOR;i++) {
+    product *= i;
+  }
+  known_product = KNOWN_PRODUCT;
+  if(known_product != product) {
+    result++;
+    fprintf(stderr,"Error in Product with integers: Result was %d"
+      " instead of %d\n\n",product,known_product);
+  }
+
+  /* Tests for logic AND */
+  for(i=0;i<LOOPCOUNT;i++) {
+    logics[i]=1;
+  }
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) \
+    reduction(&&:logic_and)
+  for(i=0;i<LOOPCOUNT;++i) {
+    logic_and = (logic_and && logics[i]);
+  }
+  if(!logic_and) {
+    result++;
+    fprintf(stderr,"Error in logic AND part 1.\n");
+  }
+
+  logic_and = 1;
+  logics[LOOPCOUNT/2]=0;
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) \
+    reduction(&&:logic_and)
+  for(i=0;i<LOOPCOUNT;++i) {
+    logic_and = logic_and && logics[i];
+  }
+  if(logic_and) {
+    result++;
+    fprintf(stderr,"Error in logic AND part 2.\n");
+  }
+
+  /* Tests for logic OR */
+  for(i=0;i<LOOPCOUNT;i++) {
+    logics[i]=0;
+  }
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) \
+    reduction(||:logic_or)
+  for(i=0;i<LOOPCOUNT;++i) {
+    logic_or = logic_or || logics[i];
+  }
+  if(logic_or) {
+    result++;
+    fprintf(stderr,"Error in logic OR part 1.\n");
+  }
+  logic_or = 0;
+  logics[LOOPCOUNT/2]=1;
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) \
+    reduction(||:logic_or)
+  for(i=0;i<LOOPCOUNT;++i) {
+    logic_or = logic_or || logics[i];
+  }
+  if(!logic_or) {
+    result++;
+    fprintf(stderr,"Error in logic OR part 2.\n");
+  }
+
+  /* Tests for bitwise AND */
+  for(i=0;i<LOOPCOUNT;++i) {
+    logics[i]=1;
+  }
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) \
+    reduction(&:bit_and)
+  for(i=0;i<LOOPCOUNT;++i) {
+    bit_and = (bit_and & logics[i]);
+  }
+  if(!bit_and) {
+    result++;
+    fprintf(stderr,"Error in BIT AND part 1.\n");
+  }
+
+  bit_and = 1;
+  logics[LOOPCOUNT/2]=0;
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) \
+    reduction(&:bit_and)
+  for(i=0;i<LOOPCOUNT;++i) {
+    bit_and = bit_and & logics[i];
+  }
+  if(bit_and) {
+    result++;
+    fprintf(stderr,"Error in BIT AND part 2.\n");
+  }
+
+  /* Tests for bitwise OR */
+  for(i=0;i<LOOPCOUNT;i++) {
+    logics[i]=0;
+  }
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) \
+    reduction(|:bit_or)
+  for(i=0;i<LOOPCOUNT;++i) {
+    bit_or = bit_or | logics[i];
+  }
+  if(bit_or) {
+    result++;
+    fprintf(stderr,"Error in BIT OR part 1\n");
+  }
+  bit_or = 0;
+  logics[LOOPCOUNT/2]=1;
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) \
+    reduction(|:bit_or)
+  for(i=0;i<LOOPCOUNT;++i) {
+    bit_or = bit_or | logics[i];
+  }
+  if(!bit_or) {
+    result++;
+    fprintf(stderr,"Error in BIT OR part 2\n");
+  }
+
+  /* Tests for bitwise XOR */
+  for(i=0;i<LOOPCOUNT;i++) {
+    logics[i]=0;
+  }
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) \
+    reduction(^:exclusiv_bit_or)
+  for(i=0;i<LOOPCOUNT;++i) {
+    exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+  }
+  if(exclusiv_bit_or) {
+    result++;
+    fprintf(stderr,"Error in EXCLUSIV BIT OR part 1\n");
+  }
+
+  exclusiv_bit_or = 0;
+  logics[LOOPCOUNT/2]=1;
+
+  #pragma omp parallel for schedule(dynamic,1) private(i) \
+    reduction(^:exclusiv_bit_or)
+  for(i=0;i<LOOPCOUNT;++i) {
+    exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+  }
+  if(!exclusiv_bit_or) {
+    result++;
+    fprintf(stderr,"Error in EXCLUSIV BIT OR part 2\n");
+  }
+
+  /*printf("\nResult:%d\n",result);*/
+  return (result==0);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_for_reduction()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/sections/omp_parallel_sections_firstprivate.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/sections/omp_parallel_sections_firstprivate.c
@@ -0,0 +1,54 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int test_omp_parallel_sections_firstprivate()
+{
+  int sum;
+  int sum0;
+  int known_sum;
+
+  sum =7;
+  sum0=11;
+
+  #pragma omp parallel sections firstprivate(sum0)
+  {
+    #pragma omp section 
+    {
+      #pragma omp critical
+      {
+        sum= sum+sum0;
+      }
+    }  
+    #pragma omp section
+    {
+      #pragma omp critical
+      {
+        sum= sum+sum0;
+      }
+    }
+    #pragma omp section
+    {
+      #pragma omp critical
+      {
+        sum= sum+sum0;
+      }
+    }         
+  }
+
+  known_sum=11*3+7;
+  return (known_sum==sum); 
+} /* end of check_section_firstprivate*/
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_sections_firstprivate()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/sections/omp_parallel_sections_lastprivate.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/sections/omp_parallel_sections_lastprivate.c
@@ -0,0 +1,71 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int test_omp_parallel_sections_lastprivate()
+{
+  int sum;
+  int sum0;
+  int i;
+  int i0;
+  int known_sum;
+  sum =0;
+  sum0 = 0;
+  i0 = -1;
+
+  #pragma omp parallel sections private(i,sum0) lastprivate(i0)
+  {
+    #pragma omp section  
+    {
+      sum0=0;
+      for (i=1;i<400;i++) {
+        sum0=sum0+i;
+        i0=i;
+      }
+      #pragma omp critical
+      {
+        sum= sum+sum0;
+      }
+    }
+    #pragma omp section 
+    {
+      sum0=0;
+      for(i=400;i<700;i++) {
+        sum0=sum0+i;
+        i0=i;
+      }
+      #pragma omp critical
+      {
+        sum= sum+sum0;
+      }
+    }
+    #pragma omp section 
+    {
+      sum0=0;
+      for(i=700;i<1000;i++) {
+        sum0=sum0+i;
+        i0=i;
+      }
+      #pragma omp critical
+      {
+        sum= sum+sum0;
+      }
+    }
+  }
+
+  known_sum=(999*1000)/2;
+  return ((known_sum==sum) && (i0==999) );
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_sections_lastprivate()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/sections/omp_parallel_sections_private.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/sections/omp_parallel_sections_private.c
@@ -0,0 +1,64 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int test_omp_parallel_sections_private()
+{
+  int sum;
+  int sum0;
+  int i;
+  int known_sum;
+
+  sum = 7;
+  sum0=0;
+
+  #pragma omp parallel sections private(sum0, i)
+  {
+    #pragma omp section 
+    {
+      sum0=0;
+      for (i=1;i<400;i++)
+        sum0=sum0+i;
+      #pragma omp critical
+      {
+        sum= sum+sum0;
+      }
+    }
+    #pragma omp section
+    {
+      sum0=0;
+      for(i=400;i<700;i++)
+        sum0=sum0+i;
+      #pragma omp critical
+      {
+        sum= sum+sum0;
+      }
+    }
+    #pragma omp section
+    {
+      sum0=0;
+      for(i=700;i<1000;i++)
+        sum0=sum0+i;
+      #pragma omp critical
+      {
+        sum= sum+sum0;
+      }
+    }
+  }
+
+  known_sum=(999*1000)/2+7;
+  return (known_sum==sum); 
+} /* end of check_section_private*/
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_sections_private()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/sections/omp_parallel_sections_reduction.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/sections/omp_parallel_sections_reduction.c
@@ -0,0 +1,508 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t -lm && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+int test_omp_parallel_sections_reduction()
+{
+  int sum;
+  int known_sum;  
+  double dpt;
+  double dsum;
+  double dknown_sum;
+  double dt=0.5; /* base of geometric row for + and - test*/
+  double rounding_error= 1.E-5;
+  int diff;
+  double ddiff;
+  int product;
+  int known_product;
+  int logic_and;
+  int bit_and;
+  int logic_or;
+  int bit_or;
+  int exclusiv_bit_or;
+  int logics[1000];
+  int i;
+  int result;
+
+  sum = 7;
+  dsum=0;
+  product =1;
+  dpt = 1;
+  logic_and=1;
+  bit_and=1;
+  logic_or=0;
+  bit_or=0;
+  exclusiv_bit_or=0;
+  result =0;
+  /*  int my_islarger;*/
+  /*int is_larger=1;*/
+
+  // Test summation of integers
+  known_sum = (999*1000)/2+7;
+  #pragma omp parallel sections private(i) reduction(+:sum)
+  {
+    #pragma omp section
+    {
+      for (i=1;i<300;i++) {
+        sum=sum+i;
+      }
+    }
+    #pragma omp section
+    {
+      for (i=300;i<700;i++) {
+        sum=sum+i;
+      }
+    }
+    #pragma omp section
+    {
+      for (i=700;i<1000;i++) {
+        sum=sum+i;
+      }
+    }
+  }
+  if(known_sum!=sum) {
+    result++;
+    fprintf(stderr,"Error in sum with integers: Result was %d"
+      " instead of %d.\n",sum, known_sum);
+  }
+
+  // Test differences of integers
+  diff = (999*1000)/2;
+  #pragma omp parallel sections private(i) reduction(-:diff)
+  {
+    #pragma omp section
+    {
+      for (i=1;i<300;i++) {
+        diff=diff-i;
+      }
+    }
+    #pragma omp section
+    {
+      for (i=300;i<700;i++) {
+        diff=diff-i;
+      }
+    }
+    #pragma omp section
+    {
+      for (i=700;i<1000;i++) {
+        diff=diff-i;
+      }
+    }
+  }
+  if(diff != 0) {
+    result++;
+    fprintf(stderr,"Error in Difference with integers: Result was %d"
+      " instead of 0.\n",diff);
+  }
+
+  // Test summation of doubles
+  for (i=0;i<20;++i) {
+    dpt*=dt;
+  }
+  dknown_sum = (1-dpt)/(1-dt);
+  #pragma omp parallel sections private(i) reduction(+:dsum)
+  {
+    #pragma omp section
+    {
+      for (i=0;i<6;++i) {
+        dsum += pow(dt,i);
+      }
+    }
+    #pragma omp section
+    {
+      for (i=6;i<12;++i) {
+        dsum += pow(dt,i);
+      }
+    }
+    #pragma omp section
+    {
+      for (i=12;i<20;++i) {
+        dsum += pow(dt,i);
+      }
+    }
+  }
+  if( fabs(dsum-dknown_sum) > rounding_error ) {
+    result++; 
+    fprintf(stderr,"Error in sum with doubles: Result was %f"
+      " instead of %f (Difference: %E)\n",
+      dsum, dknown_sum, dsum-dknown_sum);
+  }
+
+  // Test differences of doubles
+  dpt=1;
+  for (i=0;i<20;++i) {
+    dpt*=dt;
+  }
+  fprintf(stderr,"\n");
+  ddiff = (1-dpt)/(1-dt);
+  #pragma omp parallel sections private(i) reduction(-:ddiff)
+  {
+    #pragma omp section
+    {
+      for (i=0;i<6;++i) {
+        ddiff -= pow(dt,i);
+      }
+    }
+    #pragma omp section
+    {
+      for (i=6;i<12;++i) {
+        ddiff -= pow(dt,i);
+      }
+    }
+    #pragma omp section
+    {
+      for (i=12;i<20;++i) {
+        ddiff -= pow(dt,i);
+      }
+    }
+  }
+  if( fabs(ddiff) > rounding_error) {
+    result++;
+    fprintf(stderr,"Error in Difference with doubles: Result was %E"
+      " instead of 0.0\n",ddiff);
+  }
+
+  // Test product of integers
+  known_product = 3628800;
+  #pragma omp parallel sections private(i) reduction(*:product)
+  {
+    #pragma omp section
+    {  
+      for(i=1;i<3;i++) {
+        product *= i;
+      }
+    }
+    #pragma omp section
+    {
+      for(i=3;i<7;i++) {
+        product *= i;
+      }
+    }
+    #pragma omp section
+    {
+      for(i=7;i<11;i++) {
+        product *= i;
+      }
+    }
+  }
+  if(known_product != product) {
+    result++;
+    fprintf(stderr,"Error in Product with integers: Result was %d"
+      " instead of %d\n",product,known_product);
+  }
+
+  // Test logical AND
+  for(i=0;i<1000;i++) {
+    logics[i]=1;
+  }
+
+  #pragma omp parallel sections private(i) reduction(&&:logic_and)
+  {
+    #pragma omp section
+    {
+      for (i=1;i<300;i++) {
+        logic_and = (logic_and && logics[i]);
+      }
+    }
+    #pragma omp section
+    {
+      for (i=300;i<700;i++) {
+        logic_and = (logic_and && logics[i]);
+      }
+    }
+    #pragma omp section
+    {
+      for (i=700;i<1000;i++) {
+        logic_and = (logic_and && logics[i]);
+      }
+    }
+  }
+  if(!logic_and) {
+    result++;
+    fprintf(stderr,"Error in logic AND part 1\n");
+  }
+  logic_and = 1;
+  logics[501] = 0;
+
+  #pragma omp parallel sections private(i) reduction(&&:logic_and)
+  {
+    #pragma omp section
+    {
+      for (i=1;i<300;i++) {
+        logic_and = (logic_and && logics[i]);
+      }
+    }
+    #pragma omp section
+    {
+      for (i=300;i<700;i++) {
+        logic_and = (logic_and && logics[i]);
+      }
+    }
+    #pragma omp section
+    {
+      for (i=700;i<1000;i++) {
+        logic_and = (logic_and && logics[i]);
+      }
+    }
+  }
+  if(logic_and) {
+    result++;
+    fprintf(stderr,"Error in logic AND part 2");
+  }
+
+  // Test logical OR
+  for(i=0;i<1000;i++) {
+    logics[i]=0;
+  }
+
+  #pragma omp parallel sections private(i) reduction(||:logic_or)
+  {
+    #pragma omp section
+    {
+      for (i=1;i<300;i++) {
+        logic_or = (logic_or || logics[i]);
+      }
+    }
+    #pragma omp section
+    {
+      for (i=300;i<700;i++) {
+        logic_or = (logic_or || logics[i]);
+      }
+    }
+    #pragma omp section
+    {
+      for (i=700;i<1000;i++) {
+        logic_or = (logic_or || logics[i]);
+      }
+    }
+  }
+  if(logic_or) {
+    result++;
+    fprintf(stderr,"Error in logic OR part 1\n");
+  }
+
+  logic_or = 0;
+  logics[501]=1;
+
+  #pragma omp parallel sections private(i) reduction(||:logic_or)
+  {
+    #pragma omp section
+    {
+      for (i=1;i<300;i++) {
+        logic_or = (logic_or || logics[i]);
+      }
+    }
+    #pragma omp section
+    {
+      for (i=300;i<700;i++) {
+        logic_or = (logic_or || logics[i]);
+      }
+    }
+    #pragma omp section
+    {
+      for (i=700;i<1000;i++) {
+        logic_or = (logic_or || logics[i]);
+      }
+    }
+  }
+  if(!logic_or) {
+    result++;
+    fprintf(stderr,"Error in logic OR part 2\n");
+  }
+
+  // Test bitwise AND
+  for(i=0;i<1000;++i) {
+    logics[i]=1;
+  }
+
+  #pragma omp parallel sections private(i) reduction(&:bit_and)
+  {
+    #pragma omp section
+    {  
+      for(i=0;i<300;++i) {
+        bit_and = (bit_and & logics[i]);
+      }
+    }
+    #pragma omp section
+    {  
+      for(i=300;i<700;++i) {
+        bit_and = (bit_and & logics[i]);
+      }
+    }
+    #pragma omp section
+    {  
+      for(i=700;i<1000;++i) {
+        bit_and = (bit_and & logics[i]);
+      }
+    }
+  }
+  if(!bit_and) {
+    result++;
+    fprintf(stderr,"Error in BIT AND part 1\n");
+  }
+
+  bit_and = 1;
+  logics[501]=0;
+
+  #pragma omp parallel sections private(i) reduction(&:bit_and)
+  {
+    #pragma omp section
+    {
+      for(i=0;i<300;++i) {
+        bit_and = bit_and & logics[i];
+      }
+    }
+    #pragma omp section
+    {
+      for(i=300;i<700;++i) {
+        bit_and = bit_and & logics[i];
+      }
+    }
+    #pragma omp section
+    {
+      for(i=700;i<1000;++i) {
+        bit_and = bit_and & logics[i];
+      }
+    }
+  }
+  if(bit_and) {
+    result++;
+    fprintf(stderr,"Error in BIT AND part 2");
+  }
+
+  // Test bitwise OR
+  for(i=0;i<1000;i++) {
+    logics[i]=0;
+  }
+
+  #pragma omp parallel sections private(i) reduction(|:bit_or)
+  {
+    #pragma omp section
+    {
+      for(i=0;i<300;++i) {
+        bit_or = bit_or | logics[i];
+      }
+    }
+    #pragma omp section
+    {
+      for(i=300;i<700;++i) {
+        bit_or = bit_or | logics[i];
+      }
+    }
+    #pragma omp section
+    {
+      for(i=700;i<1000;++i) {
+        bit_or = bit_or | logics[i];
+      }
+    }
+  }
+  if(bit_or) {
+    result++;
+    fprintf(stderr,"Error in BIT OR part 1\n");
+  }
+  bit_or = 0;
+  logics[501]=1;
+
+  #pragma omp parallel sections private(i) reduction(|:bit_or)
+  {
+    #pragma omp section
+    {
+      for(i=0;i<300;++i) {
+        bit_or = bit_or | logics[i];
+      }
+    }
+    #pragma omp section
+    {
+      for(i=300;i<700;++i) {
+        bit_or = bit_or | logics[i];
+      }
+    }
+    #pragma omp section
+    {
+      for(i=700;i<1000;++i) {
+        bit_or = bit_or | logics[i];
+      }
+    }
+  }
+  if(!bit_or) {
+    result++;
+    fprintf(stderr,"Error in BIT OR part 2\n");
+  }
+
+  // Test bitwise XOR
+  for(i=0;i<1000;i++) {
+    logics[i]=0;
+  }
+
+  #pragma omp parallel sections private(i) reduction(^:exclusiv_bit_or)
+  {
+    #pragma omp section
+    {  
+      for(i=0;i<300;++i) {
+        exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+      }
+    }
+    #pragma omp section
+    {  
+      for(i=300;i<700;++i) {
+        exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+      }
+    }
+    #pragma omp section
+    {  
+      for(i=700;i<1000;++i) {
+        exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+      }
+    }
+  }
+  if(exclusiv_bit_or) {
+    result++;
+    fprintf(stderr,"Error in EXCLUSIV BIT OR part 1\n");
+  }
+
+  exclusiv_bit_or = 0;
+  logics[501]=1;
+
+  #pragma omp parallel sections private(i) reduction(^:exclusiv_bit_or)
+  {
+    #pragma omp section
+    {
+      for(i=0;i<300;++i) {
+        exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+      }
+    }
+    #pragma omp section
+    {
+      for(i=300;i<700;++i) {
+        exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+      }
+    }
+    #pragma omp section
+    {
+      for(i=700;i<1000;++i) {
+        exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+      }
+    }
+  }
+  if(!exclusiv_bit_or) {
+    result++;
+    fprintf(stderr,"Error in EXCLUSIV BIT OR part 2\n");
+  }
+
+  /*printf("\nResult:%d\n",result);*/
+  return (result==0);
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_parallel_sections_reduction()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/sections/omp_section_firstprivate.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/sections/omp_section_firstprivate.c
@@ -0,0 +1,55 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int test_omp_section_firstprivate()
+{
+  int sum;
+  int sum0;
+  int known_sum;
+
+  sum0 = 11;
+  sum = 7;
+  #pragma omp parallel
+  {
+    #pragma omp  sections firstprivate(sum0)
+    {
+      #pragma omp section 
+      {
+        #pragma omp critical
+        {
+          sum = sum + sum0;
+        }
+      }  
+      #pragma omp section
+      {
+        #pragma omp critical
+        {
+          sum = sum + sum0;
+        }
+      }
+      #pragma omp section
+      {
+        #pragma omp critical
+        {
+          sum = sum + sum0;
+        }
+      }         
+    }
+  }
+  known_sum = 11 * 3 + 7;
+  return (known_sum == sum); 
+} /* end of check_section_firstprivate*/
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_section_firstprivate()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/sections/omp_section_lastprivate.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/sections/omp_section_lastprivate.c
@@ -0,0 +1,76 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int test_omp_section_lastprivate()
+{
+  int i0 = -1;
+  int sum = 0;
+  int i;
+  int sum0 = 0;
+  int known_sum;
+
+  i0 = -1;
+  sum = 0;
+
+  #pragma omp parallel
+  {
+    #pragma omp sections lastprivate(i0) private(i,sum0)
+    {
+      #pragma omp section  
+      {
+        sum0 = 0;
+        for (i = 1; i < 400; i++)
+        {
+          sum0 = sum0 + i;
+          i0 = i;
+        }
+        #pragma omp critical
+        {
+          sum = sum + sum0;
+        } /*end of critical*/
+      } /* end of section */
+      #pragma omp section 
+      {
+        sum0 = 0;
+        for(i = 400; i < 700; i++)
+        {
+          sum0 = sum0 + i;
+          i0 = i;
+        }
+        #pragma omp critical
+        {
+          sum = sum + sum0;
+        } /*end of critical*/
+      }
+      #pragma omp section 
+      {
+        sum0 = 0;
+        for(i = 700; i < 1000; i++)
+        {
+          sum0 = sum0 + i;
+          i0 = i;
+        }
+        #pragma omp critical
+        {
+          sum = sum + sum0;
+        } /*end of critical*/
+      } /* end of section */
+    } /* end of sections*/
+  } /* end of parallel*/  
+  known_sum = (999 * 1000) / 2;
+  return ((known_sum == sum) && (i0 == 999) );
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_section_lastprivate()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/sections/omp_section_private.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/sections/omp_section_private.c
@@ -0,0 +1,66 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int test_omp_section_private()
+{
+  int sum;
+  int sum0;
+  int i;
+  int known_sum;
+
+  sum = 7;
+  sum0 = 0;
+
+  #pragma omp parallel
+  {
+    #pragma omp sections private(sum0,i)
+    {
+      #pragma omp section 
+      {
+        sum0 = 0;
+        for (i = 1; i < 400; i++)
+          sum0 = sum0 + i;
+        #pragma omp critical
+        {
+          sum = sum + sum0;
+        }
+      }  
+      #pragma omp section
+      {
+        sum0 = 0;
+        for (i = 400; i < 700; i++)
+          sum0 = sum0 + i;
+        #pragma omp critical
+        {
+          sum = sum + sum0;
+        }
+      }
+      #pragma omp section
+      {
+        sum0 = 0;
+        for (i = 700; i < 1000; i++)
+          sum0 = sum0 + i;
+        #pragma omp critical
+        {
+          sum = sum + sum0;
+        }
+      }         
+    } /*end of sections*/
+  } /* end of parallel */
+  known_sum = (999 * 1000) / 2 + 7;
+  return (known_sum == sum); 
+} /* end of check_section_private*/
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_section_private()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/sections/omp_sections_nowait.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/sections/omp_sections_nowait.c
@@ -0,0 +1,69 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+#include "omp_my_sleep.h"
+
+int test_omp_sections_nowait()
+{
+  int result;
+  int count;
+  int j;
+
+  result = 0;
+  count = 0;
+
+  #pragma omp parallel 
+  {
+    int rank;
+    rank = omp_get_thread_num ();
+    #pragma omp sections nowait
+    {
+      #pragma omp section
+      {
+        fprintf(stderr, "Thread nr %d enters first section"
+          " and gets sleeping.\n", rank);
+        my_sleep(SLEEPTIME);
+        count = 1;
+        fprintf(stderr, "Thread nr %d woke up an set"
+          " count to 1.\n", rank);
+        #pragma omp flush(count)
+      }
+      #pragma omp section
+      {
+        fprintf(stderr, "Thread nr %d executed work in the"
+          " first section.\n", rank);
+      }
+    }
+    /* Begin of second sections environment */
+    #pragma omp sections
+    {
+      #pragma omp section
+      {
+        fprintf(stderr, "Thread nr %d executed work in the"
+          " second section.\n", rank);
+      }
+      #pragma omp section
+      {
+        fprintf(stderr, "Thread nr %d executed work in the"
+          " second section and controls the value of count\n", rank);
+        if (count == 0)
+          result = 1;
+        fprintf(stderr, "count was %d\n", count);
+      }
+    }
+  }
+  return result;
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_sections_nowait()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/sections/omp_sections_reduction.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/sections/omp_sections_reduction.c
@@ -0,0 +1,543 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t -lm && %t
+#include <stdio.h>
+#include <math.h>
+#include "omp_testsuite.h"
+
+int test_omp_sections_reduction()
+{
+  int sum;
+  int known_sum;
+  double dpt,dsum;
+  double dknown_sum;
+  double dt=0.5; /* base of geometric row for + and - test*/
+  double rounding_error= 1.E-9;
+  int diff;
+  double ddiff;
+  int product;
+  int known_product;
+  int logic_and;
+  int bit_and;
+  int logic_or;
+  int bit_or;
+  int exclusiv_bit_or;
+  int logics[1000];
+  int i;
+  int result;
+  /* int my_islarger; */
+  /*int is_larger=1;*/
+  sum =7;
+  dpt =1;
+  dsum=0;
+  product =1;
+  logic_and=1;
+  bit_and=1;
+  logic_or=0;
+  bit_or=0;
+  exclusiv_bit_or=0;
+  result = 0;
+  dt = 1./3.;
+
+  known_sum = (999*1000)/2+7;
+  #pragma omp parallel
+  {
+    #pragma omp sections private(i) reduction(+:sum)
+    {
+      #pragma omp section
+      {
+        for (i=1;i<300;i++) {
+          sum=sum+i;
+        }
+      }
+      #pragma omp section
+      {
+        for (i=300;i<700;i++) {
+          sum=sum+i;
+        }
+      }
+      #pragma omp section
+      {
+        for (i=700;i<1000;i++) {
+          sum=sum+i;
+        }
+      }
+    }
+  }
+  if(known_sum!=sum) {
+    ++result;
+    fprintf(stderr,"Error in sum with integers: Result was %d"
+      " instead of %d\n", sum,known_sum);
+  }
+
+  diff = (999*1000)/2;
+  #pragma omp parallel
+  {
+    #pragma omp sections private(i) reduction(-:diff)
+    {
+      #pragma omp section
+      {
+        for (i=1;i<300;i++) {
+          diff=diff-i;
+        }
+      }
+      #pragma omp section
+      {
+        for (i=300;i<700;i++) {
+          diff=diff-i;
+        }
+      }
+      #pragma omp section
+      {
+        for (i=700;i<1000;i++) {
+          diff=diff-i;
+        }
+      }
+    }
+  }
+  if(diff != 0) {
+    result++;
+    fprintf(stderr,"Error in Difference with integers: Result was %d"
+      " instead of 0.\n",diff);
+  }
+
+  for (i=0;i<20;++i) {
+    dpt*=dt;
+  }
+  dknown_sum = (1-dpt)/(1-dt);
+  #pragma omp parallel
+  {
+    #pragma omp sections private(i) reduction(+:dsum)
+    {
+      #pragma omp section
+      {
+        for (i=0;i<6;++i) {
+          dsum += pow(dt,i);
+        }
+      }
+      #pragma omp section
+      {
+        for (i=6;i<12;++i) {
+          dsum += pow(dt,i);
+        }
+      }
+      #pragma omp section
+      {
+        for (i=12;i<20;++i) {
+          dsum += pow(dt,i);
+        }
+      }
+    }
+  }
+  if( fabs(dsum-dknown_sum) > rounding_error ) {
+    result++; 
+    fprintf(stderr,"Error in sum with doubles: Result was %f"
+      " instead of %f (Difference: %E)\n",
+      dsum, dknown_sum, dsum-dknown_sum);
+  }
+
+  dpt=1;
+  for (i=0;i<20;++i) {
+    dpt*=dt;
+  }
+  fprintf(stderr,"\n");
+  ddiff = (1-dpt)/(1-dt);
+  #pragma omp parallel
+  {
+    #pragma omp sections private(i) reduction(-:ddiff)
+    {
+      #pragma omp section
+      {
+        for (i=0;i<6;++i) {
+          ddiff -= pow(dt,i);
+        }
+      }
+      #pragma omp section
+      {
+        for (i=6;i<12;++i) {
+          ddiff -= pow(dt,i);
+        }
+      }
+      #pragma omp section
+      {
+        for (i=12;i<20;++i) {
+          ddiff -= pow(dt,i);
+        }
+      }
+    }
+  }
+
+  if(fabs(ddiff) > rounding_error) {
+    result++;
+    fprintf(stderr,"Error in Difference with doubles: Result was %E"
+      " instead of 0.0\n",ddiff);
+  }
+
+  known_product = 3628800;
+  #pragma omp parallel
+  {
+    #pragma omp sections private(i) reduction(*:product)
+    {
+      #pragma omp section
+      {  
+        for(i=1;i<3;i++) {
+          product *= i;
+        }
+      }
+      #pragma omp section
+      {
+        for(i=3;i<7;i++) {
+          product *= i;
+        }
+      }
+      #pragma omp section
+      {
+        for(i=7;i<11;i++) {
+          product *= i;
+        }
+      }
+    }
+  }
+  if(known_product != product) {
+    result++;
+    fprintf(stderr,"Error in Product with integers: Result was %d"
+      " instead of %d\n",product,known_product);
+  }
+
+  for(i=0;i<1000;i++) {
+    logics[i]=1;
+  }
+
+  #pragma omp parallel
+  {
+    #pragma omp sections private(i) reduction(&&:logic_and)
+    {
+      #pragma omp section
+      {
+        for (i=1;i<300;i++) {
+          logic_and = (logic_and && logics[i]);
+        }
+      }
+      #pragma omp section
+      {
+        for (i=300;i<700;i++) {
+          logic_and = (logic_and && logics[i]);
+        }
+      }
+      #pragma omp section
+      {
+        for (i=700;i<1000;i++) {
+          logic_and = (logic_and && logics[i]);
+        }
+      }
+    }
+  }
+  if(!logic_and) {
+    result++;
+    fprintf(stderr,"Error in logic AND part 1\n");
+  }
+
+  logic_and = 1;
+  logics[501] = 0;
+
+  #pragma omp parallel
+  {
+    #pragma omp sections private(i) reduction(&&:logic_and)
+    {
+      #pragma omp section
+      {
+        for (i=1;i<300;i++) {
+          logic_and = (logic_and && logics[i]);
+        }
+      }
+      #pragma omp section
+      {
+        for (i=300;i<700;i++) {
+          logic_and = (logic_and && logics[i]);
+        }
+      }
+      #pragma omp section
+      {
+        for (i=700;i<1000;i++) {
+          logic_and = (logic_and && logics[i]);
+        }
+      }
+    }
+  }
+  if(logic_and) {
+    result++;
+    fprintf(stderr,"Error in logic AND part 2\n");
+  }
+
+  for(i=0;i<1000;i++) {
+    logics[i]=0;
+  }
+
+  #pragma omp parallel 
+  {
+    #pragma omp sections private(i) reduction(||:logic_or)
+    {
+      #pragma omp section
+      {
+        for (i=1;i<300;i++) {
+          logic_or = (logic_or || logics[i]);
+        }
+      }
+      #pragma omp section
+      {
+        for (i=300;i<700;i++) {
+          logic_or = (logic_or || logics[i]);
+        }
+      }
+      #pragma omp section
+      {
+        for (i=700;i<1000;i++) {
+          logic_or = (logic_or || logics[i]);
+        }
+      }
+    }
+  }
+  if(logic_or) {
+    result++;
+    fprintf(stderr,"\nError in logic OR part 1\n");
+  }
+
+  logic_or = 0;
+  logics[501]=1;
+
+  #pragma omp parallel 
+  {
+    #pragma omp sections private(i) reduction(||:logic_or)
+    {
+      #pragma omp section
+      {
+        for (i=1;i<300;i++) {
+          logic_or = (logic_or || logics[i]);
+        }
+      }
+      #pragma omp section
+      {
+        for (i=300;i<700;i++) {
+          logic_or = (logic_or || logics[i]);
+        }
+      }
+      #pragma omp section
+      {
+        for (i=700;i<1000;i++) {
+          logic_or = (logic_or || logics[i]);
+        }
+      }
+    }
+  }
+  if(!logic_or) {
+    result++;
+    fprintf(stderr,"Error in logic OR part 2\n");
+  }
+
+  for(i=0;i<1000;++i) {
+    logics[i]=1;
+  }
+
+  #pragma omp parallel 
+  {
+    #pragma omp sections private(i) reduction(&:bit_and)
+    {
+      #pragma omp section
+      {  
+        for(i=0;i<300;++i) {
+          bit_and = (bit_and & logics[i]);
+        }
+      }
+      #pragma omp section
+      {  
+        for(i=300;i<700;++i) {
+          bit_and = (bit_and & logics[i]);
+        }
+      }
+      #pragma omp section
+      {  
+        for(i=700;i<1000;++i) {
+          bit_and = (bit_and & logics[i]);
+        }
+      }
+    }
+  }
+  if(!bit_and) {
+    result++;
+    fprintf(stderr,"Error in BIT AND part 1\n");
+  }
+
+  bit_and = 1;
+  logics[501]=0;
+
+  #pragma omp parallel 
+  {
+    #pragma omp sections private(i) reduction(&:bit_and)
+    {
+      #pragma omp section
+      {
+        for(i=0;i<300;++i) {
+          bit_and = bit_and & logics[i];
+        }
+      }
+      #pragma omp section
+      {
+        for(i=300;i<700;++i) {
+          bit_and = bit_and & logics[i];
+        }
+      }
+      #pragma omp section
+      {
+        for(i=700;i<1000;++i) {
+          bit_and = bit_and & logics[i];
+        }
+      }
+    }
+  }
+  if(bit_and) {
+    result++;
+    fprintf(stderr,"Error in BIT AND part 2\n");
+  }
+
+  for(i=0;i<1000;i++) {
+    logics[i]=0;
+  }
+
+  #pragma omp parallel 
+  {
+    #pragma omp sections private(i) reduction(|:bit_or)
+    {
+      #pragma omp section
+      {
+        for(i=0;i<300;++i) {
+          bit_or = bit_or | logics[i];
+        }
+      }
+      #pragma omp section
+      {
+        for(i=300;i<700;++i) {
+          bit_or = bit_or | logics[i];
+        }
+      }
+      #pragma omp section
+      {
+        for(i=700;i<1000;++i) {
+          bit_or = bit_or | logics[i];
+        }
+      }
+    }
+  }
+  if(bit_or) {
+    result++;
+    fprintf(stderr,"Error in BIT OR part 1\n");
+  }
+  bit_or = 0;
+  logics[501]=1;
+
+  #pragma omp parallel 
+  {
+    #pragma omp sections private(i) reduction(|:bit_or)
+    {
+      #pragma omp section
+      {
+        for(i=0;i<300;++i) {
+          bit_or = bit_or | logics[i];
+        }
+      }
+      #pragma omp section
+      {
+        for(i=300;i<700;++i) {
+          bit_or = bit_or | logics[i];
+        }
+      }
+      #pragma omp section
+      {
+        for(i=700;i<1000;++i) {
+          bit_or = bit_or | logics[i];
+        }
+      }
+    }
+  }
+  if(!bit_or) {
+    result++;
+    fprintf(stderr,"Error in BIT OR part 2\n");
+  }
+
+  for(i=0;i<1000;i++) {
+    logics[i]=0;
+  }
+
+  #pragma omp parallel 
+  {
+    #pragma omp sections private(i) reduction(^:exclusiv_bit_or)
+    {
+      #pragma omp section
+      {  
+        for(i=0;i<300;++i) {
+          exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+        }
+      }
+      #pragma omp section
+      {  
+        for(i=300;i<700;++i) {
+          exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+        }
+      }
+      #pragma omp section
+      {  
+        for(i=700;i<1000;++i) {
+          exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+        }
+      }
+    }
+  }
+  if(exclusiv_bit_or) {
+    result++;
+    fprintf(stderr,"Error in EXCLUSIV BIT OR part 1\n");
+  }
+
+  exclusiv_bit_or = 0;
+  logics[501]=1;
+
+  #pragma omp parallel 
+  {
+    #pragma omp sections private(i) reduction(^:exclusiv_bit_or)
+    {
+      #pragma omp section
+      {
+        for(i=0;i<300;++i) {
+          exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+        }
+      }
+      #pragma omp section
+      {
+        for(i=300;i<700;++i) {
+          exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+        }
+      }
+      #pragma omp section
+      {
+        for(i=700;i<1000;++i) {
+          exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
+        }
+      }
+    }
+  }
+  if(!exclusiv_bit_or) {
+    result++;
+    fprintf(stderr,"Error in EXCLUSIV BIT OR part 2\n");
+  }
+
+  /*printf("\nResult:%d\n",result);*/
+  return (result==0);
+}
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_sections_reduction()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/single/omp_single.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/single/omp_single.c
@@ -0,0 +1,44 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int test_omp_single()
+{
+  int nr_threads_in_single;
+  int result;
+  int nr_iterations;
+  int i;
+
+  nr_threads_in_single = 0;
+  result = 0;
+  nr_iterations = 0;
+
+  #pragma omp parallel private(i)
+  {
+    for (i = 0; i < LOOPCOUNT; i++) {
+      #pragma omp single 
+      {  
+        #pragma omp flush
+        nr_threads_in_single++;
+        #pragma omp flush             
+        nr_iterations++;
+        nr_threads_in_single--;
+        result = result + nr_threads_in_single;
+      }
+    }
+  }
+  return ((result == 0) && (nr_iterations == LOOPCOUNT));
+} /* end of check_single*/
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_single()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/single/omp_single_copyprivate.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/single/omp_single_copyprivate.c
@@ -0,0 +1,60 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include "omp_testsuite.h"
+
+#define DEBUG_TEST 0
+
+int j;
+#pragma omp threadprivate(j)
+
+int test_omp_single_copyprivate()
+{
+  int result;
+  int nr_iterations;
+
+  result = 0;
+  nr_iterations = 0;
+  #pragma omp parallel
+  {
+    int i;
+    for (i = 0; i < LOOPCOUNT; i++)
+    {
+#if DEBUG_TEST
+         int thread;
+         thread = omp_get_thread_num ();
+#endif
+      #pragma omp single copyprivate(j)
+      {
+        nr_iterations++;
+        j = i;
+#if DEBUG_TEST
+        printf ("thread %d assigns, j = %d, i = %d\n", thread, j, i);
+#endif
+      }
+#if DEBUG_TEST
+      #pragma omp barrier
+#endif
+      #pragma omp critical
+      {
+#if DEBUG_TEST
+        printf ("thread = %d, j = %d, i = %d\n", thread, j, i);
+#endif
+        result = result + j - i;
+      }
+      #pragma omp barrier
+    } /* end of for */
+  } /* end of parallel */
+  return ((result == 0) && (nr_iterations == LOOPCOUNT));
+}
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_single_copyprivate()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/single/omp_single_nowait.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/single/omp_single_nowait.c
@@ -0,0 +1,57 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int my_iterations;
+#pragma omp threadprivate(my_iterations)
+
+int test_omp_single_nowait()
+{
+  int nr_iterations;
+  int total_iterations = 0;
+  int i;
+
+  nr_iterations = 0;
+  my_iterations = 0;
+
+  #pragma omp parallel private(i)
+  {
+    for (i = 0; i < LOOPCOUNT; i++) {
+      #pragma omp single nowait
+      {
+        #pragma omp atomic  
+        nr_iterations++;
+      }
+    }
+  }
+
+  #pragma omp parallel private(i) 
+  {
+    my_iterations = 0;
+    for (i = 0; i < LOOPCOUNT; i++) {
+      #pragma omp single nowait
+      {
+        my_iterations++;
+      }
+    }
+    #pragma omp critical
+    {
+      total_iterations += my_iterations;
+    }
+
+  }
+  return ((nr_iterations == LOOPCOUNT) && (total_iterations == LOOPCOUNT));
+} /* end of check_single_nowait*/
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_single_nowait()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
Index: runtime/test/worksharing/single/omp_single_private.c
===================================================================
--- /dev/null
+++ runtime/test/worksharing/single/omp_single_private.c
@@ -0,0 +1,57 @@
+// RUN: %clang %openmp_flag %cflags %s -o %t && %t
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+int myit = 0;
+#pragma omp threadprivate(myit)
+int myresult = 0;
+#pragma omp threadprivate(myresult)
+
+int test_omp_single_private()
+{
+  int nr_threads_in_single;
+  int result;
+  int nr_iterations;
+  int i;
+
+  myit = 0;
+  nr_threads_in_single = 0;
+  nr_iterations = 0;
+  result = 0;
+
+  #pragma omp parallel private(i)
+  {
+    myresult = 0;
+    myit = 0;
+    for (i = 0; i < LOOPCOUNT; i++) {
+      #pragma omp single private(nr_threads_in_single) nowait
+      {  
+        nr_threads_in_single = 0;
+        #pragma omp flush
+        nr_threads_in_single++;
+        #pragma omp flush             
+        myit++;
+        myresult = myresult + nr_threads_in_single;
+      }
+    }
+    #pragma omp critical
+    {
+      result += nr_threads_in_single;
+      nr_iterations += myit;
+    }
+  }
+  return ((result == 0) && (nr_iterations == LOOPCOUNT));
+} /* end of check_single private */ 
+
+int main()
+{
+  int i;
+  int num_failed=0;
+
+  for(i = 0; i < REPETITIONS; i++) {
+    if(!test_omp_single_private()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}