Commit 14df3f36 by Oleg Endo

re PR target/54760 ([SH] Add __builtin_thread_pointer, __builtin_set_thread_pointer)

	PR target/54760
	* config/sh/sh.c (sh_find_base_reg_disp): Stop searching insns when
	hitting a call insn if GBR is marked as call used.
	* config/sh/iterators.md (QIHISIDI): New mode iterator.
	* config/sh/predicates.md (gbr_address_mem): New predicate.
	* config/sh/sh.md (*movdi_gbr_load, *movdi_gbr_store): New
	insn_and_split.
	Use QIHISIDI instead of QIHISI in unnamed GBR addressing splits.

	PR target/54760
	* gcc.target/sh/pr54760-2.c: Add long long and unsigned long long test
	functions.
	* gcc.target/sh/pr54760-4.c: New.

From-SVN: r192480
parent 845f4111
2012-10-15 Oleg Endo <olegendo@gcc.gnu.org> 2012-10-15 Oleg Endo <olegendo@gcc.gnu.org>
PR target/54760
* config/sh/sh.c (sh_find_base_reg_disp): Stop searching insns when
hitting a call insn if GBR is marked as call used.
* config/sh/iterators.md (QIHISIDI): New mode iterator.
* config/sh/predicates.md (gbr_address_mem): New predicate.
* config/sh/sh.md (*movdi_gbr_load, *movdi_gbr_store): New
insn_and_split.
Use QIHISIDI instead of QIHISI in unnamed GBR addressing splits.
2012-10-15 Oleg Endo <olegendo@gcc.gnu.org>
* config/sh/sh.c: Update function attribute comments. * config/sh/sh.c: Update function attribute comments.
* doc/extend.texi (function_vector): Rephrase SH2A specific part. * doc/extend.texi (function_vector): Rephrase SH2A specific part.
(nosave_low_regs, renesas, trapa_handler): Document SH specific (nosave_low_regs, renesas, trapa_handler): Document SH specific
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
;; along with GCC; see the file COPYING3. If not see ;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>. ;; <http://www.gnu.org/licenses/>.
(define_mode_iterator QIHISIDI [QI HI SI DI])
(define_mode_iterator QIHISI [QI HI SI]) (define_mode_iterator QIHISI [QI HI SI])
(define_mode_iterator QIHI [QI HI]) (define_mode_iterator QIHI [QI HI])
(define_mode_iterator HISI [HI SI]) (define_mode_iterator HISI [HI SI])
......
...@@ -1139,3 +1139,20 @@ ...@@ -1139,3 +1139,20 @@
return INTVAL (op) >= 0 && INTVAL (op) <= max_disp; return INTVAL (op) >= 0 && INTVAL (op) <= max_disp;
}) })
;; A predicate that determines whether OP is a valid GBR addressing mode
;; memory reference.
(define_predicate "gbr_address_mem"
(match_code "mem")
{
rtx addr = XEXP (op, 0);
if (REG_P (addr) && REGNO (addr) == GBR_REG)
return true;
if (GET_CODE (addr) == PLUS
&& REG_P (XEXP (addr, 0)) && REGNO (XEXP (addr, 0)) == GBR_REG
&& gbr_displacement (XEXP (addr, 1), mode))
return true;
return false;
})
...@@ -13395,6 +13395,10 @@ sh_find_base_reg_disp (rtx insn, rtx x, disp_t disp = 0, rtx base_reg = NULL) ...@@ -13395,6 +13395,10 @@ sh_find_base_reg_disp (rtx insn, rtx x, disp_t disp = 0, rtx base_reg = NULL)
for (rtx i = prev_nonnote_insn (insn); i != NULL; for (rtx i = prev_nonnote_insn (insn); i != NULL;
i = prev_nonnote_insn (i)) i = prev_nonnote_insn (i))
{ {
if (REGNO_REG_SET_P (regs_invalidated_by_call_regset, GBR_REG)
&& CALL_P (i))
break;
if (!NONJUMP_INSN_P (i)) if (!NONJUMP_INSN_P (i))
continue; continue;
......
...@@ -10277,6 +10277,47 @@ label: ...@@ -10277,6 +10277,47 @@ label:
"mov.<bwl> %0,@(0,gbr)" "mov.<bwl> %0,@(0,gbr)"
[(set_attr "type" "store")]) [(set_attr "type" "store")])
;; DImode memory accesses have to be split in two SImode accesses.
;; Split them before reload, so that it gets a better chance to figure out
;; how to deal with the R0 restriction for the individual SImode accesses.
;; Do not match this insn during or after reload because it can't be split
;; afterwards.
(define_insn_and_split "*movdi_gbr_load"
[(set (match_operand:DI 0 "register_operand")
(match_operand:DI 1 "gbr_address_mem"))]
"TARGET_SH1 && can_create_pseudo_p ()"
"#"
"&& 1"
[(set (match_dup 3) (match_dup 5))
(set (match_dup 4) (match_dup 6))]
{
/* Swap low/high part load order on little endian, so that the result reg
of the second load can be used better. */
int off = TARGET_LITTLE_ENDIAN ? 1 : 0;
operands[3 + off] = gen_lowpart (SImode, operands[0]);
operands[5 + off] = gen_lowpart (SImode, operands[1]);
operands[4 - off] = gen_highpart (SImode, operands[0]);
operands[6 - off] = gen_highpart (SImode, operands[1]);
})
(define_insn_and_split "*movdi_gbr_store"
[(set (match_operand:DI 0 "gbr_address_mem")
(match_operand:DI 1 "register_operand"))]
"TARGET_SH1 && can_create_pseudo_p ()"
"#"
"&& 1"
[(set (match_dup 3) (match_dup 5))
(set (match_dup 4) (match_dup 6))]
{
/* Swap low/high part store order on big endian, so that stores of function
call results can save a reg copy. */
int off = TARGET_LITTLE_ENDIAN ? 0 : 1;
operands[3 + off] = gen_lowpart (SImode, operands[0]);
operands[5 + off] = gen_lowpart (SImode, operands[1]);
operands[4 - off] = gen_highpart (SImode, operands[0]);
operands[6 - off] = gen_highpart (SImode, operands[1]);
})
;; Sometimes memory accesses do not get combined with the store_gbr insn, ;; Sometimes memory accesses do not get combined with the store_gbr insn,
;; in particular when the displacements are in the range of the regular move ;; in particular when the displacements are in the range of the regular move
;; insns. Thus, in the first split pass after the combine pass we search ;; insns. Thus, in the first split pass after the combine pass we search
...@@ -10287,15 +10328,15 @@ label: ...@@ -10287,15 +10328,15 @@ label:
;; other operand) and there's no point of doing it if the GBR is not ;; other operand) and there's no point of doing it if the GBR is not
;; referenced in a function at all. ;; referenced in a function at all.
(define_split (define_split
[(set (match_operand:QIHISI 0 "register_operand") [(set (match_operand:QIHISIDI 0 "register_operand")
(match_operand:QIHISI 1 "memory_operand"))] (match_operand:QIHISIDI 1 "memory_operand"))]
"TARGET_SH1 && !reload_in_progress && !reload_completed "TARGET_SH1 && !reload_in_progress && !reload_completed
&& df_regs_ever_live_p (GBR_REG)" && df_regs_ever_live_p (GBR_REG)"
[(set (match_dup 0) (match_dup 1))] [(set (match_dup 0) (match_dup 1))]
{ {
rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
if (gbr_mem != NULL_RTX) if (gbr_mem != NULL_RTX)
operands[1] = change_address (operands[1], GET_MODE (operands[1]), gbr_mem); operands[1] = replace_equiv_address (operands[1], gbr_mem);
else else
FAIL; FAIL;
}) })
...@@ -10309,7 +10350,7 @@ label: ...@@ -10309,7 +10350,7 @@ label:
{ {
rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
if (gbr_mem != NULL_RTX) if (gbr_mem != NULL_RTX)
operands[1] = change_address (operands[1], GET_MODE (operands[1]), gbr_mem); operands[1] = replace_equiv_address (operands[1], gbr_mem);
else else
FAIL; FAIL;
}) })
...@@ -10328,23 +10369,22 @@ label: ...@@ -10328,23 +10369,22 @@ label:
if (gbr_mem != NULL_RTX) if (gbr_mem != NULL_RTX)
{ {
operands[2] = gen_reg_rtx (GET_MODE (operands[1])); operands[2] = gen_reg_rtx (GET_MODE (operands[1]));
operands[1] = change_address (operands[1], GET_MODE (operands[1]), operands[1] = replace_equiv_address (operands[1], gbr_mem);
gbr_mem);
} }
else else
FAIL; FAIL;
}) })
(define_split (define_split
[(set (match_operand:QIHISI 0 "memory_operand") [(set (match_operand:QIHISIDI 0 "memory_operand")
(match_operand:QIHISI 1 "register_operand"))] (match_operand:QIHISIDI 1 "register_operand"))]
"TARGET_SH1 && !reload_in_progress && !reload_completed "TARGET_SH1 && !reload_in_progress && !reload_completed
&& df_regs_ever_live_p (GBR_REG)" && df_regs_ever_live_p (GBR_REG)"
[(set (match_dup 0) (match_dup 1))] [(set (match_dup 0) (match_dup 1))]
{ {
rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]); rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]);
if (gbr_mem != NULL_RTX) if (gbr_mem != NULL_RTX)
operands[0] = change_address (operands[0], GET_MODE (operands[0]), gbr_mem); operands[0] = replace_equiv_address (operands[0], gbr_mem);
else else
FAIL; FAIL;
}) })
......
2012-10-15 Oleg Endo <olegendo@gcc.gnu.org> 2012-10-15 Oleg Endo <olegendo@gcc.gnu.org>
PR target/54760
* gcc.target/sh/pr54760-2.c: Add long long and unsigned long long test
functions.
* gcc.target/sh/pr54760-4.c: New.
2012-10-15 Oleg Endo <olegendo@gcc.gnu.org>
PR target/34777 PR target/34777
* gcc.target/sh/torture/sh-torture.exp: New. * gcc.target/sh/torture/sh-torture.exp: New.
* gcc.target/sh/torture/pr34777.c: New. * gcc.target/sh/torture/pr34777.c: New.
......
/* Check that the GBR address optimization does not combine a gbr store
and its use when a function call is inbetween, when GBR is a call used
register, i.e. it is invalidated by function calls. */
/* { dg-do compile { target "sh*-*-*" } } */
/* { dg-options "-O1 -fcall-used-gbr" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler "stc\tgbr" } } */
extern int test00 (void);
int
test01 (int x)
{
/* We must see a stc gbr,rn before the function call, because
a function call could modify the gbr. In this case the user requests
the old gbr value, before the function call. */
int* p = (int*)__builtin_thread_pointer ();
p[5] = test00 ();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment