From: Oleg Endo Date: Mon, 15 Oct 2012 22:04:37 +0000 (+0000) Subject: re PR target/54760 ([SH] Add __builtin_thread_pointer, __builtin_set_thread_pointer) X-Git-Tag: misc/gccgo-go1_1_2~150 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=14df3f361e5aaa4145ab242886e3a857d4ae078c;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 765f6b403e82..78ea62237ce6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2012-10-15 Oleg Endo + + 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 * config/sh/sh.c: Update function attribute comments. diff --git a/gcc/config/sh/iterators.md b/gcc/config/sh/iterators.md index ec95013b2c3b..e118c3ef1cd5 100644 --- a/gcc/config/sh/iterators.md +++ b/gcc/config/sh/iterators.md @@ -18,6 +18,7 @@ ;; along with GCC; see the file COPYING3. If not see ;; . +(define_mode_iterator QIHISIDI [QI HI SI DI]) (define_mode_iterator QIHISI [QI HI SI]) (define_mode_iterator QIHI [QI HI]) (define_mode_iterator HISI [HI SI]) diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md index cd980556002b..83508e895aea 100644 --- a/gcc/config/sh/predicates.md +++ b/gcc/config/sh/predicates.md @@ -1139,3 +1139,20 @@ 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; +}) diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index bc4eb8bf259d..763ee9d8ad14 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -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; 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)) continue; diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 1b6c284e388b..95afd9b3996b 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -10277,6 +10277,47 @@ label: "mov. %0,@(0,gbr)" [(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, ;; 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 @@ -10287,15 +10328,15 @@ label: ;; other operand) and there's no point of doing it if the GBR is not ;; referenced in a function at all. (define_split - [(set (match_operand:QIHISI 0 "register_operand") - (match_operand:QIHISI 1 "memory_operand"))] + [(set (match_operand:QIHISIDI 0 "register_operand") + (match_operand:QIHISIDI 1 "memory_operand"))] "TARGET_SH1 && !reload_in_progress && !reload_completed && df_regs_ever_live_p (GBR_REG)" [(set (match_dup 0) (match_dup 1))] { rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); 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 FAIL; }) @@ -10309,7 +10350,7 @@ label: { rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); 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 FAIL; }) @@ -10328,23 +10369,22 @@ label: if (gbr_mem != NULL_RTX) { operands[2] = gen_reg_rtx (GET_MODE (operands[1])); - operands[1] = change_address (operands[1], GET_MODE (operands[1]), - gbr_mem); + operands[1] = replace_equiv_address (operands[1], gbr_mem); } else FAIL; }) (define_split - [(set (match_operand:QIHISI 0 "memory_operand") - (match_operand:QIHISI 1 "register_operand"))] + [(set (match_operand:QIHISIDI 0 "memory_operand") + (match_operand:QIHISIDI 1 "register_operand"))] "TARGET_SH1 && !reload_in_progress && !reload_completed && df_regs_ever_live_p (GBR_REG)" [(set (match_dup 0) (match_dup 1))] { rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]); 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 FAIL; }) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 805bfb2fad42..a155a531cd72 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2012-10-15 Oleg Endo + + 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 PR target/34777 diff --git a/gcc/testsuite/gcc.target/sh/pr54760-2.c b/gcc/testsuite/gcc.target/sh/pr54760-2.c index b8a501847856..91f3648a5998 100644 --- a/gcc/testsuite/gcc.target/sh/pr54760-2.c +++ b/gcc/testsuite/gcc.target/sh/pr54760-2.c @@ -9,107 +9,129 @@ /* --------------------------------------------------------------------------- Simple GBR load. */ -#define func(name, type, disp)\ - int \ +#define func(name, rettype, type, disp)\ + rettype \ name ## _tp_load (void) \ { \ type* tp = (type*)__builtin_thread_pointer (); \ return tp[disp]; \ } -func (test00, int, 0) -func (test01, int, 5) -func (test02, int, 255) +func (test00, int, int, 0) +func (test01, int, int, 5) +func (test02, int, int, 255) -func (test03, short, 0) -func (test04, short, 5) -func (test05, short, 255) +func (test03, int, short, 0) +func (test04, int, short, 5) +func (test05, int, short, 255) -func (test06, char, 0) -func (test07, char, 5) -func (test08, char, 255) +func (test06, int, char, 0) +func (test07, int, char, 5) +func (test08, int, char, 255) -func (test09, unsigned int, 0) -func (test10, unsigned int, 5) -func (test11, unsigned int, 255) +func (test09, int, unsigned int, 0) +func (test10, int, unsigned int, 5) +func (test11, int, unsigned int, 255) -func (test12, unsigned short, 0) -func (test13, unsigned short, 5) -func (test14, unsigned short, 255) +func (test12, int, unsigned short, 0) +func (test13, int, unsigned short, 5) +func (test14, int, unsigned short, 255) -func (test15, unsigned char, 0) -func (test16, unsigned char, 5) -func (test17, unsigned char, 255) +func (test15, int, unsigned char, 0) +func (test16, int, unsigned char, 5) +func (test17, int, unsigned char, 255) + +func (test18, long long, long long, 0) +func (test19, long long, long long, 5) +func (test20, long long, long long, 127) + +func (test21, long long, unsigned long long, 0) +func (test22, long long, unsigned long long, 5) +func (test23, long long, unsigned long long, 127) #undef func /* --------------------------------------------------------------------------- Simple GBR store. */ -#define func(name, type, disp)\ +#define func(name, argtype, type, disp)\ void \ - name ## _tp_store (int a) \ + name ## _tp_store (argtype a) \ { \ type* tp = (type*)__builtin_thread_pointer (); \ tp[disp] = (type)a; \ } -func (test00, int, 0) -func (test01, int, 5) -func (test02, int, 255) +func (test00, int, int, 0) +func (test01, int, int, 5) +func (test02, int, int, 255) + +func (test03, int, short, 0) +func (test04, int, short, 5) +func (test05, int, short, 255) + +func (test06, int, char, 0) +func (test07, int, char, 5) +func (test08, int, char, 255) -func (test03, short, 0) -func (test04, short, 5) -func (test05, short, 255) +func (test09, int, unsigned int, 0) +func (test10, int, unsigned int, 5) +func (test11, int, unsigned int, 255) -func (test06, char, 0) -func (test07, char, 5) -func (test08, char, 255) +func (test12, int, unsigned short, 0) +func (test13, int, unsigned short, 5) +func (test14, int, unsigned short, 255) -func (test09, unsigned int, 0) -func (test10, unsigned int, 5) -func (test11, unsigned int, 255) +func (test15, int, unsigned char, 0) +func (test16, int, unsigned char, 5) +func (test17, int, unsigned char, 255) -func (test12, unsigned short, 0) -func (test13, unsigned short, 5) -func (test14, unsigned short, 255) +func (test18, long long, long long, 0) +func (test19, long long, long long, 5) +func (test20, long long, long long, 127) -func (test15, unsigned char, 0) -func (test16, unsigned char, 5) -func (test17, unsigned char, 255) +func (test21, long long, unsigned long long, 0) +func (test22, long long, unsigned long long, 5) +func (test23, long long, unsigned long long, 127) #undef func /* --------------------------------------------------------------------------- Arithmetic on the result of a GBR load. */ -#define func(name, type, disp, op, opname)\ - int \ - name ## _tp_load_arith_ ##opname (int a) \ +#define func(name, retargtype, type, disp, op, opname)\ + retargtype \ + name ## _tp_load_arith_ ##opname (retargtype a) \ { \ type* tp = (type*)__builtin_thread_pointer (); \ return tp[disp] op a; \ } #define funcs(op, opname) \ - func (test00, int, 0, op, opname) \ - func (test01, int, 5, op, opname) \ - func (test02, int, 255, op, opname) \ - func (test03, short, 0, op, opname) \ - func (test04, short, 5, op, opname) \ - func (test05, short, 255, op, opname) \ - func (test06, char, 0, op, opname) \ - func (test07, char, 5, op, opname) \ - func (test08, char, 255, op, opname) \ - func (test09, unsigned int, 0, op, opname) \ - func (test10, unsigned int, 5, op, opname) \ - func (test11, unsigned int, 255, op, opname) \ - func (test12, unsigned short, 0, op, opname) \ - func (test13, unsigned short, 5, op, opname) \ - func (test14, unsigned short, 255, op, opname) \ - func (test15, unsigned char, 0, op, opname) \ - func (test16, unsigned char, 5, op, opname) \ - func (test17, unsigned char, 255, op, opname) \ + func (test00, int, int, 0, op, opname) \ + func (test01, int, int, 5, op, opname) \ + func (test02, int, int, 255, op, opname) \ + func (test03, int, short, 0, op, opname) \ + func (test04, int, short, 5, op, opname) \ + func (test05, int, short, 255, op, opname) \ + func (test06, int, char, 0, op, opname) \ + func (test07, int, char, 5, op, opname) \ + func (test08, int, char, 255, op, opname) \ + func (test09, int, unsigned int, 0, op, opname) \ + func (test10, int, unsigned int, 5, op, opname) \ + func (test11, int, unsigned int, 255, op, opname) \ + func (test12, int, unsigned short, 0, op, opname) \ + func (test13, int, unsigned short, 5, op, opname) \ + func (test14, int, unsigned short, 255, op, opname) \ + func (test15, int, unsigned char, 0, op, opname) \ + func (test16, int, unsigned char, 5, op, opname) \ + func (test17, int, unsigned char, 255, op, opname) \ + func (test18, long long, long long, 0, op, opname) \ + func (test19, long long, long long, 5, op, opname) \ + func (test20, long long, long long, 127, op, opname) \ + func (test21, long long, unsigned long long, 0, op, opname) \ + func (test22, long long, unsigned long long, 5, op, opname) \ + func (test23, long long, unsigned long long, 127, op, opname) \ funcs (+, plus) funcs (-, minus) @@ -124,8 +146,8 @@ funcs (^, xor) /* --------------------------------------------------------------------------- Arithmetic of the result of two GBR loads. */ -#define func(name, type, disp0, disp1, op, opname)\ - int \ +#define func(name, rettype, type, disp0, disp1, op, opname)\ + rettype \ name ## _tp_load_load_arith_ ##opname (void) \ { \ type* tp = (type*)__builtin_thread_pointer (); \ @@ -133,18 +155,22 @@ funcs (^, xor) } #define funcs(op, opname) \ - func (test00, int, 0, 5, op, opname) \ - func (test02, int, 1, 255, op, opname) \ - func (test03, short, 0, 5, op, opname) \ - func (test05, short, 1, 255, op, opname) \ - func (test06, char, 0, 5, op, opname) \ - func (test08, char, 1, 255, op, opname) \ - func (test09, unsigned int, 0, 5, op, opname) \ - func (test11, unsigned int, 1, 255, op, opname) \ - func (test12, unsigned short, 0, 5, op, opname) \ - func (test14, unsigned short, 1, 255, op, opname) \ - func (test15, unsigned char, 0, 5, op, opname) \ - func (test17, unsigned char, 1, 255, op, opname) \ + func (test00, int, int, 0, 5, op, opname) \ + func (test02, int, int, 1, 255, op, opname) \ + func (test03, int, short, 0, 5, op, opname) \ + func (test05, int, short, 1, 255, op, opname) \ + func (test06, int, char, 0, 5, op, opname) \ + func (test08, int, char, 1, 255, op, opname) \ + func (test09, int, unsigned int, 0, 5, op, opname) \ + func (test11, int, unsigned int, 1, 255, op, opname) \ + func (test12, int, unsigned short, 0, 5, op, opname) \ + func (test14, int, unsigned short, 1, 255, op, opname) \ + func (test15, int, unsigned char, 0, 5, op, opname) \ + func (test17, int, unsigned char, 1, 255, op, opname) \ + func (test18, long long, long long, 0, 5, op, opname) \ + func (test19, long long, long long, 1, 127, op, opname) \ + func (test20, long long, unsigned long long, 0, 5, op, opname) \ + func (test21, long long, unsigned long long, 1, 127, op, opname) \ funcs (+, plus) funcs (-, minus) @@ -180,6 +206,10 @@ func (test12, unsigned short, 0, 5) func (test14, unsigned short, 1, 255) func (test15, unsigned char, 0, 5) func (test17, unsigned char, 1, 255) +func (test18, long long, 0, 5) +func (test19, long long, 1, 127) +func (test20, unsigned long long, 0, 5) +func (test21, unsigned long long, 1, 127) #undef func @@ -187,33 +217,39 @@ func (test17, unsigned char, 1, 255) GBR load, arithmetic, GBR store */ -#define func(name, type, disp, op, opname)\ +#define func(name, argtype, type, disp, op, opname)\ void \ - name ## _tp_load_arith_store_ ##opname (int a) \ + name ## _tp_load_arith_store_ ##opname (argtype a) \ { \ type* tp = (type*)__builtin_thread_pointer (); \ tp[disp] op a; \ } #define funcs(op, opname) \ - func (test00, int, 0, op, opname) \ - func (test01, int, 5, op, opname) \ - func (test02, int, 255, op, opname) \ - func (test03, short, 0, op, opname) \ - func (test04, short, 5, op, opname) \ - func (test05, short, 255, op, opname) \ - func (test06, char, 0, op, opname) \ - func (test07, char, 5, op, opname) \ - func (test08, char, 255, op, opname) \ - func (test09, unsigned int, 0, op, opname) \ - func (test10, unsigned int, 5, op, opname) \ - func (test11, unsigned int, 255, op, opname) \ - func (test12, unsigned short, 0, op, opname) \ - func (test13, unsigned short, 5, op, opname) \ - func (test14, unsigned short, 255, op, opname) \ - func (test15, unsigned char, 0, op, opname) \ - func (test16, unsigned char, 5, op, opname) \ - func (test17, unsigned char, 255, op, opname) \ + func (test00, int, int, 0, op, opname) \ + func (test01, int, int, 5, op, opname) \ + func (test02, int, int, 255, op, opname) \ + func (test03, int, short, 0, op, opname) \ + func (test04, int, short, 5, op, opname) \ + func (test05, int, short, 255, op, opname) \ + func (test06, int, char, 0, op, opname) \ + func (test07, int, char, 5, op, opname) \ + func (test08, int, char, 255, op, opname) \ + func (test09, int, unsigned int, 0, op, opname) \ + func (test10, int, unsigned int, 5, op, opname) \ + func (test11, int, unsigned int, 255, op, opname) \ + func (test12, int, unsigned short, 0, op, opname) \ + func (test13, int, unsigned short, 5, op, opname) \ + func (test14, int, unsigned short, 255, op, opname) \ + func (test15, int, unsigned char, 0, op, opname) \ + func (test16, int, unsigned char, 5, op, opname) \ + func (test17, int, unsigned char, 255, op, opname) \ + func (test18, long long, long long, 0, op, opname) \ + func (test19, long long, long long, 5, op, opname) \ + func (test20, long long, long long, 127, op, opname) \ + func (test21, long long, unsigned long long, 0, op, opname) \ + func (test22, long long, unsigned long long, 5, op, opname) \ + func (test23, long long, unsigned long long, 127, op, opname) \ funcs (+=, plus) funcs (-=, minus) diff --git a/gcc/testsuite/gcc.target/sh/pr54760-4.c b/gcc/testsuite/gcc.target/sh/pr54760-4.c new file mode 100644 index 000000000000..3ee36a31389e --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr54760-4.c @@ -0,0 +1,19 @@ +/* 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; +}