Summary: Currently CMake doesn't build builtins for AArch64 and if one does this anyway it's likely that at least `__multc3`, `__floatditf` and `__floatunditf` will be missing. There is actually more builtins to add, but these come from different libc implementations, thus providing them makes compiler-rt for AArch64 good enough at least for basic usage. Builtins implementation were originally taken from FreeBSD project: * [[ https://reviews.freebsd.org/D2173 | __multc3 ]] * [[ https://reviews.freebsd.org/D2174 | __floatditf and __floatunditf ]] Until they have been tested to find mistakes in `__float*` functions. `__floatditf` was based on `__floatsitf`, which had the same mistakes (fixed it in r243746). Version of the builtins in this patch are fixed and complemented with basic tests. Additionally they were tested via GCC's torture (this is what revealed these issues). P.S. Ed (author of FreeBSD patches) asked for feedback on the list some time ago (here [[ http://lists.cs.uiuc.edu/pipermail/llvmdev/2015-March/084064.html | here ]]) and got no response, but it seems to be worth adding these builtins as is and extracting common part later. Reviewers: howard.hinnant, t.p.northover, jmolloy, enefaim, rengolin, zatrazz Subscribers: asl, emaste, samsonov, aemerson, llvm-commits, rengolin Differential Revision: http://reviews.llvm.org/D11679 llvm-svn: 245296
376 lines
7.5 KiB
C
376 lines
7.5 KiB
C
//===-- multc3_test.c - Test __multc3 -------------------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
|
// Source Licenses. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file tests __multc3 for the compiler_rt library.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include <stdio.h>
|
|
|
|
#if _ARCH_PPC || __aarch64__
|
|
|
|
#include "int_lib.h"
|
|
#include <math.h>
|
|
#include <complex.h>
|
|
|
|
// Returns: the product of a + ib and c + id
|
|
|
|
COMPILER_RT_ABI long double _Complex
|
|
__multc3(long double __a, long double __b, long double __c, long double __d);
|
|
|
|
enum {zero, non_zero, inf, NaN, non_zero_nan};
|
|
|
|
int
|
|
classify(long double _Complex x)
|
|
{
|
|
if (x == 0)
|
|
return zero;
|
|
if (isinf(creall(x)) || isinf(cimagl(x)))
|
|
return inf;
|
|
if (isnan(creall(x)) && isnan(cimagl(x)))
|
|
return NaN;
|
|
if (isnan(creall(x)))
|
|
{
|
|
if (cimagl(x) == 0)
|
|
return NaN;
|
|
return non_zero_nan;
|
|
}
|
|
if (isnan(cimagl(x)))
|
|
{
|
|
if (creall(x) == 0)
|
|
return NaN;
|
|
return non_zero_nan;
|
|
}
|
|
return non_zero;
|
|
}
|
|
|
|
int test__multc3(long double a, long double b, long double c, long double d)
|
|
{
|
|
long double _Complex r = __multc3(a, b, c, d);
|
|
// printf("test__multc3(%Lf, %Lf, %Lf, %Lf) = %Lf + I%Lf\n",
|
|
// a, b, c, d, creall(r), cimagl(r));
|
|
long double _Complex dividend;
|
|
long double _Complex divisor;
|
|
|
|
__real__ dividend = a;
|
|
__imag__ dividend = b;
|
|
__real__ divisor = c;
|
|
__imag__ divisor = d;
|
|
|
|
switch (classify(dividend))
|
|
{
|
|
case zero:
|
|
switch (classify(divisor))
|
|
{
|
|
case zero:
|
|
if (classify(r) != zero)
|
|
return 1;
|
|
break;
|
|
case non_zero:
|
|
if (classify(r) != zero)
|
|
return 1;
|
|
break;
|
|
case inf:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case NaN:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero_nan:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
}
|
|
break;
|
|
case non_zero:
|
|
switch (classify(divisor))
|
|
{
|
|
case zero:
|
|
if (classify(r) != zero)
|
|
return 1;
|
|
break;
|
|
case non_zero:
|
|
if (classify(r) != non_zero)
|
|
return 1;
|
|
if (r != a * c - b * d + _Complex_I*(a * d + b * c))
|
|
return 1;
|
|
break;
|
|
case inf:
|
|
if (classify(r) != inf)
|
|
return 1;
|
|
break;
|
|
case NaN:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero_nan:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
}
|
|
break;
|
|
case inf:
|
|
switch (classify(divisor))
|
|
{
|
|
case zero:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero:
|
|
if (classify(r) != inf)
|
|
return 1;
|
|
break;
|
|
case inf:
|
|
if (classify(r) != inf)
|
|
return 1;
|
|
break;
|
|
case NaN:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero_nan:
|
|
if (classify(r) != inf)
|
|
return 1;
|
|
break;
|
|
}
|
|
break;
|
|
case NaN:
|
|
switch (classify(divisor))
|
|
{
|
|
case zero:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case inf:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case NaN:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero_nan:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
}
|
|
break;
|
|
case non_zero_nan:
|
|
switch (classify(divisor))
|
|
{
|
|
case zero:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case inf:
|
|
if (classify(r) != inf)
|
|
return 1;
|
|
break;
|
|
case NaN:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero_nan:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
long double x[][2] =
|
|
{
|
|
{ 1.e-6, 1.e-6},
|
|
{-1.e-6, 1.e-6},
|
|
{-1.e-6, -1.e-6},
|
|
{ 1.e-6, -1.e-6},
|
|
|
|
{ 1.e+6, 1.e-6},
|
|
{-1.e+6, 1.e-6},
|
|
{-1.e+6, -1.e-6},
|
|
{ 1.e+6, -1.e-6},
|
|
|
|
{ 1.e-6, 1.e+6},
|
|
{-1.e-6, 1.e+6},
|
|
{-1.e-6, -1.e+6},
|
|
{ 1.e-6, -1.e+6},
|
|
|
|
{ 1.e+6, 1.e+6},
|
|
{-1.e+6, 1.e+6},
|
|
{-1.e+6, -1.e+6},
|
|
{ 1.e+6, -1.e+6},
|
|
|
|
{NAN, NAN},
|
|
{-INFINITY, NAN},
|
|
{-2, NAN},
|
|
{-1, NAN},
|
|
{-0.5, NAN},
|
|
{-0., NAN},
|
|
{+0., NAN},
|
|
{0.5, NAN},
|
|
{1, NAN},
|
|
{2, NAN},
|
|
{INFINITY, NAN},
|
|
|
|
{NAN, -INFINITY},
|
|
{-INFINITY, -INFINITY},
|
|
{-2, -INFINITY},
|
|
{-1, -INFINITY},
|
|
{-0.5, -INFINITY},
|
|
{-0., -INFINITY},
|
|
{+0., -INFINITY},
|
|
{0.5, -INFINITY},
|
|
{1, -INFINITY},
|
|
{2, -INFINITY},
|
|
{INFINITY, -INFINITY},
|
|
|
|
{NAN, -2},
|
|
{-INFINITY, -2},
|
|
{-2, -2},
|
|
{-1, -2},
|
|
{-0.5, -2},
|
|
{-0., -2},
|
|
{+0., -2},
|
|
{0.5, -2},
|
|
{1, -2},
|
|
{2, -2},
|
|
{INFINITY, -2},
|
|
|
|
{NAN, -1},
|
|
{-INFINITY, -1},
|
|
{-2, -1},
|
|
{-1, -1},
|
|
{-0.5, -1},
|
|
{-0., -1},
|
|
{+0., -1},
|
|
{0.5, -1},
|
|
{1, -1},
|
|
{2, -1},
|
|
{INFINITY, -1},
|
|
|
|
{NAN, -0.5},
|
|
{-INFINITY, -0.5},
|
|
{-2, -0.5},
|
|
{-1, -0.5},
|
|
{-0.5, -0.5},
|
|
{-0., -0.5},
|
|
{+0., -0.5},
|
|
{0.5, -0.5},
|
|
{1, -0.5},
|
|
{2, -0.5},
|
|
{INFINITY, -0.5},
|
|
|
|
{NAN, -0.},
|
|
{-INFINITY, -0.},
|
|
{-2, -0.},
|
|
{-1, -0.},
|
|
{-0.5, -0.},
|
|
{-0., -0.},
|
|
{+0., -0.},
|
|
{0.5, -0.},
|
|
{1, -0.},
|
|
{2, -0.},
|
|
{INFINITY, -0.},
|
|
|
|
{NAN, 0.},
|
|
{-INFINITY, 0.},
|
|
{-2, 0.},
|
|
{-1, 0.},
|
|
{-0.5, 0.},
|
|
{-0., 0.},
|
|
{+0., 0.},
|
|
{0.5, 0.},
|
|
{1, 0.},
|
|
{2, 0.},
|
|
{INFINITY, 0.},
|
|
|
|
{NAN, 0.5},
|
|
{-INFINITY, 0.5},
|
|
{-2, 0.5},
|
|
{-1, 0.5},
|
|
{-0.5, 0.5},
|
|
{-0., 0.5},
|
|
{+0., 0.5},
|
|
{0.5, 0.5},
|
|
{1, 0.5},
|
|
{2, 0.5},
|
|
{INFINITY, 0.5},
|
|
|
|
{NAN, 1},
|
|
{-INFINITY, 1},
|
|
{-2, 1},
|
|
{-1, 1},
|
|
{-0.5, 1},
|
|
{-0., 1},
|
|
{+0., 1},
|
|
{0.5, 1},
|
|
{1, 1},
|
|
{2, 1},
|
|
{INFINITY, 1},
|
|
|
|
{NAN, 2},
|
|
{-INFINITY, 2},
|
|
{-2, 2},
|
|
{-1, 2},
|
|
{-0.5, 2},
|
|
{-0., 2},
|
|
{+0., 2},
|
|
{0.5, 2},
|
|
{1, 2},
|
|
{2, 2},
|
|
{INFINITY, 2},
|
|
|
|
{NAN, INFINITY},
|
|
{-INFINITY, INFINITY},
|
|
{-2, INFINITY},
|
|
{-1, INFINITY},
|
|
{-0.5, INFINITY},
|
|
{-0., INFINITY},
|
|
{+0., INFINITY},
|
|
{0.5, INFINITY},
|
|
{1, INFINITY},
|
|
{2, INFINITY},
|
|
{INFINITY, INFINITY}
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int main()
|
|
{
|
|
#if _ARCH_PPC || __aarch64__
|
|
const unsigned N = sizeof(x) / sizeof(x[0]);
|
|
unsigned i, j;
|
|
for (i = 0; i < N; ++i)
|
|
{
|
|
for (j = 0; j < N; ++j)
|
|
{
|
|
if (test__multc3(x[i][0], x[i][1], x[j][0], x[j][1]))
|
|
return 1;
|
|
}
|
|
}
|
|
#else
|
|
printf("skipped\n");
|
|
#endif
|
|
return 0;
|
|
}
|