public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [ping][patch] Fixed-point patch 3/10
@ 2007-08-01 23:54 Fu, Chao-Ying
  2007-08-06  3:52 ` Mark Mitchell
  2007-08-06 21:37 ` Tom Tromey
  0 siblings, 2 replies; 9+ messages in thread
From: Fu, Chao-Ying @ 2007-08-01 23:54 UTC (permalink / raw)
  To: gcc-patches; +Cc: Thekkath, Radhika, Stephens, Nigel, Mark Mitchell

[-- Attachment #1: Type: text/plain, Size: 11939 bytes --]

Hi,

  Here is the patch #3.  Please review it.  Thanks!

> 1. Merge in machine modes to support signed and unsigned
> fract and accum modes.  Handle scalar and vector modes.
DONE!
> 2. Merge in fixed-value.h and fixed-value.c to handle fixed-point values.
(fixed-value.diff)
> 3. Merge in TREE structures for fixed-point types and constants.
(tree.diff)
> 4. Merge in C front-end changes to parse _Sat, _Fract and _Accum.
> 5. Merge in RTL structures for fixed-point constants and operators.
> 6. Merge in libcpp to parse fixed-point constants.
> 7. Merge in changes to support "case" of FIXED_POINT_TYPE, FIXED_CST,
> and CONST_FIXED in .c and .h files.
> 8. Merge in the MIPS backend that supports fixed-point instructions.
> 9. Merge in configure/build system changes for the runtime library.
> 10. Merge in testsuite (from gcc.dg/fixed-point) that only run
> when the compiler is configured to enable fixed-point.

Regards,
Chao-ying

gcc/ChangeLog
2007-08-01  Chao-ying Fu  <fu@mips.com>

	* tree.def (FIXED_POINT_TYPE): New type.
	(FIXED_CST): New constant.
	(FIXED_CONVERT_EXPR): New expr.
	* doc/c-tree.texi (Types): Document FIXED_POINT_TYPE.
	(Expressions): Document FIXED_CST and FIXED_CONVERT_EXPR.
	* tree.h (struct tree_base): Add saturating_flag.
	Remove one bit of spare for saturating_flag.
	(NUMERICAL_TYPE_CHECK): Support FIXED_POINT_TYPE.
	(NON_SAT_FIXED_POINT_TYPE_P, SAT_FIXED_POINT_TYPE_P,
	FIXED_POINT_TYPE_P): Define.
	(TYPE_SATURATING): Define.
	(TREE_FIXED_CST_PTR, TREE_FIXED_CST): Define.
	(struct tree_fixed_cst): New.
	(TYPE_IBIT, TYPE_FBIT): Define.
	(tree_node): Add fixed_cst.
	(enum tree_index): Add new enumeration values of
	TI_SAT_SFRACT_TYPE, TI_SAT_FRACT_TYPE, TI_SAT_LFRACT_TYPE,
	TI_SAT_LLFRACT_TYPE, TI_SAT_USFRACT_TYPE, TI_SAT_UFRACT_TYPE,
	TI_SAT_ULFRACT_TYPE, TI_SAT_ULLFRACT_TYPE, TI_SFRACT_TYPE,
	TI_FRACT_TYPE, TI_LFRACT_TYPE, TI_LLFRACT_TYPE, TI_USFRACT_TYPE,
	TI_UFRACT_TYPE, TI_ULFRACT_TYPE, TI_ULLFRACT_TYPE,
	TI_SAT_SACCUM_TYPE, TI_SAT_ACCUM_TYPE, TI_SAT_LACCUM_TYPE,
	TI_SAT_LLACCUM_TYPE, TI_SAT_USACCUM_TYPE, TI_SAT_UACCUM_TYPE,
	TI_SAT_ULACCUM_TYPE, TI_SAT_ULLACCUM_TYPE, TI_SACCUM_TYPE,
	TI_ACCUM_TYPE, TI_LACCUM_TYPE, TI_LLACCUM_TYPE, TI_USACCUM_TYPE,
	TI_UACCUM_TYPE, TI_ULACCUM_TYPE, TI_ULLACCUM_TYPE,
	TI_QQ_TYPE, TI_HQ_TYPE,_TYPE, TI_SQ_TYPE, TI_DQ_TYPE, TI_TQ_TYPE,
	TI_UQQ_TYPE, TI_UHQ_TYPE, TI_USQ_TYPE, TI_UDQ_TYPE, TI_UTQ_TYPE,
	TI_SAT_QQ_TYPE, TI_SAT_HQ_TYPE, TI_SAT_SQ_TYPE, TI_SAT_DQ_TYPE,
	TI_SAT_TQ_TYPE, TI_SAT_UQQ_TYPE, TI_SAT_UHQ_TYPE, TI_SAT_USQ_TYPE,
	TI_SAT_UDQ_TYPE, TI_SAT_UTQ_TYPE, TI_HA_TYPE, TI_SA_TYPE, TI_DA_TYPE,
	TI_TA_TYPE, TI_UHA_TYPE, TI_USA_TYPE, TI_UDA_TYPE, TI_UTA_TYPE,
	TI_SAT_HA_TYPE, TI_SAT_SA_TYPE, TI_SAT_DA_TYPE, TI_SAT_TA_TYPE,
	TI_SAT_UHA_TYPE, TI_SAT_USA_TYPE, TI_SAT_UDA_TYPE, TI_SAT_UTA_TYPE.
	(sat_short_fract_type_node, sat_fract_type_node,
	sat_long_fract_type_node, sat_long_long_fract_type_node,
	sat_unsigned_short_fract_type_node, sat_unsigned_fract_type_node,
	sat_unsigned_long_fract_type_node,
	sat_unsigned_long_long_fract_type_node, short_fract_type_node,
	fract_type_node, long_fract_type_node, long_long_fract_type_node,
	unsigned_short_fract_type_node, unsigned_fract_type_node,
	unsigned_long_fract_type_node, unsigned_long_long_fract_type_node,
	sat_short_accum_type_node, sat_accum_type_node,
	sat_long_accum_type_node, sat_long_long_accum_type_node,
	sat_unsigned_short_accum_type_node, sat_unsigned_accum_type_node,
	sat_unsigned_long_accum_type_node,
	sat_unsigned_long_long_accum_type_node, short_accum_type_node,
	accum_type_node, long_accum_type_node, long_long_accum_type_node,
	unsigned_short_accum_type_node, unsigned_accum_type_node,
	unsigned_long_accum_type_node, unsigned_long_long_accum_type_node,
	qq_type_node, hq_type_node, sq_type_node, dq_type_node, tq_type_node,
	uqq_type_node, uhq_type_node, usq_type_node, udq_type_node,
	utq_type_node, sat_qq_type_node, sat_hq_type_node, sat_sq_type_node,
	sat_dq_type_node, sat_tq_type_node, sat_uqq_type_node,
	sat_uhq_type_node, sat_usq_type_node, sat_udq_type_node,
	sat_utq_type_node, ha_type_node, sa_type_node, da_type_node
	ta_type_node, uha_type_node, usa_type_node, uda_type_node,
	uta_type_node, sat_ha_type_node, sat_sa_type_node, sat_da_type_node,
	sat_ta_type_node, sat_uha_type_node, sat_usa_type_node,
	sat_uda_type_node, sat_uta_type_node): New macro.
	(make_fract_type, make_accum_type): Declare.
	(make_signed_fract_type, make_unsigned_fract_type,
	make_sat_signed_fract_type, make_sat_unsigned_fract_type,
	make_signed_accum_type, make_unsigned_accum_type,
	make_sat_signed_accum_type, make_sat_unsigned_accum_type,
	make_or_reuse_signed_fract_type, make_or_reuse_unsigned_fract_type,
	make_or_reuse_sat_signed_fract_type,
	make_or_reuse_sat_unsigned_fract_type, make_or_reuse_signed_accum_type,
	make_or_reuse_unsigned_accum_type, make_or_reuse_sat_signed_accum_type,
	make_or_reuse_sat_unsigned_accum_type): New macro.
	(fixed_zerop): Declare.
	* defaults.h (SHORT_FRACT_TYPE_SIZE, FRACT_TYPE_SIZE,
	LONG_FRACT_TYPE_SIZE, LONG_LONG_FRACT_TYPE_SIZE,
	SHORT_ACCUM_TYPE_SIZE, ACCUM_TYPE_SIZE, LONG_ACCUM_TYPE_SIZE,
	LONG_LONG_ACCUM_TYPE_SIZE): Define.
	* treestruct.def: Add TS_FIXED_CST.
	* Makefile.in (c-pretty-print.o): Add dependence on fixed-value.h.
	(tree.o): Likewise.
	(tree-dump.o): Likewise.
	(print-tree.o): Likewise.
	(tree-pretty-print.o): Likewise.
	(fold-const.o): Likewise.
	* tree-complex.c (some_nonzerop): Handle FIXED_CST.
	* tree-gimple.c (is_gimple_formal_tmp_rhs): Handle FIXED_CST.
	(is_gimple_min_invariant): Handle FIXED_CST.
	* stor-layout.c (int_mode_for_mode): Handle MODE_FRACT, MODE_UFRACT,
	MODE_ACCUM, MODE_UACCUM, MODE_VECTOR_FRACT, MODE_VECTOR_UFRACT,
	MODE_VECTOR_ACCUM, MODE_VECTOR_UACCUM.
	(layout_type): Handle FIXED_POINT_TYPE.
	(make_fract_type, make_accum_type): New functions.
	* tree-browser.c (browse_tree): Handle FIXED_POINT_TYPE.
	* tree-dump.c (fixed-value.h): New include.
	(dump_fixed): New function.
	(dequeue_and_dump): Handle FIXED_POINT_TYPE and FIXED_CST.
	* tree-inline.c (remap_type_1): Handle FIXED_POINT_TYPE.
	(estimate_num_insns_1): Handle FIXED_CST and FIXED_CONVERT_EXPR.
	* tree-pretty-print.c (fixed-value.h): New include.
	(dump_generic_node): Handle FIXED_POINT_TYPE, FIXED_CST, and
	FIXED_CONVERT_EXPR.
	* tree-scalar-evolution.c (get_scalar_evolution): Handle FIXED_CST.
	* tree-ssa-loop-im.c (for_each_index): Handle FIXED_CST.
	* tree-ssa-pre.c (poolify_tree): Handle FIXED_CST.
	* tree-ssa-reassoc.c (break_up_subtract_bb): We can do reassociation
	for non-saturating fixed-point types
	(reassociate_bb): Likewise.
	* emit-rtl.c (fixed-value.h): New include.
	(fconst0, fconst1): New array.
	(init_emit_once): Initialize fconst0 and fconst1 for fixed-point modes.
	* tree-vect-generic.c expand_vector_operation): Support
	MODE_VECTOR_FRACT, MODE_VECTOR_UFRACT, MODE_VECTOR_ACCUM, and
	MODE_VECTOR_UACCUM.
	(type_for_widest_vector_mode): Add one parameter for the 
	saturating flag.
	Check scalar FRACT, UFRACT, ACCUM, and UACCUM mode to select their
	vector mode.
	Pass the satp parameter to type_for_mode for fixed-point types.
	(expand_vector_operations_1): Pass the saturating flag to
	type_for_widest_vector_mode.
	Support MODE_VECTOR_FRACT, MODE_VECTOR_UFRACT, MODE_VECTOR_ACCUM,
	and MODE_VECTOR_UACCUM.
	* tree-vect-transform.c (vect_is_simple_cond): Support FIXED_CST.
	(vectorizable_condition): Likewise.
	* tree.c (fixed-value.h): New include.
	(tree_code_size): Support FIXED_CST.
	(build_fixed): New function.
	(build_one_cst): Support FIXED_POINT_TYPE for accum types.
	(fixed_zerop): New function.
	(tree_node_structure): Support FIXED_CST.
	(type_contains_placeholder_1): Support FIXED_POINT_TYPE.
	(build_type_attribute_qual_variant): Handle FIXED_POINT_TYPE.
	(type_hash_eq): Handle FIXED_POINT_TYPE.
	(simple_cst_equal): Support FIXED_CST.
	(iterative_hash_expr): Handle FIXED_CST.
	(get_unwidened): Make sure type is not FIXED_POINT_TYPE.
	(get_narrower): Likewise.
	(variably_modified_type_p): Handle FIXED_POINT_TYPE.
	(make_or_reuse_fract_type, make_or_reuse_accum_type): New functions.
	(build_common_tree_nodes_2): Use MAKE_FIXED_TYPE_NODE_FAMILY and
	MAKE_FIXED_MODE_NODE macros to initialize fixed-point type
	nodes.
	(build_vector_type_for_mode): Handle MODE_VECTOR_FRACT,
	MODE_VECTOR_UFRACT, MODE_VECTOR_ACCUM, MODE_VECTOR_UACCUM.
	(initializer_zerop): Support FIXED_CST.
	(walk_tree): Handle FIXED_CST and FIXED_POINT_TYPE.
	* dwarf2out.c (base_type_die): Use DW_ATE_signed_fixed or
	DW_ATE_unsigned_fixed to describe FIXED_POINT_TYPE.
	(is_base_type): Handle FIXED_POINT_TYPE.
	(add_type_attribute): Handle FIXED_POINT_TYPE.
	(gen_type_die_with_usage): Handle FIXED_POINT_TYPE.
	* print-tree.c (fixed-value.h): New include.
	(print_node_brief): Support FIXED_CST.
	(print_node): Support FIXED_POINT_TYPE and FIXED_CST.
	* c-pretty-print.c (fixed-value.h): New include.
	(pp_c_type_specifier): Handle FIXED_POINT_TYPE.  Need to pass
	TYPE_SATURATING to c_common_type_for_mode for fixed-point modes.
	(pp_c_direct_abstract_declarator): Handle FIXED_POINT_TYPE.
	Support fixed-point types for inner items in VECTOR_TYPE.
	(pp_c_direct_declarator): Likewise.
	(pp_c_declarator): Likewise.
	(pp_c_fixed_constant): New function.
	(pp_c_constant): Handle FIXED_CST.
	(pp_c_primary_expression): Likewise.
	(pp_c_expression): Likewise.
	* fold-const.c (fixed-value.h): New include.
	(negate_expr_p): Return true for FIXED_CST.
	(fold_negate_expr): Support FIXED_CST.
	(split_tree): Support FIXED_CST.
	(const_binop): Support FIXED_CST.
	(fold_convert_const_int_from_fixed): New function to convert from
	fixed to int.
	(fold_convert_const_real_from_fixed): New function to convert from
	fixed to real.
	(fold_convert_const_fixed_from_fixed): New function to convert from
	fixed to another fixed.
	(fold_convert_const_fixed_from_int): New function to convert from
	int to fixed.
	(fold_convert_const_fixed_from_real): New function to convert from
	real to fixed.
	(fold_convert_const): Support conversions from fixed to int, from
	fixed to real, from fixed to fixed, from int to fixed, and from real
	to fixed.
	(fold_convert): Support FIXED_CST and FIXED_POINT_TYPE.
	(operand_equal_p): Support FIXED_CST.
	(make_range): For fixed-point modes, we need to pass the
	saturating flag as the 2nd parameter.
	(tree_swap_operands_p): Handle FIXED_CST.
	(fold_plusminus_mult_expr): For fract modes, we cannot generate
	constant 1.
	(fold_unary): Support FIXED_CONVERT_EXPR.
	(fold_binary): Handle FIXED_CST.
	Make sure the type is not saturating, before associating operations.
	Ex: A + B + C, A * B * C, (A1 * C1) +/- (A2 * C2).
	(tree_expr_nonnegative_warnv_p): Handle FIXED_CST.
	(fold_negate_const): Support FIXED_CST.
	(fold_relational_const): Support FIXED_CST.
	* gimplify.c (omp_firstprivatize_type_sizes): Handle FIXED_POINT_TYPE.
	(gimplify_expr): Handle FIXED_CST.
	(gimplify_type_sizes): Handle FIXED_POINT_TYPE.
	* ipa-prop.c (ipa_callsite_compute_param): Support FIXED_CST.
	* ipa-type-escape.c (type_to_consider): Handle FIXED_POINT_TYPE.
	* doc/tm.texi (Type Layout): Document SHORT_FRACT_TYPE_SIZE,
	FRACT_TYPE_SIZE, LONG_FRACT_TYPE_SIZE, LONG_LONG_FRACT_TYPE_SIZE,
	SHORT_ACCUM_TYPE_SIZE, ACCUM_TYPE_SIZE, LONG_ACCUM_TYPE_SIZE,
	LONG_LONG_ACCUM_TYPE_SIZE.
	* dbxout.c (dbxout_type): Handle FIXED_POINT_TYPE.
	* c-aux-info.c (gen_type): Handle FIXED_POINT_TYPE.
	* tree-sra.c (is_sra_scalar_type): Support FIXED_POINT_TYPE.
	* expmed.c (extract_bit_field): Support MODE_FRACT, MODE_UFRACT,
	MODE_ACCUM, and MODE_UACCUM.
	* tree-vectorizer.c (vect_is_simple_reduction): Check for saturating
	fixed-point types to disable reduction.
	* explow.c (promote_mode): Support FIXED_POINT_TYPE.




