Commit 894d8b41 by Eric Botcazou

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
parent 9a5e1efc
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> 2016-10-28 Segher Boessenkool <segher@kernel.crashing.org>
PR target/71847 PR target/71847
...@@ -13,7 +25,7 @@ ...@@ -13,7 +25,7 @@
PR tree-optimization/43721 PR tree-optimization/43721
* target.def: New hook expand_divmod_libfunc. * 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. * doc/tm.texi: Regenerate.
* internal-fn.def: Add new entry for DIVMOD ifn. * internal-fn.def: Add new entry for DIVMOD ifn.
* internal-fn.c (expand_DIVMOD): New. * internal-fn.c (expand_DIVMOD): New.
...@@ -23,10 +35,9 @@ ...@@ -23,10 +35,9 @@
(target_supports_divmod_p): New. (target_supports_divmod_p): New.
(divmod_candidate_p): Likewise. (divmod_candidate_p): Likewise.
(convert_to_divmod): Likewise. (convert_to_divmod): Likewise.
(pass_optimize_widening_mul::execute): Call (pass_optimize_widening_mul::execute): Call calculate_dominance_info,
calculate_dominance_info(), renumber_gimple_stmt_uids() at renumber_gimple_stmt_uids at beginning of function. Call
beginning of function. Call convert_to_divmod() convert_to_divmod and record stats for divmod.
and record stats for divmod.
* config/arm/arm.c (arm_expand_divmod_libfunc): Override hook * config/arm/arm.c (arm_expand_divmod_libfunc): Override hook
TARGET_EXPAND_DIVMOD_LIBFUNC. TARGET_EXPAND_DIVMOD_LIBFUNC.
* doc/sourcebuild.texi: Add items for arm_divmod_simode, divmod, * doc/sourcebuild.texi: Add items for arm_divmod_simode, divmod,
...@@ -648,6 +648,7 @@ static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t, ...@@ -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 machine_mode sparc_cstore_mode (enum insn_code icode);
static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *); static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *);
static bool sparc_fixed_condition_code_regs (unsigned int *, unsigned int *); static bool sparc_fixed_condition_code_regs (unsigned int *, unsigned int *);
static unsigned int sparc_min_arithmetic_precision (void);
#ifdef SUBTARGET_ATTRIBUTE_TABLE #ifdef SUBTARGET_ATTRIBUTE_TABLE
/* Table of valid machine attributes. */ /* Table of valid machine attributes. */
...@@ -866,6 +867,9 @@ char sparc_hard_reg_printed[8]; ...@@ -866,6 +867,9 @@ char sparc_hard_reg_printed[8];
#undef TARGET_FIXED_CONDITION_CODE_REGS #undef TARGET_FIXED_CONDITION_CODE_REGS
#define TARGET_FIXED_CONDITION_CODE_REGS sparc_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 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
#define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 1 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 1
...@@ -2749,6 +2753,14 @@ sparc_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2) ...@@ -2749,6 +2753,14 @@ sparc_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
return true; 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, /* 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, 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 CCFP[E]mode is used. CCNZmode should be used when the first operand
......
...@@ -10623,6 +10623,23 @@ smaller than a word are always performed on the entire register. ...@@ -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. Most RISC machines have this property and most CISC machines do not.
@end defmac @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}) @defmac LOAD_EXTEND_OP (@var{mem_mode})
Define this macro to be a C expression indicating when insns that read 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 memory in @var{mem_mode}, an integral mode narrower than a word, set the
......
...@@ -7577,6 +7577,8 @@ smaller than a word are always performed on the entire register. ...@@ -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. Most RISC machines have this property and most CISC machines do not.
@end defmac @end defmac
@hook TARGET_MIN_ARITHMETIC_PRECISION
@defmac LOAD_EXTEND_OP (@var{mem_mode}) @defmac LOAD_EXTEND_OP (@var{mem_mode})
Define this macro to be a C expression indicating when insns that read 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 memory in @var{mem_mode}, an integral mode narrower than a word, set the
......
...@@ -1836,12 +1836,11 @@ expand_arith_overflow (enum tree_code code, gimple *stmt) ...@@ -1836,12 +1836,11 @@ expand_arith_overflow (enum tree_code code, gimple *stmt)
return; return;
} }
/* For sub-word operations, if target doesn't have them, start /* For operations with low precision, if target doesn't have them, start
with precres widening right away, otherwise do it only with precres widening right away, otherwise do it only if the most
if the most simple cases can't be used. */ simple cases can't be used. */
if (WORD_REGISTER_OPERATIONS const int min_precision = targetm.min_arithmetic_precision ();
&& orig_precres == precres if (orig_precres == precres && precres < min_precision)
&& precres < BITS_PER_WORD)
; ;
else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
&& prec1 <= precres) && prec1 <= precres)
...@@ -1876,7 +1875,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt) ...@@ -1876,7 +1875,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt)
/* For sub-word operations, retry with a wider type first. */ /* For sub-word operations, retry with a wider type first. */
if (orig_precres == precres && precop <= BITS_PER_WORD) 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); enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m), tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
uns0_p && uns1_p uns0_p && uns1_p
......
...@@ -5941,6 +5941,24 @@ comparison code or operands.", ...@@ -5941,6 +5941,24 @@ comparison code or operands.",
void, (int *code, rtx *op0, rtx *op1, bool op0_preserve_value), void, (int *code, rtx *op0, rtx *op1, bool op0_preserve_value),
default_canonicalize_comparison) 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 DEFHOOKPOD
(atomic_test_and_set_trueval, (atomic_test_and_set_trueval,
"This value should be set if the result written by\ "This value should be set if the result written by\
......
...@@ -2127,4 +2127,12 @@ default_max_noce_ifcvt_seq_cost (edge e) ...@@ -2127,4 +2127,12 @@ default_max_noce_ifcvt_seq_cost (edge e)
return BRANCH_COST (true, predictable_p) * COSTS_N_INSNS (3); 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" #include "gt-targhooks.h"
...@@ -260,7 +260,7 @@ extern void default_setup_incoming_vararg_bounds (cumulative_args_t ca ATTRIBUTE ...@@ -260,7 +260,7 @@ extern void default_setup_incoming_vararg_bounds (cumulative_args_t ca ATTRIBUTE
int second_time ATTRIBUTE_UNUSED); int second_time ATTRIBUTE_UNUSED);
extern bool default_optab_supported_p (int, machine_mode, machine_mode, extern bool default_optab_supported_p (int, machine_mode, machine_mode,
optimization_type); optimization_type);
extern unsigned int default_max_noce_ifcvt_seq_cost (edge); extern unsigned int default_max_noce_ifcvt_seq_cost (edge);
extern unsigned int default_min_arithmetic_precision (void);
#endif /* GCC_TARGHOOKS_H */ #endif /* GCC_TARGHOOKS_H */
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> 2016-10-28 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
Kugan Vivekanandarajah <kuganv@linaro.org> Kugan Vivekanandarajah <kuganv@linaro.org>
Jim Wilson <jim.wilson@linaro.org> Jim Wilson <jim.wilson@linaro.org>
......
...@@ -5,40 +5,39 @@ ...@@ -5,40 +5,39 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.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); 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); 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); 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); 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); 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); return __builtin_sub_overflow (0, a, res);
} }
/* { dg-final { scan-assembler-times "addcc\t%" 2 } } */ /* { dg-final { scan-assembler-times "addcc\t%" 2 } } */
/* { dg-final { scan-assembler-times "subcc\t%" 4 } } */ /* { dg-final { scan-assembler-times "subcc\t%" 4 } } */
/* { dg-final { scan-assembler-times "movlu\t%" 1 } } */ /* { dg-final { scan-assembler-times "addx\t%" 3 } } */
/* { dg-final { scan-assembler-times "blu" 2 } } */
/* { dg-final { scan-assembler-times "bvs" 3 } } */ /* { dg-final { scan-assembler-times "bvs" 3 } } */
/* { dg-final { scan-assembler-not "cmp\t%" } } */ /* { dg-final { scan-assembler-not "cmp\t%" } } */
/* { dg-final { scan-assembler-not "save\t%" } } */ /* { dg-final { scan-assembler-not "save\t%" } } */
/* { 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%" } } */
/* { 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%" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment