Commit 873140e6 by Jakub Jelinek

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
parent 6508fa9c
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> 2019-09-10 Christophe Lyon <christophe.lyon@st.com>
* config/arm/arm.md (stack_protect_combined_set_insn): Handle * config/arm/arm.md (stack_protect_combined_set_insn): Handle
...@@ -5,7 +11,7 @@ ...@@ -5,7 +11,7 @@
(stack_protect_combined_test_insn): Likewise. (stack_protect_combined_test_insn): Likewise.
2019-09-10 Christophe Lyon <christophe.lyon@st.com> 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.c (arm_load_tp): Add FDPIC support.
* config/arm/arm.md (FDPIC_REGNUM): New constant. * config/arm/arm.md (FDPIC_REGNUM): New constant.
...@@ -13,7 +19,7 @@ ...@@ -13,7 +19,7 @@
(load_tp_soft): Disable in FDPIC mode. (load_tp_soft): Disable in FDPIC mode.
2019-09-10 Christophe Lyon <christophe.lyon@st.com> 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, * config/arm/arm.c (tls_reloc): Add TLS_GD32_FDPIC,
TLS_LDM32_FDPIC and TLS_IE32_FDPIC. TLS_LDM32_FDPIC and TLS_IE32_FDPIC.
...@@ -22,7 +28,7 @@ ...@@ -22,7 +28,7 @@
(arm_emit_tls_decoration): Likewise. (arm_emit_tls_decoration): Likewise.
2019-09-10 Christophe Lyon <christophe.lyon@st.com> 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 * config/arm/arm.c (arm_asm_trampoline_template): Add FDPIC
support. support.
...@@ -31,7 +37,7 @@ ...@@ -31,7 +37,7 @@
* config/arm/arm.h (TRAMPOLINE_SIZE): Likewise. * config/arm/arm.h (TRAMPOLINE_SIZE): Likewise.
2019-09-10 Christophe Lyon <christophe.lyon@st.com> 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. * config/arm/arm.c (arm_fdpic_local_funcdesc_p): New function.
(legitimize_pic_address): Enforce binding rules on function (legitimize_pic_address): Enforce binding rules on function
...@@ -39,20 +45,20 @@ ...@@ -39,20 +45,20 @@
(arm_assemble_integer): Likewise. (arm_assemble_integer): Likewise.
2019-09-10 Christophe Lyon <christophe.lyon@st.com> 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.h (PIC_REGISTER_MAY_NEED_SAVING): New helper.
* config/arm/arm.c (arm_compute_save_reg0_reg12_mask): Handle * config/arm/arm.c (arm_compute_save_reg0_reg12_mask): Handle
FDPIC. FDPIC.
2019-09-10 Christophe Lyon <christophe.lyon@st.com> 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 * ginclude/unwind-arm-common.h (unwinder_cache): Add reserved5
field. field.
2019-09-10 Christophe Lyon <christophe.lyon@st.com> 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 * config/arm/arm-c.c (__FDPIC__): Define new pre-processor macro
in FDPIC mode. in FDPIC mode.
...@@ -80,7 +86,7 @@ ...@@ -80,7 +86,7 @@
* config/arm/unspecs.md (UNSPEC_PIC_RESTORE): New. * config/arm/unspecs.md (UNSPEC_PIC_RESTORE): New.
2019-09-10 Christophe Lyon <christophe.lyon@st.com> 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.gcc: Handle arm*-*-uclinuxfdpiceabi.
* config/arm/bpabi.h (TARGET_FDPIC_ASM_SPEC): New. * config/arm/bpabi.h (TARGET_FDPIC_ASM_SPEC): New.
...@@ -95,7 +101,7 @@ ...@@ -95,7 +101,7 @@
* config.gcc: Handle *-*-uclinuxfdpiceabi. * config.gcc: Handle *-*-uclinuxfdpiceabi.
2019-09-10 Christophe Lyon <christophe.lyon@st.com> 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. * config/arm/arm.opt: Add -mfdpic option.
* doc/invoke.texi: Add documentation for -mfdpic. * doc/invoke.texi: Add documentation for -mfdpic.
......
...@@ -305,13 +305,29 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) ...@@ -305,13 +305,29 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* (A / (1 << B)) -> (A >> B). /* (A / (1 << B)) -> (A >> B).
Only for unsigned A. For signed A, this would not preserve rounding Only for unsigned A. For signed A, this would not preserve rounding
toward zero. toward zero.
For example: (-1 / ( 1 << B)) != -1 >> B. */ For example: (-1 / ( 1 << B)) != -1 >> B.
(simplify Also also widening conversions, like:
(trunc_div @0 (lshift integer_onep@1 @2)) (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)) (if ((TYPE_UNSIGNED (type) || tree_expr_nonnegative_p (@0))
&& (!VECTOR_TYPE_P (type) && (!VECTOR_TYPE_P (type)
|| target_supports_op_p (type, RSHIFT_EXPR, optab_vector) || 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))) (rshift @0 @2)))
/* Preserve explicit divisions by 0: the C++ front-end wants to detect /* Preserve explicit divisions by 0: the C++ front-end wants to detect
......
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> 2019-09-10 Paolo Carlini <paolo.carlini@oracle.com>
* g++.dg/cpp0x/enum29.C: Test location(s) too. * g++.dg/cpp0x/enum29.C: Test location(s) too.
......
/* 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 ();
}
}
/* 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;
}
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