[-- Attachment #2: tree.diff --]
[-- Type: application/octet-stream, Size: 83243 bytes --]

Index: gcc4x/gcc/gcc/tree.def
===================================================================
--- gcc4x.orig/gcc/gcc/tree.def	2007-08-01 11:56:20.000000000 -0700
+++ gcc4x/gcc/gcc/tree.def	2007-08-01 14:39:26.000000000 -0700
@@ -172,6 +172,11 @@
    The TREE_TYPE points to the node for the type pointed to.  */
 DEFTREECODE (POINTER_TYPE, "pointer_type", tcc_type, 0)
 
+/* _Fract and _Accum types in Embedded-C.  Different fixed-point types
+   are distinguished by machine mode and by the TYPE_SIZE and the
+   TYPE_PRECISION.  */
+DEFTREECODE (FIXED_POINT_TYPE, "fixed_point_type", tcc_type, 0)
+
 /* A reference is like a pointer except that it is coerced
    automatically to the value it points to.  Used in C++.  */
 DEFTREECODE (REFERENCE_TYPE, "reference_type", tcc_type, 0)
@@ -272,6 +277,9 @@
 /* Contents are in TREE_REAL_CST field.  */
 DEFTREECODE (REAL_CST, "real_cst", tcc_constant, 0)
 
+/* Contents are in TREE_FIXED_CST field.  */
+DEFTREECODE (FIXED_CST, "fixed_cst", tcc_constant, 0)
+
 /* Contents are in TREE_REALPART and TREE_IMAGPART fields,
    whose contents are other constant nodes.  */
 DEFTREECODE (COMPLEX_CST, "complex_cst", tcc_constant, 0)
@@ -730,6 +738,11 @@
    represented by CONVERT_EXPR or NOP_EXPR nodes.  */
 DEFTREECODE (CONVERT_EXPR, "convert_expr", tcc_unary, 1)
 
+/* Conversion of a fixed-point value to an integer, a real, or a fixed-point
+   value.  Or conversion of a fixed-point value from an integer, a real, or
+   a fixed-point value.  */
+DEFTREECODE (FIXED_CONVERT_EXPR, "fixed_convert_expr", tcc_unary, 1)
+
 /* Represents a conversion expected to require no code to be generated.  */
 DEFTREECODE (NOP_EXPR, "nop_expr", tcc_unary, 1)
 
Index: gcc4x/gcc/gcc/doc/c-tree.texi
===================================================================
--- gcc4x.orig/gcc/gcc/doc/c-tree.texi	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/doc/c-tree.texi	2007-08-01 14:39:26.000000000 -0700
@@ -271,6 +271,7 @@
 @tindex TYPE_MIN_VALUE
 @tindex TYPE_MAX_VALUE
 @tindex REAL_TYPE
+@tindex FIXED_POINT_TYPE
 @tindex COMPLEX_TYPE
 @tindex ENUMERAL_TYPE
 @tindex BOOLEAN_TYPE
@@ -498,6 +499,19 @@
 double} types.  The number of bits in the floating-point representation
 is given by @code{TYPE_PRECISION}, as in the @code{INTEGER_TYPE} case.
 
+@item FIXED_POINT_TYPE
+Used to represent the @code{short _Fract}, @code{_Fract}, @code{long
+_Fract}, @code{long long _Fract}, @code{short _Accum}, @code{_Accum},
+@code{long _Accum}, and @code{long long _Accum} types.  The number of bits
+in the fixed-point representation is given by @code{TYPE_PRECISION},
+as in the @code{INTEGER_TYPE} case.  There may be padding bits, fractional
+bits and integral bits.  The number of fractional bits is given by
+@code{TYPE_FBIT}, and the number of integral bits is given by @code{TYPE_IBIT}.
+The fixed-point type is unsigned if @code{TYPE_UNSIGNED} holds; otherwise,
+it is signed.
+The fixed-point type is saturating if @code{TYPE_SATURATING} holds; otherwise,
+it is not saturating.
+
 @item COMPLEX_TYPE
 Used to represent GCC built-in @code{__complex__} data types.  The
 @code{TREE_TYPE} is the type of the real and imaginary parts.
@@ -1879,6 +1893,7 @@
 @findex tree_int_cst_lt
 @findex tree_int_cst_equal
 @tindex REAL_CST
+@tindex FIXED_CST
 @tindex COMPLEX_CST
 @tindex VECTOR_CST
 @tindex STRING_CST
@@ -1907,6 +1922,7 @@
 @tindex NON_LVALUE_EXPR
 @tindex NOP_EXPR
 @tindex CONVERT_EXPR
+@tindex FIXED_CONVERT_EXPR
 @tindex THROW_EXPR
 @tindex LSHIFT_EXPR
 @tindex RSHIFT_EXPR
@@ -2080,6 +2096,15 @@
 FIXME: Talk about how to obtain representations of this constant, do
 comparisons, and so forth.
 
+@item FIXED_CST
+
+These nodes represent fixed-point constants.  The type of these constants
+is obtained with @code{TREE_TYPE}.  @code{TREE_FIXED_CST_PTR} points to
+to struct fixed_value;  @code{TREE_FIXED_CST} returns the structure itself.
+Struct fixed_value contains @code{data} with the size of two
+HOST_BITS_PER_WIDE_INT and @code{mode} as the associated fixed-point
+machine mode for @code{data}.
+
 @item COMPLEX_CST
 These nodes are used to represent complex number constants, that is a
 @code{__complex__} whose parts are constant nodes.  The
@@ -2246,6 +2271,13 @@
 conversion is never represented by a @code{CONVERT_EXPR}; instead, the
 function calls are made explicit.
 
+@item FIXED_CONVERT_EXPR
+These nodes are used to represent conversions that involve fixed-point
+values.  For example, from a fixed-point value to another fixed-point value,
+from an integer to a fixed-point value, from a fixed-point value to an
+integer, from a floating-point value to a fixed-point value, or from
+a fixed-point value to a floating-point value.
+
 @item THROW_EXPR
 These nodes represent @code{throw} expressions.  The single operand is
 an expression for the code that should be executed to throw the
Index: gcc4x/gcc/gcc/tree.h
===================================================================
--- gcc4x.orig/gcc/gcc/tree.h	2007-08-01 11:56:20.000000000 -0700
+++ gcc4x/gcc/gcc/tree.h	2007-08-01 14:39:26.000000000 -0700
@@ -384,6 +384,7 @@
   unsigned protected_flag : 1;
   unsigned deprecated_flag : 1;
   unsigned invariant_flag : 1;
+  unsigned saturating_flag : 1;
 
   unsigned lang_flag_0 : 1;
   unsigned lang_flag_1 : 1;
@@ -394,7 +395,7 @@
   unsigned lang_flag_6 : 1;
   unsigned visited : 1;
 
-  unsigned spare : 24;
+  unsigned spare : 23;
 
   /* FIXME tuples: Eventually, we need to move this somewhere external to
      the trees.  */
@@ -575,6 +576,11 @@
 	TREE_INVARIANT in
 	    all expressions.
 
+   saturating_flag:
+
+       TYPE_SATURATING in
+           all types
+
    nowarning_flag:
 
        TREE_NO_WARNING in
@@ -951,7 +957,8 @@
   TREE_NOT_CHECK3 (T, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE)
 
 #define NUMERICAL_TYPE_CHECK(T)					\
-  TREE_CHECK4 (T, INTEGER_TYPE, ENUMERAL_TYPE, BOOLEAN_TYPE, REAL_TYPE)
+  TREE_CHECK5 (T, INTEGER_TYPE, ENUMERAL_TYPE, BOOLEAN_TYPE, REAL_TYPE,	\
+	       FIXED_POINT_TYPE)
 
 /* Nonzero if NODE is a GIMPLE statement.  */
 #define GIMPLE_STMT_P(NODE) \
@@ -1039,6 +1046,20 @@
    || TREE_CODE (TYPE) == BOOLEAN_TYPE \
    || TREE_CODE (TYPE) == INTEGER_TYPE)
 
+/* Nonzero if TYPE represents a non-saturating fixed-point type.  */
+
+#define NON_SAT_FIXED_POINT_TYPE_P(TYPE) \
+  (TREE_CODE (TYPE) == FIXED_POINT_TYPE && !TYPE_SATURATING (TYPE))
+
+/* Nonzero if TYPE represents a saturating fixed-point type.  */
+
+#define SAT_FIXED_POINT_TYPE_P(TYPE) \
+  (TREE_CODE (TYPE) == FIXED_POINT_TYPE && TYPE_SATURATING (TYPE))
+
+/* Nonzero if TYPE represents a fixed-point type.  */
+
+#define FIXED_POINT_TYPE_P(TYPE)	(TREE_CODE (TYPE) == FIXED_POINT_TYPE)
+
 /* Nonzero if TYPE represents a scalar floating-point type.  */
 
 #define SCALAR_FLOAT_TYPE_P(TYPE) (TREE_CODE (TYPE) == REAL_TYPE)
@@ -1336,6 +1357,9 @@
    any expression node.  */
 #define TREE_INVARIANT(NODE) ((NODE)->base.invariant_flag)
 
+/* In fixed-point types, means a saturating type.  */
+#define TYPE_SATURATING(NODE) ((NODE)->base.saturating_flag)
+
 /* These flags are available for each language front end to use internally.  */
 #define TREE_LANG_FLAG_0(NODE) ((NODE)->base.lang_flag_0)
 #define TREE_LANG_FLAG_1(NODE) ((NODE)->base.lang_flag_1)
@@ -1387,6 +1411,18 @@
   struct real_value * real_cst_ptr;
 };
 
+/* In a FIXED_CST node.  */
+struct fixed_value;
+
+#define TREE_FIXED_CST_PTR(NODE) (FIXED_CST_CHECK (NODE)->fixed_cst.fixed_cst_ptr)
+#define TREE_FIXED_CST(NODE) (*TREE_FIXED_CST_PTR (NODE))
+
+struct tree_fixed_cst GTY(())
+{
+  struct tree_common common;
+  struct fixed_value * fixed_cst_ptr;
+};
+
 /* In a STRING_CST */
 #define TREE_STRING_LENGTH(NODE) (STRING_CST_CHECK (NODE)->string.length)
 #define TREE_STRING_POINTER(NODE) \
@@ -2084,6 +2120,8 @@
    type node requires structural equality. */
 #define SET_TYPE_STRUCTURAL_EQUALITY(NODE) (TYPE_CANONICAL (NODE) = NULL_TREE)
 #define TYPE_LANG_SPECIFIC(NODE) (TYPE_CHECK (NODE)->type.lang_specific)
