Problem in the combiner
Christian Iseli
chris@lslsun.epfl.ch
Tue Sep 9 07:50:00 GMT 1997
Hi folks,
I've hit a problem in the combiner, more specifically in the try_combine
routine. The bug bites when one of the operands in the rtx code is
a hard register and one of the instructions takes a subreg of this register.
Consider the following instructions at the start of try_combine:
Breakpoint 2, try_combine (i3=0x189e18, i2=0x189db0, i1=0x189d10) at combine.c:1213
(gdb) call debug_rtx(i1)
(insn 53 50 54 (parallel[
(set (reg:HI 3 %r1)
(mult:HI (reg:HI 37)
(const_int 4)))
(clobber (reg:HI 1 %r3))
] ) 33 {*mulhi3} (nil)
(expr_list:REG_DEAD (reg:HI 37)
(expr_list:REG_UNUSED (reg:HI 1 %r3)
(nil))))
(gdb) call debug_rtx(i2)
(insn 55 54 56 (set (reg:HI 51)
(ior:HI (reg:HI 47)
(reg:HI 3 %r1))) 193 {*log_ophi3} (insn_list 53 (insn_list 50 (nil)))
(expr_list:REG_DEAD (reg:HI 3 %r1)
(nil)))
(gdb) call debug_rtx(i3)
(insn 56 55 57 (set (reg:QI 52)
(and:QI (subreg:QI (reg:HI 51) 1)
(const_int 7))) 192 {*com_opqi3_accu} (insn_list 55 (nil))
(expr_list:REG_DEAD (reg:HI 51)
(nil)))
Notice that i1 sets hard register r1 in HImode, since that is the way
the mult operation is specified in the machine description file.
i2 in turn uses r1 in HImode. After try_combine combines i2 and i3,
the tentative new instruction newpat looks as follows:
(gdb) call debug_rtx(newpat)
(set (reg:QI 52)
(and:QI (ior:QI (subreg:QI (reg:HI 47) 1)
(reg:QI 4 %r0))
(const_int 7)))
Notice that because i3 is using a subreg in QImode, the
hard register r1 in HImode has become hard register r0 in QImode.
That is because the (subreg:QI (reg:HI 3 %r1) 1) has been optimized
into (reg:QI 4 %r0) during the combination performed by subst.
Now the problem arises when the combiner tries to combine that new
pattern with i1, since it will fail to notice that
(subreg:QI (reg:HI 3 %r1) 1) and (reg:QI 4 %r0) are actually the same
thing. The following patch tries to address this issue.
Christian
*** combine.c.orig Mon Aug 11 22:07:10 1997
--- combine.c Mon Sep 8 10:52:04 1997
*************** combinable_i3pat (i3, loc, i2dest, i1des
*** 1202,1207 ****
--- 1202,1249 ----
return 1;
}
+ /* Return x where hard regs lying between from and (from + size - 1)
+ have been changed to subregs. */
+ static rtx
+ restore_subreg(rtx x, enum machine_mode mode, int from, int size)
+ {
+ char *fmt;
+ enum rtx_code code = GET_CODE(x);
+ int i;
+
+ switch (code) {
+ case REG: {
+ enum machine_mode rmode = GET_MODE(x);
+ int rsize = GET_MODE_SIZE(rmode);
+ int regno = REGNO(x);
+ if (rsize < size && regno >= from && regno < (from + size))
+ return gen_rtx(SUBREG, rmode, gen_rtx(REG, mode, from),
+ (regno - from) / rsize);
+ /* Fall thru */
+ }
+ case SUBREG:
+ case SCRATCH:
+ case CLOBBER:
+ case CC0:
+ case PC:
+ case CONST_INT:
+ case CONST_DOUBLE:
+ return x;
+ default:
+ }
+ fmt = GET_RTX_FORMAT(code);
+ for (i = GET_RTX_LENGTH(code) - 1; i >= 0; i--) {
+ if (fmt[i] == 'E') {
+ int j;
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ XVECEXP(x, i, j) = restore_subreg(XVECEXP(x, i, j),
+ mode, from, size);
+ } else if (fmt[i] == 'e')
+ XEXP(x, i) = restore_subreg(XEXP(x, i), mode, from, size);
+ }
+ return x;
+ }
+
/* Try to combine the insns I1 and I2 into I3.
Here I1 and I2 appear earlier than I3.
I1 can be zero; then we combine just I2 into I3.
*************** try_combine (i3, i2, i1)
*** 1638,1643 ****
--- 1680,1703 ----
undo_all ();
return 0;
}
+
+ /* CI - Check SUBREG thing. */
+ if (GET_CODE (i1dest) == REG
+ && REGNO (i1dest) < FIRST_PSEUDO_REGISTER
+ && REGNO (i1dest) != FRAME_POINTER_REGNUM
+ #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+ && REGNO (i1dest) != HARD_FRAME_POINTER_REGNUM
+ #endif
+ #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+ && REGNO (i1dest) != ARG_POINTER_REGNUM
+ #endif
+ && REGNO (i1dest) != STACK_POINTER_REGNUM
+ && GET_MODE_CLASS(GET_MODE(i1dest)) == MODE_INT
+ && GET_MODE(i1dest) != QImode)
+ newpat = restore_subreg(newpat, GET_MODE(i1dest),
+ REGNO(i1dest),
+ GET_MODE_SIZE(GET_MODE(i1dest)));
+ /* CI - End check. */
n_occurrences = 0;
subst_low_cuid = INSN_CUID (i1);
More information about the Gcc
mailing list