diff options
Diffstat (limited to 'gcc')
36 files changed, 1419 insertions, 44 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7d9769a..0f67a79 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,218 @@ +2007-08-08 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. + 2007-08-08 David Edelsohn <edelsohn@gnu.org> * config/rs6000/x-rs6000: New file. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index fe059d0..7dafff6 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1772,7 +1772,7 @@ c-common.o : c-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ 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 @@ tree.o : tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ $(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 @@ tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ 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-nomudflap.o : $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TREE_INLINE_H) \ 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 diff --git a/gcc/c-aux-info.c b/gcc/c-aux-info.c index 1a40f0d..28da8e0 100644 --- a/gcc/c-aux-info.c +++ b/gcc/c-aux-info.c @@ -426,6 +426,7 @@ gen_type (const char *ret_val, tree t, formals_style style) 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. */ diff --git a/gcc/c-pretty-print.c b/gcc/c-pretty-print.c index 98e6337..e11d83c 100644 --- a/gcc/c-pretty-print.c +++ b/gcc/c-pretty-print.c @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see #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 @@ pp_c_type_specifier (c_pretty_printer *pp, tree t) 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 @@ pp_c_type_specifier (c_pretty_printer *pp, tree t) 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 @@ pp_c_type_specifier (c_pretty_printer *pp, tree t) 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 @@ pp_c_direct_abstract_declarator (c_pretty_printer *pp, tree t) 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 @@ pp_c_direct_declarator (c_pretty_printer *pp, tree t) case INTEGER_TYPE: case REAL_TYPE: + case FIXED_POINT_TYPE: case ENUMERAL_TYPE: case UNION_TYPE: case RECORD_TYPE: @@ -678,6 +688,7 @@ pp_c_declarator (c_pretty_printer *pp, tree t) { case INTEGER_TYPE: case REAL_TYPE: + case FIXED_POINT_TYPE: case ENUMERAL_TYPE: case UNION_TYPE: case RECORD_TYPE: @@ -925,6 +936,16 @@ pp_c_floating_constant (c_pretty_printer *pp, tree r) 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 @@ pp_c_compound_literal (c_pretty_printer *pp, tree e) /* constant: integer-constant floating-constant + fixed-point-constant enumeration-constant character-constant */ @@ -982,6 +1004,10 @@ pp_c_constant (c_pretty_printer *pp, tree e) 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 @@ pp_c_primary_expression (c_pretty_printer *pp, tree e) case INTEGER_CST: case REAL_CST: + case FIXED_CST: case STRING_CST: pp_c_constant (pp, e); break; @@ -1842,6 +1869,10 @@ pp_c_expression (c_pretty_printer *pp, tree e) 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; diff --git a/gcc/dbxout.c b/gcc/dbxout.c index e7553ed..9657120 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -1906,6 +1906,7 @@ dbxout_type (tree type, int full) 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'); diff --git a/gcc/defaults.h b/gcc/defaults.h index 4add6e3..698438f 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -454,6 +454,38 @@ along with GCC; see the file COPYING3. If not see #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 diff --git a/gcc/doc/c-tree.texi b/gcc/doc/c-tree.texi index 4134007..a53329a 100644 --- a/gcc/doc/c-tree.texi +++ b/gcc/doc/c-tree.texi @@ -271,6 +271,7 @@ The elements are indexed from zero. @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 @@ Used to represent the @code{float}, @code{double}, and @code{long 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 @@ This macro returns the attributes on the type @var{type}. @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 @@ This macro returns the attributes on the type @var{type}. @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 @@ its bit-pattern. 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 @@ cases are always indicated explicitly. Similarly, a user-defined 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 diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index a8bd036..bf6859d 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1605,6 +1605,54 @@ the target machine. If you don't define this, the default is two 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 diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 5f71e82..dc352b1 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -8396,6 +8396,13 @@ base_type_die (tree type) 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 @@ is_base_type (tree type) 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 @@ add_type_attribute (dw_die_ref object_die, tree type, int decl_const, 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 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die, 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. */ diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 020847a..803f740 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see #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 dconstthird; 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. @@ -5256,6 +5261,62 @@ init_emit_once (int line_numbers) 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; diff --git a/gcc/explow.c b/gcc/explow.c index 1b9deb9..636dcb9 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -793,7 +793,7 @@ promote_mode (tree type, enum machine_mode mode, int *punsignedp, { #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) { diff --git a/gcc/expmed.c b/gcc/expmed.c index 4f8c58d..061fbbb 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -1182,6 +1182,14 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, 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; diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 154454a..eadcb97 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see #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 @@ negate_expr_p (tree t) return (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type)); + case FIXED_CST: case REAL_CST: case NEGATE_EXPR: return true; @@ -1257,6 +1259,10 @@ fold_negate_expr (tree t) 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 @@ split_tree (tree in, enum tree_code code, tree *conp, tree *litp, /* 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 @@ split_tree (tree in, enum tree_code code, tree *conp, tree *litp, 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 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) 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 @@ fold_convert_const_int_from_real (enum tree_code code, tree type, tree arg1) 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 @@ fold_convert_const_real_from_real (tree type, tree arg1) 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 @@ fold_convert_const (enum tree_code code, tree type, tree arg1) 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 @@ fold_convert (tree type, tree arg) 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 @@ fold_convert (tree type, tree arg) 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 @@ fold_convert (tree type, tree arg) 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 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) 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 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh, 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 @@ tree_swap_operands_p (const_tree arg0, const_tree arg1, bool reorder) 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 @@ fold_plusminus_mult_expr (enum tree_code code, tree type, tree arg0, tree arg1) } 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 @@ fold_plusminus_mult_expr (enum tree_code code, tree type, tree arg0, tree arg1) } 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 @@ fold_unary (enum tree_code code, tree type, tree op0) 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 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) 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 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) } /* 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 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) /* 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; @@ -9874,9 +10167,10 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) 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); @@ -13480,6 +13774,9 @@ tree_expr_nonnegative_warnv_p (tree t, bool *strict_overflow_p) 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))) @@ -14082,7 +14379,7 @@ fold_read_from_constant_string (tree exp) } /* 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. */ @@ -14110,6 +14407,24 @@ fold_negate_const (tree arg0, tree type) 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 (); } @@ -14240,6 +14555,13 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1) 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) { diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 8b77c80..c6c0788 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -4488,6 +4488,7 @@ omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type) 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 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, /* 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 @@ gimplify_type_sizes (tree type, tree *list_p) 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); diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 52fea2c..76e2d3b 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -481,7 +481,8 @@ ipa_callsite_compute_param (struct cgraph_edge *cs) 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 @@ ipa_callsite_compute_param (struct cgraph_edge *cs) { 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); diff --git a/gcc/ipa-type-escape.c b/gcc/ipa-type-escape.c index a291971..5303e79 100644 --- a/gcc/ipa-type-escape.c +++ b/gcc/ipa-type-escape.c @@ -274,6 +274,7 @@ type_to_consider (tree type) case INTEGER_TYPE: case QUAL_UNION_TYPE: case REAL_TYPE: + case FIXED_POINT_TYPE: case RECORD_TYPE: case UNION_TYPE: case VECTOR_TYPE: diff --git a/gcc/print-tree.c b/gcc/print-tree.c index 297f62f..55efdf4 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see #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 @@ print_node_brief (FILE *file, const char *prefix, const_tree node, int indent) 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 *file, const char *prefix, tree node, int indent) 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 @@ print_node (FILE *file, const char *prefix, tree node, int indent) } 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); diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index fc33d8e..ea658a8 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -236,6 +236,14 @@ int_mode_for_mode (enum machine_mode mode) 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 @@ layout_type (tree type) 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 @@ layout_type (tree type) /* 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 @@ layout_type (tree type) 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 @@ make_unsigned_type (int precision) return type; } +/* 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. */ diff --git a/gcc/tree-browser.c b/gcc/tree-browser.c index 5458e28..89c3bf3 100644 --- a/gcc/tree-browser.c +++ b/gcc/tree-browser.c @@ -162,7 +162,8 @@ browse_tree (tree begin) 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 @@ browse_tree (tree begin) 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; diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c index ea0eafc..693c8c9 100644 --- a/gcc/tree-complex.c +++ b/gcc/tree-complex.c @@ -96,6 +96,8 @@ some_nonzerop (tree t) 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); diff --git a/gcc/tree-dump.c b/gcc/tree-dump.c index 1ac0175..f370bcd 100644 --- a/gcc/tree-dump.c +++ b/gcc/tree-dump.c @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #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 @@ dump_real (dump_info_p di, const char *field, const REAL_VALUE_TYPE *r) 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 @@ dequeue_and_dump (dump_info_p di) 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 @@ dequeue_and_dump (dump_info_p di) 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: diff --git a/gcc/tree-gimple.c b/gcc/tree-gimple.c index e9753eb..def2b12 100644 --- a/gcc/tree-gimple.c +++ b/gcc/tree-gimple.c @@ -67,6 +67,7 @@ is_gimple_formal_tmp_rhs (tree t) 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 @@ is_gimple_min_invariant (const_tree t) case INTEGER_CST: case REAL_CST: + case FIXED_CST: case STRING_CST: case COMPLEX_CST: case VECTOR_CST: diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index af0c7d4..3609480 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -340,6 +340,7 @@ remap_type_1 (tree type, copy_body_data *id) { 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 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) 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 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) case MINUS_EXPR: case MULT_EXPR: + case FIXED_CONVERT_EXPR: case FIX_TRUNC_EXPR: case NEGATE_EXPR: diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index bd71a7d..a502da0 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #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 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, 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 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, 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 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, NIY; break; + case FIXED_CONVERT_EXPR: case FIX_TRUNC_EXPR: case FLOAT_EXPR: case CONVERT_EXPR: diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c index 4fe1a86..64627ef 100644 --- a/gcc/tree-scalar-evolution.c +++ b/gcc/tree-scalar-evolution.c @@ -600,6 +600,7 @@ get_scalar_evolution (tree scalar) break; case REAL_CST: + case FIXED_CST: case INTEGER_CST: res = scalar; break; diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index f55449f..f2e64c7 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -220,6 +220,7 @@ is_sra_scalar_type (tree type) { 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); diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index c623a47..d2ab41c 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -204,6 +204,7 @@ for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data) case COMPLEX_CST: case INTEGER_CST: case REAL_CST: + case FIXED_CST: return true; case TARGET_MEM_REF: diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 1cebc4a..059af12 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -3081,6 +3081,7 @@ poolify_tree (tree node) case INTEGER_CST: case STRING_CST: case REAL_CST: + case FIXED_CST: case PARM_DECL: case VAR_DECL: case RESULT_DECL: diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index b09c60f..87db02f 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -1245,12 +1245,15 @@ break_up_subtract_bb (basic_block bb) 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 @@ reassociate_bb (basic_block bb) 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))) diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index b30915e..aa67325 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -295,7 +295,11 @@ expand_vector_operation (block_stmt_iterator *bsi, tree type, tree compute_type, 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 @@ expand_vector_operation (block_stmt_iterator *bsi, tree type, tree compute_type, } /* 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 @@ type_for_widest_vector_mode (enum machine_mode inner_mode, optab op) 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 @@ expand_vector_operations_1 (block_stmt_iterator *bsi) 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 @@ expand_vector_operations_1 (block_stmt_iterator *bsi) { 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; diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c index 0965165..30930c6 100644 --- a/gcc/tree-vect-transform.c +++ b/gcc/tree-vect-transform.c @@ -4913,7 +4913,8 @@ vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo) 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 @@ vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo) 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 @@ vectorizable_condition (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) 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 @@ vectorizable_condition (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) 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; diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index be17297..47a25f8 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -2150,6 +2150,16 @@ vect_is_simple_reduction (struct loop *loop, tree phi) } 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 @@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see #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 @@ tree_code_size (enum tree_code code) { 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 @@ build_constructor_from_list (tree type, tree vals) 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 @@ build_one_cst (tree type) 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 (const_tree expr) || 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 @@ tree_node_structure (const_tree t) /* 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 @@ type_contains_placeholder_1 (const_tree type) 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 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) (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 @@ type_hash_eq (const void *va, const void *vb) || 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 @@ simple_cst_equal (const_tree t1, const_tree t2) 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 @@ iterative_hash_expr (const_tree t, hashval_t val) 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 @@ get_unwidened (tree op, tree for_type) 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 @@ get_narrower (tree op, int *unsignedp_ptr) 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 @@ variably_modified_type_p (tree type, tree fn) 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 @@ make_or_reuse_type (unsigned size, int unsignedp) 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 @@ build_common_tree_nodes_2 (int short_double) 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 @@ build_vector_type_for_mode (tree innertype, enum machine_mode mode) { 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 @@ initializer_zerop (const_tree init) 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 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) case IDENTIFIER_NODE: case INTEGER_CST: case REAL_CST: + case FIXED_CST: case VECTOR_CST: case STRING_CST: case BLOCK: @@ -8389,6 +8565,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) 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)); diff --git a/gcc/tree.def b/gcc/tree.def index 72c6d24..ea8449b 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -172,6 +172,11 @@ DEFTREECODE (REAL_TYPE, "real_type", tcc_type, 0) 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 @@ DEFTREECODE (INTEGER_CST, "integer_cst", tcc_constant, 0) /* 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 @@ DEFTREECODE (RANGE_EXPR, "range_expr", tcc_binary, 2) 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) @@ -384,6 +384,7 @@ struct tree_base GTY(()) 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 @@ struct tree_base GTY(()) 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 @@ struct gimple_stmt GTY(()) TREE_INVARIANT in all expressions. + saturating_flag: + + TYPE_SATURATING in + all types + nowarning_flag: TREE_NO_WARNING in @@ -951,7 +957,8 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, 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 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, || 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 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, 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 tree_real_cst GTY(()) 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 @@ struct tree_block GTY(()) 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 @@ union tree_node GTY ((ptr_alias (union lang_tree_node), 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 @@ enum tree_index 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 @@ extern GTY(()) tree global_trees[TI_MAX]; #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 tree_expr_nonnegative_warnv_p (tree, bool *); 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 int integer_nonzerop (const_tree); 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. */ diff --git a/gcc/treestruct.def b/gcc/treestruct.def index b7f2cdd..ef4a724 100644 --- a/gcc/treestruct.def +++ b/gcc/treestruct.def @@ -31,6 +31,7 @@ DEFTREESTRUCT(TS_BASE, "base") 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") |