diff options
author | Kyrylo Tkachov <kyrylo.tkachov@arm.com> | 2015-10-27 12:23:51 +0000 |
---|---|---|
committer | Kyrylo Tkachov <ktkachov@gcc.gnu.org> | 2015-10-27 12:23:51 +0000 |
commit | 85f5231d73ab398af64c03e4121ab16c6c172cf6 (patch) | |
tree | 7c83b571709ea976ea9027deb40568a1997e9227 /gcc/config/arm | |
parent | 86c0733fed7007dd41efe7739c8295e9933e7f98 (diff) | |
download | gcc-85f5231d73ab398af64c03e4121ab16c6c172cf6.zip gcc-85f5231d73ab398af64c03e4121ab16c6c172cf6.tar.gz gcc-85f5231d73ab398af64c03e4121ab16c6c172cf6.tar.bz2 |
[ARM] PR target/67929 Tighten vfp3_const_double_for_bits checks
PR target/67929
* config/arm/arm.c (vfp3_const_double_for_bits): Rewrite.
* config/arm/constraints.md (Dp): Update callsite.
* config/arm/predicates.md (const_double_vcvt_power_of_two): Likewise.
* gcc.target/arm/pr67929_1.c: New test.
From-SVN: r229436
Diffstat (limited to 'gcc/config/arm')
-rw-r--r-- | gcc/config/arm/arm.c | 38 | ||||
-rw-r--r-- | gcc/config/arm/constraints.md | 3 | ||||
-rw-r--r-- | gcc/config/arm/predicates.md | 2 |
3 files changed, 28 insertions, 15 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index a379121..a598c84 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -27747,25 +27747,37 @@ vfp3_const_double_for_fract_bits (rtx operand) return 0; } +/* If X is a CONST_DOUBLE with a value that is a power of 2 whose + log2 is in [1, 32], return that log2. Otherwise return -1. + This is used in the patterns for vcvt.s32.f32 floating-point to + fixed-point conversions. */ + int -vfp3_const_double_for_bits (rtx operand) +vfp3_const_double_for_bits (rtx x) { - const REAL_VALUE_TYPE *r0; + const REAL_VALUE_TYPE *r; - if (!CONST_DOUBLE_P (operand)) - return 0; + if (!CONST_DOUBLE_P (x)) + return -1; - r0 = CONST_DOUBLE_REAL_VALUE (operand); - if (exact_real_truncate (DFmode, r0)) - { - HOST_WIDE_INT value = real_to_integer (r0); - value = value & 0xffffffff; - if ((value != 0) && ( (value & (value - 1)) == 0)) - return int_log2 (value); - } + r = CONST_DOUBLE_REAL_VALUE (x); - return 0; + if (REAL_VALUE_NEGATIVE (*r) + || REAL_VALUE_ISNAN (*r) + || REAL_VALUE_ISINF (*r) + || !real_isinteger (r, SFmode)) + return -1; + + HOST_WIDE_INT hwint = exact_log2 (real_to_integer (r)); + +/* The exact_log2 above will have returned -1 if this is + not an exact log2. */ + if (!IN_RANGE (hwint, 1, 32)) + return -1; + + return hwint; } + /* Emit a memory barrier around an atomic sequence according to MODEL. */ diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md index e24858f..901cfe5 100644 --- a/gcc/config/arm/constraints.md +++ b/gcc/config/arm/constraints.md @@ -339,7 +339,8 @@ "@internal In ARM/ Thumb2 a const_double which can be used with a vcvt.s32.f32 with bits operation" (and (match_code "const_double") - (match_test "TARGET_32BIT && TARGET_VFP && vfp3_const_double_for_bits (op)"))) + (match_test "TARGET_32BIT && TARGET_VFP + && vfp3_const_double_for_bits (op) > 0"))) (define_register_constraint "Ts" "(arm_restrict_it) ? LO_REGS : GENERAL_REGS" "For arm_restrict_it the core registers @code{r0}-@code{r7}. GENERAL_REGS otherwise.") diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index 08cc899..48e4ba8 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -668,7 +668,7 @@ (define_predicate "const_double_vcvt_power_of_two" (and (match_code "const_double") (match_test "TARGET_32BIT && TARGET_VFP - && vfp3_const_double_for_bits (op)"))) + && vfp3_const_double_for_bits (op) > 0"))) (define_predicate "neon_struct_operand" (and (match_code "mem") |