https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105477

Jeffrey A. Law <law at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|---                         |WONTFIX

--- Comment #4 from Jeffrey A. Law <law at gcc dot gnu.org> ---
And with zicond it collapses down to:

        czero.eqz       a1,a1,a2
        czero.nez       a0,a0,a2
        add     a0,a0,a1

There's a sequence without zicond that would look like seq+neg to get 0/-1,
then an andn+and+add to do the select.  So 5 instructions assuming Zbb, 6
without Zbb and probably a temporary or two.  Probably not worth if-converting
without zicond in general.

We still have an annoying copy with not using zicond.

The relevant insns

bb2:



(insn 25 5 26 2 (set (reg:DI 140 [ b ])
        (reg:DI 11 a1 [ b ])) "j.c":2:1 275 {*movdi_64bit}
     (expr_list:REG_DEAD (reg:DI 11 a1 [ b ])
        (nil)))
(insn 3 26 24 2 (set (reg/v:DI 136 [ b ])
        (reg:DI 140 [ b ])) "j.c":2:1 275 {*movdi_64bit}
     (expr_list:REG_DEAD (reg:DI 140 [ b ])
        (nil)))
(insn 24 3 9 2 (set (reg:DI 139 [ a ])
        (reg:DI 10 a0 [ a ])) "j.c":2:1 275 {*movdi_64bit}
     (expr_list:REG_DEAD (reg:DI 10 a0 [ a ])
        (nil)))

bb3:

(insn 6 10 32 4 (set (reg/v:DI 136 [ b ])
        (reg:DI 139 [ a ])) "j.c":3:18 discrim 1 275 {*movdi_64bit}
     (expr_list:REG_DEAD (reg:DI 139 [ a ])
        (nil)))

bb4:
(insn 17 34 18 7 (set (reg/i:DI 10 a0)
        (reg/v:DI 136 [ b ])) "j.c":4:1 275 {*movdi_64bit}
     (expr_list:REG_DEAD (reg/v:DI 136 [ b ])
        (nil)))

The relevant part of the conflict table

;; a0(r136,l0) conflicts: a1(r139,l0) a2(r141,l0)
;;     total conflict hard regs: 10
;;     conflict hard regs: 10

;; a1(r139,l0) conflicts: a0(r136,l0) a2(r141,l0)
;;     total conflict hard regs:
;;     conflict hard regs:

;; a3(r140,l0) conflicts: a2(r141,l0)
;;     total conflict hard regs: 10 12
;;     conflict hard regs: 10 12


At this point we're hosed.  We really want r136 to allocate into a0, but that's
not possible because of insn 3 (we would end up clobbering a0 before insn 24). 
At some level that's make_more_copies.  But even if we neuter that we still
don't get good code.

bb2:
(insn 2 4 3 2 (set (reg/v:DI 135 [ a ])
        (reg:DI 10 a0 [ a ])) "j.c":2:1 275 {*movdi_64bit}
     (expr_list:REG_DEAD (reg:DI 10 a0 [ a ])
        (nil)))
(insn 3 2 9 2 (set (reg/v:DI 136 [ b ])
        (reg:DI 11 a1 [ b ])) "j.c":2:1 275 {*movdi_64bit}
     (expr_list:REG_DEAD (reg:DI 11 a1 [ b ])
        (nil)))

bb3:
(insn 6 10 29 4 (set (reg/v:DI 136 [ b ])
        (reg/v:DI 135 [ a ])) "j.c":3:18 discrim 1 275 {*movdi_64bit}
     (expr_list:REG_DEAD (reg/v:DI 135 [ a ])
        (nil)))

bb4:
(insn 17 31 18 7 (set (reg/i:DI 10 a0)
        (reg/v:DI 136 [ b ])) "j.c":4:1 275 {*movdi_64bit}
     (expr_list:REG_DEAD (reg/v:DI 136 [ b ])
        (nil)))


;; a0(r136,l0) conflicts: a1(r135,l0) a2(r137,l0)
;;     total conflict hard regs:
;;     conflict hard regs:

;; a1(r135,l0) conflicts: a0(r136,l0) a2(r137,l0)
;;     total conflict hard regs: 11
;;     conflict hard regs: 11

r136 is the first allocno popped off the coloring stack and we assign it to a1.
 All downhill from there.   Allocating r136 first is the right move since insn
17 is always executed while insn 6 is conditionally executed.   r136 is going
to prefer either a0 (via insn 3) or a0 (via insn 17). With r135 conflicing with
a1, r136 is virtually guaranteed to get a1 to make a0 available for r135.

In the end I think this is largely coming down to chance (if we expanded via EQ
and reversed the true/false blocks), then we'd get optimal code.  Similarly if
we made the same kind of change at the source level by reversing the true/false
arms.

I don't really see anything to guide combine or IRA here.  We either get lucky
or we don't.

Reply via email to