diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 007b928..cd58605 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -169,6 +169,7 @@ static tree handle_objc_nullability_attribute (tree *, tree, tree, int, bool *); static tree handle_signed_bool_precision_attribute (tree *, tree, tree, int, bool *); static tree handle_retain_attribute (tree *, tree, tree, int, bool *); +static tree handle_saturating_attribute (tree *, tree, tree, int, bool *); /* Helper to define attribute exclusions. */ #define ATTR_EXCL(name, function, type, variable) \ @@ -536,6 +537,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_special_var_sec_attribute, attr_section_exclusions }, { "access", 1, 3, false, true, true, false, handle_access_attribute, NULL }, + { "saturating", 0, 0, false, true, false, false, + handle_saturating_attribute, NULL }, /* Attributes used by Objective-C. */ { "NSObject", 0, 0, true, false, false, false, handle_nsobject_attribute, NULL }, @@ -5761,6 +5764,27 @@ handle_objc_nullability_attribute (tree *node, tree name, tree args, return NULL_TREE; } +/* Handle a "saturating" attribute. */ + +static tree +handle_saturating_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int flags, bool *no_add_attrs) +{ + tree type = *node; + + *no_add_attrs = true; + + if (TREE_CODE (type) == INTEGER_TYPE) + { + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = type = build_duplicate_type (type); + TYPE_SATURATING (type) = 1; + } + else + warning (OPT_Wattributes,"saturating attribute on non-integer type"); + return NULL_TREE; +} + /* Attempt to partially validate a single attribute ATTR as if it were to be applied to an entity OPER. */ diff --git a/gcc/config/nvptx/nvptx.md b/gcc/config/nvptx/nvptx.md index 108de1c..79fa300 100644 --- a/gcc/config/nvptx/nvptx.md +++ b/gcc/config/nvptx/nvptx.md @@ -1217,6 +1217,22 @@ return asms[INTVAL (operands[2])]; }) +;; Saturating integer arithmetic + +(define_insn "ssaddsi3" + [(set (match_operand:SI 0 "nvptx_register_operand" "=R") + (ss_plus:SI (match_operand:SI 1 "nvptx_register_operand" "R") + (match_operand:SI 2 "nvptx_nonmemory_operand" "Ri")))] + "" + "%.\\tadd.sat.s32\\t%0, %1, %2;") + +(define_insn "sssubsi3" + [(set (match_operand:SI 0 "nvptx_register_operand" "=R") + (ss_minus:SI (match_operand:SI 1 "nvptx_register_operand" "R") + (match_operand:SI 2 "nvptx_register_operand" "R")))] + "" + "%.\\tsub.sat.s32\\t%0, %1, %2;") + ;; Miscellaneous (define_insn "nop" diff --git a/gcc/optabs.def b/gcc/optabs.def index 201b8aa..7d157ad 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -106,14 +106,18 @@ OPTAB_NX(add_optab, "add$Q$a3") OPTAB_VL(addv_optab, "addv$I$a3", PLUS, "add", '3', gen_intv_fp_libfunc) OPTAB_VX(addv_optab, "add$F$a3") OPTAB_NL(ssadd_optab, "ssadd$Q$a3", SS_PLUS, "ssadd", '3', gen_signed_fixed_libfunc) +OPTAB_NX(ssadd_optab, "ssadd$I$a3") OPTAB_NL(usadd_optab, "usadd$Q$a3", US_PLUS, "usadd", '3', gen_unsigned_fixed_libfunc) +OPTAB_NX(usadd_optab, "usadd$I$a3") OPTAB_NL(sub_optab, "sub$P$a3", MINUS, "sub", '3', gen_int_fp_fixed_libfunc) OPTAB_NX(sub_optab, "sub$F$a3") OPTAB_NX(sub_optab, "sub$Q$a3") OPTAB_VL(subv_optab, "subv$I$a3", MINUS, "sub", '3', gen_intv_fp_libfunc) OPTAB_VX(subv_optab, "sub$F$a3") OPTAB_NL(sssub_optab, "sssub$Q$a3", SS_MINUS, "sssub", '3', gen_signed_fixed_libfunc) +OPTAB_NX(sssub_optab, "sssub$I$a3") OPTAB_NL(ussub_optab, "ussub$Q$a3", US_MINUS, "ussub", '3', gen_unsigned_fixed_libfunc) +OPTAB_NX(sssub_optab, "ussub$I$a3") OPTAB_NL(smul_optab, "mul$Q$a3", MULT, "mul", '3', gen_int_fp_fixed_libfunc) OPTAB_NX(smul_optab, "mul$P$a3") OPTAB_NX(smul_optab, "mul$F$a3") diff --git a/gcc/print-tree.c b/gcc/print-tree.c index d1fbd04..d0e135e 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -620,6 +620,10 @@ print_node (FILE *file, const char *prefix, tree node, int indent, && TYPE_REVERSE_STORAGE_ORDER (node)) fputs (" reverse-storage-order", file); + if (code == INTEGER_TYPE + && TYPE_SATURATING (node)) + fputs(" saturating", file); + if ((code == RECORD_TYPE || code == UNION_TYPE) && TYPE_CXX_ODR_P (node))