re PR target/20666 (SPARC builtins should be folded if possible)
2005-06-08 James A. Morrison <phython@gcc.gnu.org> PR target/20666 * config/sparc/sparc.c (sparc_fold_builtin): New function (sparc_vis_mul8x16): New function. (sparc_handle_vis_mul8x16): New function. (TARGET_FOLD_BUILTIN): Define to sparc_fold_builtin. From-SVN: r100762
This commit is contained in:
parent
a6cddf6e80
commit
8b0096b486
@ -1,3 +1,11 @@
|
||||
2005-06-08 James A. Morrison <phython@gcc.gnu.org>
|
||||
|
||||
PR target/20666
|
||||
* config/sparc/sparc.c (sparc_fold_builtin): New function
|
||||
(sparc_vis_mul8x16): New function.
|
||||
(sparc_handle_vis_mul8x16): New function.
|
||||
(TARGET_FOLD_BUILTIN): Define to sparc_fold_builtin.
|
||||
|
||||
2005-06-08 David Edelsohn <edelsohn@gnu.org>
|
||||
|
||||
* config/rs6000/rs6000.md (call_indirect_nonlocal_aix32): Prefer
|
||||
|
@ -341,6 +341,9 @@ static void sparc_init_libfuncs (void);
|
||||
static void sparc_init_builtins (void);
|
||||
static void sparc_vis_init_builtins (void);
|
||||
static rtx sparc_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
|
||||
static tree sparc_fold_builtin (tree, tree, bool);
|
||||
static int sparc_vis_mul8x16 (int, int);
|
||||
static tree sparc_handle_vis_mul8x16 (int, tree, tree, tree);
|
||||
static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
|
||||
HOST_WIDE_INT, tree);
|
||||
static bool sparc_can_output_mi_thunk (tree, HOST_WIDE_INT,
|
||||
@ -437,6 +440,8 @@ static bool fpu_option_set = false;
|
||||
|
||||
#undef TARGET_EXPAND_BUILTIN
|
||||
#define TARGET_EXPAND_BUILTIN sparc_expand_builtin
|
||||
#undef TARGET_FOLD_BUILTIN
|
||||
#define TARGET_FOLD_BUILTIN sparc_fold_builtin
|
||||
|
||||
#if TARGET_TLS
|
||||
#undef TARGET_HAVE_TLS
|
||||
@ -7904,6 +7909,204 @@ sparc_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
|
||||
|
||||
return op[0];
|
||||
}
|
||||
|
||||
static int
|
||||
sparc_vis_mul8x16 (int e8, int e16)
|
||||
{
|
||||
return (e8 * e16 + 128) / 256;
|
||||
}
|
||||
|
||||
/* Multiply the vector elements in ELTS0 to the elements in ELTS1 as specified
|
||||
by FNCODE. All of the elements in ELTS0 and ELTS1 lists must be integer
|
||||
constants. A tree list with the results of the multiplications is returned,
|
||||
and each element in the list is of INNER_TYPE. */
|
||||
|
||||
static tree
|
||||
sparc_handle_vis_mul8x16 (int fncode, tree inner_type, tree elts0, tree elts1)
|
||||
{
|
||||
tree n_elts = NULL_TREE;
|
||||
int scale;
|
||||
|
||||
switch (fncode)
|
||||
{
|
||||
case CODE_FOR_fmul8x16_vis:
|
||||
for (; elts0 && elts1;
|
||||
elts0 = TREE_CHAIN (elts0), elts1 = TREE_CHAIN (elts1))
|
||||
{
|
||||
int val
|
||||
= sparc_vis_mul8x16 (TREE_INT_CST_LOW (TREE_VALUE (elts0)),
|
||||
TREE_INT_CST_LOW (TREE_VALUE (elts1)));
|
||||
n_elts = tree_cons (NULL_TREE,
|
||||
build_int_cst (inner_type, val),
|
||||
n_elts);
|
||||
}
|
||||
break;
|
||||
|
||||
case CODE_FOR_fmul8x16au_vis:
|
||||
scale = TREE_INT_CST_LOW (TREE_VALUE (elts1));
|
||||
|
||||
for (; elts0; elts0 = TREE_CHAIN (elts0))
|
||||
{
|
||||
int val
|
||||
= sparc_vis_mul8x16 (TREE_INT_CST_LOW (TREE_VALUE (elts0)),
|
||||
scale);
|
||||
n_elts = tree_cons (NULL_TREE,
|
||||
build_int_cst (inner_type, val),
|
||||
n_elts);
|
||||
}
|
||||
break;
|
||||
|
||||
case CODE_FOR_fmul8x16al_vis:
|
||||
scale = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (elts1)));
|
||||
|
||||
for (; elts0; elts0 = TREE_CHAIN (elts0))
|
||||
{
|
||||
int val
|
||||
= sparc_vis_mul8x16 (TREE_INT_CST_LOW (TREE_VALUE (elts0)),
|
||||
scale);
|
||||
n_elts = tree_cons (NULL_TREE,
|
||||
build_int_cst (inner_type, val),
|
||||
n_elts);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
return nreverse (n_elts);
|
||||
|
||||
}
|
||||
/* Handle TARGET_FOLD_BUILTIN target hook.
|
||||
Fold builtin functions for SPARC intrinsics. If INGNORE is true the
|
||||
result of the function call is ignored. NULL_TREE is returned if the
|
||||
function could not be folded. */
|
||||
|
||||
static tree
|
||||
sparc_fold_builtin (tree fndecl, tree arglist, bool ignore)
|
||||
{
|
||||
tree arg0, arg1, arg2;
|
||||
tree rtype = TREE_TYPE (TREE_TYPE (fndecl));
|
||||
|
||||
|
||||
if (ignore && DECL_FUNCTION_CODE (fndecl) != CODE_FOR_alignaddrsi_vis
|
||||
&& DECL_FUNCTION_CODE (fndecl) != CODE_FOR_alignaddrdi_vis)
|
||||
return build_int_cst (rtype, 0);
|
||||
|
||||
switch (DECL_FUNCTION_CODE (fndecl))
|
||||
{
|
||||
case CODE_FOR_fexpand_vis:
|
||||
arg0 = TREE_VALUE (arglist);
|
||||
STRIP_NOPS (arg0);
|
||||
|
||||
if (TREE_CODE (arg0) == VECTOR_CST)
|
||||
{
|
||||
tree inner_type = TREE_TYPE (rtype);
|
||||
tree elts = TREE_VECTOR_CST_ELTS (arg0);
|
||||
tree n_elts = NULL_TREE;
|
||||
|
||||
for (; elts; elts = TREE_CHAIN (elts))
|
||||
{
|
||||
unsigned int val = TREE_INT_CST_LOW (TREE_VALUE (elts)) << 4;
|
||||
n_elts = tree_cons (NULL_TREE,
|
||||
build_int_cst (inner_type, val),
|
||||
n_elts);
|
||||
}
|
||||
return build_vector (rtype, nreverse (n_elts));
|
||||
}
|
||||
break;
|
||||
|
||||
case CODE_FOR_fmul8x16_vis:
|
||||
case CODE_FOR_fmul8x16au_vis:
|
||||
case CODE_FOR_fmul8x16al_vis:
|
||||
arg0 = TREE_VALUE (arglist);
|
||||
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
STRIP_NOPS (arg0);
|
||||
STRIP_NOPS (arg1);
|
||||
|
||||
if (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST)
|
||||
{
|
||||
tree inner_type = TREE_TYPE (rtype);
|
||||
tree elts0 = TREE_VECTOR_CST_ELTS (arg0);
|
||||
tree elts1 = TREE_VECTOR_CST_ELTS (arg1);
|
||||
tree n_elts = sparc_handle_vis_mul8x16 (DECL_FUNCTION_CODE (fndecl),
|
||||
inner_type, elts0, elts1);
|
||||
|
||||
return build_vector (rtype, n_elts);
|
||||
}
|
||||
break;
|
||||
|
||||
case CODE_FOR_fpmerge_vis:
|
||||
arg0 = TREE_VALUE (arglist);
|
||||
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
STRIP_NOPS (arg0);
|
||||
STRIP_NOPS (arg1);
|
||||
|
||||
if (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST)
|
||||
{
|
||||
tree elts0 = TREE_VECTOR_CST_ELTS (arg0);
|
||||
tree elts1 = TREE_VECTOR_CST_ELTS (arg1);
|
||||
tree n_elts = NULL_TREE;
|
||||
|
||||
for (; elts0 && elts1;
|
||||
elts0 = TREE_CHAIN (elts0), elts1 = TREE_CHAIN (elts1))
|
||||
{
|
||||
n_elts = tree_cons (NULL_TREE, TREE_VALUE (elts0), n_elts);
|
||||
n_elts = tree_cons (NULL_TREE, TREE_VALUE (elts1), n_elts);
|
||||
}
|
||||
|
||||
return build_vector (rtype, nreverse (n_elts));
|
||||
}
|
||||
break;
|
||||
|
||||
case CODE_FOR_pdist_vis:
|
||||
arg0 = TREE_VALUE (arglist);
|
||||
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
||||
STRIP_NOPS (arg0);
|
||||
STRIP_NOPS (arg1);
|
||||
STRIP_NOPS (arg2);
|
||||
|
||||
if (TREE_CODE (arg0) == VECTOR_CST
|
||||
&& TREE_CODE (arg1) == VECTOR_CST
|
||||
&& TREE_CODE (arg2) == INTEGER_CST)
|
||||
{
|
||||
int overflow = 0;
|
||||
unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (arg2);
|
||||
HOST_WIDE_INT high = TREE_INT_CST_HIGH (arg2);
|
||||
tree elts0 = TREE_VECTOR_CST_ELTS (arg0);
|
||||
tree elts1 = TREE_VECTOR_CST_ELTS (arg1);
|
||||
|
||||
for (; elts0 && elts1;
|
||||
elts0 = TREE_CHAIN (elts0), elts1 = TREE_CHAIN (elts1))
|
||||
{
|
||||
unsigned HOST_WIDE_INT
|
||||
low0 = TREE_INT_CST_LOW (TREE_VALUE (elts0)),
|
||||
low1 = TREE_INT_CST_LOW (TREE_VALUE (elts1));
|
||||
HOST_WIDE_INT high0 = TREE_INT_CST_HIGH (TREE_VALUE (elts0));
|
||||
HOST_WIDE_INT high1 = TREE_INT_CST_HIGH (TREE_VALUE (elts1));
|
||||
|
||||
unsigned HOST_WIDE_INT l;
|
||||
HOST_WIDE_INT h;
|
||||
|
||||
overflow |= neg_double (low1, high1, &l, &h);
|
||||
overflow |= add_double (low0, high0, l, h, &l, &h);
|
||||
if (h < 0)
|
||||
overflow |= neg_double (l, h, &l, &h);
|
||||
|
||||
overflow |= add_double (low, high, l, h, &low, &high);
|
||||
}
|
||||
|
||||
gcc_assert (overflow == 0);
|
||||
|
||||
return build_int_cst_wide (rtype, low, high);
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
int
|
||||
sparc_extra_constraint_check (rtx op, int c, int strict)
|
||||
|
@ -1,3 +1,13 @@
|
||||
2005-06-08 James A. Morrison <phython@gcc.gnu.org>
|
||||
|
||||
PR target/20666
|
||||
* gcc.target/sparc/fexpand-2.c: New.
|
||||
* gcc.target/sparc/fpmerge-2.c: New.
|
||||
* gcc.target/sparc/fpmul-2.c: New.
|
||||
* gcc.target/sparc/noresult.c: New.
|
||||
* gcc.target/sparc/pdist-2.c: New.
|
||||
* gcc.target/sparc/pdist-3.c: New.
|
||||
|
||||
2005-06-08 Alex V. Breger <atrus.ru@atrus.ru>
|
||||
|
||||
PR testsuite/21702
|
||||
|
11
gcc/testsuite/gcc.target/sparc/fexpand-2.c
Normal file
11
gcc/testsuite/gcc.target/sparc/fexpand-2.c
Normal file
@ -0,0 +1,11 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O1 -fdump-tree-final_cleanup -mcpu=ultrasparc -mvis" } */
|
||||
typedef short vec16 __attribute__((vector_size(8)));
|
||||
typedef unsigned char vec8 __attribute__((vector_size(4)));
|
||||
|
||||
vec16 foo () {
|
||||
vec8 a = {(unsigned char)1,(unsigned char)2,(unsigned char)4,(unsigned char)8};
|
||||
return __builtin_vis_fexpand (a);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "{ 16, 32, 64, 128 }" "final_cleanup" } } */
|
15
gcc/testsuite/gcc.target/sparc/fpmerge-2.c
Normal file
15
gcc/testsuite/gcc.target/sparc/fpmerge-2.c
Normal file
@ -0,0 +1,15 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-mcpu=ultrasparc -mvis -O1 -fdump-tree-final_cleanup" } */
|
||||
typedef unsigned char pixel __attribute__((vector_size(8)));
|
||||
typedef unsigned char vec8 __attribute__((vector_size(4)));
|
||||
|
||||
#define _(ARG) (unsigned char)ARG
|
||||
|
||||
pixel foo () {
|
||||
vec8 a = { _(1), _(3), _(5), _(7) };
|
||||
vec8 b = { _(2), _(4), _(6), _(8) };
|
||||
return __builtin_vis_fpmerge (a, b);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-not "fpmerge\t%" } } */
|
||||
/* { dg-final { scan-tree-dump "{ 1, 2, 3, 4, 5, 6, 7, 8 }" "final_cleanup" } } */
|
47
gcc/testsuite/gcc.target/sparc/fpmul-2.c
Normal file
47
gcc/testsuite/gcc.target/sparc/fpmul-2.c
Normal file
@ -0,0 +1,47 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-mcpu=ultrasparc -mvis -O1 -fdump-tree-final_cleanup" } */
|
||||
|
||||
typedef int vec32 __attribute__((vector_size(8)));
|
||||
typedef short vec16 __attribute__((vector_size(8)));
|
||||
typedef unsigned char vec8 __attribute__((vector_size(8)));
|
||||
|
||||
typedef unsigned char pixel __attribute__((vector_size(4)));
|
||||
typedef short pixel16 __attribute__((vector_size(4)));
|
||||
|
||||
vec16 foo1 () {
|
||||
pixel a = { (unsigned char)1, (unsigned char)2, (unsigned char)3, (unsigned char)4 };
|
||||
vec16 b = { (short)1, (short)2, (short)3, (short)4 };
|
||||
return __builtin_vis_fmul8x16 (a, b);
|
||||
}
|
||||
|
||||
vec16 foo1_1 () {
|
||||
pixel a = { (unsigned char)1, (unsigned char)1, (unsigned char)1, (unsigned char)1 };
|
||||
vec16 b = { (short)256, (short)512, (short)1024, (short)2048 };
|
||||
return __builtin_vis_fmul8x16 (a, b);
|
||||
}
|
||||
|
||||
vec16 foo1_2 () {
|
||||
pixel a = { (unsigned char)255, (unsigned char)255, (unsigned char)255, (unsigned char)255 };
|
||||
vec16 b = { (short)256, (short)512, (short)1024, (short)32767 };
|
||||
return __builtin_vis_fmul8x16 (a, b);
|
||||
}
|
||||
/* { dg-final { scan-assembler-not "fmul8x16\t%" } } */
|
||||
/* { dg-final { scan-tree-dump "{ 0, 0, 0, 0 }" "final_cleanup" } } */
|
||||
/* { dg-final { scan-tree-dump "{ 1, 2, 4, 8 }" "final_cleanup" } } */
|
||||
/* { dg-final { scan-tree-dump "{ 255, 510, 1020, 32639 }" "final_cleanup" } } */
|
||||
|
||||
vec16 foo2 () {
|
||||
pixel a = { 1, 2, 3, 4 };
|
||||
pixel16 b = { 256, 512 };
|
||||
return __builtin_vis_fmul8x16au (a, b);
|
||||
}
|
||||
/* { dg-final { scan-assembler-not "fmul8x16au\t%" } } */
|
||||
/* { dg-final { scan-tree-dump "{ 1, 2, 3, 4 }" "final_cleanup" } } */
|
||||
|
||||
vec16 foo3 () {
|
||||
pixel a = { 1, 2, 3, 4 };
|
||||
pixel16 b = { 256, 512 };
|
||||
return __builtin_vis_fmul8x16al (a, b);
|
||||
}
|
||||
/* { dg-final { scan-assembler-not "fmul8x16al\t%" } } */
|
||||
/* { dg-final { scan-tree-dump "{ 2, 4, 6, 8 }" "final_cleanup" } } */
|
10
gcc/testsuite/gcc.target/sparc/noresult.c
Normal file
10
gcc/testsuite/gcc.target/sparc/noresult.c
Normal file
@ -0,0 +1,10 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-mcpu=ultrasparc -mvis" } */
|
||||
typedef short vec16 __attribute__((vector_size(8)));
|
||||
typedef char vec8 __attribute__((vector_size(4)));
|
||||
|
||||
void foo (vec16 a) {
|
||||
__builtin_vis_fpack16 (a);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-not "fpack16\t%" } } */
|
18
gcc/testsuite/gcc.target/sparc/pdist-2.c
Normal file
18
gcc/testsuite/gcc.target/sparc/pdist-2.c
Normal file
@ -0,0 +1,18 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-mcpu=ultrasparc -mvis -O1 -fdump-tree-final_cleanup" } */
|
||||
|
||||
typedef long long int64_t;
|
||||
typedef unsigned char vec8 __attribute__((vector_size(8)));
|
||||
|
||||
#define _(A) (unsigned char)A
|
||||
|
||||
int64_t foo () {
|
||||
int64_t d = 2;
|
||||
vec8 a = { _(1), _(2), _(3), _(4), _(5), _(6), _(7), _(255) };
|
||||
vec8 b = { _(2), _(4), _(8), _(16), _(32), _(64), _(128), _(8) };
|
||||
d = __builtin_vis_pdist (a, b, d);
|
||||
return d;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-not "pdist\t%" } } */
|
||||
/* { dg-final { scan-tree-dump "return 475" "final_cleanup" } } */
|
36
gcc/testsuite/gcc.target/sparc/pdist-3.c
Normal file
36
gcc/testsuite/gcc.target/sparc/pdist-3.c
Normal file
@ -0,0 +1,36 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-mcpu=ultrasparc -mvis -O1" } */
|
||||
|
||||
typedef long long int64_t;
|
||||
typedef unsigned char vec8 __attribute__((vector_size(8)));
|
||||
|
||||
extern void abort ();
|
||||
extern void exit (int);
|
||||
|
||||
#define _(A) (unsigned char)A
|
||||
|
||||
int64_t foo (vec8 a, vec8 b) {
|
||||
int64_t d = 2;
|
||||
d = __builtin_vis_pdist (a, b, d);
|
||||
return d;
|
||||
}
|
||||
|
||||
int64_t bar () {
|
||||
int64_t d = 2;
|
||||
vec8 a = { _(1), _(2), _(3), _(4), _(5), _(6), _(7), _(255) };
|
||||
vec8 b = { _(2), _(4), _(8), _(16), _(32), _(64), _(128), _(8) };
|
||||
d = __builtin_vis_pdist (a, b, d);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
static vec8 a = { 1, 2, 3, 4, 5, 6, 7, 255 };
|
||||
static vec8 b = { 2, 4, 8, 16, 32, 64, 128, 8 };
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
|
||||
if (foo (a, b) != bar ())
|
||||
abort ();
|
||||
|
||||
exit (0);
|
||||
}
|
Loading…
Reference in New Issue
Block a user