+#define TYPE_IBIT(NODE) (GET_MODE_IBIT (TYPE_MODE (NODE)))
+#define TYPE_FBIT(NODE) (GET_MODE_FBIT (TYPE_MODE (NODE)))
 
 /* For a VECTOR_TYPE node, this describes a different type which is emitted
    in the debugging output.  We use this to describe a vector as a
@@ -3365,6 +3403,7 @@
   struct tree_common GTY ((tag ("TS_COMMON"))) common;
   struct tree_int_cst GTY ((tag ("TS_INT_CST"))) int_cst;
   struct tree_real_cst GTY ((tag ("TS_REAL_CST"))) real_cst;
+  struct tree_fixed_cst GTY ((tag ("TS_FIXED_CST"))) fixed_cst;
   struct tree_vector GTY ((tag ("TS_VECTOR"))) vector;
   struct tree_string GTY ((tag ("TS_STRING"))) string;
   struct tree_complex GTY ((tag ("TS_COMPLEX"))) complex;
@@ -3476,6 +3515,75 @@
 
   TI_MAIN_IDENTIFIER,
 
+  TI_SAT_SFRACT_TYPE,
+  TI_SAT_FRACT_TYPE,
+  TI_SAT_LFRACT_TYPE,
+  TI_SAT_LLFRACT_TYPE,
+  TI_SAT_USFRACT_TYPE,
+  TI_SAT_UFRACT_TYPE,
+  TI_SAT_ULFRACT_TYPE,
+  TI_SAT_ULLFRACT_TYPE,
+  TI_SFRACT_TYPE,
+  TI_FRACT_TYPE,
+  TI_LFRACT_TYPE,
+  TI_LLFRACT_TYPE,
+  TI_USFRACT_TYPE,
+  TI_UFRACT_TYPE,
+  TI_ULFRACT_TYPE,
+  TI_ULLFRACT_TYPE,
+  TI_SAT_SACCUM_TYPE,
+  TI_SAT_ACCUM_TYPE,
+  TI_SAT_LACCUM_TYPE,
+  TI_SAT_LLACCUM_TYPE,
+  TI_SAT_USACCUM_TYPE,
+  TI_SAT_UACCUM_TYPE,
+  TI_SAT_ULACCUM_TYPE,
+  TI_SAT_ULLACCUM_TYPE,
+  TI_SACCUM_TYPE,
+  TI_ACCUM_TYPE,
+  TI_LACCUM_TYPE,
+  TI_LLACCUM_TYPE,
+  TI_USACCUM_TYPE,
+  TI_UACCUM_TYPE,
+  TI_ULACCUM_TYPE,
+  TI_ULLACCUM_TYPE,
+  TI_QQ_TYPE,
+  TI_HQ_TYPE,
+  TI_SQ_TYPE,
+  TI_DQ_TYPE,
+  TI_TQ_TYPE,
+  TI_UQQ_TYPE,
+  TI_UHQ_TYPE,
+  TI_USQ_TYPE,
+  TI_UDQ_TYPE,
+  TI_UTQ_TYPE,
+  TI_SAT_QQ_TYPE,
+  TI_SAT_HQ_TYPE,
+  TI_SAT_SQ_TYPE,
+  TI_SAT_DQ_TYPE,
+  TI_SAT_TQ_TYPE,
+  TI_SAT_UQQ_TYPE,
+  TI_SAT_UHQ_TYPE,
+  TI_SAT_USQ_TYPE,
+  TI_SAT_UDQ_TYPE,
+  TI_SAT_UTQ_TYPE,
+  TI_HA_TYPE,
+  TI_SA_TYPE,
+  TI_DA_TYPE,
+  TI_TA_TYPE,
+  TI_UHA_TYPE,
+  TI_USA_TYPE,
+  TI_UDA_TYPE,
+  TI_UTA_TYPE,
+  TI_SAT_HA_TYPE,
+  TI_SAT_SA_TYPE,
+  TI_SAT_DA_TYPE,
+  TI_SAT_TA_TYPE,
+  TI_SAT_UHA_TYPE,
+  TI_SAT_USA_TYPE,
+  TI_SAT_UDA_TYPE,
+  TI_SAT_UTA_TYPE,
+
   TI_MAX
 };
 
@@ -3555,6 +3663,84 @@
 #define dfloat64_ptr_type_node          global_trees[TI_DFLOAT64_PTR_TYPE]
 #define dfloat128_ptr_type_node         global_trees[TI_DFLOAT128_PTR_TYPE]
 
+/* The fixed-point types.  */
+#define sat_short_fract_type_node       global_trees[TI_SAT_SFRACT_TYPE]
+#define sat_fract_type_node             global_trees[TI_SAT_FRACT_TYPE]
+#define sat_long_fract_type_node        global_trees[TI_SAT_LFRACT_TYPE]
+#define sat_long_long_fract_type_node   global_trees[TI_SAT_LLFRACT_TYPE]
+#define sat_unsigned_short_fract_type_node \
+					global_trees[TI_SAT_USFRACT_TYPE]
+#define sat_unsigned_fract_type_node    global_trees[TI_SAT_UFRACT_TYPE]
+#define sat_unsigned_long_fract_type_node \
+					global_trees[TI_SAT_ULFRACT_TYPE]
+#define sat_unsigned_long_long_fract_type_node \
+					global_trees[TI_SAT_ULLFRACT_TYPE]
+#define short_fract_type_node           global_trees[TI_SFRACT_TYPE]
+#define fract_type_node                 global_trees[TI_FRACT_TYPE]
+#define long_fract_type_node            global_trees[TI_LFRACT_TYPE]
+#define long_long_fract_type_node       global_trees[TI_LLFRACT_TYPE]
+#define unsigned_short_fract_type_node  global_trees[TI_USFRACT_TYPE]
+#define unsigned_fract_type_node        global_trees[TI_UFRACT_TYPE]
+#define unsigned_long_fract_type_node   global_trees[TI_ULFRACT_TYPE]
+#define unsigned_long_long_fract_type_node \
+					global_trees[TI_ULLFRACT_TYPE]
+#define sat_short_accum_type_node       global_trees[TI_SAT_SACCUM_TYPE]
+#define sat_accum_type_node             global_trees[TI_SAT_ACCUM_TYPE]
+#define sat_long_accum_type_node        global_trees[TI_SAT_LACCUM_TYPE]
+#define sat_long_long_accum_type_node   global_trees[TI_SAT_LLACCUM_TYPE]
+#define sat_unsigned_short_accum_type_node \
+					global_trees[TI_SAT_USACCUM_TYPE]
+#define sat_unsigned_accum_type_node    global_trees[TI_SAT_UACCUM_TYPE]
+#define sat_unsigned_long_accum_type_node \
+					global_trees[TI_SAT_ULACCUM_TYPE]
+#define sat_unsigned_long_long_accum_type_node \
+					global_trees[TI_SAT_ULLACCUM_TYPE]
+#define short_accum_type_node           global_trees[TI_SACCUM_TYPE]
+#define accum_type_node                 global_trees[TI_ACCUM_TYPE]
+#define long_accum_type_node            global_trees[TI_LACCUM_TYPE]
+#define long_long_accum_type_node       global_trees[TI_LLACCUM_TYPE]
+#define unsigned_short_accum_type_node  global_trees[TI_USACCUM_TYPE]
+#define unsigned_accum_type_node        global_trees[TI_UACCUM_TYPE]
+#define unsigned_long_accum_type_node   global_trees[TI_ULACCUM_TYPE]
+#define unsigned_long_long_accum_type_node \
+					global_trees[TI_ULLACCUM_TYPE]
+#define qq_type_node                    global_trees[TI_QQ_TYPE]
+#define hq_type_node                    global_trees[TI_HQ_TYPE]
+#define sq_type_node                    global_trees[TI_SQ_TYPE]
+#define dq_type_node                    global_trees[TI_DQ_TYPE]
+#define tq_type_node                    global_trees[TI_TQ_TYPE]
+#define uqq_type_node                   global_trees[TI_UQQ_TYPE]
+#define uhq_type_node                   global_trees[TI_UHQ_TYPE]
+#define usq_type_node                   global_trees[TI_USQ_TYPE]
+#define udq_type_node                   global_trees[TI_UDQ_TYPE]
+#define utq_type_node                   global_trees[TI_UTQ_TYPE]
+#define sat_qq_type_node                global_trees[TI_SAT_QQ_TYPE]
+#define sat_hq_type_node                global_trees[TI_SAT_HQ_TYPE]
+#define sat_sq_type_node                global_trees[TI_SAT_SQ_TYPE]
+#define sat_dq_type_node                global_trees[TI_SAT_DQ_TYPE]
+#define sat_tq_type_node                global_trees[TI_SAT_TQ_TYPE]
+#define sat_uqq_type_node               global_trees[TI_SAT_UQQ_TYPE]
+#define sat_uhq_type_node               global_trees[TI_SAT_UHQ_TYPE]
+#define sat_usq_type_node               global_trees[TI_SAT_USQ_TYPE]
+#define sat_udq_type_node               global_trees[TI_SAT_UDQ_TYPE]
+#define sat_utq_type_node               global_trees[TI_SAT_UTQ_TYPE]
+#define ha_type_node                    global_trees[TI_HA_TYPE]
+#define sa_type_node                    global_trees[TI_SA_TYPE]
+#define da_type_node                    global_trees[TI_DA_TYPE]
+#define ta_type_node                    global_trees[TI_TA_TYPE]
+#define uha_type_node                   global_trees[TI_UHA_TYPE]
+#define usa_type_node                   global_trees[TI_USA_TYPE]
+#define uda_type_node                   global_trees[TI_UDA_TYPE]
+#define uta_type_node                   global_trees[TI_UTA_TYPE]
+#define sat_ha_type_node                global_trees[TI_SAT_HA_TYPE]
+#define sat_sa_type_node                global_trees[TI_SAT_SA_TYPE]
+#define sat_da_type_node                global_trees[TI_SAT_DA_TYPE]
+#define sat_ta_type_node                global_trees[TI_SAT_TA_TYPE]
+#define sat_uha_type_node               global_trees[TI_SAT_UHA_TYPE]
+#define sat_usa_type_node               global_trees[TI_SAT_USA_TYPE]
+#define sat_uda_type_node               global_trees[TI_SAT_UDA_TYPE]
+#define sat_uta_type_node               global_trees[TI_SAT_UTA_TYPE]
+
 /* The node that should be placed at the end of a parameter list to
    indicate that the function does not take a variable number of
    arguments.  The TREE_VALUE will be void_type_node and there will be
@@ -3834,6 +4020,37 @@
 extern bool may_negate_without_overflow_p (const_tree);
 extern tree get_inner_array_type (const_tree);
 
+/* Construct various nodes representing fract or accum data types.  */
+
+extern tree make_fract_type (int, int, int);
+extern tree make_accum_type (int, int, int);
+
+#define make_signed_fract_type(P) make_fract_type (P, 0, 0)
+#define make_unsigned_fract_type(P) make_fract_type (P, 1, 0)
+#define make_sat_signed_fract_type(P) make_fract_type (P, 0, 1)
+#define make_sat_unsigned_fract_type(P) make_fract_type (P, 1, 1)
+#define make_signed_accum_type(P) make_accum_type (P, 0, 0)
+#define make_unsigned_accum_type(P) make_accum_type (P, 1, 0)
+#define make_sat_signed_accum_type(P) make_accum_type (P, 0, 1)
+#define make_sat_unsigned_accum_type(P) make_accum_type (P, 1, 1)
+
+#define make_or_reuse_signed_fract_type(P) \
+		make_or_reuse_fract_type (P, 0, 0)
+#define make_or_reuse_unsigned_fract_type(P) \
+		make_or_reuse_fract_type (P, 1, 0)
+#define make_or_reuse_sat_signed_fract_type(P) \
+		make_or_reuse_fract_type (P, 0, 1)
+#define make_or_reuse_sat_unsigned_fract_type(P) \
+		make_or_reuse_fract_type (P, 1, 1)
+#define make_or_reuse_signed_accum_type(P) \
+		make_or_reuse_accum_type (P, 0, 0)
+#define make_or_reuse_unsigned_accum_type(P) \
+		make_or_reuse_accum_type (P, 1, 0)
+#define make_or_reuse_sat_signed_accum_type(P) \
+		make_or_reuse_accum_type (P, 0, 1)
+#define make_or_reuse_sat_unsigned_accum_type(P) \
+		make_or_reuse_accum_type (P, 1, 1)
+
 /* From expmed.c.  Since rtl.h is included after tree.h, we can't
    put the prototype here.  Rtl.h does declare the prototype if
    tree.h had been included.  */
@@ -4209,6 +4426,11 @@
 extern bool cst_and_fits_in_hwi (const_tree);
 extern tree num_ending_zeros (const_tree);
 
+/* fixed_zerop (tree x) is nonzero if X is a fixed-point constant of
+   value 0.  */
+
+extern int fixed_zerop (tree);
+
 /* staticp (tree x) is nonzero if X is a reference to data allocated
    at a fixed address in memory.  Returns the outermost data.  */
 
Index: gcc4x/gcc/gcc/defaults.h
===================================================================
--- gcc4x.orig/gcc/gcc/defaults.h	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/defaults.h	2007-08-01 14:39:26.000000000 -0700
@@ -454,6 +454,38 @@
 #define DECIMAL128_TYPE_SIZE 128
 #endif
 
+#ifndef SHORT_FRACT_TYPE_SIZE
+#define SHORT_FRACT_TYPE_SIZE BITS_PER_UNIT
+#endif
+
+#ifndef FRACT_TYPE_SIZE
+#define FRACT_TYPE_SIZE (BITS_PER_UNIT * 2)
+#endif
+
+#ifndef LONG_FRACT_TYPE_SIZE
+#define LONG_FRACT_TYPE_SIZE (BITS_PER_UNIT * 4)
+#endif
+
+#ifndef LONG_LONG_FRACT_TYPE_SIZE
+#define LONG_LONG_FRACT_TYPE_SIZE (BITS_PER_UNIT * 8)
+#endif
+
+#ifndef SHORT_ACCUM_TYPE_SIZE
+#define SHORT_ACCUM_TYPE_SIZE (SHORT_FRACT_TYPE_SIZE * 2)
+#endif
+
+#ifndef ACCUM_TYPE_SIZE
+#define ACCUM_TYPE_SIZE (FRACT_TYPE_SIZE * 2)
+#endif
+
+#ifndef LONG_ACCUM_TYPE_SIZE
+#define LONG_ACCUM_TYPE_SIZE (LONG_FRACT_TYPE_SIZE * 2)
+#endif
+
+#ifndef LONG_LONG_ACCUM_TYPE_SIZE
+#define LONG_LONG_ACCUM_TYPE_SIZE (LONG_LONG_FRACT_TYPE_SIZE * 2)
+#endif
+
 /* Width in bits of a pointer.  Mind the value of the macro `Pmode'.  */
 #ifndef POINTER_SIZE
 #define POINTER_SIZE BITS_PER_WORD
Index: gcc4x/gcc/gcc/treestruct.def
===================================================================
--- gcc4x.orig/gcc/gcc/treestruct.def	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/treestruct.def	2007-08-01 14:39:26.000000000 -0700
@@ -31,6 +31,7 @@
 DEFTREESTRUCT(TS_COMMON, "common")
 DEFTREESTRUCT(TS_INT_CST, "integer cst")
 DEFTREESTRUCT(TS_REAL_CST, "real cst")
+DEFTREESTRUCT(TS_FIXED_CST, "fixed cst")
 DEFTREESTRUCT(TS_VECTOR, "vector")
 DEFTREESTRUCT(TS_STRING, "string")
 DEFTREESTRUCT(TS_COMPLEX, "complex")
Index: gcc4x/gcc/gcc/Makefile.in
===================================================================
--- gcc4x.orig/gcc/gcc/Makefile.in	2007-08-01 14:39:24.000000000 -0700
+++ gcc4x/gcc/gcc/Makefile.in	2007-08-01 14:39:26.000000000 -0700
@@ -1772,7 +1772,7 @@
 
 c-pretty-print.o : c-pretty-print.c $(C_PRETTY_PRINT_H) \
 	$(C_TREE_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(REAL_H) \
-	$(DIAGNOSTIC_H) tree-iterator.h
+	$(DIAGNOSTIC_H) tree-iterator.h fixed-value.h
 
 c-opts.o : c-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)		\
         $(TREE_H) $(C_PRAGMA_H) $(FLAGS_H) toplev.h langhooks.h		\
@@ -1932,10 +1932,10 @@
    $(FLAGS_H) $(FUNCTION_H) $(PARAMS_H) \
    toplev.h $(GGC_H) $(HASHTAB_H) $(TARGET_H) output.h $(TM_P_H) langhooks.h \
    $(REAL_H) gt-tree.h tree-iterator.h $(BASIC_BLOCK_H) $(TREE_FLOW_H) \
-   $(OBSTACK_H) pointer-set.h
+   $(OBSTACK_H) pointer-set.h fixed-value.h
 tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TREE_H) langhooks.h toplev.h $(SPLAY_TREE_H) $(TREE_DUMP_H) \
-   tree-iterator.h tree-pass.h $(DIAGNOSTIC_H) $(REAL_H)
+   tree-iterator.h tree-pass.h $(DIAGNOSTIC_H) $(REAL_H) fixed-value.h
 tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TREE_H) $(RTL_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h insn-config.h \
    $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h \
@@ -1943,7 +1943,7 @@
    debug.h $(DIAGNOSTIC_H) $(TREE_FLOW_H) tree-iterator.h tree-mudflap.h \
    ipa-prop.h value-prof.h
 print-tree.o : print-tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
-   $(GGC_H) langhooks.h $(REAL_H) tree-iterator.h
+   $(GGC_H) langhooks.h $(REAL_H) tree-iterator.h fixed-value.h
 stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TREE_H) $(PARAMS_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) $(RTL_H) \
    $(GGC_H) $(TM_P_H) $(TARGET_H) langhooks.h $(REGS_H) gt-stor-layout.h \
@@ -2267,10 +2267,10 @@
 tree-pretty-print.o : tree-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \
    $(TREE_H) $(DIAGNOSTIC_H) $(REAL_H) $(HASHTAB_H) $(TREE_FLOW_H) \
    $(TM_H) coretypes.h tree-iterator.h tree-chrec.h langhooks.h tree-pass.h \
-   value-prof.h
+   value-prof.h fixed-value.h
 fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TREE_H) $(FLAGS_H) $(REAL_H) toplev.h $(HASHTAB_H) $(EXPR_H) $(RTL_H) \
-   $(GGC_H) $(TM_P_H) langhooks.h $(MD5_H) intl.h
+   $(GGC_H) $(TM_P_H) langhooks.h $(MD5_H) intl.h fixed-value.h
 diagnostic.o : diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TREE_H) version.h $(TM_P_H) $(FLAGS_H) input.h toplev.h intl.h \
    $(DIAGNOSTIC_H) langhooks.h $(LANGHOOKS_DEF_H) diagnostic.def opts.h
Index: gcc4x/gcc/gcc/tree-complex.c
===================================================================
--- gcc4x.orig/gcc/gcc/tree-complex.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/tree-complex.c	2007-08-01 14:39:26.000000000 -0700
@@ -96,6 +96,8 @@
 
   if (TREE_CODE (t) == REAL_CST)
     zerop = REAL_VALUES_IDENTICAL (TREE_REAL_CST (t), dconst0);
+  else if (TREE_CODE (t) == FIXED_CST)
+    zerop = fixed_zerop (t);
   else if (TREE_CODE (t) == INTEGER_CST)
     zerop = integer_zerop (t);
 
Index: gcc4x/gcc/gcc/tree-gimple.c
===================================================================
--- gcc4x.orig/gcc/gcc/tree-gimple.c	2007-08-01 11:56:20.000000000 -0700
+++ gcc4x/gcc/gcc/tree-gimple.c	2007-08-01 14:39:26.000000000 -0700
@@ -67,6 +67,7 @@
     case COMPLEX_EXPR:
     case INTEGER_CST:
     case REAL_CST:
+    case FIXED_CST:
     case STRING_CST:
     case COMPLEX_CST:
     case VECTOR_CST:
@@ -178,6 +179,7 @@
 
     case INTEGER_CST:
     case REAL_CST:
+    case FIXED_CST:
     case STRING_CST:
     case COMPLEX_CST:
     case VECTOR_CST:
Index: gcc4x/gcc/gcc/stor-layout.c
===================================================================
--- gcc4x.orig/gcc/gcc/stor-layout.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/stor-layout.c	2007-08-01 14:39:26.000000000 -0700
@@ -236,6 +236,14 @@
     case MODE_DECIMAL_FLOAT:
     case MODE_VECTOR_INT:
     case MODE_VECTOR_FLOAT:
+    case MODE_FRACT:
+    case MODE_ACCUM:
+    case MODE_UFRACT:
+    case MODE_UACCUM:
+    case MODE_VECTOR_FRACT:
+    case MODE_VECTOR_ACCUM:
+    case MODE_VECTOR_UFRACT:
+    case MODE_VECTOR_UACCUM:
       mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
       break;
 
@@ -1602,6 +1610,12 @@
       TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
       break;
 
+   case FIXED_POINT_TYPE:
+     /* TYPE_MODE (type) has been set already.  */
+     TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
+     TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
+     break;
+
     case COMPLEX_TYPE:
       TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
       TYPE_MODE (type)
@@ -1629,6 +1643,14 @@
 	    /* First, look for a supported vector type.  */
 	    if (SCALAR_FLOAT_MODE_P (innermode))
 	      mode = MIN_MODE_VECTOR_FLOAT;
+	    else if (SCALAR_FRACT_MODE_P (innermode))
+	      mode = MIN_MODE_VECTOR_FRACT;
+	    else if (SCALAR_UFRACT_MODE_P (innermode))
+	      mode = MIN_MODE_VECTOR_UFRACT;
+	    else if (SCALAR_ACCUM_MODE_P (innermode))
+	      mode = MIN_MODE_VECTOR_ACCUM;
+	    else if (SCALAR_UACCUM_MODE_P (innermode))
+	      mode = MIN_MODE_VECTOR_UACCUM;
 	    else
 	      mode = MIN_MODE_VECTOR_INT;
 
