diff --git a/SingleSource/UnitTests/Vectorizer/recurrences.cpp b/SingleSource/UnitTests/Vectorizer/recurrences.cpp new file mode 100644 --- /dev/null +++ b/SingleSource/UnitTests/Vectorizer/recurrences.cpp @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include + +// Tests for vectorizing loops with recurrences. + +static std::mt19937 rng; + +// Initialize arrays A with random numbers. +template +static void init_data(const std::unique_ptr &A, unsigned N) { + std::uniform_int_distribution distrib( + std::numeric_limits::min(), std::numeric_limits::max()); + for (unsigned i = 0; i < N; i++) + A[i] = distrib(rng); +} + +template +static void check(const std::unique_ptr &Reference, + const std::unique_ptr &Tmp, unsigned NumElements) { + if (!std::equal(&Reference[0], &Reference[0] + NumElements, &Tmp[0])) { + std::cerr << "Miscompare\n"; + exit(1); + } +} + +#define DEFINE_SCALAR_AND_VECTOR_FN2(Init, Loop) \ + auto ScalarFn = [](auto *A, auto *B, unsigned TC) { \ + Init _Pragma("clang loop vectorize(disable)") Loop \ + }; \ + auto VectorFn = [](auto *A, auto *B, unsigned TC) { \ + Init _Pragma("clang loop vectorize(enable)") Loop \ + }; + +template using Fn2Ty = std::function; +template +static void checkVectorFunction(Fn2Ty ScalarFn, Fn2Ty VectorFn, + const char *Name) { + std::cout << "Checking " << Name << "\n"; + + unsigned N = 1000; + std::unique_ptr Src1(new Ty[N]); + init_data(Src1, N); + std::unique_ptr Src2(new Ty[N]); + for (unsigned I = 0; I < N; ++I) + Src2[I] = Src1[I]; + std::unique_ptr Reference(new Ty[N]); + std::unique_ptr ToCheck(new Ty[N]); + + ScalarFn(&Src1[0], &Reference[0], N); + VectorFn(&Src2[0], &ToCheck[0], N); + check(Reference, ToCheck, N); +} + +int main(void) { + rng = std::mt19937(15); + + { + DEFINE_SCALAR_AND_VECTOR_FN2( + int for1 = 33;, + for (unsigned I = 0; I < TC; I++) { + B[I] = for1 + I; + for1 = I; + }); + checkVectorFunction(ScalarFn, VectorFn, "first_order_recurrence"); + } + + { + DEFINE_SCALAR_AND_VECTOR_FN2( + int for2 = 22; int for1 = 33;, + for (unsigned I = 0; I < TC; I++) { + int t1 = for1; + int t2 = for2; + for2 = for1; + for1 = A[I]; + B[I] = t1 + t2; + }); + + checkVectorFunction(ScalarFn, VectorFn, + "second_order_recurrence"); + } + + { + DEFINE_SCALAR_AND_VECTOR_FN2( + int for1 = 33; int for2 = 22; int for3 = 11;, + for (unsigned I = 0; I < TC; I++) { + int t1 = for1; + int t2 = for2; + int t3 = for3; + for3 = for2; + for2 = for1; + for1 = A[I]; + B[I] = t1 + t2 + t3; + }); + + checkVectorFunction(ScalarFn, VectorFn, "third_order_recurrence"); + } + return 0; +} diff --git a/SingleSource/UnitTests/Vectorizer/recurrences.reference_output b/SingleSource/UnitTests/Vectorizer/recurrences.reference_output new file mode 100644 --- /dev/null +++ b/SingleSource/UnitTests/Vectorizer/recurrences.reference_output @@ -0,0 +1,4 @@ +Checking first_order_recurrence +Checking second_order_recurrence +Checking third_order_recurrence +exit 0