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
It is caused by revision 158187: http://gcc.gnu.org/ml/gcc-cvs/2010-04/msg00291.html
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"
(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>"))]
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.
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.
> 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.
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))"
Guess a comment should be added there explaining it too, will add it once you pick up which version do you prefer. Uros?
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
Fixed.