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

--- Comment #17 from Oleg Endo <olegendo at gcc dot gnu.org> ---
I have tried this:

Index: gcc/config/sh/sh.md
===================================================================
--- gcc/config/sh/sh.md (revision 233324)
+++ gcc/config/sh/sh.md (working copy)
@@ -10481,7 +10481,7 @@
        (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
              (match_operand 2 "" "")))
    (use (reg:SI FPSCR_MODES_REG))
-   (clobber (match_scratch:SI 3 "=&k"))
+   (clobber (match_scratch:SI 3 "=k"))
    (return)]
   "TARGET_SH2 && !TARGET_FDPIC"
   "#"

... and compiling the example in comment #1 with -m2 -mb -O2 -mlra works fine. 
However, it results in the following wrong code:

        mov.l   .L2,r7   <<< r7 is used by function arg, can't clobber it.
        mov     r4,r0
        mov     r5,r1
        mov     r6,r2
        mov     r0,r4
        mov     r1,r5
        braf    r7
.LPCS0:
        mov     r2,r6


I guess because the recently added "sibcall_value_pcrel_fdpic" pattern also
uses "=k" as the clobber constraint, it might run into the same problem.  To
play safe for now, I'd like to commit the following to trunk and backport it to
5 and possibly 4.9:

Index: gcc/config/sh/sh.md
===================================================================
--- gcc/config/sh/sh.md (revision 233324)
+++ gcc/config/sh/sh.md (working copy)
@@ -10476,12 +10476,16 @@
                      (const_string "single") (const_string "double")))
    (set_attr "type" "jump_ind")])

+;; sibcall_value_pcrel used to have a =&k clobber for the scratch register
+;; that it needs for the branch address.  This causes troubles when there
+;; is a big overlap of argument and return value registers.  Hence, use a
+;; fixed call clobbered register for the address.  See also PR 67260.
 (define_insn_and_split "sibcall_value_pcrel"
   [(set (match_operand 0 "" "=rf")
        (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
              (match_operand 2 "" "")))
    (use (reg:SI FPSCR_MODES_REG))
-   (clobber (match_scratch:SI 3 "=&k"))
+   (clobber (reg:SI R1_REG))
    (return)]
   "TARGET_SH2 && !TARGET_FDPIC"
   "#"
@@ -10491,6 +10495,8 @@
   rtx lab = PATTERN (gen_call_site ());
   rtx call_insn;

+  operands[3] =  gen_rtx_REG (SImode, R1_REG);
+
   sh_expand_sym_label2reg (operands[3], operands[1], lab, true);
   call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
                                                        operands[3],
@@ -10505,6 +10511,8 @@
                      (const_string "single") (const_string "double")))
    (set_attr "type" "jump_ind")])

+;; Like for sibcall_value_pcrel, use a fixed call clobbered register for
+;; the branch address.
 (define_insn_and_split "sibcall_value_pcrel_fdpic"
   [(set (match_operand 0 "" "=rf")
        (call (mem:SI (match_operand:SI 1 "symbol_ref_operand"))
@@ -10511,7 +10519,7 @@
              (match_operand 2)))
    (use (reg:SI FPSCR_MODES_REG))
    (use (reg:SI PIC_REG))
-   (clobber (match_scratch:SI 3 "=k"))
+   (clobber (reg:SI R1_REG))
    (return)]
   "TARGET_SH2 && TARGET_FDPIC"
   "#"
@@ -10520,6 +10528,8 @@
 {
   rtx lab = PATTERN (gen_call_site ());

+  operands[3] =  gen_rtx_REG (SImode, R1_REG);
+
   sh_expand_sym_label2reg (operands[3], operands[1], lab, true);
   rtx i = emit_call_insn (gen_sibcall_valuei_pcrel_fdpic (operands[0],
                                                          operands[3],

Kaz, what do you think?

Reply via email to