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)