diff mbox

ifcvt: Don't make invalid insns for a cond trap (PR78751)

Message ID 81462c6130048c245ec740faca7610f01ba1f1e8.1484444528.git.segher@kernel.crashing.org
State New
Headers show

Commit Message

Segher Boessenkool Jan. 15, 2017, 1:55 a.m. UTC
As shown in the PR, ifcvt will happily make invalid insns when given the
chance.  This patch teaches it some manners.

Bootstrapped and tested on powerpc64-linux.  Is this okay for trunk?


Segher


2017-01-15  Segher Boessenkool  <segher@kernel.crashing.org>

	PR rtl-optimization/78751
	* ifcvt.c (find_cond_trap): If we generated a non-existing insn,
	give up.

---
 gcc/ifcvt.c | 5 +++++
 1 file changed, 5 insertions(+)

Comments

Jeff Law Jan. 15, 2017, 4:23 a.m. UTC | #1
On 01/14/2017 06:55 PM, Segher Boessenkool wrote:
> As shown in the PR, ifcvt will happily make invalid insns when given the
> chance.  This patch teaches it some manners.
>
> Bootstrapped and tested on powerpc64-linux.  Is this okay for trunk?
>
>
> Segher
>
>
> 2017-01-15  Segher Boessenkool  <segher@kernel.crashing.org>
>
> 	PR rtl-optimization/78751
> 	* ifcvt.c (find_cond_trap): If we generated a non-existing insn,
> 	give up.
But isn't this a backend failing?  ISTM that gen_cond_trap just calls 
standard expansion routines and they should either have generated a 
valid sequence or NULL.

What in particular generated insn 64 and shouldn't it instead have 
indicated a failure?


Jeff
Segher Boessenkool Jan. 15, 2017, 5:11 a.m. UTC | #2
On Sat, Jan 14, 2017 at 09:23:45PM -0700, Jeff Law wrote:
> But isn't this a backend failing?  ISTM that gen_cond_trap just calls 
> standard expansion routines and they should either have generated a 
> valid sequence or NULL.
> 
> What in particular generated insn 64 and shouldn't it instead have 
> indicated a failure?

ifcvt calls gen_cond_trap which then calls prepare_cmp_insn, which then
calls prepare_operand on the two arms, which ends up as copy_to_mode_reg
IIRC.  The instructions copy_to_mode_reg comes up with are *not* valid
machine insns; their RHS is ultimately given by what ifcvt called
gen_cond_trap with (the comparison of the *two* RHS together is a valid
instruction! -- well, a splitter; but there is no such trap insn).

I have tried to handle things in expand, but it is a) ugly and b) caused
problems all over the place.  I wonder if anyone can still modify any of
the expander code, sigh -- lots of rope there, and it's a maze.

ifcvt already has a lot of that "if we made a bad insn, back out", so it
fits well here.  This patch also is much less risky.


Segher
Jeff Law Jan. 15, 2017, 5:59 a.m. UTC | #3
On 01/14/2017 10:11 PM, Segher Boessenkool wrote:
> On Sat, Jan 14, 2017 at 09:23:45PM -0700, Jeff Law wrote:
>> But isn't this a backend failing?  ISTM that gen_cond_trap just calls
>> standard expansion routines and they should either have generated a
>> valid sequence or NULL.
>>
>> What in particular generated insn 64 and shouldn't it instead have
>> indicated a failure?
>
> ifcvt calls gen_cond_trap which then calls prepare_cmp_insn, which then
> calls prepare_operand on the two arms, which ends up as copy_to_mode_reg
> IIRC.  The instructions copy_to_mode_reg comes up with are *not* valid
> machine insns; their RHS is ultimately given by what ifcvt called
> gen_cond_trap with (the comparison of the *two* RHS together is a valid
> instruction! -- well, a splitter; but there is no such trap insn).
So it's the  setup bits done by prepare_cmp_insn that are the problem 
and thus the test in gen_cond_trap isn't going to help.  Ugh.  AFAICT 
prepare_cmp_insn, through a series of calls, ends up in emit_move_insn 
which is just going to blindly emit the move and we've lost.  Sigh.

OK.  Let's go with your patch.

Thanks,
jeff
diff mbox

Patch

diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 68c1a1d..6d30639 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -4686,6 +4686,11 @@  find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge)
   if (seq == NULL)
     return FALSE;
 
+  /* If that results in an invalid insn, back out.  */
+  for (rtx_insn *x = seq; x; x = NEXT_INSN (x))
+    if (recog_memoized (x) < 0)
+      return FALSE;
+
   /* Emit the new insns before cond_earliest.  */
   emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATION (trap));