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
This commit is contained in:
parent
9a5e1efcac
commit
894d8b4163
@ -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.
|
||||
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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\
|
||||
|
@ -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"
|
||||
|
@ -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 */
|
||||
|
@ -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>
|
||||
|
@ -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%" } } */
|
||||
|
44
gcc/testsuite/gcc.target/sparc/overflow-4.c
Normal file
44
gcc/testsuite/gcc.target/sparc/overflow-4.c
Normal file
@ -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%" } } */
|
43
gcc/testsuite/gcc.target/sparc/overflow-5.c
Normal file
43
gcc/testsuite/gcc.target/sparc/overflow-5.c
Normal file
@ -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%" } } */
|
Loading…
Reference in New Issue
Block a user