@@ -1650,6 +1672,7 @@
 	      TYPE_MODE (type) = mode;
 	  }
 
+	TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type));
         TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
 	TYPE_SIZE_UNIT (type) = int_const_binop (MULT_EXPR,
 					         TYPE_SIZE_UNIT (innertype),
@@ -1905,6 +1928,58 @@
   return type;
 }
 \f
+/* Create and return a type for fract of PRECISION bits, UNSIGNEDP,
+   and SATP.  */
+
+tree
+make_fract_type (int precision, int unsignedp, int satp)
+{
+  tree type = make_node (FIXED_POINT_TYPE);
+
+  TYPE_PRECISION (type) = precision;
+
+  if (satp)
+    TYPE_SATURATING (type) = 1;
+
+  /* Lay out the type: set its alignment, size, etc.  */
+  if (unsignedp)
+    {
+      TYPE_UNSIGNED (type) = 1;
+      TYPE_MODE (type) = mode_for_size (precision, MODE_UFRACT, 0);
+    }
+  else
+    TYPE_MODE (type) = mode_for_size (precision, MODE_FRACT, 0);
+  layout_type (type);
+
+  return type;
+}
+
+/* Create and return a type for accum of PRECISION bits, UNSIGNEDP,
+   and SATP.  */
+
+tree
+make_accum_type (int precision, int unsignedp, int satp)
+{
+  tree type = make_node (FIXED_POINT_TYPE);
+
+  TYPE_PRECISION (type) = precision;
+
+  if (satp)
+    TYPE_SATURATING (type) = 1;
+
+  /* Lay out the type: set its alignment, size, etc.  */
+  if (unsignedp)
+    {
+      TYPE_UNSIGNED (type) = 1;
+      TYPE_MODE (type) = mode_for_size (precision, MODE_UACCUM, 0);
+    }
+  else
+    TYPE_MODE (type) = mode_for_size (precision, MODE_ACCUM, 0);
+  layout_type (type);
+
+  return type;
+}
+
 /* Initialize sizetype and bitsizetype to a reasonable and temporary
    value to enable integer types to be created.  */
 
Index: gcc4x/gcc/gcc/tree-browser.c
===================================================================
--- gcc4x.orig/gcc/gcc/tree-browser.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/tree-browser.c	2007-08-01 14:39:26.000000000 -0700
@@ -162,7 +162,8 @@
 
 	case TB_MAX:
 	  if (head && (INTEGRAL_TYPE_P (head)
-		       || TREE_CODE (head) == REAL_TYPE))
+		       || TREE_CODE (head) == REAL_TYPE
+		       || TREE_CODE (head) == FIXED_POINT_TYPE))
 	    TB_SET_HEAD (TYPE_MAX_VALUE (head));
 	  else
 	    TB_WF;
@@ -170,7 +171,8 @@
 
 	case TB_MIN:
 	  if (head && (INTEGRAL_TYPE_P (head)
-		       || TREE_CODE (head) == REAL_TYPE))
+		       || TREE_CODE (head) == REAL_TYPE
+		       || TREE_CODE (head) == FIXED_POINT_TYPE))
 	    TB_SET_HEAD (TYPE_MIN_VALUE (head));
 	  else
 	    TB_WF;
Index: gcc4x/gcc/gcc/tree-dump.c
===================================================================
--- gcc4x.orig/gcc/gcc/tree-dump.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/tree-dump.c	2007-08-01 14:39:26.000000000 -0700
@@ -32,6 +32,7 @@
 #include "langhooks.h"
 #include "tree-iterator.h"
 #include "real.h"
+#include "fixed-value.h"
 
 static unsigned int queue (dump_info_p, tree, int);
 static void dump_index (dump_info_p, unsigned int);
@@ -191,6 +192,18 @@
   di->column += strlen (buf) + 7;
 }
 
+/* Dump the fixed-point value F, using FIELD to identify it.  */
+
+static void
+dump_fixed (dump_info_p di, const char *field, const FIXED_VALUE_TYPE *f)
+{
+  char buf[32];
+  fixed_to_decimal (buf, f, sizeof (buf));
+  dump_maybe_newline (di);
+  fprintf (di->stream, "%-4s: %s ", field, buf);
+  di->column += strlen (buf) + 7;
+}
+
 
 /* Dump the string S.  */
 
@@ -453,6 +466,13 @@
       dump_int (di, "prec", TYPE_PRECISION (t));
       break;
 
+    case FIXED_POINT_TYPE:
+      dump_int (di, "prec", TYPE_PRECISION (t));
+      dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
+      dump_string_field (di, "saturating",
+			 TYPE_SATURATING (t) ? "saturating": "non-saturating");
+      break;
+
     case POINTER_TYPE:
       dump_child ("ptd", TREE_TYPE (t));
       break;
@@ -549,6 +569,10 @@
       dump_real (di, "valu", TREE_REAL_CST_PTR (t));
       break;
 
+    case FIXED_CST:
+      dump_fixed (di, "valu", TREE_FIXED_CST_PTR (t));
+      break;
+
     case TRUTH_NOT_EXPR:
     case ADDR_EXPR:
     case INDIRECT_REF:
Index: gcc4x/gcc/gcc/tree-inline.c
===================================================================
--- gcc4x.orig/gcc/gcc/tree-inline.c	2007-08-01 11:56:20.000000000 -0700
+++ gcc4x/gcc/gcc/tree-inline.c	2007-08-01 14:39:26.000000000 -0700
@@ -340,6 +340,7 @@
     {
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
     case ENUMERAL_TYPE:
     case BOOLEAN_TYPE:
       t = TYPE_MIN_VALUE (new);
@@ -2020,6 +2021,7 @@
     case IDENTIFIER_NODE:
     case INTEGER_CST:
     case REAL_CST:
+    case FIXED_CST:
     case COMPLEX_CST:
     case VECTOR_CST:
     case STRING_CST:
@@ -2085,6 +2087,7 @@
     case MINUS_EXPR:
     case MULT_EXPR:
 
+    case FIXED_CONVERT_EXPR:
     case FIX_TRUNC_EXPR:
 
     case NEGATE_EXPR:
Index: gcc4x/gcc/gcc/tree-pretty-print.c
===================================================================
--- gcc4x.orig/gcc/gcc/tree-pretty-print.c	2007-08-01 11:56:20.000000000 -0700
+++ gcc4x/gcc/gcc/tree-pretty-print.c	2007-08-01 14:39:26.000000000 -0700
@@ -32,6 +32,7 @@
 #include "tree-iterator.h"
 #include "tree-chrec.h"
 #include "tree-pass.h"
+#include "fixed-value.h"
 #include "value-prof.h"
 
 /* Local functions, macros and variables.  */
@@ -527,6 +528,7 @@
     case VOID_TYPE:
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
     case COMPLEX_TYPE:
     case VECTOR_TYPE:
     case ENUMERAL_TYPE:
@@ -804,6 +806,14 @@
 	break;
       }
 
+    case FIXED_CST:
+      {
+	char string[100];
+	fixed_to_decimal (string, TREE_FIXED_CST_PTR (node), sizeof (string));
+	pp_string (buffer, string);
+	break;
+      }
+
     case COMPLEX_CST:
       pp_string (buffer, "__complex__ (");
       dump_generic_node (buffer, TREE_REALPART (node), spc, flags, false);
@@ -1378,6 +1388,7 @@
       NIY;
       break;
 
+    case FIXED_CONVERT_EXPR:
     case FIX_TRUNC_EXPR:
     case FLOAT_EXPR:
     case CONVERT_EXPR:
Index: gcc4x/gcc/gcc/tree-scalar-evolution.c
===================================================================
--- gcc4x.orig/gcc/gcc/tree-scalar-evolution.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/tree-scalar-evolution.c	2007-08-01 14:39:26.000000000 -0700
@@ -600,6 +600,7 @@
       break;
 
     case REAL_CST:
+    case FIXED_CST:
     case INTEGER_CST:
       res = scalar;
       break;
Index: gcc4x/gcc/gcc/tree-ssa-loop-im.c
===================================================================
--- gcc4x.orig/gcc/gcc/tree-ssa-loop-im.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/tree-ssa-loop-im.c	2007-08-01 14:39:26.000000000 -0700
@@ -204,6 +204,7 @@
 	case COMPLEX_CST:
 	case INTEGER_CST:
 	case REAL_CST:
+	case FIXED_CST:
 	  return true;
 
 	case TARGET_MEM_REF:
Index: gcc4x/gcc/gcc/tree-ssa-pre.c
===================================================================
--- gcc4x.orig/gcc/gcc/tree-ssa-pre.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/tree-ssa-pre.c	2007-08-01 14:39:26.000000000 -0700
@@ -3081,6 +3081,7 @@
     case INTEGER_CST:
     case STRING_CST:
     case REAL_CST:
+    case FIXED_CST:
     case PARM_DECL:
     case VAR_DECL:
     case RESULT_DECL:
Index: gcc4x/gcc/gcc/tree-ssa-reassoc.c
===================================================================
--- gcc4x.orig/gcc/gcc/tree-ssa-reassoc.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/tree-ssa-reassoc.c	2007-08-01 14:39:26.000000000 -0700
@@ -1245,12 +1245,15 @@
 
 	  TREE_VISITED (stmt) = 0;
 	  /* If unsafe math optimizations we can do reassociation for
-	     non-integral types.  */
+	     non-integral types.  Or, we can do reassociation for
+	     non-saturating fixed-point types.  */
 	  if ((!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
 	       || !INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
 	      && (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs))
 		  || !SCALAR_FLOAT_TYPE_P (TREE_TYPE(lhs))
-		  || !flag_unsafe_math_optimizations))
+		  || !flag_unsafe_math_optimizations)
+	      && (!NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE (rhs))
+		  || !NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE(lhs))))
 	    continue;
 
 	  /* Check for a subtract used only in an addition.  If this
@@ -1292,12 +1295,15 @@
 	    continue;
 
 	  /* If unsafe math optimizations we can do reassociation for
-	     non-integral types.  */
+	     non-integral types.  Or, we can do reassociation for
+	     non-saturating fixed-point types.  */
 	  if ((!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
 	       || !INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
 	      && (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs))
 		  || !SCALAR_FLOAT_TYPE_P (TREE_TYPE(lhs))
-		  || !flag_unsafe_math_optimizations))
+		  || !flag_unsafe_math_optimizations)
+	      && (!NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE (rhs))
+		  || !NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE(lhs))))
 	    continue;
 
 	  if (associative_tree_code (TREE_CODE (rhs)))
Index: gcc4x/gcc/gcc/emit-rtl.c
===================================================================
--- gcc4x.orig/gcc/gcc/emit-rtl.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/emit-rtl.c	2007-08-01 14:39:26.000000000 -0700
@@ -50,6 +50,7 @@
 #include "insn-config.h"
 #include "recog.h"
 #include "real.h"
+#include "fixed-value.h"
 #include "bitmap.h"
 #include "basic-block.h"
 #include "ggc.h"
@@ -108,6 +109,10 @@
 REAL_VALUE_TYPE dconstsqrt2;
 REAL_VALUE_TYPE dconste;
 
+/* Record fixed-point constant 0 and 1.  */
+FIXED_VALUE_TYPE fconst0[MAX_FCONST0];
+FIXED_VALUE_TYPE fconst1[MAX_FCONST1];
+
 /* All references to the following fixed hard registers go through
    these unique rtl objects.  On machines where the frame-pointer and
    arg-pointer are the same register, they use the same unique object.
@@ -5248,6 +5253,62 @@
       const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1);
     }
 
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_FRACT);
+       mode != VOIDmode;
+       mode = GET_MODE_WIDER_MODE (mode))
+    {
+      FCONST0(mode).data.high = 0;
+      FCONST0(mode).data.low = 0;
+      FCONST0(mode).mode = mode;
+    }
+
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_UFRACT);
+       mode != VOIDmode;
+       mode = GET_MODE_WIDER_MODE (mode))
+    {
+      FCONST0(mode).data.high = 0;
+      FCONST0(mode).data.low = 0;
+      FCONST0(mode).mode = mode;
+    }
+
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_ACCUM);
+       mode != VOIDmode;
+       mode = GET_MODE_WIDER_MODE (mode))
+    {
+      FCONST0(mode).data.high = 0;
+      FCONST0(mode).data.low = 0;
+      FCONST0(mode).mode = mode;
+
+      /* We store the value 1.  */
+      FCONST1(mode).data.high = 0;
+      FCONST1(mode).data.low = 0;
+      FCONST1(mode).mode = mode;
+      lshift_double (1, 0, GET_MODE_FBIT (mode),
+                     2 * HOST_BITS_PER_WIDE_INT,
+                     &FCONST1(mode).data.low,
+		     &FCONST1(mode).data.high,
+                     SIGNED_FIXED_POINT_MODE_P (mode));
+    }
+
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_UACCUM);
+       mode != VOIDmode;
+       mode = GET_MODE_WIDER_MODE (mode))
+    {
+      FCONST0(mode).data.high = 0;
+      FCONST0(mode).data.low = 0;
+      FCONST0(mode).mode = mode;
+
+      /* We store the value 1.  */
+      FCONST1(mode).data.high = 0;
+      FCONST1(mode).data.low = 0;
+      FCONST1(mode).mode = mode;
+      lshift_double (1, 0, GET_MODE_FBIT (mode),
+                     2 * HOST_BITS_PER_WIDE_INT,
+                     &FCONST1(mode).data.low,
+		     &FCONST1(mode).data.high,
+                     SIGNED_FIXED_POINT_MODE_P (mode));
+    }
+
   for (i = (int) CCmode; i < (int) MAX_MACHINE_MODE; ++i)
     if (GET_MODE_CLASS ((enum machine_mode) i) == MODE_CC)
       const_tiny_rtx[0][i] = const0_rtx;
Index: gcc4x/gcc/gcc/tree-vect-generic.c
===================================================================
--- gcc4x.orig/gcc/gcc/tree-vect-generic.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/tree-vect-generic.c	2007-08-01 14:39:26.000000000 -0700
@@ -295,7 +295,11 @@
      a BLKmode vector to smaller, hardware-supported vectors), we may want
      to expand the operations in parallel.  */
   if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT)
+      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
+      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
+      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
+      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
+      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
     switch (code)
       {
       case PLUS_EXPR:
@@ -340,15 +344,25 @@
 }
 \f
 /* Return a type for the widest vector mode whose components are of mode
-   INNER_MODE, or NULL_TREE if none is found.  */
+   INNER_MODE, or NULL_TREE if none is found.
+   SATP is true for saturating fixed-point types.  */
+
 static tree
-type_for_widest_vector_mode (enum machine_mode inner_mode, optab op)
+type_for_widest_vector_mode (enum machine_mode inner_mode, optab op, int satp)
 {
   enum machine_mode best_mode = VOIDmode, mode;
   int best_nunits = 0;
 
   if (SCALAR_FLOAT_MODE_P (inner_mode))
     mode = MIN_MODE_VECTOR_FLOAT;
+  else if (SCALAR_FRACT_MODE_P (inner_mode))
+    mode = MIN_MODE_VECTOR_FRACT;
+  else if (SCALAR_UFRACT_MODE_P (inner_mode))
+    mode = MIN_MODE_VECTOR_UFRACT;
+  else if (SCALAR_ACCUM_MODE_P (inner_mode))
+    mode = MIN_MODE_VECTOR_ACCUM;
+  else if (SCALAR_UACCUM_MODE_P (inner_mode))
+    mode = MIN_MODE_VECTOR_UACCUM;
   else
     mode = MIN_MODE_VECTOR_INT;
 
@@ -361,7 +375,13 @@
   if (best_mode == VOIDmode)
     return NULL_TREE;
   else
-    return lang_hooks.types.type_for_mode (best_mode, 1);
+    {
+      /* For fixed-point modes, we need to pass satp as the 2nd parameter.  */
+      if (ALL_FIXED_POINT_MODE_P (best_mode))
+	return lang_hooks.types.type_for_mode (best_mode, satp);
+
+      return lang_hooks.types.type_for_mode (best_mode, 1);
+    }
 }
 
 /* Process one statement.  If we identify a vector operation, expand it.  */
@@ -445,7 +465,8 @@
   if (TYPE_MODE (type) == BLKmode && op)
     {
       tree vector_compute_type
-        = type_for_widest_vector_mode (TYPE_MODE (TREE_TYPE (type)), op);
+        = type_for_widest_vector_mode (TYPE_MODE (TREE_TYPE (type)), op,
+				       TYPE_SATURATING (TREE_TYPE (type)));
       if (vector_compute_type != NULL_TREE)
         compute_type = vector_compute_type;
     }
@@ -457,7 +478,11 @@
     {
       compute_mode = TYPE_MODE (compute_type);
       if ((GET_MODE_CLASS (compute_mode) == MODE_VECTOR_INT
-	   || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FLOAT)
+	   || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FLOAT
+	   || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FRACT
+	   || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_UFRACT
+	   || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_ACCUM
+	   || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_UACCUM)
           && op != NULL
 	  && op->handlers[compute_mode].insn_code != CODE_FOR_nothing)
 	return;
Index: gcc4x/gcc/gcc/tree-vect-transform.c
===================================================================
--- gcc4x.orig/gcc/gcc/tree-vect-transform.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/tree-vect-transform.c	2007-08-01 14:39:26.000000000 -0700
@@ -4913,7 +4913,8 @@
       if (!vect_is_simple_use (lhs, loop_vinfo, &lhs_def_stmt, &def, &dt))
 	return false;
     }
-  else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST)
+  else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST
+	   && TREE_CODE (lhs) != FIXED_CST)
     return false;
 
   if (TREE_CODE (rhs) == SSA_NAME)
@@ -4922,7 +4923,8 @@
       if (!vect_is_simple_use (rhs, loop_vinfo, &rhs_def_stmt, &def, &dt))
 	return false;
     }
-  else if (TREE_CODE (rhs) != INTEGER_CST  && TREE_CODE (rhs) != REAL_CST)
+  else if (TREE_CODE (rhs) != INTEGER_CST  && TREE_CODE (rhs) != REAL_CST
+	   && TREE_CODE (rhs) != FIXED_CST)
     return false;
 
   return true;
@@ -5003,7 +5005,8 @@
 	return false;
     }
   else if (TREE_CODE (then_clause) != INTEGER_CST 
-	   && TREE_CODE (then_clause) != REAL_CST)
+	   && TREE_CODE (then_clause) != REAL_CST
+	   && TREE_CODE (then_clause) != FIXED_CST)
     return false;
 
   if (TREE_CODE (else_clause) == SSA_NAME)
@@ -5014,7 +5017,8 @@
 	return false;
     }
   else if (TREE_CODE (else_clause) != INTEGER_CST 
-	   && TREE_CODE (else_clause) != REAL_CST)
+	   && TREE_CODE (else_clause) != REAL_CST
+	   && TREE_CODE (else_clause) != FIXED_CST)
     return false;
 
 
Index: gcc4x/gcc/gcc/tree.c
===================================================================
--- gcc4x.orig/gcc/gcc/tree.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/tree.c	2007-08-01 14:39:26.000000000 -0700
@@ -50,6 +50,7 @@
 #include "tree-flow.h"
 #include "params.h"
 #include "pointer-set.h"
+#include "fixed-value.h"
 
 /* Each tree code class has an associated string representation.
    These must correspond to the tree_code_class entries.  */
@@ -399,6 +400,7 @@
 	{
 	case INTEGER_CST:	return sizeof (struct tree_int_cst);
 	case REAL_CST:		return sizeof (struct tree_real_cst);
+	case FIXED_CST:		return sizeof (struct tree_fixed_cst);
 	case COMPLEX_CST:	return sizeof (struct tree_complex);
 	case VECTOR_CST:	return sizeof (struct tree_vector);
 	case STRING_CST:	gcc_unreachable ();
@@ -1095,6 +1097,22 @@
   return t;
 }
 
+/* Return a new FIXED_CST node whose type is TYPE and value is F.  */
+
+tree
+build_fixed (tree type, FIXED_VALUE_TYPE f)
+{
+  tree v;
+  FIXED_VALUE_TYPE *fp;
+
+  v = make_node (FIXED_CST);
+  fp = ggc_alloc (sizeof (FIXED_VALUE_TYPE));
+  memcpy (fp, &f, sizeof (FIXED_VALUE_TYPE));
+
+  TREE_TYPE (v) = type;
+  TREE_FIXED_CST_PTR (v) = fp;
+  return v;
+}
 
 /* Return a new REAL_CST node whose type is TYPE and value is D.  */
 
@@ -1215,6 +1233,11 @@
     case REAL_TYPE:
       return build_real (type, dconst1);
 
+    case FIXED_POINT_TYPE:
+      /* We can only generate 1 for accum types.  */
+      gcc_assert (ALL_SCALAR_ACCUM_MODE_P (TYPE_MODE (type)));
+      return build_fixed (type, FCONST1(TYPE_MODE (type)));
+
     case VECTOR_TYPE:
       {
 	tree scalar, cst;
@@ -1434,6 +1457,15 @@
 		  || integer_nonzerop (TREE_IMAGPART (expr)))));
 }
 
+/* Return 1 if EXPR is the fixed-point constant zero.  */
+
+int
+fixed_zerop (tree expr)
+{
+  return (TREE_CODE (expr) == FIXED_CST
+	  && double_int_zero_p (TREE_FIXED_CST (expr).data));
+}
+
 /* Return the power of two represented by a tree node known to be a
    power of two.  */
 
@@ -2184,6 +2216,7 @@
       /* tcc_constant cases.  */
     case INTEGER_CST:		return TS_INT_CST;
     case REAL_CST:		return TS_REAL_CST;
+    case FIXED_CST:		return TS_FIXED_CST;
     case COMPLEX_CST:		return TS_COMPLEX;
     case VECTOR_CST:		return TS_VECTOR;
     case STRING_CST:		return TS_STRING;
@@ -2324,6 +2357,7 @@
 
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
       /* Here we just check the bounds.  */
       return (CONTAINS_PLACEHOLDER_P (TYPE_MIN_VALUE (type))
 	      || CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type)));
@@ -3677,6 +3711,7 @@
 	    (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (ntype)), hashcode);
 	  break;
 	case REAL_TYPE:
+	case FIXED_POINT_TYPE:
 	  {
 	    unsigned int precision = TYPE_PRECISION (ntype);
 	    hashcode = iterative_hash_object (precision, hashcode);
@@ -4551,6 +4586,9 @@
 		  || tree_int_cst_equal (TYPE_MIN_VALUE (a->type),
 					 TYPE_MIN_VALUE (b->type))));
 
+    case FIXED_POINT_TYPE:
+      return TYPE_SATURATING (a->type) == TYPE_SATURATING (b->type);
+
     case OFFSET_TYPE:
       return TYPE_OFFSET_BASETYPE (a->type) == TYPE_OFFSET_BASETYPE (b->type);
 
@@ -5011,6 +5049,9 @@
     case REAL_CST:
       return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
 
+    case FIXED_CST:
+      return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1), TREE_FIXED_CST (t2));
+
     case STRING_CST:
       return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
 	      && ! memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
@@ -5234,6 +5275,12 @@
 
 	return iterative_hash_hashval_t (val2, val);
       }
+    case FIXED_CST:
+      {
+	unsigned int val2 = fixed_hash (TREE_FIXED_CST_PTR (t));
+
+	return iterative_hash_hashval_t (val2, val);
+      }
     case STRING_CST:
       return iterative_hash (TREE_STRING_POINTER (t),
 			     TREE_STRING_LENGTH (t), val);
@@ -6064,6 +6111,7 @@
   if (TREE_CODE (op) == COMPONENT_REF
       /* Since type_for_size always gives an integer type.  */
       && TREE_CODE (type) != REAL_TYPE
+      && TREE_CODE (type) != FIXED_POINT_TYPE
       /* Don't crash if field not laid out yet.  */
       && DECL_SIZE (TREE_OPERAND (op, 1)) != 0
       && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1))
@@ -6155,6 +6203,7 @@
   if (TREE_CODE (op) == COMPONENT_REF
       /* Since type_for_size always gives an integer type.  */
       && TREE_CODE (TREE_TYPE (op)) != REAL_TYPE
+      && TREE_CODE (TREE_TYPE (op)) != FIXED_POINT_TYPE
       /* Ensure field is laid out already.  */
       && DECL_SIZE (TREE_OPERAND (op, 1)) != 0
       && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1))
@@ -6378,6 +6427,7 @@
 
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
     case ENUMERAL_TYPE:
     case BOOLEAN_TYPE:
       /* Scalar types are variably modified if their end points
@@ -7048,6 +7098,80 @@
     return make_signed_type (size);
 }
 
+/* Create or reuse a fract type by SIZE, UNSIGNEDP, and SATP.  */
+
+static tree
+make_or_reuse_fract_type (unsigned size, int unsignedp, int satp)
+{
+  if (satp)
+    {
+      if (size == SHORT_FRACT_TYPE_SIZE)
+	return unsignedp ? sat_unsigned_short_fract_type_node
+			 : sat_short_fract_type_node;
+      if (size == FRACT_TYPE_SIZE)
+	return unsignedp ? sat_unsigned_fract_type_node : sat_fract_type_node;
+      if (size == LONG_FRACT_TYPE_SIZE)
+	return unsignedp ? sat_unsigned_long_fract_type_node
+			 : sat_long_fract_type_node;
+      if (size == LONG_LONG_FRACT_TYPE_SIZE)
+	return unsignedp ? sat_unsigned_long_long_fract_type_node
+			 : sat_long_long_fract_type_node;
+    }
+  else
+    {
+      if (size == SHORT_FRACT_TYPE_SIZE)
+	return unsignedp ? unsigned_short_fract_type_node
+			 : short_fract_type_node;
+      if (size == FRACT_TYPE_SIZE)
+	return unsignedp ? unsigned_fract_type_node : fract_type_node;
+      if (size == LONG_FRACT_TYPE_SIZE)
+	return unsignedp ? unsigned_long_fract_type_node
+			 : long_fract_type_node;
+      if (size == LONG_LONG_FRACT_TYPE_SIZE)
+	return unsignedp ? unsigned_long_long_fract_type_node
+			 : long_long_fract_type_node;
+    }
+
+  return make_fract_type (size, unsignedp, satp);
+}
+
+/* Create or reuse an accum type by SIZE, UNSIGNEDP, and SATP.  */
+
+static tree
+make_or_reuse_accum_type (unsigned size, int unsignedp, int satp)
+{
+  if (satp)
+    {
+      if (size == SHORT_ACCUM_TYPE_SIZE)
+	return unsignedp ? sat_unsigned_short_accum_type_node
+			 : sat_short_accum_type_node;
+      if (size == ACCUM_TYPE_SIZE)
+	return unsignedp ? sat_unsigned_accum_type_node : sat_accum_type_node;
+      if (size == LONG_ACCUM_TYPE_SIZE)
+	return unsignedp ? sat_unsigned_long_accum_type_node
+			 : sat_long_accum_type_node;
+      if (size == LONG_LONG_ACCUM_TYPE_SIZE)
+	return unsignedp ? sat_unsigned_long_long_accum_type_node
+			 : sat_long_long_accum_type_node;
+    }
+  else
+    {
+      if (size == SHORT_ACCUM_TYPE_SIZE)
+	return unsignedp ? unsigned_short_accum_type_node
+			 : short_accum_type_node;
+      if (size == ACCUM_TYPE_SIZE)
+	return unsignedp ? unsigned_accum_type_node : accum_type_node;
+      if (size == LONG_ACCUM_TYPE_SIZE)
+	return unsignedp ? unsigned_long_accum_type_node
+			 : long_accum_type_node;
+      if (size == LONG_LONG_ACCUM_TYPE_SIZE)
+	return unsignedp ? unsigned_long_long_accum_type_node
+			 : long_long_accum_type_node;
+    }
+
+  return make_accum_type (size, unsignedp, satp);
+}
+
 /* 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.  */
@@ -7195,6 +7319,50 @@
   complex_double_type_node = build_complex_type (double_type_node);
   complex_long_double_type_node = build_complex_type (long_double_type_node);
 
