diff options
author | Jakub Jelinek <jakub@gcc.gnu.org> | 2019-09-10 10:15:46 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2019-09-10 10:15:46 +0200 |
commit | 873140e65d4332557301db341eb40ed285e34c6d (patch) | |
tree | f1e61e58fa3672f7730ad80754c8307dfab8b3df | |
parent | 6508fa9c067d1d20a32703516ad774e3f6f90f0c (diff) | |
download | gcc-873140e65d4332557301db341eb40ed285e34c6d.zip gcc-873140e65d4332557301db341eb40ed285e34c6d.tar.gz gcc-873140e65d4332557301db341eb40ed285e34c6d.tar.bz2 |
re PR middle-end/91680 (Integer promotion quirk prevents efficient power of 2 division)
PR middle-end/91680
* match.pd ((A / (1 << B)) -> (A >> B)): Allow widening cast from
the shift type to type.
* gcc.dg/tree-ssa/pr91680.c: New test.
* g++.dg/torture/pr91680.C: New test.
From-SVN: r275587
-rw-r--r-- | gcc/ChangeLog | 24 | ||||
-rw-r--r-- | gcc/match.pd | 24 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr91680.C | 35 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr91680.c | 37 |
5 files changed, 113 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3bf2a0b..6139e3c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-09-10 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/91680 + * match.pd ((A / (1 << B)) -> (A >> B)): Allow widening cast from + the shift type to type. + 2019-09-10 Christophe Lyon <christophe.lyon@st.com> * config/arm/arm.md (stack_protect_combined_set_insn): Handle @@ -5,7 +11,7 @@ (stack_protect_combined_test_insn): Likewise. 2019-09-10 Christophe Lyon <christophe.lyon@st.com> - Mickaël Guêné <mickael.guene@st.com> + Mickaël Guêné <mickael.guene@st.com> * config/arm/arm.c (arm_load_tp): Add FDPIC support. * config/arm/arm.md (FDPIC_REGNUM): New constant. @@ -13,7 +19,7 @@ (load_tp_soft): Disable in FDPIC mode. 2019-09-10 Christophe Lyon <christophe.lyon@st.com> - Mickaël Guêné <mickael.guene@st.com> + Mickaël Guêné <mickael.guene@st.com> * config/arm/arm.c (tls_reloc): Add TLS_GD32_FDPIC, TLS_LDM32_FDPIC and TLS_IE32_FDPIC. @@ -22,7 +28,7 @@ (arm_emit_tls_decoration): Likewise. 2019-09-10 Christophe Lyon <christophe.lyon@st.com> - Mickaël Guêné <mickael.guene@st.com> + Mickaël Guêné <mickael.guene@st.com> * config/arm/arm.c (arm_asm_trampoline_template): Add FDPIC support. @@ -31,7 +37,7 @@ * config/arm/arm.h (TRAMPOLINE_SIZE): Likewise. 2019-09-10 Christophe Lyon <christophe.lyon@st.com> - Mickaël Guêné <mickael.guene@st.com> + Mickaël Guêné <mickael.guene@st.com> * config/arm/arm.c (arm_fdpic_local_funcdesc_p): New function. (legitimize_pic_address): Enforce binding rules on function @@ -39,20 +45,20 @@ (arm_assemble_integer): Likewise. 2019-09-10 Christophe Lyon <christophe.lyon@st.com> - Mickaël Guêné <mickael.guene@st.com> + Mickaël Guêné <mickael.guene@st.com> * config/arm/arm.h (PIC_REGISTER_MAY_NEED_SAVING): New helper. * config/arm/arm.c (arm_compute_save_reg0_reg12_mask): Handle FDPIC. 2019-09-10 Christophe Lyon <christophe.lyon@st.com> - Mickaël Guêné <mickael.guene@st.com> + Mickaël Guêné <mickael.guene@st.com> * ginclude/unwind-arm-common.h (unwinder_cache): Add reserved5 field. 2019-09-10 Christophe Lyon <christophe.lyon@st.com> - Mickaël Guêné <mickael.guene@st.com> + Mickaël Guêné <mickael.guene@st.com> * config/arm/arm-c.c (__FDPIC__): Define new pre-processor macro in FDPIC mode. @@ -80,7 +86,7 @@ * config/arm/unspecs.md (UNSPEC_PIC_RESTORE): New. 2019-09-10 Christophe Lyon <christophe.lyon@st.com> - Mickaël Guêné <mickael.guene@st.com> + Mickaël Guêné <mickael.guene@st.com> * config.gcc: Handle arm*-*-uclinuxfdpiceabi. * config/arm/bpabi.h (TARGET_FDPIC_ASM_SPEC): New. @@ -95,7 +101,7 @@ * config.gcc: Handle *-*-uclinuxfdpiceabi. 2019-09-10 Christophe Lyon <christophe.lyon@st.com> - Mickaël Guêné <mickael.guene@st.com> + Mickaël Guêné <mickael.guene@st.com> * config/arm/arm.opt: Add -mfdpic option. * doc/invoke.texi: Add documentation for -mfdpic. diff --git a/gcc/match.pd b/gcc/match.pd index 5b2d95d..309a094 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -305,13 +305,29 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* (A / (1 << B)) -> (A >> B). Only for unsigned A. For signed A, this would not preserve rounding toward zero. - For example: (-1 / ( 1 << B)) != -1 >> B. */ -(simplify - (trunc_div @0 (lshift integer_onep@1 @2)) + For example: (-1 / ( 1 << B)) != -1 >> B. + Also also widening conversions, like: + (A / (unsigned long long) (1U << B)) -> (A >> B) + or + (A / (unsigned long long) (1 << B)) -> (A >> B). + If the left shift is signed, it can be done only if the upper bits + of A starting from shift's type sign bit are zero, as + (unsigned long long) (1 << 31) is -2147483648ULL, not 2147483648ULL, + so it is valid only if A >> 31 is zero. */ +(simplify + (trunc_div @0 (convert? (lshift integer_onep@1 @2))) (if ((TYPE_UNSIGNED (type) || tree_expr_nonnegative_p (@0)) && (!VECTOR_TYPE_P (type) || target_supports_op_p (type, RSHIFT_EXPR, optab_vector) - || target_supports_op_p (type, RSHIFT_EXPR, optab_scalar))) + || target_supports_op_p (type, RSHIFT_EXPR, optab_scalar)) + && (useless_type_conversion_p (type, TREE_TYPE (@1)) + || (element_precision (type) >= element_precision (TREE_TYPE (@1)) + && (TYPE_UNSIGNED (TREE_TYPE (@1)) + || (element_precision (type) + == element_precision (TREE_TYPE (@1))) + || (get_nonzero_bits (@0) + & wi::mask (element_precision (TREE_TYPE (@1)) - 1, true, + element_precision (type))) == 0)))) (rshift @0 @2))) /* Preserve explicit divisions by 0: the C++ front-end wants to detect diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 31b54f8..6f487a8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-09-10 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/91680 + * gcc.dg/tree-ssa/pr91680.c: New test. + * g++.dg/torture/pr91680.C: New test. + 2019-09-10 Paolo Carlini <paolo.carlini@oracle.com> * g++.dg/cpp0x/enum29.C: Test location(s) too. diff --git a/gcc/testsuite/g++.dg/torture/pr91680.C b/gcc/testsuite/g++.dg/torture/pr91680.C new file mode 100644 index 0000000..afed400 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr91680.C @@ -0,0 +1,35 @@ +/* PR middle-end/91680 */ +/* { dg-do run { target { ilp32 || lp64 } } } */ + +extern "C" void abort (); + +#include "../../gcc.dg/tree-ssa/pr91680.c" + +int +main () +{ + unsigned char i; + for (i = 0; i < __SIZEOF_INT__ * __CHAR_BIT__; i++) + { + volatile unsigned long long q = 1 << i; + if (foo (i) != 256 / q) + abort (); + q = 1U << i; + if (bar (i) != 256 / q) + abort (); + q = 1 << i; + if (baz (i, (1U << i) - 1) != ((1U << i) - 1) / q) + abort (); + if (baz (i, 1U << i) != (1U << i) / q) + abort (); + if (baz (i, -1) != -1 / q) + abort (); + q = 1U << i; + if (qux (i, (1U << i) - 1) != ((1U << i) - 1) / q) + abort (); + if (qux (i, 1U << i) != (1U << i) / q) + abort (); + if (qux (i, -1) != -1 / q) + abort (); + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr91680.c b/gcc/testsuite/gcc.dg/tree-ssa/pr91680.c new file mode 100644 index 0000000..6d1912b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr91680.c @@ -0,0 +1,37 @@ +/* PR middle-end/91680 */ +/* { dg-do compile { target { ilp32 || lp64 } } } */ +/* { dg-options "-O2 -fdump-tree-forwprop1" } */ +/* { dg-final { scan-tree-dump-times " / " 1 "forwprop1" } } */ +/* { dg-final { scan-tree-dump-times " >> " 3 "forwprop1" } } */ + +__attribute__((noipa)) unsigned long long +foo (unsigned char x) +{ + unsigned long long q = 1 << x; + return 256 / q; +} + +__attribute__((noipa)) unsigned long long +bar (unsigned char x) +{ + unsigned long long q = 1U << x; + return 256 / q; +} + +__attribute__((noipa)) unsigned long long +baz (unsigned char x, unsigned long long y) +{ + /* This can't be optimized, at least not in C++ and maybe not + in C89, because for x 31 q is -2147483648ULL, not + 2147483648ULL, and e.g. 2147483648ULL >> 31 is 1, while + 2147483648ULL / -2147483648ULL is 0. */ + unsigned long long q = 1 << x; + return y / q; +} + +__attribute__((noipa)) unsigned long long +qux (unsigned char x, unsigned long long y) +{ + unsigned long long q = 1U << x; + return y / q; +} |