Hi! We ICE on the following test because rest_of_insert_endbranch separates a setjmp call from the following NOTE_INSN_CALL_ARG_LOCATION that must always immediately follow the call. No other note or debug insn (which aren't around after var-tracking anyway) needs to follow the call, so the loop it was doing is unnecessary, on the other side, we are already at a late state where bb boundaries are fuzzy and we are going to throw away the cfg before doing final.
So, all we need is just check if the call is followed by this note and if yes, emit the endbr after it. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2018-01-31 Jakub Jelinek <ja...@redhat.com> PR target/84146 * config/i386/i386.c (rest_of_insert_endbranch): Only skip NOTE_INSN_CALL_ARG_LOCATION after a call, not anything else, and skip it regardless of bb boundaries. Use CALL_P macro, don't test INSN_P (insn) together with CALL_P or JUMP_P check unnecessarily, formatting fix. * gcc.target/i386/pr84146.c: New test. --- gcc/config/i386/i386.c.jj 2018-01-31 09:26:18.341505667 +0100 +++ gcc/config/i386/i386.c 2018-01-31 14:13:33.815243832 +0100 @@ -2609,31 +2609,27 @@ rest_of_insert_endbranch (void) for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); insn = NEXT_INSN (insn)) { - if (INSN_P (insn) && GET_CODE (insn) == CALL_INSN) + if (CALL_P (insn)) { if (find_reg_note (insn, REG_SETJMP, NULL) == NULL) continue; /* Generate ENDBRANCH after CALL, which can return more than twice, setjmp-like functions. */ - /* Skip notes and debug insns that must be next to the - call insn. ??? This might skip a lot more than - that... ??? Skipping barriers and emitting code - after them surely looks like a mistake; we probably - won't ever hit it, for we'll hit BB_END first. */ + /* Skip notes that must immediately follow the call insn. */ rtx_insn *next_insn = insn; - while ((next_insn != BB_END (bb)) - && (DEBUG_INSN_P (NEXT_INSN (next_insn)) - || NOTE_P (NEXT_INSN (next_insn)) - || BARRIER_P (NEXT_INSN (next_insn)))) - next_insn = NEXT_INSN (next_insn); + if (NEXT_INSN (insn) + && NOTE_P (NEXT_INSN (insn)) + && (NOTE_KIND (NEXT_INSN (insn)) + == NOTE_INSN_CALL_ARG_LOCATION)) + next_insn = NEXT_INSN (insn); cet_eb = gen_nop_endbr (); emit_insn_after_setloc (cet_eb, next_insn, INSN_LOCATION (insn)); continue; } - if (INSN_P (insn) && JUMP_P (insn) && flag_cet_switch) + if (JUMP_P (insn) && flag_cet_switch) { rtx target = JUMP_LABEL (insn); if (target == NULL_RTX || ANY_RETURN_P (target)) @@ -2668,7 +2664,7 @@ rest_of_insert_endbranch (void) if ((LABEL_P (insn) && LABEL_PRESERVE_P (insn)) || (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL)) -/* TODO. Check /s bit also. */ + /* TODO. Check /s bit also. */ { cet_eb = gen_nop_endbr (); emit_insn_after (cet_eb, insn); --- gcc/testsuite/gcc.target/i386/pr84146.c.jj 2018-01-31 16:32:28.099929916 +0100 +++ gcc/testsuite/gcc.target/i386/pr84146.c 2018-01-31 14:04:17.796122397 +0100 @@ -0,0 +1,14 @@ +/* PR target/84146 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -g -mcet -fcf-protection=full" } */ + +int __setjmp (void **); +void *buf[64]; + +void +foo (void) +{ + __setjmp (buf); + for (;;) + ; +} Jakub