]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/54760 ([SH] Add __builtin_thread_pointer, __builtin_set_thread_pointer)
authorOleg Endo <olegendo@gcc.gnu.org>
Mon, 15 Oct 2012 22:04:37 +0000 (22:04 +0000)
committerOleg Endo <olegendo@gcc.gnu.org>
Mon, 15 Oct 2012 22:04:37 +0000 (22:04 +0000)
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

gcc/ChangeLog
gcc/config/sh/iterators.md
gcc/config/sh/predicates.md
gcc/config/sh/sh.c
gcc/config/sh/sh.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/sh/pr54760-2.c
gcc/testsuite/gcc.target/sh/pr54760-4.c [new file with mode: 0644]

index 765f6b403e823d53897753691a11ae6013556036..78ea62237ce68867c6d78694a91d45371795cf78 100644 (file)
@@ -1,3 +1,14 @@
+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.
index ec95013b2c3bd17e876eac0ee46492242a2ba7e8..e118c3ef1cd5718136021d2e58674c1c228b9995 100644 (file)
@@ -18,6 +18,7 @@
 ;; along with GCC; see the file COPYING3.  If not see
 ;; <http://www.gnu.org/licenses/>.
 
+(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])
index cd980556002b61dc4d829eb016c1cf5710429975..83508e895aea900d2aa97f000932f4f9009ff2d6 100644 (file)
 
   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;
+})
index bc4eb8bf259d58a56a03f2a555f7a9f81ef44052..763ee9d8ad14fd66cac3006b70ee5197ad405c1a 100644 (file)
@@ -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;
 
index 1b6c284e388b60ae904c9e81462a6ff322792868..95afd9b3996b1790ca2fccd78463cc64e2459579 100644 (file)
@@ -10277,6 +10277,47 @@ label:
   "mov.<bwl>   %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;
 })
index 805bfb2fad42a7f5d77af7ed04fc3d2ce7044795..a155a531cd72af2687df8f37f13f26313f823b97 100644 (file)
@@ -1,3 +1,10 @@
+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
index b8a501847856f1d861a0ace986921b10e9358671..91f3648a5998ee1ae7c45330d0607b59a8d998d3 100644 (file)
 /* ---------------------------------------------------------------------------
   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 (file)
index 0000000..3ee36a3
--- /dev/null
@@ -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;
+}