This change introduces a check-libomp target which is based upon llvm's lit test infrastructure. Each test (generated from the University of Houston's OpenMP testsuite) is compiled and then run. For each test, an exit status of 0 indicates success and non-zero indicates failure. This way, FileCheck is not needed. I've added a bit of logic to generate symlinks (libiomp5 and libgomp) in the build tree so that gcc can be tested as well. When building out-of- tree builds, the user will have to provide llvm-lit either by specifying -DLIBOMP_LLVM_LIT_EXECUTABLE or having llvm-lit in their PATH. Differential Revision: http://reviews.llvm.org/D11821 llvm-svn: 248211
367 lines
6.8 KiB
C
367 lines
6.8 KiB
C
// RUN: %libomp-compile-and-run
|
|
#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_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;
|
|
}
|