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

            Bug ID: 116932
           Summary: [SH] GBR not used for some atomic imask/tcb insns
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: olegendo at gcc dot gnu.org
  Target Milestone: ---

While working on PR 55212, I've noticed that some of the atomic insns from the
pr64661 tests do not use GBR addressing, while some do use it.

__Z9test_36_1v:
.LFB1:
        .cfi_startproc
        stc     gbr,r1      <<< gbr stored to r1

        stc     sr,r0
        mov     r0,r2
        or      #0xF0,r0
        ldc     r0,sr
        mov.b   @r1,r0      <<< should actually use mov.b @(0,gbr),r0
        add     #1,r0
        mov.b   r0,@r1      <<<
        ldc     r2,sr
        rts     
        exts.b  r0,r0


__Z9test_37_1v:
.LFB7:
        .cfi_startproc

        stc     sr,r0
        mov     r0,r1
        or      #0xF0,r0
        ldc     r0,sr
        mov.b   @(4,gbr),r0   <<< gbr is used
        add     #1,r0
        mov.b   r0,@(4,gbr)   <<<
        ldc     r1,sr
        rts     
        exts.b  r0,r0


The GBR addressing is formed during combine/split1.  So before register
allocation, an insn will typicall look like this:

insn 6 5 9 2 (parallel [
            (set (reg:QI 166)
                (mem/v:QI (plus:SI (reg:SI 144 gbr)
                        (const_int 4 [0x4])) [-1  S1 A8]))
            (set (mem/v:QI (plus:SI (reg:SI 144 gbr)
                        (const_int 4 [0x4])) [-1  S1 A8])
                (unspec:QI [
                        (and:QI (mem/v:QI (plus:SI (reg:SI 144 gbr)
                                    (const_int 4 [0x4])) [-1  S1 A8])
                            (const_int 1 [0x1]))
                    ] UNSPEC_ATOMIC))
            (clobber (reg:SI 0 r0))
            (clobber (reg:QI 169))
        ]) "../gcc/gcc/testsuite/gcc.target/sh/pr64661-0.h":50:173 discrim 1
538 {atomic_fetch_andqi_soft_imask}
     (expr_list:REG_DEAD (reg:SI 144 gbr)
        (expr_list:REG_UNUSED (reg:QI 169)
            (expr_list:REG_UNUSED (reg:SI 0 r0)
                (nil)))))


After reload/LRA it might look like this (GBR substituted by other GP reg):

(insn 6 22 9 2 (parallel [
            (set (reg:QI 1 r1 [166])
                (mem/v:QI (plus:SI (reg:SI 3 r3 [171])
                        (const_int 4 [0x4])) [-1  S1 A8]))
            (set (mem/v:QI (plus:SI (reg:SI 3 r3 [171])
                        (const_int 4 [0x4])) [-1  S1 A8])
                (unspec:QI [
                        (and:QI (mem/v:QI (plus:SI (reg:SI 3 r3 [171])
                                    (const_int 4 [0x4])) [-1  S1 A8])
                            (const_int 1 [0x1]))
                    ] UNSPEC_ATOMIC))
            (clobber (reg:SI 0 r0))
            (clobber (reg:QI 2 r2 [169]))
        ]) "../gcc/gcc/testsuite/gcc.target/sh/pr64661-0.h":50:173 discrim 1
538 {atomic_fetch_andqi_soft_imask}
     (nil))


---------------
* the issue happens always when LRA is enabled.  with old reload it happens
only for addresses where the address offset/displacement would be 0.

* 0-displacement GBR addresses will require something to convert an address
'@gbr' into '@(0,gbr)' during asm printing.

* some insns use atomic_mem_operand_0 predicate which doesn't allow GBR
addressing, it should use atomic_mem_operand_1 instead in those places

* Sra and Sdd constraints don't allow GBR as part of the address with LRA
enabled.  However, even after adding a constraint like 

(define_memory_constraint "Sgb"
  "A memory renference that uses GBR addressing."
  (match_test "gbr_address_mem (op, GET_MODE (op))"))

LRA will always change the "pre-allocated" GBR hard-reg into something else,
which is counterproductive in this case.

Reply via email to