Bug 46088 - [4.6 Regression] ICE: SIGSEGV in ix86_binary_operator_ok (i386.c:15025) with -Os -fnon-call-exceptions -fpeel-loops
Summary: [4.6 Regression] ICE: SIGSEGV in ix86_binary_operator_ok (i386.c:15025) with ...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.6.0
: P1 normal
Target Milestone: 4.6.0
Assignee: Jakub Jelinek
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2010-10-19 23:36 UTC by Zdenek Sojka
Modified: 2010-11-11 23:53 UTC (History)
5 users (show)

See Also:
Host: x86_64-pc-linux-gnu
Target: x86_64-pc-linux-gnu
Build:
Known to work: 4.5.2
Known to fail: 4.6.0
Last reconfirmed: 2010-11-04 03:22:14


Attachments
reduced testcase (68 bytes, text/plain)
2010-10-19 23:36 UTC, Zdenek Sojka
Details
gcc46-pr46088.patch (643 bytes, patch)
2010-11-11 11:29 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Zdenek Sojka 2010-10-19 23:36:16 UTC
Created attachment 22088 [details]
reduced testcase

Command line:
$ gcc -Os -fnon-call-exceptions -fpeel-loops pr46088.c

Related valgrind output:
$ valgrind -q --trace-children=yes gcc -Os -fnon-call-exceptions -fpeel-loops pr46088.c
==14275== Invalid read of size 2
==14275==    at 0xA7C8EC: ix86_binary_operator_ok (i386.c:15025)
==14275==    by 0xDF3063: recog (i386.md:10038)
==14275==    by 0xEE9313: recog_for_combine (combine.c:10480)
==14275==    by 0xF16107: try_combine (combine.c:3220)
==14275==    by 0xF2141D: rest_of_handle_combine (combine.c:1187)
==14275==    by 0x79613E: execute_one_pass (passes.c:1562)
==14275==    by 0x7963D4: execute_pass_list (passes.c:1617)
==14275==    by 0x7963E6: execute_pass_list (passes.c:1618)
==14275==    by 0x8E30F5: tree_rest_of_compilation (tree-optimize.c:419)
==14275==    by 0xAAC341: cgraph_expand_function (cgraphunit.c:1494)
==14275==    by 0xAAE909: cgraph_optimize (cgraphunit.c:1553)
==14275==    by 0xAAEE69: cgraph_finalize_compilation_unit (cgraphunit.c:1016)
==14275==  Address 0xabababababababab is not stack'd, malloc'd or (recently) free'd
==14275== 
pr46088.c: In function 'foo':
pr46088.c:7:1: internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.

Tested revisions:
r165699 - crash
r159696 - crash
r158095 - OK
4.5 r163761 - OK
Comment 1 H.J. Lu 2010-10-20 03:22:14 UTC
It is caused by revision 158187:

http://gcc.gnu.org/ml/gcc-cvs/2010-04/msg00291.html
Comment 2 Richard Biener 2010-11-04 13:23:36 UTC
Program received signal SIGSEGV, Segmentation fault.
0x0000000000cc9dcb in ix86_binary_operator_ok (code=LSHIFTRT, mode=SImode, 
    operands=0x1815e80)
    at /space/rguenther/src/svn/trunk/gcc/config/i386/i386.c:15665
15665     if (MEM_P (dst) && !rtx_equal_p (dst, src1))
(gdb) p dst
$1 = (rtx) 0xabababababababab

We're matching

