This is the mail archive of the gcc-patches@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]

Re: Don't delete REG_UNUSED


Jeffrey A Law <law@hurl.cygnus.com> writes:

|>   In message <vyzemqlzerw.fsf@issan.cs.uni-dortmund.de>you write:
|>   > Jeffrey A Law <law@hurl.cygnus.com> writes:
|>   > 
|>   > |> I went and looked at Andreas's testcase, and I don't see where/how he sh
|>   > ould
|>   > |> have ever had a REG_UNUSED note for the "mod" part of the single divmod 
|>   > insn
|>   > |> in the testcase since both results are used (the divmod is inside a loop
|>   >  and
|>   > |> the mod part is used by the next loop iteration.
|>   > 
|>   > There are two divmod insn, one where mod is unused, the other where div is
|>   > unused (the compiler did not combine them for whatever reason).  Only the
|>   > one where the mod is unused makes a problem, because the m68k cannot
|>   > compute the mod without computing the div, and the constraints in the
|>   > [u]divmodsi4 pattern makes sure that there is no conflict for the div part
|>   > (which must match one of the inputs).
|> I only saw one divmod insn in the .lreg dumps.  Even when I reverted to the
|> Nov 1 CVS tree.

This is what i get after local alloc for the loop:

----------------------------------------------------------------------
(note 189 374 196 "" NOTE_INSN_LOOP_BEG)

;; Start of basic block 13, registers live: 14 [%a6] 15 [%sp] 30 31 32 33 34 35 36 37 38 39 42 47 71 77 85 99 102 103
(code_label 196 189 198 11 "")

(note 198 196 383 "" NOTE_INSN_DELETED)

(insn 383 198 201 (set (reg:SI 70)
        (reg/v:SI 39)) 42 {movsi+1} (nil)
    (nil))

(insn 201 383 206 (set (reg:SI 70)
        (ashift:SI (reg:SI 70)
            (const_int 2))) 288 {ashlsi3} (nil)
    (expr_list:REG_EQUAL (mult:SI (reg/v:SI 39)
            (const_int 4))
        (nil)))

(insn 206 201 208 (set (reg/v:SI 42)
        (ashift:SI (reg/v:SI 42)
            (const_int 16))) 286 {ashlsi_16} (nil)
    (expr_list:REG_EQUAL (mult:SI (reg/v:SI 42)
            (const_int 65536))
        (nil)))

(note 208 206 209 "" NOTE_INSN_DELETED)

(insn 209 208 219 (set (reg/v:SI 41)
        (plus:SI (mem/s:SI (plus:SI (reg:SI 71)
                    (reg:SI 70)) 0)
            (reg/v:SI 42))) 126 {*addsi3_internal} (insn_list 201 (insn_list 206 (nil)))
    (expr_list:REG_DEAD (reg/v:SI 42)
        (nil)))

(note 219 209 220 "" NOTE_INSN_DELETED)

(note 220 219 222 "" NOTE_INSN_DELETED)

(insn 222 220 369 (parallel [
            (set (mem/s:SI (plus:SI (reg:SI 77)
                        (reg:SI 70)) 0)
                (udiv:SI (reg/v:SI 41)
                    (reg:SI 102)))
            (set (reg:SI 82)
                (umod:SI (reg/v:SI 41)
                    (reg:SI 102)))
        ]) 213 {udivmodsi4} (insn_list 209 (nil))
    (expr_list:REG_UNUSED (reg:SI 82)
        (expr_list:REG_DEAD (reg:SI 102)
            (expr_list:REG_DEAD (reg:SI 70)
                (nil)))))

(insn 369 222 228 (set (reg:SI 102)
        (reg:SI 85)) 42 {movsi+1} (nil)
    (nil))

(note 228 369 230 "" NOTE_INSN_DELETED)

(insn 230 228 233 (parallel [
            (set (reg:SI 86)
                (udiv:SI (reg/v:SI 41)
                    (reg:SI 85)))
            (set (reg/v:SI 42)
                (umod:SI (reg/v:SI 41)
                    (reg:SI 85)))
        ]) 213 {udivmodsi4} (nil)
    (expr_list:REG_UNUSED (reg:SI 86)
        (expr_list:REG_DEAD (reg/v:SI 41)
            (nil))))

(note 233 230 235 "" NOTE_INSN_LOOP_CONT)

(note 235 233 358 "" NOTE_INSN_DELETED)

(note 358 235 192 "" NOTE_INSN_LOOP_VTOP)

(note 192 358 193 "" NOTE_INSN_DELETED)

(jump_insn 193 192 241 (parallel [
            (set (pc)
                (if_then_else (ge (plus:SI (reg/v:SI 39)
                            (const_int -1))
                        (const_int 0))
                    (label_ref 196)
                    (pc)))
            (set (reg/v:SI 39)
                (plus:SI (reg/v:SI 39)
                    (const_int -1)))
        ]) 421 {decrement_and_branch_until_zero+1} (nil)
    (expr_list:REG_NONNEG (nil)
        (expr_list:REG_NONNEG (nil)
            (nil))))
;; End of basic block 13

(note 241 193 244 "" NOTE_INSN_LOOP_END)
----------------------------------------------------------------------

Interestingly, gcc-980929 gets it right and produces only one divmod.  The
difference is in the loop optimizer, where egcs transmoglifies the loop in
a way such that cse2 gets confused and does not notice that the second
umod computes the same value as the first umod.  Please note the strange
use of register 102 in the loop:

----------------------------------------------------------------------
;; Function div_and_round_double


Loop from 189 to 241: 16 real insns.
Continue at insn 233.
Insn 203: regno 71 (life 2), savings 1  moved to 372
Insn 215: regno 77 (life 3), savings 1  moved to 373
Insn 227: regno 85 (life 2), savings 1  moved to 374
Insn 369: possible biv, reg 102, const = (reg:SI 85)
Insn 235: possible biv, reg 39, const = -1
Reg 39: biv verified
Reg 102: biv discarded, never incremented
[...]

(insn 181 179 368 (set (reg:SI 68)
        (mem:SI (plus:SI (reg:SI 14 %a6)
                (const_int -68)) 0)) 42 {movsi+1} (nil)
    (nil))

(insn 368 181 183 (set (reg:SI 102)
        (reg:SI 68)) -1 (nil)
    (nil))

[...]

(insn 374 373 189 (set (reg:SI 85)
        (mem:SI (plus:SI (reg:SI 14 %a6)
                (const_int -68)) 0)) -1 (nil)
    (nil))

(note 189 374 196 "" NOTE_INSN_LOOP_BEG)

(code_label 196 189 198 11 "")

(note 198 196 201 "" NOTE_INSN_DELETED)

(insn 201 198 206 (set (reg:SI 70)
        (ashift:SI (reg/v:SI 39)
            (const_int 2))) -1 (nil)
    (expr_list:REG_EQUAL (mult:SI (reg/v:SI 39)
            (const_int 4))
        (nil)))

(insn 206 201 208 (set (reg:SI 73)
        (ashift:SI (reg/v:SI 42)
            (const_int 16))) -1 (nil)
    (expr_list:REG_EQUAL (mult:SI (reg/v:SI 42)
            (const_int 65536))
        (nil)))

(insn 208 206 209 (set (reg:SI 74)
        (mem/s:SI (plus:SI (reg:SI 71)
                (reg:SI 70)) 0)) -1 (nil)
    (nil))

(insn 209 208 219 (set (reg/v:SI 41)
        (plus:SI (reg:SI 74)
            (reg:SI 73))) -1 (nil)
    (nil))

(insn 219 209 220 (set (reg:SI 81)
        (reg:SI 102)) -1 (nil)
    (nil))

(insn 220 219 222 (parallel [
            (set (reg:SI 80)
                (udiv:SI (reg/v:SI 41)
                    (reg:SI 81)))
            (set (reg:SI 82)
                (umod:SI (reg/v:SI 41)
                    (reg:SI 81)))
        ]) -1 (nil)
    (nil))

(insn 222 220 369 (set (mem/s:SI (plus:SI (reg:SI 77)
                (reg:SI 70)) 0)
        (reg:SI 80)) -1 (nil)
    (nil))

(insn 369 222 228 (set (reg:SI 102)
        (reg:SI 85)) -1 (nil)
    (nil))

(insn 228 369 230 (parallel [
            (set (reg:SI 86)
                (udiv:SI (reg/v:SI 41)
                    (reg:SI 85)))
            (set (reg:SI 84)
                (umod:SI (reg/v:SI 41)
                    (reg:SI 85)))
        ]) -1 (nil)
    (nil))

(insn 230 228 233 (set (reg/v:SI 42)
        (reg:SI 84)) -1 (nil)
    (nil))

(note 233 230 235 "" NOTE_INSN_LOOP_CONT)

(insn 235 233 358 (set (reg/v:SI 39)
        (plus:SI (reg/v:SI 39)
            (const_int -1))) -1 (nil)
    (nil))

(note 358 235 192 "" NOTE_INSN_LOOP_VTOP)
----------------------------------------------------------------------

When compiling with -fno-rerun-cse-after-loop then gcc2 will produce two
divmods as well.

Andreas.

-- 
Andreas Schwab                                      "And now for something
schwab@issan.cs.uni-dortmund.de                      completely different"
schwab@gnu.org


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