ifcvt: Don't introduce trapping or faulting reads in noce_try_sign_mask [PR106032]
noce_try_sign_mask as documented will optimize if (c < 0) x = t; else x = 0; into x = (c >> bitsm1) & t; The optimization is done if either t is unconditional (e.g. for x = t; if (c >= 0) x = 0; ) or if it is cheap. We already check that t doesn't have side-effects, but if t is conditional, we need to punt also if it may trap or fault, as we make it unconditional. I've briefly skimmed other noce_try* optimizations and didn't find one that would suffer from the same problem. 2022-06-21 Jakub Jelinek <jakub@redhat.com> PR rtl-optimization/106032 * ifcvt.cc (noce_try_sign_mask): Punt if !t_unconditional, and t may_trap_or_fault_p, even if it is cheap. * gcc.c-torture/execute/pr106032.c: New test.
This commit is contained in:
parent
2df1df945f
commit
a0c30fe3b8
15
gcc/ifcvt.cc
15
gcc/ifcvt.cc
@ -2833,18 +2833,19 @@ noce_try_sign_mask (struct noce_if_info *if_info)
|
||||
return FALSE;
|
||||
|
||||
/* This is only profitable if T is unconditionally executed/evaluated in the
|
||||
original insn sequence or T is cheap. The former happens if B is the
|
||||
non-zero (T) value and if INSN_B was taken from TEST_BB, or there was no
|
||||
INSN_B which can happen for e.g. conditional stores to memory. For the
|
||||
cost computation use the block TEST_BB where the evaluation will end up
|
||||
after the transformation. */
|
||||
original insn sequence or T is cheap and can't trap or fault. The former
|
||||
happens if B is the non-zero (T) value and if INSN_B was taken from
|
||||
TEST_BB, or there was no INSN_B which can happen for e.g. conditional
|
||||
stores to memory. For the cost computation use the block TEST_BB where
|
||||
the evaluation will end up after the transformation. */
|
||||
t_unconditional
|
||||
= (t == if_info->b
|
||||
&& (if_info->insn_b == NULL_RTX
|
||||
|| BLOCK_FOR_INSN (if_info->insn_b) == if_info->test_bb));
|
||||
if (!(t_unconditional
|
||||
|| (set_src_cost (t, mode, if_info->speed_p)
|
||||
< COSTS_N_INSNS (2))))
|
||||
|| ((set_src_cost (t, mode, if_info->speed_p)
|
||||
< COSTS_N_INSNS (2))
|
||||
&& !may_trap_or_fault_p (t))))
|
||||
return FALSE;
|
||||
|
||||
if (!noce_can_force_operand (t))
|
||||
|
21
gcc/testsuite/gcc.c-torture/execute/pr106032.c
Normal file
21
gcc/testsuite/gcc.c-torture/execute/pr106032.c
Normal file
@ -0,0 +1,21 @@
|
||||
/* PR rtl-optimization/106032 */
|
||||
|
||||
__attribute__((noipa)) int
|
||||
foo (int x, int *y)
|
||||
{
|
||||
int a = 0;
|
||||
if (x < 0)
|
||||
a = *y;
|
||||
return a;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int a = 42;
|
||||
if (foo (0, 0) != 0 || foo (1, 0) != 0)
|
||||
__builtin_abort ();
|
||||
if (foo (-1, &a) != 42 || foo (-42, &a) != 42)
|
||||
__builtin_abort ();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user