Index: SingleSource/UnitTests/AggressiveFMA/AArch64/CMakeLists.txt =================================================================== --- SingleSource/UnitTests/AggressiveFMA/AArch64/CMakeLists.txt +++ SingleSource/UnitTests/AggressiveFMA/AArch64/CMakeLists.txt @@ -0,0 +1,4 @@ +list(APPEND CFLAGS -O2 -std=c99 -mcpu=thunderx2t99) +list(APPEND CFLAGS -funroll-loops -ffast-math) +list(APPEND CFLAGS -Xclang -menable-unsafe-fp-math) +llvm_singlesource() Index: SingleSource/UnitTests/AggressiveFMA/AArch64/Makefile =================================================================== --- SingleSource/UnitTests/AggressiveFMA/AArch64/Makefile +++ SingleSource/UnitTests/AggressiveFMA/AArch64/Makefile @@ -0,0 +1,10 @@ +# SingleSource/UnitTests/AggressiveFMA/AArch64/Makefile + +DIRS = +LEVEL = ../../../.. + +include $(LEVEL)/SingleSource/Makefile.singlesrc + +CFLAGS += -O2 -std=c99 -mcpu=thunderx2t99 -march=armv8.1-a+lse +CFLAGS += -funroll-loops -ffast-math -Xclang -menable-unsafe-fp-math + Index: SingleSource/UnitTests/AggressiveFMA/AArch64/aarch64_aggressive_fma.c =================================================================== --- SingleSource/UnitTests/AggressiveFMA/AArch64/aarch64_aggressive_fma.c +++ SingleSource/UnitTests/AggressiveFMA/AArch64/aarch64_aggressive_fma.c @@ -0,0 +1,86 @@ +/* This test program demonstrates the effects of enabling aggressive FMA + * on AArch64. With aggressive FMA enabled, CodeGen will fuse instructions + * for SDValues with one or more use. With aggressive FMA disabled, this + * fusion does not happen. + */ + +/* clang -O2 -std=c99 -Wall -mcpu=thunderx2t99 -march=armv8.1-a+lse + * -funroll-loops -ffast-math -Xclang -menable-unsafe-fp-math + * -emit-llvm -S fma.c -o fma.ll + */ + +#include +#include +#include + +static const double AE[] = { -0.00, 0.00, 0.00, 0.00, 0.00, 0.00, + 0.00, 0.00, 0.00, 0.00 }; + +static const double BE[] = { 1102499.00, -2.00, -3.00, -4.00, -5.00, + -6.00, -7.00, -8.00, -9.00, -10.00 }; + +double reset(double x, double y) +{ + double i; + if (modf(x, &i) == 0.0) + return x + y; + + return x - y; +} + +int main(int argc, char* argv[]) +{ + int z; + if (argc >= 2) + z = atoi(argv[1]); + else + z = 10; + + double a = 3.0; + double b = 5.0; + double c = 10.0; + (void) fprintf(stderr, "a=%lf b=%lf c=%lf\n", a, b, c); + + for (int i = 0; i < z; ++i) { + double x = (double) i; + double p1 = 1.0; + double n1 = -1.0; + double y; + + if ((i % 2) == 0) + y = p1; + else + y = n1; + + a *= y + p1 + a; + a *= y + ((c + a) * 2.0) - (a + y + x); + a -= n1 * (y * a); + + (void) fprintf(stderr, "a=%lf b=%lf c=%lf\n", a, b, c); + + if ((i % 2) == 0) + b = p1 - ((n1 + a) * (a - n1)); + else + b = p1 + ((n1 - a) * (a - n1)); + + a *= (p1 - a) * x; + b -= reset(x, b - y + (a + b)); + + (void) fprintf(stderr, "a=%lf b=%lf c=%lf", a, b, c); + if ((a == AE[i]) && (b == BE[i])) + (void) fprintf(stderr, " -----> PASS."); + else { + (void) fprintf(stderr, " -----> FAIL: "); + if (a != AE[i]) + (void) fprintf(stderr, "(a == %lf, expected %lf)", a, AE[i]); + else if (b != BE[i]) + (void) fprintf(stderr, "(b == %lf, expected %lf)", b, BE[i]); + } + + (void) fprintf(stderr, "\n\n"); + } + + return 0; +} + + Index: SingleSource/UnitTests/AggressiveFMA/AArch64/aarch64_aggressive_fma.reference_output =================================================================== --- SingleSource/UnitTests/AggressiveFMA/AArch64/aarch64_aggressive_fma.reference_output +++ SingleSource/UnitTests/AggressiveFMA/AArch64/aarch64_aggressive_fma.reference_output @@ -0,0 +1,32 @@ +a=3.000000 b=5.000000 c=10.000000 +a=1050.000000 b=5.000000 c=10.000000 +a=0.000000 b=1102499.000000 c=10.000000 -----> PASS. + +a=0.000000 b=1102499.000000 c=10.000000 +a=0.000000 b=-2.000000 c=10.000000 -----> PASS. + +a=0.000000 b=-2.000000 c=10.000000 +a=0.000000 b=-3.000000 c=10.000000 -----> PASS. + +a=0.000000 b=-3.000000 c=10.000000 +a=0.000000 b=-4.000000 c=10.000000 -----> PASS. + +a=0.000000 b=-4.000000 c=10.000000 +a=0.000000 b=-5.000000 c=10.000000 -----> PASS. + +a=0.000000 b=-5.000000 c=10.000000 +a=0.000000 b=-6.000000 c=10.000000 -----> PASS. + +a=0.000000 b=-6.000000 c=10.000000 +a=0.000000 b=-7.000000 c=10.000000 -----> PASS. + +a=0.000000 b=-7.000000 c=10.000000 +a=0.000000 b=-8.000000 c=10.000000 -----> PASS. + +a=0.000000 b=-8.000000 c=10.000000 +a=0.000000 b=-9.000000 c=10.000000 -----> PASS. + +a=0.000000 b=-9.000000 c=10.000000 +a=0.000000 b=-10.000000 c=10.000000 -----> PASS. + +exit 0 Index: SingleSource/UnitTests/AggressiveFMA/CMakeLists.txt =================================================================== --- SingleSource/UnitTests/AggressiveFMA/CMakeLists.txt +++ SingleSource/UnitTests/AggressiveFMA/CMakeLists.txt @@ -0,0 +1,5 @@ +if(ARCH STREQUAL "AArch64") + add_subdirectory(AArch64) +endif() + +llvm_singlesource(PREFIX "AggessiveFMA-") Index: SingleSource/UnitTests/CMakeLists.txt =================================================================== --- SingleSource/UnitTests/CMakeLists.txt +++ SingleSource/UnitTests/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(AggressiveFMA) add_subdirectory(C++11) add_subdirectory(SignlessTypes) add_subdirectory(Threads) Index: SingleSource/UnitTests/Makefile =================================================================== --- SingleSource/UnitTests/Makefile +++ SingleSource/UnitTests/Makefile @@ -7,6 +7,7 @@ # FIXME: Disable SJLJ tests for now, until EH edges are represented. DIRS := +DIRS += AggressiveFMA DIRS += Vector DIRS += Vectorizer