This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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
  };


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]