From: Eric Botcazou Date: Fri, 28 Oct 2016 21:04:51 +0000 (+0000) Subject: target.def (min_arithmetic_precision): New hook. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=894d8b416343817776946da50d0b660f20742921;p=gcc.git target.def (min_arithmetic_precision): New hook. * target.def (min_arithmetic_precision): New hook. * doc/tm.texi.in (Misc): Add TARGET_MIN_ARITHMETIC_PRECISION. * doc/tm.texi: Regenerate. * internal-fn.c (expand_arith_overflow): Adjust handling of target dependent support by means of TARGET_MIN_ARITHMETIC_PRECISION. * targhooks.c (default_min_arithmetic_precision): New function. * targhooks.h (default_min_arithmetic_precision): Declare. * config/sparc/sparc.c (TARGET_MIN_ARITHMETIC_PRECISION): Define. (sparc_min_arithmetic_precision): New function. From-SVN: r241665 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 32f6435a900..3687ecd4a36 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2016-10-28 Eric Botcazou + + * target.def (min_arithmetic_precision): New hook. + * doc/tm.texi.in (Misc): Add TARGET_MIN_ARITHMETIC_PRECISION. + * doc/tm.texi: Regenerate. + * internal-fn.c (expand_arith_overflow): Adjust handling of target + dependent support by means of TARGET_MIN_ARITHMETIC_PRECISION. + * targhooks.c (default_min_arithmetic_precision): New function. + * targhooks.h (default_min_arithmetic_precision): Declare. + * config/sparc/sparc.c (TARGET_MIN_ARITHMETIC_PRECISION): Define. + (sparc_min_arithmetic_precision): New function. + 2016-10-28 Segher Boessenkool PR target/71847 @@ -13,7 +25,7 @@ PR tree-optimization/43721 * target.def: New hook expand_divmod_libfunc. - * doc/tm.texi.in: Add hook for TARGET_EXPAND_DIVMOD_LIBFUNC + * doc/tm.texi.in: Add hook for TARGET_EXPAND_DIVMOD_LIBFUNC. * doc/tm.texi: Regenerate. * internal-fn.def: Add new entry for DIVMOD ifn. * internal-fn.c (expand_DIVMOD): New. @@ -23,10 +35,9 @@ (target_supports_divmod_p): New. (divmod_candidate_p): Likewise. (convert_to_divmod): Likewise. - (pass_optimize_widening_mul::execute): Call - calculate_dominance_info(), renumber_gimple_stmt_uids() at - beginning of function. Call convert_to_divmod() - and record stats for divmod. + (pass_optimize_widening_mul::execute): Call calculate_dominance_info, + renumber_gimple_stmt_uids at beginning of function. Call + convert_to_divmod and record stats for divmod. * config/arm/arm.c (arm_expand_divmod_libfunc): Override hook TARGET_EXPAND_DIVMOD_LIBFUNC. * doc/sourcebuild.texi: Add items for arm_divmod_simode, divmod, diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index c5638ccd2aa..2d1f598434b 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -648,6 +648,7 @@ static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t, static machine_mode sparc_cstore_mode (enum insn_code icode); static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *); static bool sparc_fixed_condition_code_regs (unsigned int *, unsigned int *); +static unsigned int sparc_min_arithmetic_precision (void); #ifdef SUBTARGET_ATTRIBUTE_TABLE /* Table of valid machine attributes. */ @@ -866,6 +867,9 @@ char sparc_hard_reg_printed[8]; #undef TARGET_FIXED_CONDITION_CODE_REGS #define TARGET_FIXED_CONDITION_CODE_REGS sparc_fixed_condition_code_regs +#undef TARGET_MIN_ARITHMETIC_PRECISION +#define TARGET_MIN_ARITHMETIC_PRECISION sparc_min_arithmetic_precision + #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 1 @@ -2749,6 +2753,14 @@ sparc_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2) return true; } +/* Implement TARGET_MIN_ARITHMETIC_PRECISION. */ + +static unsigned int +sparc_min_arithmetic_precision (void) +{ + return 32; +} + /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, return the mode to be used for the comparison. For floating-point, CCFP[E]mode is used. CCNZmode should be used when the first operand diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index d2bcdca6d8c..0aed3d4f1bb 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10623,6 +10623,23 @@ smaller than a word are always performed on the entire register. Most RISC machines have this property and most CISC machines do not. @end defmac +@deftypefn {Target Hook} {unsigned int} TARGET_MIN_ARITHMETIC_PRECISION (void) +On some RISC architectures with 64-bit registers, the processor also +maintains 32-bit condition codes that make it possible to do real 32-bit +arithmetic, although the operations are performed on the full registers. + +On such architectures, defining this hook to 32 tells the compiler to try +using 32-bit arithmetical operations setting the condition codes instead +of doing full 64-bit arithmetic. + +More generally, define this hook on RISC architectures if you want the +compiler to try using arithmetical operations setting the condition codes +with a precision lower than the word precision. + +You need not define this hook if @code{WORD_REGISTER_OPERATIONS} is not +defined to 1. +@end deftypefn + @defmac LOAD_EXTEND_OP (@var{mem_mode}) Define this macro to be a C expression indicating when insns that read memory in @var{mem_mode}, an integral mode narrower than a word, set the diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 3399465fa05..9e5b45661a9 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -7577,6 +7577,8 @@ smaller than a word are always performed on the entire register. Most RISC machines have this property and most CISC machines do not. @end defmac +@hook TARGET_MIN_ARITHMETIC_PRECISION + @defmac LOAD_EXTEND_OP (@var{mem_mode}) Define this macro to be a C expression indicating when insns that read memory in @var{mem_mode}, an integral mode narrower than a word, set the diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index 1eeb15e4a50..168adc68105 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -1836,12 +1836,11 @@ expand_arith_overflow (enum tree_code code, gimple *stmt) return; } - /* For sub-word operations, if target doesn't have them, start - with precres widening right away, otherwise do it only - if the most simple cases can't be used. */ - if (WORD_REGISTER_OPERATIONS - && orig_precres == precres - && precres < BITS_PER_WORD) + /* For operations with low precision, if target doesn't have them, start + with precres widening right away, otherwise do it only if the most + simple cases can't be used. */ + const int min_precision = targetm.min_arithmetic_precision (); + if (orig_precres == precres && precres < min_precision) ; else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres && prec1 <= precres) @@ -1876,7 +1875,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt) /* For sub-word operations, retry with a wider type first. */ if (orig_precres == precres && precop <= BITS_PER_WORD) { - int p = WORD_REGISTER_OPERATIONS ? BITS_PER_WORD : precop; + int p = MAX (min_precision, precop); enum machine_mode m = smallest_mode_for_size (p, MODE_INT); tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m), uns0_p && uns1_p diff --git a/gcc/target.def b/gcc/target.def index ae0ea16e57f..c3c87b031b3 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -5941,6 +5941,24 @@ comparison code or operands.", void, (int *code, rtx *op0, rtx *op1, bool op0_preserve_value), default_canonicalize_comparison) +DEFHOOK +(min_arithmetic_precision, + "On some RISC architectures with 64-bit registers, the processor also\n\ +maintains 32-bit condition codes that make it possible to do real 32-bit\n\ +arithmetic, although the operations are performed on the full registers.\n\ +\n\ +On such architectures, defining this hook to 32 tells the compiler to try\n\ +using 32-bit arithmetical operations setting the condition codes instead\n\ +of doing full 64-bit arithmetic.\n\ +\n\ +More generally, define this hook on RISC architectures if you want the\n\ +compiler to try using arithmetical operations setting the condition codes\n\ +with a precision lower than the word precision.\n\ +\n\ +You need not define this hook if @code{WORD_REGISTER_OPERATIONS} is not\n\ +defined to 1.", + unsigned int, (void), default_min_arithmetic_precision) + DEFHOOKPOD (atomic_test_and_set_trueval, "This value should be set if the result written by\ diff --git a/gcc/targhooks.c b/gcc/targhooks.c index d6fd8b8a77f..866747a9ddf 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -2127,4 +2127,12 @@ default_max_noce_ifcvt_seq_cost (edge e) return BRANCH_COST (true, predictable_p) * COSTS_N_INSNS (3); } +/* Default implementation of TARGET_MIN_ARITHMETIC_PRECISION. */ + +unsigned int +default_min_arithmetic_precision (void) +{ + return WORD_REGISTER_OPERATIONS ? BITS_PER_WORD : BITS_PER_UNIT; +} + #include "gt-targhooks.h" diff --git a/gcc/targhooks.h b/gcc/targhooks.h index afb1c00caf4..94f5e31f80f 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -260,7 +260,7 @@ extern void default_setup_incoming_vararg_bounds (cumulative_args_t ca ATTRIBUTE int second_time ATTRIBUTE_UNUSED); extern bool default_optab_supported_p (int, machine_mode, machine_mode, optimization_type); - extern unsigned int default_max_noce_ifcvt_seq_cost (edge); +extern unsigned int default_min_arithmetic_precision (void); #endif /* GCC_TARGHOOKS_H */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cd2b1eb073c..087d4f3b359 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-10-28 Eric Botcazou + + * gcc.target/sparc/overflow-3.c: Replace and move old one to... + * gcc.target/sparc/overflow-4.c: ...here. + * gcc.target/sparc/overflow-5.c: New test. + 2016-10-28 Prathamesh Kulkarni Kugan Vivekanandarajah Jim Wilson diff --git a/gcc/testsuite/gcc.target/sparc/overflow-3.c b/gcc/testsuite/gcc.target/sparc/overflow-3.c index 31b326486ee..8cb24f52f7b 100644 --- a/gcc/testsuite/gcc.target/sparc/overflow-3.c +++ b/gcc/testsuite/gcc.target/sparc/overflow-3.c @@ -5,40 +5,39 @@ #include #include -bool my_uadd_overflow (uint64_t a, uint64_t b, uint64_t *res) +bool my_uadd_overflow (uint32_t a, uint32_t b, uint32_t *res) { return __builtin_add_overflow (a, b, res); } -bool my_usub_overflow (uint64_t a, uint64_t b, uint64_t *res) +bool my_usub_overflow (uint32_t a, uint32_t b, uint32_t *res) { return __builtin_sub_overflow (a, b, res); } -bool my_uneg_overflow (uint64_t a, uint64_t *res) +bool my_uneg_overflow (uint32_t a, uint32_t *res) { return __builtin_sub_overflow (0, a, res); } -bool my_add_overflow (int64_t a, int64_t b, int64_t *res) +bool my_add_overflow (int32_t a, int32_t b, int32_t *res) { return __builtin_add_overflow (a, b, res); } -bool my_sub_overflow (int64_t a, int64_t b, int64_t *res) +bool my_sub_overflow (int32_t a, int32_t b, int32_t *res) { return __builtin_sub_overflow (a, b, res); } -bool my_neg_overflow (int64_t a, int64_t *res) +bool my_neg_overflow (int32_t a, int32_t *res) { return __builtin_sub_overflow (0, a, res); } /* { dg-final { scan-assembler-times "addcc\t%" 2 } } */ /* { dg-final { scan-assembler-times "subcc\t%" 4 } } */ -/* { dg-final { scan-assembler-times "movlu\t%" 1 } } */ -/* { dg-final { scan-assembler-times "blu" 2 } } */ +/* { dg-final { scan-assembler-times "addx\t%" 3 } } */ /* { dg-final { scan-assembler-times "bvs" 3 } } */ /* { dg-final { scan-assembler-not "cmp\t%" } } */ /* { dg-final { scan-assembler-not "save\t%" } } */ diff --git a/gcc/testsuite/gcc.target/sparc/overflow-4.c b/gcc/testsuite/gcc.target/sparc/overflow-4.c new file mode 100644 index 00000000000..31b326486ee --- /dev/null +++ b/gcc/testsuite/gcc.target/sparc/overflow-4.c @@ -0,0 +1,44 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ +/* { dg-require-effective-target lp64 } */ + +#include +#include + +bool my_uadd_overflow (uint64_t a, uint64_t b, uint64_t *res) +{ + return __builtin_add_overflow (a, b, res); +} + +bool my_usub_overflow (uint64_t a, uint64_t b, uint64_t *res) +{ + return __builtin_sub_overflow (a, b, res); +} + +bool my_uneg_overflow (uint64_t a, uint64_t *res) +{ + return __builtin_sub_overflow (0, a, res); +} + +bool my_add_overflow (int64_t a, int64_t b, int64_t *res) +{ + return __builtin_add_overflow (a, b, res); +} + +bool my_sub_overflow (int64_t a, int64_t b, int64_t *res) +{ + return __builtin_sub_overflow (a, b, res); +} + +bool my_neg_overflow (int64_t a, int64_t *res) +{ + return __builtin_sub_overflow (0, a, res); +} + +/* { dg-final { scan-assembler-times "addcc\t%" 2 } } */ +/* { dg-final { scan-assembler-times "subcc\t%" 4 } } */ +/* { dg-final { scan-assembler-times "movlu\t%" 1 } } */ +/* { dg-final { scan-assembler-times "blu" 2 } } */ +/* { dg-final { scan-assembler-times "bvs" 3 } } */ +/* { dg-final { scan-assembler-not "cmp\t%" } } */ +/* { dg-final { scan-assembler-not "save\t%" } } */ diff --git a/gcc/testsuite/gcc.target/sparc/overflow-5.c b/gcc/testsuite/gcc.target/sparc/overflow-5.c new file mode 100644 index 00000000000..501ce04f7a1 --- /dev/null +++ b/gcc/testsuite/gcc.target/sparc/overflow-5.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-O -mvis3" } */ +/* { dg-require-effective-target lp64 } */ + +#include +#include + +bool my_uadd_overflow (uint64_t a, uint64_t b, uint64_t *res) +{ + return __builtin_add_overflow (a, b, res); +} + +bool my_usub_overflow (uint64_t a, uint64_t b, uint64_t *res) +{ + return __builtin_sub_overflow (a, b, res); +} + +bool my_uneg_overflow (uint64_t a, uint64_t *res) +{ + return __builtin_sub_overflow (0, a, res); +} + +bool my_add_overflow (int64_t a, int64_t b, int64_t *res) +{ + return __builtin_add_overflow (a, b, res); +} + +bool my_sub_overflow (int64_t a, int64_t b, int64_t *res) +{ + return __builtin_sub_overflow (a, b, res); +} + +bool my_neg_overflow (int64_t a, int64_t *res) +{ + return __builtin_sub_overflow (0, a, res); +} + +/* { dg-final { scan-assembler-times "addcc\t%" 2 } } */ +/* { dg-final { scan-assembler-times "subcc\t%" 4 } } */ +/* { dg-final { scan-assembler-times "addxc\t%" 3 } } */ +/* { dg-final { scan-assembler-times "bvs" 3 } } */ +/* { dg-final { scan-assembler-not "cmp\t%" } } */ +/* { dg-final { scan-assembler-not "save\t%" } } */