+/* Make fixed-point nodes based on sat/non-sat and signed/unsigned.  */
+#define MAKE_FIXED_TYPE_NODE(KIND,WIDTH,SIZE) \
+  sat_ ## WIDTH ## KIND ## _type_node = \
+    make_sat_signed_ ## KIND ## _type (SIZE); \
+  sat_unsigned_ ## WIDTH ## KIND ## _type_node = \
+    make_sat_unsigned_ ## KIND ## _type (SIZE); \
+  WIDTH ## KIND ## _type_node = make_signed_ ## KIND ## _type (SIZE); \
+  unsigned_ ## WIDTH ## KIND ## _type_node = \
+    make_unsigned_ ## KIND ## _type (SIZE);
+
+/* Make fixed-point type nodes based on four different widths.  */
+#define MAKE_FIXED_TYPE_NODE_FAMILY(N1,N2) \
+  MAKE_FIXED_TYPE_NODE (N1, short_, SHORT_ ## N2 ## _TYPE_SIZE) \
+  MAKE_FIXED_TYPE_NODE (N1, , N2 ## _TYPE_SIZE) \
+  MAKE_FIXED_TYPE_NODE (N1, long_, LONG_ ## N2 ## _TYPE_SIZE) \
+  MAKE_FIXED_TYPE_NODE (N1, long_long_, LONG_LONG_ ## N2 ## _TYPE_SIZE)
+
+/* Make fixed-point mode nodes based on sat/non-sat and signed/unsigned.  */
+#define MAKE_FIXED_MODE_NODE(KIND,NAME,MODE) \
+  NAME ## _type_node = \
+    make_or_reuse_signed_ ## KIND ## _type (GET_MODE_BITSIZE (MODE ## mode)); \
+  u ## NAME ## _type_node = \
+    make_or_reuse_unsigned_ ## KIND ## _type \
+      (GET_MODE_BITSIZE (U ## MODE ## mode)); \
+  sat_ ## NAME ## _type_node = \
+    make_or_reuse_sat_signed_ ## KIND ## _type \
+      (GET_MODE_BITSIZE (MODE ## mode)); \
+  sat_u ## NAME ## _type_node = \
+    make_or_reuse_sat_unsigned_ ## KIND ## _type \
+      (GET_MODE_BITSIZE (U ## MODE ## mode));
+
+  /* Fixed-point type and mode nodes.  */
+  MAKE_FIXED_TYPE_NODE_FAMILY (fract, FRACT)
+  MAKE_FIXED_TYPE_NODE_FAMILY (accum, ACCUM)
+  MAKE_FIXED_MODE_NODE (fract, qq, QQ)
+  MAKE_FIXED_MODE_NODE (fract, hq, HQ)
+  MAKE_FIXED_MODE_NODE (fract, sq, SQ)
+  MAKE_FIXED_MODE_NODE (fract, dq, DQ)
+  MAKE_FIXED_MODE_NODE (fract, tq, TQ)
+  MAKE_FIXED_MODE_NODE (accum, ha, HA)
+  MAKE_FIXED_MODE_NODE (accum, sa, SA)
+  MAKE_FIXED_MODE_NODE (accum, da, DA)
+  MAKE_FIXED_MODE_NODE (accum, ta, TA)
+
   {
     tree t = targetm.build_builtin_va_list ();
 
@@ -7458,6 +7626,10 @@
     {
     case MODE_VECTOR_INT:
     case MODE_VECTOR_FLOAT:
+    case MODE_VECTOR_FRACT:
+    case MODE_VECTOR_UFRACT:
+    case MODE_VECTOR_ACCUM:
+    case MODE_VECTOR_UACCUM:
       nunits = GET_MODE_NUNITS (mode);
       break;
 
@@ -7518,6 +7690,9 @@
       return real_zerop (init)
 	&& ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (init));
 
+    case FIXED_CST:
+      return fixed_zerop (init);
+
     case COMPLEX_CST:
       return integer_zerop (init)
 	|| (real_zerop (init)
@@ -8211,6 +8386,7 @@
     case IDENTIFIER_NODE:
     case INTEGER_CST:
     case REAL_CST:
+    case FIXED_CST:
     case VECTOR_CST:
     case STRING_CST:
     case BLOCK:
@@ -8389,6 +8565,7 @@
 	  else if (TREE_CODE (*type_p) == BOOLEAN_TYPE
 		   || TREE_CODE (*type_p) == ENUMERAL_TYPE
 		   || TREE_CODE (*type_p) == INTEGER_TYPE
+		   || TREE_CODE (*type_p) == FIXED_POINT_TYPE
 		   || TREE_CODE (*type_p) == REAL_TYPE)
 	    {
 	      WALK_SUBTREE (TYPE_MIN_VALUE (*type_p));
Index: gcc4x/gcc/gcc/dwarf2out.c
===================================================================
--- gcc4x.orig/gcc/gcc/dwarf2out.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/dwarf2out.c	2007-08-01 14:39:26.000000000 -0700
@@ -8396,6 +8396,13 @@
 	encoding = DW_ATE_float;
       break;
 
+    case FIXED_POINT_TYPE:
+      if (TYPE_UNSIGNED (type))
+	encoding = DW_ATE_signed_fixed;
+      else
+	encoding = DW_ATE_unsigned_fixed;
+      break;
+
       /* Dwarf2 doesn't know anything about complex ints, so use
 	 a user defined type for it.  */
     case COMPLEX_TYPE:
@@ -8440,6 +8447,7 @@
     case VOID_TYPE:
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
     case COMPLEX_TYPE:
     case BOOLEAN_TYPE:
       return 1;
@@ -11401,11 +11409,11 @@
   enum tree_code code  = TREE_CODE (type);
   dw_die_ref type_die  = NULL;
 
-  /* ??? If this type is an unnamed subrange type of an integral or
-     floating-point type, use the inner type.  This is because we have no
+  /* ??? If this type is an unnamed subrange type of an integral, floating-point
+     or fixed-point type, use the inner type.  This is because we have no
      support for unnamed types in base_type_die.  This can happen if this is
      an Ada subrange type.  Correct solution is emit a subrange type die.  */
-  if ((code == INTEGER_TYPE || code == REAL_TYPE)
+  if ((code == INTEGER_TYPE || code == REAL_TYPE || code == FIXED_POINT_TYPE)
       && TREE_TYPE (type) != 0 && TYPE_NAME (type) == 0)
     type = TREE_TYPE (type), code = TREE_CODE (type);
 
@@ -13082,6 +13090,7 @@
     case VOID_TYPE:
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
     case COMPLEX_TYPE:
     case BOOLEAN_TYPE:
       /* No DIEs needed for fundamental types.  */
Index: gcc4x/gcc/gcc/print-tree.c
===================================================================
--- gcc4x.orig/gcc/gcc/print-tree.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/print-tree.c	2007-08-01 14:39:26.000000000 -0700
@@ -25,6 +25,7 @@
 #include "tm.h"
 #include "tree.h"
 #include "real.h"
+#include "fixed-value.h"
 #include "ggc.h"
 #include "langhooks.h"
 #include "tree-iterator.h"
@@ -147,6 +148,18 @@
 	  fprintf (file, " %s", string);
 	}
     }
+  if (TREE_CODE (node) == FIXED_CST)
+    {
+      FIXED_VALUE_TYPE f;
+      char string[60];
+
+      if (TREE_OVERFLOW (node))
+	fprintf (file, " overflow");
+
+      f = TREE_FIXED_CST (node);
+      fixed_to_decimal (string, &f, sizeof (string));
+      fprintf (file, " %s", string);
+    }
 
   fprintf (file, ">");
 }
@@ -610,7 +623,8 @@
       
       print_node (file, "attributes", TYPE_ATTRIBUTES (node), indent + 4);
 
-      if (INTEGRAL_TYPE_P (node) || TREE_CODE (node) == REAL_TYPE)
+      if (INTEGRAL_TYPE_P (node) || TREE_CODE (node) == REAL_TYPE
+	  || TREE_CODE (node) == FIXED_POINT_TYPE)
 	{
 	  fprintf (file, " precision %d", TYPE_PRECISION (node));
 	  print_node_brief (file, "min", TYPE_MIN_VALUE (node), indent + 4);
@@ -755,6 +769,20 @@
 	  }
 	  break;
 
+	case FIXED_CST:
+	  {
+	    FIXED_VALUE_TYPE f;
+	    char string[64];
+
+	    if (TREE_OVERFLOW (node))
+	      fprintf (file, " overflow");
+
+	    f = TREE_FIXED_CST (node);
+	    fixed_to_decimal (string, &f, sizeof (string));
+	    fprintf (file, " %s", string);
+	  }
+	  break;
+
 	case VECTOR_CST:
 	  {
 	    tree vals = TREE_VECTOR_CST_ELTS (node);
Index: gcc4x/gcc/gcc/c-pretty-print.c
===================================================================
--- gcc4x.orig/gcc/gcc/c-pretty-print.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/c-pretty-print.c	2007-08-01 14:39:26.000000000 -0700
@@ -23,6 +23,7 @@
 #include "coretypes.h"
 #include "tm.h"
 #include "real.h"
+#include "fixed-value.h"
 #include "c-pretty-print.h"
 #include "c-tree.h"
 #include "tree-iterator.h"
@@ -312,6 +313,7 @@
     case BOOLEAN_TYPE:
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
       if (TYPE_NAME (t))
 	{
 	  t = TYPE_NAME (t);
@@ -320,7 +322,10 @@
       else
 	{
 	  int prec = TYPE_PRECISION (t);
-	  t = c_common_type_for_mode (TYPE_MODE (t), TYPE_UNSIGNED (t));
+	  if (ALL_FIXED_POINT_MODE_P (TYPE_MODE (t)))
+	    t = c_common_type_for_mode (TYPE_MODE (t), TYPE_SATURATING (t));
+	  else
+	    t = c_common_type_for_mode (TYPE_MODE (t), TYPE_UNSIGNED (t));
 	  if (TYPE_NAME (t))
 	    {
 	      pp_c_type_specifier (pp, t);
@@ -342,6 +347,9 @@
 		case REAL_TYPE:
 		  pp_string (pp, "<unnamed-float:");
 		  break;
+		case FIXED_POINT_TYPE:
+		  pp_string (pp, "<unnamed-fixed:");
+		  break;
 		default:
 		  gcc_unreachable ();
 		}
@@ -539,6 +547,7 @@
     case BOOLEAN_TYPE:
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
     case ENUMERAL_TYPE:
     case RECORD_TYPE:
     case UNION_TYPE:
@@ -656,6 +665,7 @@
 
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
     case ENUMERAL_TYPE:
     case UNION_TYPE:
     case RECORD_TYPE:
@@ -678,6 +688,7 @@
     {
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
     case ENUMERAL_TYPE:
     case UNION_TYPE:
     case RECORD_TYPE:
@@ -925,6 +936,16 @@
     pp_string (pp, "df");
 }
 
+/* Print out a FIXED value as a decimal-floating-constant.  */
+
+static void
+pp_c_fixed_constant (c_pretty_printer *pp, tree r)
+{
+  fixed_to_decimal (pp_buffer (pp)->digit_buffer, &TREE_FIXED_CST (r),
+		   sizeof (pp_buffer (pp)->digit_buffer));
+  pp_string (pp, pp_buffer(pp)->digit_buffer);
+}
+
 /* Pretty-print a compound literal expression.  GNU extensions include
    vector constants.  */
 
@@ -953,6 +974,7 @@
 /* constant:
       integer-constant
       floating-constant
+      fixed-point-constant
       enumeration-constant
       character-constant   */
 
@@ -982,6 +1004,10 @@
       pp_c_floating_constant (pp, e);
       break;
 
+    case FIXED_CST:
+      pp_c_fixed_constant (pp, e);
+      break;
+
     case STRING_CST:
       pp_c_string_literal (pp, e);
       break;
@@ -1037,6 +1063,7 @@
 
     case INTEGER_CST:
     case REAL_CST:
+    case FIXED_CST:
     case STRING_CST:
       pp_c_constant (pp, e);
       break;
@@ -1842,6 +1869,10 @@
       pp_c_floating_constant (pp, e);
       break;
 
+    case FIXED_CST:
+      pp_c_fixed_constant (pp, e);
+      break;
+
     case STRING_CST:
       pp_c_string_literal (pp, e);
       break;
Index: gcc4x/gcc/gcc/fold-const.c
===================================================================
--- gcc4x.orig/gcc/gcc/fold-const.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/fold-const.c	2007-08-01 14:39:26.000000000 -0700
@@ -54,6 +54,7 @@
 #include "flags.h"
 #include "tree.h"
 #include "real.h"
+#include "fixed-value.h"
 #include "rtl.h"
 #include "expr.h"
 #include "tm_p.h"
@@ -1127,6 +1128,7 @@
       return (INTEGRAL_TYPE_P (type)
 	      && TYPE_OVERFLOW_WRAPS (type));
 
+    case FIXED_CST:
     case REAL_CST:
     case NEGATE_EXPR:
       return true;
@@ -1257,6 +1259,10 @@
 	return tem;
       break;
 
+    case FIXED_CST:
+      tem = fold_negate_const (t, type);
+      return tem;
+
     case COMPLEX_CST:
       {
 	tree rpart = negate_expr (TREE_REALPART (t));
@@ -1479,10 +1485,12 @@
   /* Strip any conversions that don't change the machine mode or signedness.  */
   STRIP_SIGN_NOPS (in);
 
-  if (TREE_CODE (in) == INTEGER_CST || TREE_CODE (in) == REAL_CST)
+  if (TREE_CODE (in) == INTEGER_CST || TREE_CODE (in) == REAL_CST
+      || TREE_CODE (in) == FIXED_CST)
     *litp = in;
   else if (TREE_CODE (in) == code
 	   || (! FLOAT_TYPE_P (TREE_TYPE (in))
+	       && ! SAT_FIXED_POINT_TYPE_P (TREE_TYPE (in))
 	       /* We can associate addition and subtraction together (even
 		  though the C standard doesn't say so) for integers because
 		  the value is not affected.  For reals, the value might be
@@ -1496,9 +1504,11 @@
       int neg_litp_p = 0, neg_conp_p = 0, neg_var_p = 0;
 
       /* First see if either of the operands is a literal, then a constant.  */
-      if (TREE_CODE (op0) == INTEGER_CST || TREE_CODE (op0) == REAL_CST)
+      if (TREE_CODE (op0) == INTEGER_CST || TREE_CODE (op0) == REAL_CST
+	  || TREE_CODE (op0) == FIXED_CST)
 	*litp = op0, op0 = 0;
-      else if (TREE_CODE (op1) == INTEGER_CST || TREE_CODE (op1) == REAL_CST)
+      else if (TREE_CODE (op1) == INTEGER_CST || TREE_CODE (op1) == REAL_CST
+	       || TREE_CODE (op1) == FIXED_CST)
 	*litp = op1, neg_litp_p = neg1_p, op1 = 0;
 
       if (op0 != 0 && TREE_CONSTANT (op0))
@@ -1886,6 +1896,52 @@
       return t;
     }
 
+  if (TREE_CODE (arg1) == FIXED_CST)
+    {
+      FIXED_VALUE_TYPE f1;
+      FIXED_VALUE_TYPE f2;
+      FIXED_VALUE_TYPE result;
+      tree t, type;
+      int sat_p;
+      bool overflow_p;
+
+      /* The following codes are handled by fixed_arithmetic.  */
+      switch (code)
+        {
+	case PLUS_EXPR:
+	case MINUS_EXPR:
+	case MULT_EXPR:
+	case TRUNC_DIV_EXPR:
+	  f2 = TREE_FIXED_CST (arg2);
+	  break;
+
+	case LSHIFT_EXPR:
+	case RSHIFT_EXPR:
+	  f2.data.high = TREE_INT_CST_HIGH (arg2);
+	  f2.data.low = TREE_INT_CST_LOW (arg2);
+	  f2.mode = SImode;
+	  break;
+
+        default:
+	  return NULL_TREE;
+        }
+
+      f1 = TREE_FIXED_CST (arg1);
+      type = TREE_TYPE (arg1);
+      sat_p = TYPE_SATURATING (type);
+      overflow_p = fixed_arithmetic (&result, code, &f1, &f2, sat_p);
+      t = build_fixed (type, result);
+      /* Propagate overflow flags.  */
+      if (overflow_p | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2))
+	{
+	  TREE_OVERFLOW (t) = 1;
+	  TREE_CONSTANT_OVERFLOW (t) = 1;
+	}
+      else if (TREE_CONSTANT_OVERFLOW (arg1) | TREE_CONSTANT_OVERFLOW (arg2))
+	TREE_CONSTANT_OVERFLOW (t) = 1;
+      return t;
+    }
+
   if (TREE_CODE (arg1) == COMPLEX_CST)
     {
       tree type = TREE_TYPE (arg1);
@@ -2151,6 +2207,61 @@
   return t;
 }
 
+/* A subroutine of fold_convert_const handling conversions of a
+   FIXED_CST to an integer type.  */
+
+static tree
+fold_convert_const_int_from_fixed (tree type, tree arg1)
+{
+  tree t;
+  double_int temp, temp_trunc;
+  unsigned int mode;
+
+  /* Right shift FIXED_CST to temp by fbit.  */
+  temp = TREE_FIXED_CST (arg1).data;
+  mode = TREE_FIXED_CST (arg1).mode;
+  if (GET_MODE_FBIT (mode) < 2 * HOST_BITS_PER_WIDE_INT)
+    {
+      lshift_double (temp.low, temp.high,
+		     - GET_MODE_FBIT (mode), 2 * HOST_BITS_PER_WIDE_INT,
+		     &temp.low, &temp.high, SIGNED_FIXED_POINT_MODE_P (mode));
+
+      /* Left shift temp to temp_trunc by fbit.  */
+      lshift_double (temp.low, temp.high,
+		     GET_MODE_FBIT (mode), 2 * HOST_BITS_PER_WIDE_INT,
+		     &temp_trunc.low, &temp_trunc.high,
+		     SIGNED_FIXED_POINT_MODE_P (mode));
+    }
+  else
+    {
+      temp.low = 0;
+      temp.high = 0;
+      temp_trunc.low = 0;
+      temp_trunc.high = 0;
+    }
+
+  /* If FIXED_CST is negative, we need to round the value toward 0.
+     By checking if the fractional bits are not zero to add 1 to temp.  */
+  if (SIGNED_FIXED_POINT_MODE_P (mode) && temp_trunc.high < 0
+      && !double_int_equal_p (TREE_FIXED_CST (arg1).data, temp_trunc))
+    {
+      double_int one;
+      one.low = 1;
+      one.high = 0;
+      temp = double_int_add (temp, one);
+    }
+
+  /* Given a fixed-point constant, make new constant with new type,
+     appropriately sign-extended or truncated.  */
+  t = force_fit_type_double (type, temp.low, temp.high, -1,
+			     (temp.high < 0
+		 	      && (TYPE_UNSIGNED (type)
+				  < TYPE_UNSIGNED (TREE_TYPE (arg1))))
+			     | TREE_OVERFLOW (arg1));
+
+  return t;
+}
+
 /* A subroutine of fold_convert_const handling conversions a REAL_CST
    to another floating point type.  */
 
@@ -2167,6 +2278,102 @@
   return t;
 }
 
+/* A subroutine of fold_convert_const handling conversions a FIXED_CST
+   to a floating point type.  */
+
+static tree
+fold_convert_const_real_from_fixed (tree type, tree arg1)
+{
+  REAL_VALUE_TYPE value;
+  tree t;
+
+  real_convert_from_fixed (&value, TYPE_MODE (type), &TREE_FIXED_CST (arg1));
+  t = build_real (type, value);
+
+  TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
+  TREE_CONSTANT_OVERFLOW (t)
+    = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+  return t;
+}
+
+/* A subroutine of fold_convert_const handling conversions a FIXED_CST
+   to another fixed-point type.  */
+
+static tree
+fold_convert_const_fixed_from_fixed (tree type, tree arg1)
+{
+  FIXED_VALUE_TYPE value;
+  tree t;
+  bool overflow_p;
+
+  overflow_p = fixed_convert (&value, TYPE_MODE (type), &TREE_FIXED_CST (arg1),
+			      TYPE_SATURATING (type));
+  t = build_fixed (type, value);
+
+  /* Propagate overflow flags.  */
+  if (overflow_p | TREE_OVERFLOW (arg1))
+    {
+      TREE_OVERFLOW (t) = 1;
+      TREE_CONSTANT_OVERFLOW (t) = 1;
+    }
+  else if (TREE_CONSTANT_OVERFLOW (arg1))
+    TREE_CONSTANT_OVERFLOW (t) = 1;
+  return t;
+}
+
+/* A subroutine of fold_convert_const handling conversions an INTEGER_CST
+   to a fixed-point type.  */
+
+static tree
+fold_convert_const_fixed_from_int (tree type, tree arg1)
+{
+  FIXED_VALUE_TYPE value;
+  tree t;
+  bool overflow_p;
+
+  overflow_p = fixed_convert_from_int (&value, TYPE_MODE (type),
+				       TREE_INT_CST (arg1),
+				       TYPE_UNSIGNED (TREE_TYPE (arg1)),
+				       TYPE_SATURATING (type));
+  t = build_fixed (type, value);
+
+  /* Propagate overflow flags.  */
+  if (overflow_p | TREE_OVERFLOW (arg1))
+    {
+      TREE_OVERFLOW (t) = 1;
+      TREE_CONSTANT_OVERFLOW (t) = 1;
+    }
+  else if (TREE_CONSTANT_OVERFLOW (arg1))
+    TREE_CONSTANT_OVERFLOW (t) = 1;
+  return t;
+}
+
+/* A subroutine of fold_convert_const handling conversions a REAL_CST
+   to a fixed-point type.  */
+
+static tree
+fold_convert_const_fixed_from_real (tree type, tree arg1)
+{
+  FIXED_VALUE_TYPE value;
+  tree t;
+  bool overflow_p;
+
+  overflow_p = fixed_convert_from_real (&value, TYPE_MODE (type),
+					&TREE_REAL_CST (arg1),
+					TYPE_SATURATING (type));
+  t = build_fixed (type, value);
+
+  /* Propagate overflow flags.  */
+  if (overflow_p | TREE_OVERFLOW (arg1))
+    {
+      TREE_OVERFLOW (t) = 1;
+      TREE_CONSTANT_OVERFLOW (t) = 1;
+    }
+  else if (TREE_CONSTANT_OVERFLOW (arg1))
+    TREE_CONSTANT_OVERFLOW (t) = 1;
+  return t;
+}
+
 /* Attempt to fold type conversion operation CODE of expression ARG1 to
    type TYPE.  If no simplification can be done return NULL_TREE.  */
 
@@ -2182,13 +2389,26 @@
 	return fold_convert_const_int_from_int (type, arg1);
       else if (TREE_CODE (arg1) == REAL_CST)
 	return fold_convert_const_int_from_real (code, type, arg1);
+      else if (TREE_CODE (arg1) == FIXED_CST)
+	return fold_convert_const_int_from_fixed (type, arg1);
     }
   else if (TREE_CODE (type) == REAL_TYPE)
     {
       if (TREE_CODE (arg1) == INTEGER_CST)
 	return build_real_from_int_cst (type, arg1);
-      if (TREE_CODE (arg1) == REAL_CST)
+      else if (TREE_CODE (arg1) == REAL_CST)
 	return fold_convert_const_real_from_real (type, arg1);
+      else if (TREE_CODE (arg1) == FIXED_CST)
+	return fold_convert_const_real_from_fixed (type, arg1);
+    }
+  else if (TREE_CODE (type) == FIXED_POINT_TYPE)
+    {
+      if (TREE_CODE (arg1) == FIXED_CST)
+	return fold_convert_const_fixed_from_fixed (type, arg1);
+      else if (TREE_CODE (arg1) == INTEGER_CST)
+	return fold_convert_const_fixed_from_int (type, arg1);
+      else if (TREE_CODE (arg1) == REAL_CST)
+	return fold_convert_const_fixed_from_real (type, arg1);
     }
   return NULL_TREE;
 }
@@ -2300,6 +2520,12 @@
 	  if (tem != NULL_TREE)
 	    return tem;
 	}
+      else if (TREE_CODE (arg) == FIXED_CST)
+	{
+	  tem = fold_convert_const (FIXED_CONVERT_EXPR, type, arg);
+	  if (tem != NULL_TREE)
+	    return tem;
+	}
 
       switch (TREE_CODE (orig))
 	{
@@ -2311,6 +2537,35 @@
 	case REAL_TYPE:
 	  return fold_build1 (NOP_EXPR, type, arg);
 
+	case FIXED_POINT_TYPE:
+	  return fold_build1 (FIXED_CONVERT_EXPR, type, arg);
+
+	case COMPLEX_TYPE:
+	  tem = fold_build1 (REALPART_EXPR, TREE_TYPE (orig), arg);
+	  return fold_convert (type, tem);
+
+	default:
+	  gcc_unreachable ();
+	}
+
+    case FIXED_POINT_TYPE:
+      if (TREE_CODE (arg) == FIXED_CST || TREE_CODE (arg) == INTEGER_CST
+	  || TREE_CODE (arg) == REAL_CST)
+	{
+	  tem = fold_convert_const (FIXED_CONVERT_EXPR, type, arg);
+	  if (tem != NULL_TREE)
+	    return tem;
+	}
+
+      switch (TREE_CODE (orig))
+	{
+	case FIXED_POINT_TYPE:
+	case INTEGER_TYPE:
+	case ENUMERAL_TYPE:
+	case BOOLEAN_TYPE:
+	case REAL_TYPE:
+	  return fold_build1 (FIXED_CONVERT_EXPR, type, arg);
+
 	case COMPLEX_TYPE:
 	  tem = fold_build1 (REALPART_EXPR, TREE_TYPE (orig), arg);
 	  return fold_convert (type, tem);
@@ -2326,6 +2581,7 @@
 	case BOOLEAN_TYPE: case ENUMERAL_TYPE:
 	case POINTER_TYPE: case REFERENCE_TYPE:
 	case REAL_TYPE:
+	case FIXED_POINT_TYPE:
 	  return build2 (COMPLEX_EXPR, type,
 			 fold_convert (TREE_TYPE (type), arg),
 			 fold_convert (TREE_TYPE (type), integer_zero_node));
@@ -2808,6 +3064,10 @@
       case INTEGER_CST:
 	return tree_int_cst_equal (arg0, arg1);
 
+      case FIXED_CST:
+	return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (arg0),
+				       TREE_FIXED_CST (arg1));
+
       case REAL_CST:
 	if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (arg0),
 				   TREE_REAL_CST (arg1)))
@@ -4265,8 +4525,16 @@
 	  if (!TYPE_UNSIGNED (exp_type) && TYPE_UNSIGNED (arg0_type))
 	    {
 	      tree high_positive;
-	      tree equiv_type = lang_hooks.types.type_for_mode
-		(TYPE_MODE (arg0_type), 1);
+	      tree equiv_type;
+	      /* For fixed-point modes, we need to pass the saturating flag
+		 as the 2nd parameter.  */
+	      if (ALL_FIXED_POINT_MODE_P (TYPE_MODE (arg0_type)))
+		equiv_type = lang_hooks.types.type_for_mode
+			     (TYPE_MODE (arg0_type),
+			      TYPE_SATURATING (arg0_type));
+	      else
+		equiv_type = lang_hooks.types.type_for_mode
+			     (TYPE_MODE (arg0_type), 1);
 
 	      /* A range without an upper bound is, naturally, unbounded.
 		 Since convert would have cropped a very large value, use
@@ -6737,6 +7005,11 @@
   if (TREE_CODE (arg0) == REAL_CST)
     return 1;
 
+  if (TREE_CODE (arg1) == FIXED_CST)
+    return 0;
+  if (TREE_CODE (arg0) == FIXED_CST)
+    return 1;
+
   if (TREE_CODE (arg1) == COMPLEX_CST)
     return 0;
   if (TREE_CODE (arg0) == COMPLEX_CST)
@@ -7136,6 +7409,9 @@
     }
   else
     {
+      /* We cannot generate constant 1 for fract.  */
+      if (ALL_FRACT_MODE_P (TYPE_MODE (type)))
+	return NULL_TREE;
       arg00 = arg0;
       arg01 = build_one_cst (type);
     }
@@ -7151,6 +7427,9 @@
     }
   else
     {
+      /* We cannot generate constant 1 for fract.  */
+      if (ALL_FRACT_MODE_P (TYPE_MODE (type)))
+	return NULL_TREE;
       arg10 = arg1;
       arg11 = build_one_cst (type);
     }
@@ -8011,6 +8290,10 @@
       tem = fold_convert_const (code, type, op0);
       return tem ? tem : NULL_TREE;
 
+    case FIXED_CONVERT_EXPR:
+      tem = fold_convert_const (code, type, arg0);
+      return tem ? tem : NULL_TREE;
+
     case VIEW_CONVERT_EXPR:
       if (TREE_TYPE (op0) == type)
 	return op0;
@@ -9114,11 +9397,18 @@
      constant but we can't do arithmetic on them.  */
   if ((TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
       || (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST)
+      || (TREE_CODE (arg0) == FIXED_CST && TREE_CODE (arg1) == FIXED_CST)
+      || (TREE_CODE (arg0) == FIXED_CST && TREE_CODE (arg1) == INTEGER_CST)
       || (TREE_CODE (arg0) == COMPLEX_CST && TREE_CODE (arg1) == COMPLEX_CST)
       || (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST))
     {
       if (kind == tcc_binary)
-	tem = const_binop (code, arg0, arg1, 0);
+	{
+	  /* Make sure type and arg0 have the same saturating flag.  */
+	  gcc_assert (TYPE_SATURATING (type)
+		      == TYPE_SATURATING (TREE_TYPE (arg0)));
+	  tem = const_binop (code, arg0, arg1, 0);
+	}
       else if (kind == tcc_comparison)
 	tem = fold_relational_const (code, type, arg0, arg1);
       else
@@ -9323,9 +9613,10 @@
 	}
 
       /* Handle (A1 * C1) + (A2 * C2) with A1, A2 or C1, C2 being the
-	 same or one.  */
+	 same or one.  Make sure type is not saturating.  */
       if ((TREE_CODE (arg0) == MULT_EXPR
 	   || TREE_CODE (arg1) == MULT_EXPR)
+	  && !TYPE_SATURATING (type)
 	  && (!FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
         {
 	  tree tem = fold_plusminus_mult_expr (code, type, arg0, arg1);
@@ -9569,9 +9860,11 @@
       /* In most languages, can't associate operations on floats through
 	 parentheses.  Rather than remember where the parentheses were, we
 	 don't associate floats at all, unless the user has specified
-	 -funsafe-math-optimizations.  */
+	 -funsafe-math-optimizations.
+	 And, we need to make sure type is not saturating.  */
 
-      if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+      if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+	  && !TYPE_SATURATING (type))
 	{
 	  tree var0, con0, lit0, minus_lit0;
 	  tree var1, con1, lit1, minus_lit1;
@@ -9870,9 +10163,10 @@
 	return tem;
 
       /* Handle (A1 * C1) - (A2 * C2) with A1, A2 or C1, C2 being the
-	 same or one.  */
+	 same or one.  Make sure type is not saturating.  */
       if ((TREE_CODE (arg0) == MULT_EXPR
 	   || TREE_CODE (arg1) == MULT_EXPR)
+	  && !TYPE_SATURATING (type)
 	  && (!FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
         {
 	  tree tem = fold_plusminus_mult_expr (code, type, arg0, arg1);
@@ -13476,6 +13770,9 @@
     case REAL_CST:
       return ! REAL_VALUE_NEGATIVE (TREE_REAL_CST (t));
 
+    case FIXED_CST:
+      return ! FIXED_VALUE_NEGATIVE (TREE_FIXED_CST (t));
+
     case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
       if (FLOAT_TYPE_P (TREE_TYPE (t)))
@@ -14078,7 +14375,7 @@
 }
 
 /* Return the tree for neg (ARG0) when ARG0 is known to be either
-   an integer constant or real constant.
+   an integer constant, real, or fixed-point constant.
 
    TYPE is the type of the result.  */
 
@@ -14106,6 +14403,24 @@
       t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
       break;
 
+    case FIXED_CST:
+      {
+        FIXED_VALUE_TYPE f;
+        bool overflow_p = fixed_arithmetic (&f, NEGATE_EXPR,
+					    &(TREE_FIXED_CST (arg0)), NULL,
+					    TYPE_SATURATING (type));
+	t = build_fixed (type, f);
+	/* Propagate overflow flags.  */
+	if (overflow_p | TREE_OVERFLOW (arg0))
+	  {
+	    TREE_OVERFLOW (t) = 1;
+	    TREE_CONSTANT_OVERFLOW (t) = 1;
+	  }
+	else if (TREE_CONSTANT_OVERFLOW (arg0))
+	  TREE_CONSTANT_OVERFLOW (t) = 1;
+	break;
+      }
+
     default:
       gcc_unreachable ();
     }
@@ -14236,6 +14551,13 @@
       return constant_boolean_node (real_compare (code, c0, c1), type);
     }
 
+  if (TREE_CODE (op0) == FIXED_CST && TREE_CODE (op1) == FIXED_CST)
+    {
+      const FIXED_VALUE_TYPE *c0 = TREE_FIXED_CST_PTR (op0);
+      const FIXED_VALUE_TYPE *c1 = TREE_FIXED_CST_PTR (op1);
+      return constant_boolean_node (fixed_compare (code, c0, c1), type);
+    }
+
   /* Handle equality/inequality of complex constants.  */
   if (TREE_CODE (op0) == COMPLEX_CST && TREE_CODE (op1) == COMPLEX_CST)
     {
Index: gcc4x/gcc/gcc/gimplify.c
===================================================================
--- gcc4x.orig/gcc/gcc/gimplify.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/gimplify.c	2007-08-01 14:39:27.000000000 -0700
@@ -4488,6 +4488,7 @@
     case ENUMERAL_TYPE:
     case BOOLEAN_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
       omp_firstprivatize_variable (ctx, TYPE_MIN_VALUE (type));
       omp_firstprivatize_variable (ctx, TYPE_MAX_VALUE (type));
       break;
@@ -5728,6 +5729,7 @@
 	  /* Constants need not be gimplified.  */
 	case INTEGER_CST:
 	case REAL_CST:
+	case FIXED_CST:
 	case STRING_CST:
 	case COMPLEX_CST:
 	case VECTOR_CST:
@@ -6271,6 +6273,7 @@
     case ENUMERAL_TYPE:
     case BOOLEAN_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
       gimplify_one_sizepos (&TYPE_MIN_VALUE (type), list_p);
       gimplify_one_sizepos (&TYPE_MAX_VALUE (type), list_p);
 
Index: gcc4x/gcc/gcc/ipa-prop.c
===================================================================
--- gcc4x.orig/gcc/gcc/ipa-prop.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/ipa-prop.c	2007-08-01 14:39:27.000000000 -0700
@@ -481,7 +481,8 @@
          we store CONST_IPATYPE and its value as the jump function 
          of this argument.  */
       else if (TREE_CODE (arg) == INTEGER_CST
-	       || TREE_CODE (arg) == REAL_CST)
+	       || TREE_CODE (arg) == REAL_CST
+	       || TREE_CODE (arg) == FIXED_CST)
 	{
 	  ipa_callsite_param_set_type (cs, arg_num, CONST_IPATYPE);
 	  ipa_callsite_param_set_info_type (cs, arg_num, arg);
@@ -495,7 +496,8 @@
 	{
 	  cst_decl = TREE_OPERAND (arg, 0);
 	  if (TREE_CODE (DECL_INITIAL (cst_decl)) == INTEGER_CST
-	      || TREE_CODE (DECL_INITIAL (cst_decl)) == REAL_CST)
+	      || TREE_CODE (DECL_INITIAL (cst_decl)) == REAL_CST
+	      || TREE_CODE (DECL_INITIAL (cst_decl)) == FIXED_CST)
 	    {
 	      ipa_callsite_param_set_type (cs, arg_num,
 					   CONST_IPATYPE_REF);
Index: gcc4x/gcc/gcc/ipa-type-escape.c
===================================================================
--- gcc4x.orig/gcc/gcc/ipa-type-escape.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/ipa-type-escape.c	2007-08-01 14:39:27.000000000 -0700
@@ -274,6 +274,7 @@
     case INTEGER_TYPE:
     case QUAL_UNION_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
     case RECORD_TYPE:
     case UNION_TYPE:
     case VECTOR_TYPE:
Index: gcc4x/gcc/gcc/doc/tm.texi
===================================================================
--- gcc4x.orig/gcc/gcc/doc/tm.texi	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/doc/tm.texi	2007-08-01 14:39:27.000000000 -0700
@@ -1605,6 +1605,54 @@
 words.
 @end defmac
 
+@defmac SHORT_FRACT_TYPE_SIZE
+A C expression for the size in bits of the type @code{short _Fract} on
+the target machine.  If you don't define this, the default is
+@code{BITS_PER_UNIT}.
+@end defmac
+
+@defmac FRACT_TYPE_SIZE
+A C expression for the size in bits of the type @code{_Fract} on
+the target machine.  If you don't define this, the default is
+@code{BITS_PER_UNIT * 2}.
+@end defmac
+
+@defmac LONG_FRACT_TYPE_SIZE
+A C expression for the size in bits of the type @code{long _Fract} on
+the target machine.  If you don't define this, the default is
+@code{BITS_PER_UNIT * 4}.
+@end defmac
+
+@defmac LONG_LONG_FRACT_TYPE_SIZE
+A C expression for the size in bits of the type @code{long long _Fract} on
+the target machine.  If you don't define this, the default is
+@code{BITS_PER_UNIT * 8}.
+@end defmac
+
+@defmac SHORT_ACCUM_TYPE_SIZE
+A C expression for the size in bits of the type @code{short _Accum} on
+the target machine.  If you don't define this, the default is
+@code{BITS_PER_UNIT * 2}.
+@end defmac
+
+@defmac ACCUM_TYPE_SIZE
+A C expression for the size in bits of the type @code{_Accum} on
+the target machine.  If you don't define this, the default is
+@code{BITS_PER_UNIT * 4}.
+@end defmac
+
+@defmac LONG_ACCUM_TYPE_SIZE
+A C expression for the size in bits of the type @code{long _Accum} on
+the target machine.  If you don't define this, the default is
+@code{BITS_PER_UNIT * 8}.
+@end defmac
+
+@defmac LONG_LONG_ACCUM_TYPE_SIZE
+A C expression for the size in bits of the type @code{long long _Accum} on
+the target machine.  If you don't define this, the default is
+@code{BITS_PER_UNIT * 16}.
+@end defmac
+
 @defmac LIBGCC2_LONG_DOUBLE_TYPE_SIZE
 Define this macro if @code{LONG_DOUBLE_TYPE_SIZE} is not constant or
 if you want routines in @file{libgcc2.a} for a size other than
Index: gcc4x/gcc/gcc/dbxout.c
===================================================================
--- gcc4x.orig/gcc/gcc/dbxout.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/dbxout.c	2007-08-01 14:39:27.000000000 -0700
@@ -1906,6 +1906,7 @@
       break;
 
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
       /* This used to say `r1' and we used to take care
 	 to make sure that `int' was type number 1.  */
       stabstr_C ('r');
Index: gcc4x/gcc/gcc/c-aux-info.c
===================================================================
--- gcc4x.orig/gcc/gcc/c-aux-info.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/c-aux-info.c	2007-08-01 14:39:27.000000000 -0700
@@ -426,6 +426,7 @@
 	  break;
 
 	case INTEGER_TYPE:
+	case FIXED_POINT_TYPE:
 	  data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
 	  /* Normally, `unsigned' is part of the deal.  Not so if it comes
 	     with a type qualifier.  */
Index: gcc4x/gcc/gcc/tree-sra.c
===================================================================
--- gcc4x.orig/gcc/gcc/tree-sra.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/tree-sra.c	2007-08-01 14:39:27.000000000 -0700
@@ -220,6 +220,7 @@
 {
   enum tree_code code = TREE_CODE (type);
   return (code == INTEGER_TYPE || code == REAL_TYPE || code == VECTOR_TYPE
+	  || code == FIXED_POINT_TYPE
 	  || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE
 	  || code == POINTER_TYPE || code == OFFSET_TYPE
 	  || code == REFERENCE_TYPE);
Index: gcc4x/gcc/gcc/expmed.c
===================================================================
--- gcc4x.orig/gcc/gcc/expmed.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/expmed.c	2007-08-01 14:39:27.000000000 -0700
@@ -1182,6 +1182,14 @@
 
       if (GET_MODE_CLASS (tmode) == MODE_FLOAT)
 	new_mode = MIN_MODE_VECTOR_FLOAT;
+      else if (GET_MODE_CLASS (tmode) == MODE_FRACT)
+	new_mode = MIN_MODE_VECTOR_FRACT;
+      else if (GET_MODE_CLASS (tmode) == MODE_UFRACT)
+	new_mode = MIN_MODE_VECTOR_UFRACT;
+      else if (GET_MODE_CLASS (tmode) == MODE_ACCUM)
+	new_mode = MIN_MODE_VECTOR_ACCUM;
+      else if (GET_MODE_CLASS (tmode) == MODE_UACCUM)
+	new_mode = MIN_MODE_VECTOR_UACCUM;
       else
 	new_mode = MIN_MODE_VECTOR_INT;
 
Index: gcc4x/gcc/gcc/tree-vectorizer.c
===================================================================
--- gcc4x.orig/gcc/gcc/tree-vectorizer.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/tree-vectorizer.c	2007-08-01 14:39:27.000000000 -0700
@@ -2150,6 +2150,16 @@
         }
       return NULL_TREE;
     }
+  else if (SAT_FIXED_POINT_TYPE_P (type))
+    {
+      /* Changing the order of operations changes the semantics.  */
+      if (vect_print_dump_info (REPORT_DETAILS))
+        {
+          fprintf (vect_dump, "reduction: unsafe fixed-point math optimization: ");
+          print_generic_expr (vect_dump, operation, TDF_SLIM);
+        }
+      return NULL_TREE;
+    }
 
   /* reduction is safe. we're dealing with one of the following:
      1) integer arithmetic and no trapv
Index: gcc4x/gcc/gcc/explow.c
===================================================================
--- gcc4x.orig/gcc/gcc/explow.c	2007-08-01 11:51:18.000000000 -0700
+++ gcc4x/gcc/gcc/explow.c	2007-08-01 14:39:27.000000000 -0700
@@ -793,7 +793,7 @@
     {
 #ifdef PROMOTE_FUNCTION_MODE
     case INTEGER_TYPE:   case ENUMERAL_TYPE:   case BOOLEAN_TYPE:
-    case REAL_TYPE:      case OFFSET_TYPE:
+    case REAL_TYPE:      case OFFSET_TYPE:     case FIXED_POINT_TYPE:
 #ifdef PROMOTE_MODE
       if (for_call)
 	{

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [ping][patch] Fixed-point patch 3/10
  2007-08-01 23:54 [ping][patch] Fixed-point patch 3/10 Fu, Chao-Ying
@ 2007-08-06  3:52 ` Mark Mitchell
  2007-08-08 22:34   ` Fu, Chao-Ying
  2007-08-06 21:37 ` Tom Tromey
  1 sibling, 1 reply; 9+ messages in thread
From: Mark Mitchell @ 2007-08-06  3:52 UTC (permalink / raw)
  To: Fu, Chao-Ying; +Cc: gcc-patches, Thekkath, Radhika, Stephens, Nigel

Fu, Chao-Ying wrote:

> gcc/ChangeLog
> 2007-08-01  Chao-ying Fu  <fu@mips.com>
> 
> 	* tree.def (FIXED_POINT_TYPE): New type.
> 	(FIXED_CST): New constant.
> 	(FIXED_CONVERT_EXPR): New expr.
>       ...

OK, once we've resolved 2/10.

-- 
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [ping][patch] Fixed-point patch 3/10
  2007-08-01 23:54 [ping][patch] Fixed-point patch 3/10 Fu, Chao-Ying
  2007-08-06  3:52 ` Mark Mitchell
@ 2007-08-06 21:37 ` Tom Tromey
  2007-08-06 21:42   ` Andrew Pinski
  2007-08-06 21:53   ` Fu, Chao-Ying
  1 sibling, 2 replies; 9+ messages in thread
From: Tom Tromey @ 2007-08-06 21:37 UTC (permalink / raw)
  To: Fu, Chao-Ying
  Cc: gcc-patches, Thekkath, Radhika, Stephens, Nigel, Mark Mitchell

>>>>> ">" == Fu, Chao-Ying <fu@mips.com> writes:

>> 	* tree.def (FIXED_POINT_TYPE): New type.
>> 	(FIXED_CST): New constant.
>> 	(FIXED_CONVERT_EXPR): New expr.

I was curious -- why a new FIXED_CONVERT_EXPR instead of just using
the types on a CONVERT_EXPR?  After all, we don't have a new tree code
for int<->double conversions.

Tom

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [ping][patch] Fixed-point patch 3/10
  2007-08-06 21:37 ` Tom Tromey
@ 2007-08-06 21:42   ` Andrew Pinski
  2007-08-06 21:50     ` Tom Tromey
  2007-08-06 21:53   ` Fu, Chao-Ying
  1 sibling, 1 reply; 9+ messages in thread
From: Andrew Pinski @ 2007-08-06 21:42 UTC (permalink / raw)
  To: tromey
  Cc: Fu, Chao-Ying, gcc-patches, Thekkath, Radhika, Stephens, Nigel,
	Mark Mitchell

On 8/6/07, Tom Tromey <tromey@redhat.com> wrote:
> After all, we don't have a new tree code
> for int<->double conversions.

Yes we do ... FIX_TRUNC_EXPR and FLOAT_EXPR.

-- Pinski

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [ping][patch] Fixed-point patch 3/10
  2007-08-06 21:42   ` Andrew Pinski
@ 2007-08-06 21:50     ` Tom Tromey
  0 siblings, 0 replies; 9+ messages in thread
From: Tom Tromey @ 2007-08-06 21:50 UTC (permalink / raw)
  To: Andrew Pinski
  Cc: Fu, Chao-Ying, gcc-patches, Thekkath, Radhika, Stephens, Nigel,
	Mark Mitchell

>>>>> "Andrew" == Andrew Pinski <pinskia@gmail.com> writes:

Andrew> On 8/6/07, Tom Tromey <tromey@redhat.com> wrote:
>> After all, we don't have a new tree code
>> for int<->double conversions.

Andrew> Yes we do ... FIX_TRUNC_EXPR and FLOAT_EXPR.

Sigh.  How embarrassing for me.

I'd still like to know why a new one is needed.  It often seems to me
that we have too many conversion operators on trees.  Apparently I've
been pre-emptively deleting them in my mind.

Tom

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [ping][patch] Fixed-point patch 3/10
  2007-08-06 21:37 ` Tom Tromey
  2007-08-06 21:42   ` Andrew Pinski
@ 2007-08-06 21:53   ` Fu, Chao-Ying
  1 sibling, 0 replies; 9+ messages in thread
From: Fu, Chao-Ying @ 2007-08-06 21:53 UTC (permalink / raw)
  To: tromey; +Cc: gcc-patches, Thekkath, Radhika, Stephens, Nigel, Mark Mitchell

Tom Tromey wrote:
> 
> >>>>> ">" == Fu, Chao-Ying <fu@mips.com> writes:
> 
> >> 	* tree.def (FIXED_POINT_TYPE): New type.
> >> 	(FIXED_CST): New constant.
> >> 	(FIXED_CONVERT_EXPR): New expr.
> 
> I was curious -- why a new FIXED_CONVERT_EXPR instead of just using
> the types on a CONVERT_EXPR?  After all, we don't have a new tree code
> for int<->double conversions.
> 
> Tom
> 

  The new tree code of "FIXED_CONVERT_EXPR" helps me to isolate all the
changes about conversions involving fixed-point types.  If CONVERT_EXPR
is reused, I need to modify the original C code to take care of special cases, 
such as converting int/real/fixed-point values to saturating fixed-point types
by checking TYPE_SATURATING (type).  Also I need to make sure that this type
of conversions is not optimized away.

  It is easier to use a new tree code for all the fixed-point conversions.
Thanks a lot!

Regards,
Chao-ying

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [ping][patch] Fixed-point patch 3/10
  2007-08-06  3:52 ` Mark Mitchell
@ 2007-08-08 22:34   ` Fu, Chao-Ying
  2007-08-09 12:14     ` Rask Ingemann Lambertsen
  0 siblings, 1 reply; 9+ messages in thread
From: Fu, Chao-Ying @ 2007-08-08 22:34 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: gcc-patches, Thekkath, Radhika, Stephens, Nigel

Mark Mitchell wrote:
> 
> Fu, Chao-Ying wrote:
> 
> > gcc/ChangeLog
> > 2007-08-01  Chao-ying Fu  <fu@mips.com>
> > 
> > 	* tree.def (FIXED_POINT_TYPE): New type.
> > 	(FIXED_CST): New constant.
> > 	(FIXED_CONVERT_EXPR): New expr.
> >       ...
> 
> OK, once we've resolved 2/10.
> 

  Yes.  Since 2/10 was resolved and applied
on Monday (Aug. 6), I checked in the patch 3/10 today.
Thanks!

Regards,
Chao-ying

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [ping][patch] Fixed-point patch 3/10
  2007-08-08 22:34   ` Fu, Chao-Ying
@ 2007-08-09 12:14     ` Rask Ingemann Lambertsen
  2007-08-09 17:31       ` Fu, Chao-Ying
  0 siblings, 1 reply; 9+ messages in thread
From: Rask Ingemann Lambertsen @ 2007-08-09 12:14 UTC (permalink / raw)
  To: Fu, Chao-Ying
  Cc: Mark Mitchell, gcc-patches, Thekkath, Radhika, Stephens, Nigel

On Wed, Aug 08, 2007 at 03:36:13PM -0700, Fu, Chao-Ying wrote:
> Mark Mitchell wrote:
> > 
> > Fu, Chao-Ying wrote:
> > 
> > > gcc/ChangeLog
> > > 2007-08-01  Chao-ying Fu  <fu@mips.com>
> > > 
> > > 	* tree.def (FIXED_POINT_TYPE): New type.
> > > 	(FIXED_CST): New constant.
> > > 	(FIXED_CONVERT_EXPR): New expr.
> > >       ...
> > 
> > OK, once we've resolved 2/10.
> 
>   Yes.  Since 2/10 was resolved and applied
> on Monday (Aug. 6), I checked in the patch 3/10 today.

   Now x86_64-unknown-linux-gnu doesn't bootstrap:

/home/rask/src/gcc/gcc/tree.c: In function initializer_zerop:
/home/rask/src/gcc/gcc/tree.c:7694: error: passing argument 1 of fixed_zerop
discards qualifiers from pointer target type
make[3]: *** [tree.o] Error 1

If I revert to revision 127305, I can get through stage 2.

-- 
Rask Ingemann Lambertsen

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [ping][patch] Fixed-point patch 3/10
  2007-08-09 12:14     ` Rask Ingemann Lambertsen
@ 2007-08-09 17:31       ` Fu, Chao-Ying
  0 siblings, 0 replies; 9+ messages in thread
From: Fu, Chao-Ying @ 2007-08-09 17:31 UTC (permalink / raw)
  To: Rask Ingemann Lambertsen
  Cc: Mark Mitchell, gcc-patches, Thekkath, Radhika, Stephens, Nigel

Rask Ingemann wrote
> On Wed, Aug 08, 2007 at 03:36:13PM -0700, Fu, Chao-Ying wrote:
> > Mark Mitchell wrote:
> > > 
> > > Fu, Chao-Ying wrote:
> > > 
> > > > gcc/ChangeLog
> > > > 2007-08-01  Chao-ying Fu  <fu@mips.com>
> > > > 
> > > > 	* tree.def (FIXED_POINT_TYPE): New type.
> > > > 	(FIXED_CST): New constant.
> > > > 	(FIXED_CONVERT_EXPR): New expr.
> > > >       ...
> > > 
> > > OK, once we've resolved 2/10.
> > 
> >   Yes.  Since 2/10 was resolved and applied
> > on Monday (Aug. 6), I checked in the patch 3/10 today.
> 
>    Now x86_64-unknown-linux-gnu doesn't bootstrap:
> 
> /home/rask/src/gcc/gcc/tree.c: In function initializer_zerop:
> /home/rask/src/gcc/gcc/tree.c:7694: error: passing argument 1 
> of fixed_zerop
> discards qualifiers from pointer target type
> make[3]: *** [tree.o] Error 1
> 
> If I revert to revision 127305, I can get through stage 2.
> 
> -- 
> Rask Ingemann Lambertsen
> 

Thanks a lot!  The problem is the type of init is const_tree,
but the type is tree for the 1st parameter in fixed_zerop.
I will change the prototype of fixed_zerop.
Let me know if this can fix the breakage.  Thanks!

Regards,
Chao-ying

Index: tree.h
--- tree.h      (revision 127306)
+++ tree.h      (working copy)
@@ -4429,7 +4429,7 @@
 /* fixed_zerop (tree x) is nonzero if X is a fixed-point constant of
    value 0.  */

-extern int fixed_zerop (tree);
+extern int fixed_zerop (const_tree);

 /* staticp (tree x) is nonzero if X is a reference to data allocated
    at a fixed address in memory.  Returns the outermost data.  */
Index: tree.c
===================================================================
--- tree.c      (revision 127306)
+++ tree.c      (working copy)
@@ -1460,7 +1460,7 @@
 /* Return 1 if EXPR is the fixed-point constant zero.  */

 int
-fixed_zerop (tree expr)
+fixed_zerop (const_tree expr)
 {
   return (TREE_CODE (expr) == FIXED_CST
          && double_int_zero_p (TREE_FIXED_CST (expr).data));

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2007-08-09 17:31 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-08-01 23:54 [ping][patch] Fixed-point patch 3/10 Fu, Chao-Ying
2007-08-06  3:52 ` Mark Mitchell
2007-08-08 22:34   ` Fu, Chao-Ying
2007-08-09 12:14     ` Rask Ingemann Lambertsen
2007-08-09 17:31       ` Fu, Chao-Ying
2007-08-06 21:37 ` Tom Tromey
2007-08-06 21:42   ` Andrew Pinski
2007-08-06 21:50     ` Tom Tromey
2007-08-06 21:53   ` Fu, Chao-Ying

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).