mike@lynx.uucp (Mike Bunnell) (07/11/89)
Version of gcc: 1.35 Command line: gcc -O test.c Tm.h: tm-i386.h Md: i386.md Machine: Lynx 386 RTW running LynxOS Behavoir: cc1 aborts in cse_insn I have found a bug in common sub-expression elimination. It has to do with performing common sub-expression elimination on insns of type PARALLEL. A common source of a PARALLEL insn is in an insn with a SET and a CLOBBER. For example a divide instruction on a '386. The divide instruction is changed to a reg which is good, but the problem is the new insn (see dump below) does not match any template so recog() returns a -1 which causes an abort ins_extract(). I have included the template for divide (which I got off the net), the source code, and an insn dump with and without optimization. I've temporarily fixed the problem by skipping any common sub-expression elimination within a PARALLEL insn. I stuck a return in cse_insn if the insn is PARALLEL. I am interested in a better solution. Please respond on the net or mail to me directly. Thanks. # # Output template for divide # (define_insn "divsi3" [(set (match_operand:SI 0 "general_operand" "=&a") (div:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "general_operand" "rm"))) (clobber (reg:SI 1))] "" "cltd\;idiv%L0 %2") # # Source code # unsigned i, j; func() { int n; while (n) { i = n / j; n /= j; /* or n %= j */ } } # # Without optimization # ;; Function func (note 1 0 2 "" NOTE_INSN_DELETED) (note 2 1 3 "" NOTE_INSN_BLOCK_BEG) (note 3 2 4 "" NOTE_INSN_LOOP_BEG) (code_label 4 3 5 2) (insn 5 4 6 (set (cc0) (mem:SI (plus:SI (reg:SI 6) (const_int -4)))) -1 (nil) (nil)) (jump_insn 6 5 7 (set (pc) (if_then_else (ne (cc0) (const_int 0)) (pc) (label_ref 15))) -1 (nil) (nil)) (note 7 6 8 "" NOTE_INSN_DELETED) (insn 8 7 9 (parallel[ (set (reg:SI 10) (udiv:SI (mem:SI (plus:SI (reg:SI 6) (const_int -4))) (mem:SI (symbol_ref:SI ("j"))))) (clobber (reg:SI 1)) ] ) -1 (nil) (nil)) (insn 9 8 10 (set (mem:SI (symbol_ref:SI ("i"))) (reg:SI 10)) -1 (nil) (nil)) #### This is the insn that gets changed #### (insn 10 9 11 (parallel[ (set (reg:SI 11) (udiv:SI (mem:SI (plus:SI (reg:SI 6) (const_int -4))) (mem:SI (symbol_ref:SI ("j"))))) (clobber (reg:SI 1)) ] ) -1 (nil) (nil)) (insn 11 10 12 (set (mem:SI (plus:SI (reg:SI 6) (const_int -4))) (reg:SI 11)) -1 (nil) (nil)) (jump_insn 12 11 13 (set (pc) (label_ref 4)) -1 (nil) (nil)) (barrier 13 12 14) (note 14 13 15 "" NOTE_INSN_LOOP_END) (code_label 15 14 16 3) (note 16 15 17 "" NOTE_INSN_BLOCK_END) (note 17 16 18 "" NOTE_INSN_FUNCTION_END) (code_label 18 17 0 1) # # This is the code after optimization # ;; Function func (note 1 0 2 "" NOTE_INSN_DELETED) (note 2 1 3 "" NOTE_INSN_BLOCK_BEG) (note 3 2 12 "" NOTE_INSN_LOOP_BEG) (jump_insn 12 3 13 (set (pc) (label_ref 4)) -1 (nil) (nil)) (barrier 13 12 11) (code_label 11 13 7 4) (note 7 11 8 "" NOTE_INSN_DELETED) (insn 8 7 9 (parallel[ (set (reg:SI 11) (udiv:SI (reg/v:SI 10) (mem:SI (symbol_ref:SI ("j"))))) (clobber (reg:SI 1)) ] ) -1 (nil) (nil)) (insn 9 8 10 (set (mem:SI (symbol_ref:SI ("i"))) (reg:SI 11)) -1 (nil) (nil)) #### This is the new insn ### (insn 10 9 4 (parallel[ (set (reg/v:SI 10) (reg:SI 11)) (clobber (reg:SI 1)) ] ) -1 (nil) (nil)) (code_label 4 10 5 2) (insn 5 4 6 (set (cc0) (reg/v:SI 10)) -1 (nil) (nil)) (jump_insn 6 5 16 (set (pc) (if_then_else (ne (cc0) (const_int 0)) (label_ref 11) (pc))) -1 (nil) (nil)) (note 16 6 18 "" NOTE_INSN_LOOP_END) (note 18 16 0 "" NOTE_INSN_BLOCK_END)