target.def (min_arithmetic_precision): New hook.
authorEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 28 Oct 2016 21:04:51 +0000 (21:04 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 28 Oct 2016 21:04:51 +0000 (21:04 +0000)
* 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

12 files changed:
gcc/ChangeLog
gcc/config/sparc/sparc.c
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/internal-fn.c
gcc/target.def
gcc/targhooks.c
gcc/targhooks.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/sparc/overflow-3.c
gcc/testsuite/gcc.target/sparc/overflow-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/sparc/overflow-5.c [new file with mode: 0644]

index 32f6435a90085f1bace966d62c3e2f9d2e3e8c05..3687ecd4a367c5752f6426ff3decc2ca31127060 100644 (file)
@@ -1,3 +1,15 @@
+2016-10-28  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * 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  <segher@kernel.crashing.org>
 
        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.
        (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,
index c5638ccd2aae6123c49c63dddcde4c7b8917dd92..2d1f598434bfa5e9f333530def64a9cb9c451dc9 100644 (file)
@@ -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);
 \f
 #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
index d2bcdca6d8c794f37d41cbe662d959df4dc4202e..0aed3d4f1bbc8e6fe9c6a936ae7ae0ce7fea5ac5 100644 (file)
@@ -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
index 3399465fa054d3a0c40f46a3a731704a01d6c814..9e5b45661a942d3f9ac15a1ba205c64bb804c474 100644 (file)
@@ -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
index 1eeb15e4a503d1136fb96ae54dd9b72edc499c61..168adc68105924dda28103f381e1f962e7f5111d 100644 (file)
@@ -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
index ae0ea16e57fdd616982738ba9c45341eea97cbf5..c3c87b031b38c2c650dad7b804c789e7d89ae3a3 100644 (file)
@@ -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\
index d6fd8b8a77f6b6485d62ad7e4e0c50acdfbc3bc1..866747a9ddf57d71afdb8882bcc1edf683497fa8 100644 (file)
@@ -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"
index afb1c00caf491687e3645b192e6bba0a33cbc2ec..94f5e31f80f7d66bc963dfc657b05c9cf7eea74a 100644 (file)
@@ -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 */
index cd2b1eb073cb699566435398940f934cced1ae2d..087d4f3b359af57d77c6ba6fac3bbd199cfeb720 100644 (file)
@@ -1,3 +1,9 @@
+2016-10-28  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * 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  <prathamesh.kulkarni@linaro.org>
            Kugan Vivekanandarajah  <kuganv@linaro.org>
            Jim Wilson  <jim.wilson@linaro.org>
index 31b326486ee9108a9b5aa4cc0bdae3c3915f15e0..8cb24f52f7b45312a67748aa45fcd4a5798c9ab8 100644 (file)
@@ -5,40 +5,39 @@
 #include <stdbool.h>
 #include <stdint.h>
 
-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 (file)
index 0000000..31b3264
--- /dev/null
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+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 (file)
index 0000000..501ce04
--- /dev/null
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mvis3" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+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%" } } */