(define_insn "*ashl<mode>3_cconly"
Comment 3 Uroš Bizjak 2010-11-04 16:19:20 UTC
(In reply to comment #2)

> We're matching
> 
> (define_insn "*ashl<mode>3_cconly"

AFAICS, there is nothing wrong with the pattern:

  [(set (reg FLAGS_REG)
	(compare
	  (ashift:SWI (match_operand:SWI 1 "nonimmediate_operand" "0")
		      (match_operand:QI 2 "<shift_immediate_operand>" "<S>"))
	  (const_int 0)))
   (clobber (match_scratch:SWI 0 "=<r>"))]
Comment 4 Uroš Bizjak 2010-11-04 16:32:57 UTC
The insn that was matched looks like:

(gdb) up
#1  0x0000000000b9da94 in recog_7 (x0=0x7ffff1f329d8, insn=0x7ffff1f296c0, 
    pnum_clobbers=0x7fffffffdc9c)
    at ../../gcc-svn/trunk/gcc/config/i386/i386.md:10089
10089	   && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
(gdb) p debug_rtx (insn)
(insn 7 6 8 2 (set (reg:CCZ 17 flags)
        (compare:CCZ (lshiftrt:SI (reg/v:SI 60 [ i ])
                (const_int 3 [0x3]))
            (const_int 0 [0]))) pr46088.c:5 2 {*cmpsi_ccno_1}
     (nil))
$1 = void

So, clobber of the scratch reg is missing, but the insn is recognized as *lshrsi3_cconly anyway.
Comment 5 Jakub Jelinek 2010-11-11 10:59:32 UTC
That's normal before reload is completed.  Recog can be called either with pnum_clobbers NULL, then it will only try to match if all the clobbers are there, or if pnum_clobbers is non-NULL, it tries to match the insn without the clobbers and tell the caller how many clobbers would be needed to make the insn valid, then
add_clobbers may be called to actually add those clobbers.

Unfortunately, the
*ashl<mode>3_cconly
*<shiftrt_insn><mode>3_cconly
patterns (the only two I could find in config/i386/i386.md) reference this clobber through ix86_binary_operator_ok, which is of course a big no no if the clobber does not exist.

I guess the easiest fix would be just not to call ix86_binary_operator_ok here, but some different predicate, like ix86_binary_operator_ok, but which would not look at operands[0] aka dst, instead assume it is something matching scratch_operand predicate.
Comment 6 Eric Botcazou 2010-11-11 11:27:27 UTC
> The insn that was matched looks like:
> 
> (gdb) up
> #1  0x0000000000b9da94 in recog_7 (x0=0x7ffff1f329d8, insn=0x7ffff1f296c0, 
>     pnum_clobbers=0x7fffffffdc9c)
>     at ../../gcc-svn/trunk/gcc/config/i386/i386.md:10089
> 10089       && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
> (gdb) p debug_rtx (insn)
> (insn 7 6 8 2 (set (reg:CCZ 17 flags)
>         (compare:CCZ (lshiftrt:SI (reg/v:SI 60 [ i ])
>                 (const_int 3 [0x3]))
>             (const_int 0 [0]))) pr46088.c:5 2 {*cmpsi_ccno_1}
>      (nil))
> $1 = void
> 
> So, clobber of the scratch reg is missing, but the insn is recognized as
> *lshrsi3_cconly anyway.

Yes, this is the documented behavior of the combiner so back-ends need to cope with it.  A possible approach would be to define a specialized version of ix86_binary_operator_ok, e.g. ix86_binary_operator_ok_for_reg_dest, and uses it in any pattern that has match_scratch as destination.  The existing logic in ix86_binary_operator_ok can avoid reading DST if it knows it's a REG.
Comment 7 Jakub Jelinek 2010-11-11 11:29:52 UTC
Created attachment 22373 [details]
gcc46-pr46088.patch

Untested fix.

I went through ix86_binary_operator_ok:

  /* Both source operands cannot be in memory.  */
  if (MEM_P (src1) && MEM_P (src2))
    return false;

doesn't apply, because src2 is known to be const_1_to_{31,63}_operand, i.e. CONST_INT.

  /* Canonicalize operand order for commutative operators.  */
  if (ix86_swap_binary_operands_p (code, mode, operands))
    {
      rtx temp = src1;
      src1 = src2;
      src2 = temp;
    }

doesn't apply, the shifts aren't commutative.

  /* If the destination is memory, we must have a matching source operand.  */
  if (MEM_P (dst) && !rtx_equal_p (dst, src1))
      return false;

doesn't apply, dst is either missing (but then will be scratch_operand), or is a scratch_operand already.

  /* Source 1 cannot be a constant.  */
  if (CONSTANT_P (src1))
    return false;  

doesn't apply, src1 is known to be nonimmediate_operand, i.e. && ! CONSTANT_P (op).

  /* Source 1 cannot be a non-matching memory.  */
  if (MEM_P (src1) && !rtx_equal_p (dst, src1))
    {
      /* Support "andhi/andsi/anddi" as a zero-extending move.  */
      return (code == AND
              && ...

is the only one that applies, and dst is known not to be a MEM and code is known not to be AND.

That said, if you prefer to still do ix86_binary_operator_ok, there are other options, like:

-   && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
+   && (GET_CODE (PATTERN (insn)) == SET
+       ? !MEM_P (operands[1])
+       : ix86_binary_operator_ok (<CODE>, <MODE>mode, operands))"

-   && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
+   && ((!reload_completed && GET_CODE (PATTERN (insn)) == SET)
+       ? !MEM_P (operands[1])
+       : ix86_binary_operator_ok (<CODE>, <MODE>mode, operands))"
Comment 8 Jakub Jelinek 2010-11-11 11:33:17 UTC
Guess a comment should be added there explaining it too, will add it once you pick up which version do you prefer.  Uros?
Comment 9 Jakub Jelinek 2010-11-11 23:51:22 UTC
Author: jakub
Date: Thu Nov 11 23:51:18 2010
New Revision: 166635

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=166635
Log:
	PR target/46088
	* config/i386/i386.md (*ashl<mode>3_cconly,
	*<shiftrt_insn><mode>3_cconly): Don't use ix86_binary_operator_ok,
	change nonimmediate_operand predicate to register_operand.

	* gcc.dg/pr46088.c: New test.

Added:
    trunk/gcc/testsuite/gcc.dg/pr46088.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/i386/i386.md
    trunk/gcc/testsuite/ChangeLog
Comment 10 Jakub Jelinek 2010-11-11 23:53:12 UTC
Fixed.