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?