This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

LOG_LINKS field not set because of gcse1 (or fwprop1) pass


Today, I had a look at the code I get for __gcc_bcmp() from libgcc2.c. I saw
a regression from

	decw	%ax
	je	.L2

to

	movw	%ax,	%cx	; register allocation
	decw	%cx
	movw	%cx,	%ax	; register allocation
	andw	%cx,	%cx	; combine, decw sets condition codes
	je	.L2

In addition to the register allocation leaving something to be desired,
combine isn't working either. As it turns out, it isn't combine's fault.

Given this RTL in a life1 dump, shouldn't there be a LOG_LINKS field in insn
101 pointing back to insn 96?

(insn 96 91 98 9 (parallel [
            (set (reg:HI 43)
                (plus:HI (reg/v:HI 32 [ size ])
                    (const_int -1 [0xffffffff])))
            (clobber (reg:CC 12 cc))
        ]) 80 {*addhi3_any} (nil)
    (expr_list:REG_DEAD (reg/v:HI 32 [ size ])
        (expr_list:REG_UNUSED (reg:CC 12 cc)
            (nil))))

(insn 98 96 101 9 (set (reg/v:HI 32 [ size ])
        (reg:HI 43)) 33 {movhi} (insn_list:REG_DEP_TRUE 96 (nil))
    (nil))

(insn 101 98 102 9 (set (reg:CC 12 cc)
        (compare:CC (reg:HI 43)
            (const_int 0 [0x0]))) 500 {*cmphi_const0_cc} (nil)
    (expr_list:REG_DEAD (reg:HI 43)
        (nil)))

The empty LOG_LINKS field of insn 101 means combine won't combine insn 96
with insn 101.

Note that right after expand, we have:

(note 91 90 0 NOTE_INSN_BASIC_BLOCK)

;; size = size - 1
(insn 93 91 96 (set (reg:HI 42)
        (const_int -1 [0xffffffff])) -1 (nil)
    (nil))

(insn 96 93 97 (parallel [
            (set (reg:HI 43)
                (plus:HI (reg/v:HI 32 [ size ])
                    (reg:HI 42)))
            (clobber (reg:CC 12 cc))
        ]) -1 (nil)
    (nil))

(insn 97 96 98 (set (reg:HI 43)
        (reg:HI 43)) -1 (nil)
    (expr_list:REG_EQUAL (plus:HI (reg/v:HI 32 [ size ])
            (reg:HI 42))
        (nil)))

(insn 98 97 0 (set (reg/v:HI 32 [ size ])
        (reg:HI 43)) -1 (nil)
    (nil))

;; if (size != 0) goto <L0>; else (void) 0;
(insn 100 98 101 10 (set (reg:HI 44)
        (const_int 0 [0x0])) -1 (nil)
    (nil))

(insn 101 100 102 10 (set (reg:CC 12 cc)
        (compare:CC (reg/v:HI 32 [ size ])
            (reg:HI 44))) -1 (nil)
    (nil))

I.e. register 32 is used in the comparison instead of register 43. This
is changed in the gcse1 pass:

LOCAL COPY-PROP: Replacing reg 32 in insn 101 with reg 43

FWIW, the very same happens with the the fwprop1 pass by Paolo Bonzini and
Steven Bosscher (which has yet to be checked in, but I have it in my
experimental tree):

In insn 101, replacing
 (compare:CC (reg/v:HI 32 [ size ])
        (reg:HI 44))
 with (compare:CC (reg:HI 43)
        (reg:HI 44))
Changed insn 101

If I disable both, the life1 dump shows a whole chain of LOG_LINKS nicely set
up for combine to follow:

(note 91 90 93 9 [bb 9] NOTE_INSN_BASIC_BLOCK)

(insn 93 91 96 9 (set (reg:HI 42)
        (const_int -1 [0xffffffff])) 33 {movhi} (nil)
    (nil))

(insn 96 93 98 9 (parallel [
            (set (reg:HI 43)
                (plus:HI (reg/v:HI 32 [ size ])
                    (reg:HI 42)))
            (clobber (reg:CC 12 cc))
        ]) 80 {*addhi3_any} (insn_list:REG_DEP_TRUE 93 (nil))
    (expr_list:REG_DEAD (reg/v:HI 32 [ size ])
        (expr_list:REG_DEAD (reg:HI 42)
            (expr_list:REG_UNUSED (reg:CC 12 cc)
                (nil)))))

(insn 98 96 100 9 (set (reg/v:HI 32 [ size ])
        (reg:HI 43)) 33 {movhi} (insn_list:REG_DEP_TRUE 96 (nil))
    (expr_list:REG_DEAD (reg:HI 43)
        (nil)))

(insn 100 98 101 9 (set (reg:HI 44)
        (const_int 0 [0x0])) 33 {movhi} (nil)
    (nil))

(insn 101 100 102 9 (set (reg:CC 12 cc)
        (compare:CC (reg/v:HI 32 [ size ])
            (reg:HI 44))) 502 {cmphi} (insn_list:REG_DEP_TRUE 98
(insn_list:REG_DEP_TRUE 100 (nil)))
    (expr_list:REG_DEAD (reg:HI 44)
        (nil)))


And then it works, combine cleans it up nicely:

(note 91 90 93 9 [bb 9] NOTE_INSN_BASIC_BLOCK)

(note 93 91 96 9 NOTE_INSN_DELETED)

(note 96 93 98 9 NOTE_INSN_DELETED)

(note 98 96 100 9 NOTE_INSN_DELETED)

(note 100 98 101 9 NOTE_INSN_DELETED)

(insn 101 100 102 9 (parallel [
            (set (reg:CCZ 12 cc)
                (compare:CCZ (plus:HI (reg/v:HI 32 [ size ])
                        (const_int -1 [0xffffffff]))
                    (const_int 0 [0x0])))
            (set (reg/v:HI 32 [ size ])
                (plus:HI (reg/v:HI 32 [ size ])
                    (const_int -1 [0xffffffff])))
        ]) 68 {*dechi2_cc_ccz} (nil)
    (nil))

-- 
Rask Ingemann Lambertsen


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]