This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[rfc] prototype altivec function overloading rewrite
- From: Richard Henderson <rth at redhat dot com>
- To: Aldy Hernandez <aldyh at redhat dot com>, gcc-patches at gcc dot gnu dot org
- Date: Tue, 13 Apr 2004 11:23:23 -0700
- Subject: [rfc] prototype altivec function overloading rewrite
Aside from folks getting confused about what __builtin_types_compatible_p
is supposed to mean, the thing clearly doesn't scale well.
The following allows a backend to intercept places in which the front-end
builds a call to a target-specific builtin, and lets it generate anything
it likes. Kinda gross, as it's the sort of thing that's ripe for abuse,
but it does allow us to implement a kind of function overloading in C.
The following works, at least for C. In order to use this patch for real
we'd have to merge the lang_hooks.types_compatible_p change from tree-ssa.
The sets of types accepted by arithmetic vs logical AltiVec generics
seemed to be rather random to me. If there is a pattern that I wasn't
seeing, so much the better. Cause otherwise the table approach that I'm
using is gonna get pretty large.
Comments?
r~
* c-typeck.c (comptypes): Recurse for vector types instead of
just comparing modes.
(build_function_call): Honor expand_overloaded_builtin.
* target-def.h (TARGET_EXPAND_OVERLOADED_BUILTIN): New.
* target.h (expand_overloaded_builtin): New.
* tree.c (make_or_reuse_type): New.
(build_common_tree_nodes): Use it.
* config/rs6000/rs6000.c (enum rs6000_builtin_type_index): New.
(rs6000_builtin_types): New.
(opaque_V2SI_type_node, opaque_V2SF_type_node, opaque_p_V2SI_type_node,
V16QI_type_node, V2SI_type_node, V2SF_type_node, V4HI_type_node,
V4SI_type_node, V4SF_type_node, V8HI_type_node,
unsigned_V16QI_type_node, unsigned_V8HI_type_node,
unsigned_V4SI_type_node, bool_char_type_node, bool_short_type_node,
bool_int_type_node, pixel_type_node, bool_V16QI_type_node,
bool_V8HI_type_node, bool_V4SI_type_node, pixel_V8HI_type_node):
Redefine as macros.
(TARGET_EXPAND_OVERLOADED_BUILTIN): New.
(rs6000_built_in_decls): New.
(def_builtin): Redefine as function. Set it.
(struct altivec_overloaded_builtin): New.
(ALTIVEC_OVERLOADED_BUILTIN_TERMINATOR): New.
(a_o_b_vec_add): New.
(altivec_expand_overloaded_binary): New.
(altivec_expand_overloaded_builtin): New.
(altivec_init_builtins): Build __builtin_altivec_vec_add.
* config/rs6000/rs6000.h (ALTIVEC_BUILTIN_overload_min,
ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_overload_max,
RS6000_BUILT_IN_MAX): New.
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.301
diff -c -p -d -r1.301 c-typeck.c
*** c-typeck.c 10 Apr 2004 18:47:49 -0000 1.301
--- c-typeck.c 13 Apr 2004 18:03:55 -0000
*************** comptypes (tree type1, tree type2, int f
*** 488,494 ****
&& TYPE_ORIG_SIZE_TYPE (t2))
t2 = TYPE_ORIG_SIZE_TYPE (t2);
-
/* Enumerated types are compatible with integer types, but this is
not transitive: two enumerated types in the same translation unit
are compatible with each other only if they are the same type. */
--- 488,493 ----
*************** comptypes (tree type1, tree type2, int f
*** 503,509 ****
/* Different classes of types can't be compatible. */
! if (TREE_CODE (t1) != TREE_CODE (t2)) return 0;
/* Qualifiers must match. */
--- 502,509 ----
/* Different classes of types can't be compatible. */
! if (TREE_CODE (t1) != TREE_CODE (t2))
! return 0;
/* Qualifiers must match. */
*************** comptypes (tree type1, tree type2, int f
*** 519,525 ****
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
if (! (attrval = targetm.comp_type_attributes (t1, t2)))
! return 0;
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
val = 0;
--- 519,525 ----
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
if (! (attrval = targetm.comp_type_attributes (t1, t2)))
! return 0;
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
val = 0;
*************** comptypes (tree type1, tree type2, int f
*** 592,601 ****
break;
case VECTOR_TYPE:
/* The target might allow certain vector types to be compatible. */
! val = targetm.vector_opaque_p (t1)
! || targetm.vector_opaque_p (t2)
! || TYPE_MODE (t1) == TYPE_MODE (t2);
break;
default:
--- 592,606 ----
break;
case VECTOR_TYPE:
+ /* The vectors must be of the same width, no matter what. */
+ if (GET_MODE_NUNITS (TYPE_MODE (t1)) != GET_MODE_NUNITS (TYPE_MODE (t2)))
+ return 0;
+
/* The target might allow certain vector types to be compatible. */
! if (targetm.vector_opaque_p (t1) || targetm.vector_opaque_p (t2))
! val = 1;
! else
! val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2), flags);
break;
default:
*************** build_function_call (tree function, tree
*** 1697,1702 ****
--- 1702,1721 ----
/* Convert anything with function type to a pointer-to-function. */
if (TREE_CODE (function) == FUNCTION_DECL)
{
+ /* Implement target-directed function overloading for builtins.
+ The target handles all type checking. The result is a complete
+ expression that implements this function call. */
+ /* ??? This is ugly. Please don't let this existance of this hook
+ encourage anyone to emulate the horrible things that AltiVec has
+ perpetrated. */
+ if (targetm.expand_overloaded_builtin
+ && DECL_BUILT_IN_CLASS (function) == BUILT_IN_MD)
+ {
+ tem = targetm.expand_overloaded_builtin (function, params);
+ if (tem)
+ return tem;
+ }
+
name = DECL_NAME (function);
/* Differs from default_conversion by not setting TREE_ADDRESSABLE
Index: target-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target-def.h,v
retrieving revision 1.77
diff -c -p -d -r1.77 target-def.h
*** target-def.h 24 Mar 2004 00:13:20 -0000 1.77
--- target-def.h 13 Apr 2004 18:03:55 -0000
*************** Foundation, 59 Temple Place - Suite 330,
*** 275,280 ****
--- 275,281 ----
/* In builtins.c. */
#define TARGET_INIT_BUILTINS hook_void_void
#define TARGET_EXPAND_BUILTIN default_expand_builtin
+ #define TARGET_EXPAND_OVERLOADED_BUILTIN NULL
/* In varasm.c. */
#ifndef TARGET_SECTION_TYPE_FLAGS
*************** Foundation, 59 Temple Place - Suite 330,
*** 386,391 ****
--- 387,393 ----
TARGET_MS_BITFIELD_LAYOUT_P, \
TARGET_INIT_BUILTINS, \
TARGET_EXPAND_BUILTIN, \
+ TARGET_EXPAND_OVERLOADED_BUILTIN, \
TARGET_MANGLE_FUNDAMENTAL_TYPE, \
TARGET_INIT_LIBFUNCS, \
TARGET_SECTION_TYPE_FLAGS, \
Index: target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.85
diff -c -p -d -r1.85 target.h
*** target.h 24 Mar 2004 00:13:20 -0000 1.85
--- target.h 13 Apr 2004 18:03:55 -0000
*************** struct gcc_target
*** 314,319 ****
--- 314,325 ----
rtx (* expand_builtin) (tree exp, rtx target, rtx subtarget,
enum machine_mode mode, int ignore);
+ /* Select a replacement for a target-specific builtin. This is done
+ *before* regular type checking, and so allows the target to implement
+ a crude form of function overloading. The result is a complete
+ expression that implements the operation. */
+ tree (*expand_overloaded_builtin) (tree decl, tree params);
+
/* For a vendor-specific fundamental TYPE, return a pointer to
a statically-allocated string containing the C++ mangling for
TYPE. In all other cases, return NULL. */
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.367
diff -c -p -d -r1.367 tree.c
*** tree.c 12 Apr 2004 21:25:46 -0000 1.367
--- tree.c 13 Apr 2004 18:03:56 -0000
*************** finish_vector_type (tree t)
*** 5182,5187 ****
--- 5182,5208 ----
}
}
+ static tree
+ make_or_reuse_type (unsigned size, int unsignedp)
+ {
+ if (size == INT_TYPE_SIZE)
+ return unsignedp ? unsigned_type_node : integer_type_node;
+ if (size == CHAR_TYPE_SIZE)
+ return unsignedp ? unsigned_char_type_node : signed_char_type_node;
+ if (size == SHORT_TYPE_SIZE)
+ return unsignedp ? short_unsigned_type_node : short_integer_type_node;
+ if (size == LONG_TYPE_SIZE)
+ return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+ if (size == LONG_LONG_TYPE_SIZE)
+ return (unsignedp ? long_long_unsigned_type_node
+ : long_long_integer_type_node);
+
+ if (unsignedp)
+ return make_unsigned_type (size);
+ else
+ return make_signed_type (size);
+ }
+
/* Create nodes for all integer types (and error_mark_node) using the sizes
of C datatypes. The caller should call set_sizetype soon after calling
this function to select one of the types as sizetype. */
*************** build_common_tree_nodes (int signed_char
*** 5224,5240 ****
TREE_TYPE (TYPE_MAX_VALUE (boolean_type_node)) = boolean_type_node;
TYPE_PRECISION (boolean_type_node) = 1;
! intQI_type_node = make_signed_type (GET_MODE_BITSIZE (QImode));
! intHI_type_node = make_signed_type (GET_MODE_BITSIZE (HImode));
! intSI_type_node = make_signed_type (GET_MODE_BITSIZE (SImode));
! intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
! intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
! unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
! unsigned_intHI_type_node = make_unsigned_type (GET_MODE_BITSIZE (HImode));
! unsigned_intSI_type_node = make_unsigned_type (GET_MODE_BITSIZE (SImode));
! unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
! unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
access_public_node = get_identifier ("public");
access_protected_node = get_identifier ("protected");
--- 5245,5263 ----
TREE_TYPE (TYPE_MAX_VALUE (boolean_type_node)) = boolean_type_node;
TYPE_PRECISION (boolean_type_node) = 1;
! /* Fill in the rest of the sized types. Reuse existing type nodes
! when possible. */
! intQI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (QImode), 0);
! intHI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (HImode), 0);
! intSI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (SImode), 0);
! intDI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (DImode), 0);
! intTI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (TImode), 0);
! unsigned_intQI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (QImode), 1);
! unsigned_intHI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (HImode), 1);
! unsigned_intSI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (SImode), 1);
! unsigned_intDI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (DImode), 1);
! unsigned_intTI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (TImode), 1);
access_public_node = get_identifier ("public");
access_protected_node = get_identifier ("protected");
Index: config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.624
diff -c -p -d -r1.624 rs6000.c
*** config/rs6000/rs6000.c 12 Apr 2004 00:52:24 -0000 1.624
--- config/rs6000/rs6000.c 13 Apr 2004 18:03:56 -0000
*************** const char *rs6000_debug_name;
*** 215,242 ****
int rs6000_debug_stack; /* debug stack applications */
int rs6000_debug_arg; /* debug argument handling */
! /* Opaque types. */
! static GTY(()) tree opaque_V2SI_type_node;
! static GTY(()) tree opaque_V2SF_type_node;
! static GTY(()) tree opaque_p_V2SI_type_node;
! static GTY(()) tree V16QI_type_node;
! static GTY(()) tree V2SI_type_node;
! static GTY(()) tree V2SF_type_node;
! static GTY(()) tree V4HI_type_node;
! static GTY(()) tree V4SI_type_node;
! static GTY(()) tree V4SF_type_node;
! static GTY(()) tree V8HI_type_node;
! static GTY(()) tree unsigned_V16QI_type_node;
! static GTY(()) tree unsigned_V8HI_type_node;
! static GTY(()) tree unsigned_V4SI_type_node;
! static GTY(()) tree bool_char_type_node; /* __bool char */
! static GTY(()) tree bool_short_type_node; /* __bool short */
! static GTY(()) tree bool_int_type_node; /* __bool int */
! static GTY(()) tree pixel_type_node; /* __pixel */
! static GTY(()) tree bool_V16QI_type_node; /* __vector __bool char */
! static GTY(()) tree bool_V8HI_type_node; /* __vector __bool short */
! static GTY(()) tree bool_V4SI_type_node; /* __vector __bool int */
! static GTY(()) tree pixel_V8HI_type_node; /* __vector __pixel */
int rs6000_warn_altivec_long = 1; /* On by default. */
const char *rs6000_warn_altivec_long_switch;
--- 215,274 ----
int rs6000_debug_stack; /* debug stack applications */
int rs6000_debug_arg; /* debug argument handling */
! /* Built in types. */
!
! enum rs6000_builtin_type_index
! {
! R6K_BTI_opaque_V2SI,
! R6K_BTI_opaque_V2SF,
! R6K_BTI_opaque_p_V2SI,
! R6K_BTI_V16QI,
! R6K_BTI_V2SI,
! R6K_BTI_V2SF,
! R6K_BTI_V4HI,
! R6K_BTI_V4SI,
! R6K_BTI_V4SF,
! R6K_BTI_V8HI,
! R6K_BTI_unsigned_V16QI,
! R6K_BTI_unsigned_V8HI,
! R6K_BTI_unsigned_V4SI,
! R6K_BTI_bool_char, /* __bool char */
! R6K_BTI_bool_short, /* __bool short */
! R6K_BTI_bool_int, /* __bool int */
! R6K_BTI_pixel, /* __pixel */
! R6K_BTI_bool_V16QI, /* __vector __bool char */
! R6K_BTI_bool_V8HI, /* __vector __bool short */
! R6K_BTI_bool_V4SI, /* __vector __bool int */
! R6K_BTI_pixel_V8HI, /* __vector __pixel */
! R6K_BTI_MAX
! };
!
! static GTY(()) tree rs6000_builtin_types[R6K_BTI_MAX];
!
! #define opaque_V2SI_type_node (rs6000_builtin_types[R6K_BTI_opaque_V2SI])
! #define opaque_V2SF_type_node (rs6000_builtin_types[R6K_BTI_opaque_V2SF])
! #define opaque_p_V2SI_type_node (rs6000_builtin_types[R6K_BTI_opaque_p_V2SI])
! #define V16QI_type_node (rs6000_builtin_types[R6K_BTI_V16QI])
! #define V2SI_type_node (rs6000_builtin_types[R6K_BTI_V2SI])
! #define V2SF_type_node (rs6000_builtin_types[R6K_BTI_V2SF])
! #define V4HI_type_node (rs6000_builtin_types[R6K_BTI_V4HI])
! #define V4SI_type_node (rs6000_builtin_types[R6K_BTI_V4SI])
! #define V4SF_type_node (rs6000_builtin_types[R6K_BTI_V4SF])
! #define V8HI_type_node (rs6000_builtin_types[R6K_BTI_V8HI])
! #define unsigned_V16QI_type_node (rs6000_builtin_types[R6K_BTI_unsigned_V16QI])
! #define unsigned_V8HI_type_node (rs6000_builtin_types[R6K_BTI_unsigned_V8HI])
! #define unsigned_V4SI_type_node (rs6000_builtin_types[R6K_BTI_unsigned_V4SI])
! #define bool_char_type_node (rs6000_builtin_types[R6K_BTI_bool_char])
! #define bool_short_type_node (rs6000_builtin_types[R6K_BTI_bool_short])
! #define bool_int_type_node (rs6000_builtin_types[R6K_BTI_bool_int])
! #define pixel_type_node (rs6000_builtin_types[R6K_BTI_pixel])
! #define bool_V16QI_type_node (rs6000_builtin_types[R6K_BTI_bool_V16QI])
! #define bool_V8HI_type_node (rs6000_builtin_types[R6K_BTI_bool_V8HI])
! #define bool_V4SI_type_node (rs6000_builtin_types[R6K_BTI_bool_V4SI])
! #define pixel_V8HI_type_node (rs6000_builtin_types[R6K_BTI_pixel_V8HI])
!
! /* Holds all builtin function decls. */
! static GTY(()) tree rs6000_built_in_decls[RS6000_BUILT_IN_MAX];
int rs6000_warn_altivec_long = 1; /* On by default. */
const char *rs6000_warn_altivec_long_switch;
*************** static rs6000_stack_t *rs6000_stack_info
*** 390,395 ****
--- 422,428 ----
static void debug_stack_info (rs6000_stack_t *);
static rtx altivec_expand_builtin (tree, rtx, bool *);
+ static tree altivec_expand_overloaded_builtin (tree, tree);
static rtx altivec_expand_ld_builtin (tree, rtx, bool *);
static rtx altivec_expand_st_builtin (tree, rtx, bool *);
static rtx altivec_expand_dst_builtin (tree, rtx, bool *);
*************** static const char alt_reg_names[][8] =
*** 586,591 ****
--- 619,626 ----
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN rs6000_expand_builtin
+ #undef TARGET_EXPAND_OVERLOADED_BUILTIN
+ #define TARGET_EXPAND_OVERLOADED_BUILTIN altivec_expand_overloaded_builtin
#undef TARGET_MANGLE_FUNDAMENTAL_TYPE
#define TARGET_MANGLE_FUNDAMENTAL_TYPE rs6000_mangle_fundamental_type
*************** rs6000_va_arg (tree valist, tree type)
*** 5112,5123 ****
/* Builtins. */
! #define def_builtin(MASK, NAME, TYPE, CODE) \
! do { \
! if ((MASK) & target_flags) \
! builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
! NULL, NULL_TREE); \
! } while (0)
/* Simple ternary operations: VECd = foo (VECa, VECb, VECc). */
--- 5147,5160 ----
/* Builtins. */
! static void
! def_builtin (unsigned int mask, const char *name,
! tree type, enum rs6000_builtins code)
! {
! if (mask & target_flags)
! rs6000_built_in_decls[code]
! = builtin_function (name, type, code, BUILT_IN_MD, NULL, NULL_TREE);
! }
/* Simple ternary operations: VECd = foo (VECa, VECb, VECc). */
*************** altivec_expand_builtin (tree exp, rtx ta
*** 6260,6265 ****
--- 6297,6460 ----
return NULL_RTX;
}
+ struct altivec_overloaded_builtin
+ {
+ enum rs6000_builtin_type_index result_type_index;
+ enum rs6000_builtin_type_index arg0_type_index;
+ enum rs6000_builtin_type_index arg1_type_index;
+ enum rs6000_builtins impl_index;
+ };
+
+ #define ALTIVEC_OVERLOADED_BUILTIN_TERMINATOR \
+ { 0, 0, 0, ALTIVEC_BUILTIN_overload_min }
+
+ const struct altivec_overloaded_builtin a_o_b_vec_add[] =
+ {
+ { R6K_BTI_unsigned_V16QI, R6K_BTI_unsigned_V16QI, R6K_BTI_unsigned_V16QI,
+ ALTIVEC_BUILTIN_VADDUBM },
+ { R6K_BTI_unsigned_V16QI, R6K_BTI_unsigned_V16QI, R6K_BTI_bool_V16QI,
+ ALTIVEC_BUILTIN_VADDUBM },
+ { R6K_BTI_unsigned_V16QI, R6K_BTI_bool_V16QI, R6K_BTI_unsigned_V16QI,
+ ALTIVEC_BUILTIN_VADDUBM },
+ { R6K_BTI_V16QI, R6K_BTI_V16QI, R6K_BTI_V16QI,
+ ALTIVEC_BUILTIN_VADDUBM },
+ { R6K_BTI_V16QI, R6K_BTI_V16QI, R6K_BTI_bool_V16QI,
+ ALTIVEC_BUILTIN_VADDUBM },
+ { R6K_BTI_V16QI, R6K_BTI_bool_V16QI, R6K_BTI_V16QI,
+ ALTIVEC_BUILTIN_VADDUBM },
+
+ { R6K_BTI_unsigned_V8HI, R6K_BTI_unsigned_V8HI, R6K_BTI_unsigned_V8HI,
+ ALTIVEC_BUILTIN_VADDUHM },
+ { R6K_BTI_unsigned_V8HI, R6K_BTI_unsigned_V8HI, R6K_BTI_bool_V8HI,
+ ALTIVEC_BUILTIN_VADDUHM },
+ { R6K_BTI_unsigned_V8HI, R6K_BTI_bool_V8HI, R6K_BTI_unsigned_V8HI,
+ ALTIVEC_BUILTIN_VADDUHM },
+ { R6K_BTI_V8HI, R6K_BTI_V8HI, R6K_BTI_V8HI,
+ ALTIVEC_BUILTIN_VADDUHM },
+ { R6K_BTI_V8HI, R6K_BTI_V8HI, R6K_BTI_bool_V8HI,
+ ALTIVEC_BUILTIN_VADDUHM },
+ { R6K_BTI_V8HI, R6K_BTI_bool_V8HI, R6K_BTI_V8HI,
+ ALTIVEC_BUILTIN_VADDUHM },
+
+ { R6K_BTI_unsigned_V4SI, R6K_BTI_unsigned_V4SI, R6K_BTI_unsigned_V4SI,
+ ALTIVEC_BUILTIN_VADDUWM },
+ { R6K_BTI_unsigned_V4SI, R6K_BTI_unsigned_V4SI, R6K_BTI_bool_V4SI,
+ ALTIVEC_BUILTIN_VADDUWM },
+ { R6K_BTI_unsigned_V4SI, R6K_BTI_bool_V4SI, R6K_BTI_unsigned_V4SI,
+ ALTIVEC_BUILTIN_VADDUWM },
+ { R6K_BTI_V4SI, R6K_BTI_V4SI, R6K_BTI_V4SI,
+ ALTIVEC_BUILTIN_VADDUWM },
+ { R6K_BTI_V4SI, R6K_BTI_V4SI, R6K_BTI_bool_V4SI,
+ ALTIVEC_BUILTIN_VADDUWM },
+ { R6K_BTI_V4SI, R6K_BTI_bool_V4SI, R6K_BTI_V4SI,
+ ALTIVEC_BUILTIN_VADDUWM },
+
+ { R6K_BTI_V4SF, R6K_BTI_V4SF, R6K_BTI_V4SF,
+ ALTIVEC_BUILTIN_VADDFP },
+
+ ALTIVEC_OVERLOADED_BUILTIN_TERMINATOR
+ };
+
+ #ifdef TREE_SSA
+ #define COMPAT(X, Y) lang_hooks.types_compatible_p(X, Y)
+ #else
+ #define COMPAT(X, Y) comptypes (X, Y, 0)
+ #endif
+
+ static tree
+ altivec_expand_overloaded_binary (tree fndecl, tree params,
+ const struct altivec_overloaded_builtin *tmpl)
+ {
+ tree op0, op1, op0_type, op1_type;
+ tree impl_fndecl;
+ tree tmp1, tmp2;
+
+ /* Validate that we've got two arguments. */
+ op0 = op1 = NULL;
+ if (params)
+ {
+ op0 = TREE_VALUE (params);
+ params = TREE_CHAIN (params);
+ if (params)
+ {
+ op1 = TREE_VALUE (params);
+ params = TREE_CHAIN (params);
+ if (params)
+ {
+ error ("too many arguments to function `%D'", fndecl);
+ return error_mark_node;
+ }
+ }
+ }
+ if (!op0 || !op1)
+ {
+ error ("too few arguments to function `%D'", fndecl);
+ return error_mark_node;
+ }
+ if (op0 == error_mark_node || op1 == error_mark_node)
+ return error_mark_node;
+
+ op0_type = TREE_TYPE (op0);
+ op1_type = TREE_TYPE (op1);
+ if (op0_type == error_mark_node || op1_type == error_mark_node)
+ return error_mark_node;
+
+ /* Search for a type match for the operands in the template. */
+ for (; tmpl->impl_index != ALTIVEC_BUILTIN_overload_min; tmpl++)
+ {
+ tree want0 = rs6000_builtin_types[tmpl->arg0_type_index];
+ tree want1 = rs6000_builtin_types[tmpl->arg1_type_index];
+ if (COMPAT (op0_type, want0)
+ && COMPAT (op1_type, want1))
+ goto found;
+ }
+
+ /* Not found. Bitch. */
+ error ("invalid argument types for `%D'", fndecl);
+ return error_mark_node;
+
+ /* Was found. Build an expression with the implementation builtin.
+ Add casts as necessary for the arguments and the return type. */
+ found:
+ impl_fndecl = rs6000_built_in_decls[tmpl->impl_index];
+ tmp1 = TYPE_ARG_TYPES (TREE_TYPE (impl_fndecl));
+ tmp2 = TREE_VALUE (tmp1);
+ if (!COMPAT (op0_type, tmp2))
+ op0 = build1 (NOP_EXPR, tmp2, op0);
+ tmp1 = TREE_CHAIN (tmp1);
+ tmp2 = TREE_VALUE (tmp1);
+ if (!COMPAT (op1_type, tmp2))
+ op1 = build1 (NOP_EXPR, tmp2, op1);
+
+ tmp1 = tree_cons (NULL_TREE, op1, NULL_TREE);
+ tmp1 = tree_cons (NULL_TREE, op0, tmp1);
+ tmp1 = build_function_call_expr (impl_fndecl, tmp1);
+
+ tmp2 = rs6000_builtin_types[tmpl->result_type_index];
+ if (!COMPAT (tmp2, TREE_TYPE (TREE_TYPE (impl_fndecl))))
+ tmp1 = build1 (NOP_EXPR, tmp2, tmp1);
+
+ return tmp1;
+ }
+
+
+ static tree
+ altivec_expand_overloaded_builtin (tree fndecl, tree params)
+ {
+ int fcode = DECL_FUNCTION_CODE (fndecl);
+
+ switch (fcode)
+ {
+ case ALTIVEC_BUILTIN_VEC_ADD:
+ return altivec_expand_overloaded_binary (fndecl, params, a_o_b_vec_add);
+ default:
+ break;
+ }
+
+ return NULL_TREE;
+ }
+
+
/* Binops that need to be initialized manually, but can be expanded
automagically by rs6000_expand_binop_builtin. */
static struct builtin_description bdesc_2arg_spe[] =
*************** altivec_init_builtins (void)
*** 7191,7196 ****
--- 7386,7394 ----
def_builtin (d->mask, d->name, type, d->code);
}
+
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_vec_add",
+ make_node (FUNCTION_TYPE), ALTIVEC_BUILTIN_VEC_ADD);
}
static void
Index: config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.319
diff -c -p -d -r1.319 rs6000.h
*** config/rs6000/rs6000.h 25 Mar 2004 17:43:20 -0000 1.319
--- config/rs6000/rs6000.h 13 Apr 2004 18:03:57 -0000
*************** enum rs6000_builtins
*** 2902,2907 ****
--- 2902,2912 ----
ALTIVEC_BUILTIN_ABS_V16QI,
ALTIVEC_BUILTIN_COMPILETIME_ERROR,
+ /* Altivec "generic" aka overloaded builtins. */
+ ALTIVEC_BUILTIN_overload_min,
+ ALTIVEC_BUILTIN_VEC_ADD = ALTIVEC_BUILTIN_overload_min,
+ ALTIVEC_BUILTIN_overload_max,
+
/* SPE builtins. */
SPE_BUILTIN_EVADDW,
SPE_BUILTIN_EVAND,
*************** enum rs6000_builtins
*** 3135,3139 ****
SPE_BUILTIN_EVMWHGUMIAN,
SPE_BUILTIN_MTSPEFSCR,
SPE_BUILTIN_MFSPEFSCR,
! SPE_BUILTIN_BRINC
};
--- 3140,3146 ----
SPE_BUILTIN_EVMWHGUMIAN,
SPE_BUILTIN_MTSPEFSCR,
SPE_BUILTIN_MFSPEFSCR,
! SPE_BUILTIN_BRINC,
!
! RS6000_BUILT_IN_MAX
};