This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [SH] PR 49880 - Fix some more -mdiv option issues
- From: Oleg Endo <oleg dot endo at t-online dot de>
- To: Kaz Kojima <kkojima at rr dot iij4u dot or dot jp>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 25 Mar 2013 23:58:11 +0100
- Subject: Re: [SH] PR 49880 - Fix some more -mdiv option issues
- References: <1363134126 dot 2219 dot 213 dot camel at yam-132-YW-E178-FTW> <20130313 dot 120505 dot 498875564 dot kkojima at rr dot iij4u dot or dot jp>
On Wed, 2013-03-13 at 12:05 +0900, Kaz Kojima wrote:
> Oleg Endo <oleg.endo@t-online.de> wrote:
> > The attached patch should make the -mdiv= option work as it is described
> > in the documentation (which I updated recently as part of PR 56529).
> >
> > Tested with 'make all' and
> >
> > make -k check-gcc RUNTESTFLAGS="sh.exp=pr49880* --target_board=sh-sim
> > \{-m2,-m2a,-m2a-nofpu,-m2a-single,-m2a-single-only,-m3,-m3e,-m4,-m4-single,
> > -m4-single-only,-m4a,-m4a-single,-m4a-single-only}"
> >
> > OK for 4.8 and 4.7?
>
> OK.
I've committed the attached patch including the sh-linux build fixes to
the 4.7 branch as revision 197071.
Cheers,
Oleg
Index: libgcc/config/sh/lib1funcs.S
===================================================================
--- libgcc/config/sh/lib1funcs.S (revision 196758)
+++ libgcc/config/sh/lib1funcs.S (working copy)
@@ -973,7 +973,7 @@
#ifdef L_sdivsi3_i4
.title "SH DIVIDE"
!! 4 byte integer Divide code for the Renesas SH
-#ifdef __SH4__
+#if defined (__SH4__) || defined (__SH2A__)
!! args in r4 and r5, result in fpul, clobber dr0, dr2
.global GLOBAL(sdivsi3_i4)
@@ -988,7 +988,7 @@
ftrc dr0,fpul
ENDFUNC(GLOBAL(sdivsi3_i4))
-#elif defined(__SH4_SINGLE__) || defined(__SH4_SINGLE_ONLY__) || (defined (__SH5__) && ! defined __SH4_NOFPU__)
+#elif defined (__SH2A_SINGLE__) || defined (__SH2A_SINGLE_ONLY__) || defined(__SH4_SINGLE__) || defined(__SH4_SINGLE_ONLY__) || (defined (__SH5__) && ! defined __SH4_NOFPU__)
!! args in r4 and r5, result in fpul, clobber r2, dr0, dr2
#if ! __SH5__ || __SH5__ == 32
@@ -1013,13 +1013,12 @@
ENDFUNC(GLOBAL(sdivsi3_i4))
#endif /* ! __SH5__ || __SH5__ == 32 */
-#endif /* ! __SH4__ */
+#endif /* ! __SH4__ || __SH2A__ */
#endif
#ifdef L_sdivsi3
/* __SH4_SINGLE_ONLY__ keeps this part for link compatibility with
sh2e/sh3e code. */
-#if (! defined(__SH4__) && ! defined (__SH4_SINGLE__)) || defined (__linux__)
!!
!! Steve Chamberlain
!! sac@cygnus.com
@@ -1336,13 +1335,12 @@
ENDFUNC(GLOBAL(sdivsi3))
#endif /* ! __SHMEDIA__ */
-#endif /* ! __SH4__ */
#endif
#ifdef L_udivsi3_i4
.title "SH DIVIDE"
!! 4 byte integer Divide code for the Renesas SH
-#ifdef __SH4__
+#if defined (__SH4__) || defined (__SH2A__)
!! args in r4 and r5, result in fpul, clobber r0, r1, r4, r5, dr0, dr2, dr4,
!! and t bit
@@ -1384,7 +1382,7 @@
.double 2147483648
ENDFUNC(GLOBAL(udivsi3_i4))
-#elif defined (__SH5__) && ! defined (__SH4_NOFPU__)
+#elif defined (__SH5__) && ! defined (__SH4_NOFPU__) && ! defined (__SH2A_NOFPU__)
#if ! __SH5__ || __SH5__ == 32
!! args in r4 and r5, result in fpul, clobber r20, r21, dr0, fr33
.mode SHmedia
@@ -1405,7 +1403,7 @@
ENDFUNC(GLOBAL(udivsi3_i4))
#endif /* ! __SH5__ || __SH5__ == 32 */
-#elif defined(__SH4_SINGLE__) || defined(__SH4_SINGLE_ONLY__)
+#elif defined (__SH2A_SINGLE__) || defined (__SH2A_SINGLE_ONLY__) || defined(__SH4_SINGLE__) || defined(__SH4_SINGLE_ONLY__)
!! args in r4 and r5, result in fpul, clobber r0, r1, r4, r5, dr0, dr2, dr4
.global GLOBAL(udivsi3_i4)
@@ -1460,7 +1458,6 @@
#ifdef L_udivsi3
/* __SH4_SINGLE_ONLY__ keeps this part for link compatibility with
sh2e/sh3e code. */
-#if (! defined(__SH4__) && ! defined (__SH4_SINGLE__)) || defined (__linux__)
!! args in r4 and r5, result in r0, clobbers r4, pr, and t bit
.global GLOBAL(udivsi3)
@@ -1655,7 +1652,6 @@
ENDFUNC(GLOBAL(udivsi3))
#endif /* ! __SHMEDIA__ */
-#endif /* __SH4__ */
#endif /* L_udivsi3 */
#ifdef L_udivdi3
Index: gcc/testsuite/gcc.target/sh/pr49880-1.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr49880-1.c (revision 0)
+++ gcc/testsuite/gcc.target/sh/pr49880-1.c (revision 0)
@@ -0,0 +1,22 @@
+/* Check that the option -mdiv=call-div1 works. */
+/* { dg-do link { target "sh*-*-*" } } */
+/* { dg-options "-mdiv=call-div1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
+
+int
+test00 (int a, int b)
+{
+ return a / b;
+}
+
+unsigned int
+test01 (unsigned int a, unsigned b)
+{
+ return a / b;
+}
+
+int
+main (int argc, char** argv)
+{
+ return test00 (argc, 123) + test01 (argc, 123);
+}
Index: gcc/testsuite/gcc.target/sh/pr49880-2.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr49880-2.c (revision 0)
+++ gcc/testsuite/gcc.target/sh/pr49880-2.c (revision 0)
@@ -0,0 +1,22 @@
+/* Check that the option -mdiv=call-fp works. */
+/* { dg-do link { target "sh*-*-*" } } */
+/* { dg-options "-mdiv=call-fp" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
+
+int
+test00 (int a, int b)
+{
+ return a / b;
+}
+
+unsigned int
+test01 (unsigned int a, unsigned b)
+{
+ return a / b;
+}
+
+int
+main (int argc, char** argv)
+{
+ return test00 (argc, 123) + test01 (argc, 123);
+}
Index: gcc/testsuite/gcc.target/sh/pr49880-3.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr49880-3.c (revision 0)
+++ gcc/testsuite/gcc.target/sh/pr49880-3.c (revision 0)
@@ -0,0 +1,22 @@
+/* Check that the option -mdiv=call-table works. */
+/* { dg-do link { target "sh*-*-*" } } */
+/* { dg-options "-mdiv=call-table" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
+
+int
+test00 (int a, int b)
+{
+ return a / b;
+}
+
+unsigned int
+test01 (unsigned int a, unsigned b)
+{
+ return a / b;
+}
+
+int
+main (int argc, char** argv)
+{
+ return test00 (argc, 123) + test01 (argc, 123);
+}
Index: gcc/testsuite/gcc.target/sh/pr49880-4.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr49880-4.c (revision 0)
+++ gcc/testsuite/gcc.target/sh/pr49880-4.c (revision 0)
@@ -0,0 +1,19 @@
+/* Check that the option -mdiv=call-fp does not produce calls to the
+ library function that uses FPU to implement integer division if FPU insns
+ are not supported or are disabled. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-mdiv=call-fp" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "*"} { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" } } */
+/* { dg-final { scan-assembler-not "sdivsi3_i4\n|udivsi3_i4\n" } } */
+
+int
+test00 (int a, int b)
+{
+ return a / b;
+}
+
+unsigned int
+test01 (unsigned int a, unsigned b)
+{
+ return a / b;
+}
Index: gcc/testsuite/gcc.target/sh/pr49880-5.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr49880-5.c (revision 0)
+++ gcc/testsuite/gcc.target/sh/pr49880-5.c (revision 0)
@@ -0,0 +1,19 @@
+/* Check that the option -mdiv=call-fp results in the corresponding library
+ function calls on targets that have a double precision FPU. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-mdiv=call-fp" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "*"} { "-m2a" "-m4" "-m4a" "*single-only" } } */
+/* { dg-final { scan-assembler "sdivsi3_i4\n" } } */
+/* { dg-final { scan-assembler "udivsi3_i4\n" } } */
+
+int
+test00 (int a, int b)
+{
+ return a / b;
+}
+
+unsigned int
+test01 (unsigned int a, unsigned b)
+{
+ return a / b;
+}
Index: gcc/config/sh/linux.h
===================================================================
--- gcc/config/sh/linux.h (revision 196758)
+++ gcc/config/sh/linux.h (working copy)
@@ -40,7 +40,7 @@
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
- (TARGET_CPU_DEFAULT | MASK_USERMODE | TARGET_ENDIAN_DEFAULT \
+ (TARGET_CPU_DEFAULT | TARGET_ENDIAN_DEFAULT \
| TARGET_OPT_DEFAULT | MASK_SOFT_ATOMIC)
#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
@@ -135,3 +135,13 @@
/* Install the __sync libcalls. */
#undef TARGET_INIT_LIBFUNCS
#define TARGET_INIT_LIBFUNCS sh_init_sync_libfuncs
+
+#undef SUBTARGET_OVERRIDE_OPTIONS
+#define SUBTARGET_OVERRIDE_OPTIONS \
+ do \
+ { \
+ /* Set -musermode if it hasn't been specified. */ \
+ if (global_options_set.x_TARGET_USERMODE == 0) \
+ TARGET_USERMODE = true; \
+ } \
+ while (0)
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c (revision 196758)
+++ gcc/config/sh/sh.c (working copy)
@@ -682,8 +682,7 @@
if (! strcmp (sh_div_str, "call-div1"))
sh_div_strategy = SH_DIV_CALL_DIV1;
else if (! strcmp (sh_div_str, "call-fp")
- && (TARGET_FPU_DOUBLE
- || (TARGET_HARD_SH4 && TARGET_SH2E)
+ && (TARGET_FPU_DOUBLE || TARGET_FPU_SINGLE_ONLY
|| (TARGET_SHCOMPACT && TARGET_FPU_ANY)))
sh_div_strategy = SH_DIV_CALL_FP;
else if (! strcmp (sh_div_str, "call-table")
Index: gcc/config/sh/sh.h
===================================================================
--- gcc/config/sh/sh.h (revision 196758)
+++ gcc/config/sh/sh.h (working copy)
@@ -208,14 +208,16 @@
| MASK_SH2 | MASK_SH1)
#define SELECT_SH2A_NOFPU (MASK_HARD_SH2A | MASK_SH2 | MASK_SH1)
#define SELECT_SH2A_SINGLE_ONLY (MASK_SH_E | MASK_HARD_SH2A | MASK_SH2 \
- | MASK_SH1 | MASK_FPU_SINGLE)
+ | MASK_SH1 | MASK_FPU_SINGLE \
+ | MASK_FPU_SINGLE_ONLY)
#define SELECT_SH2A_SINGLE (MASK_SH_E | MASK_HARD_SH2A \
| MASK_FPU_SINGLE | MASK_HARD_SH2A_DOUBLE \
| MASK_SH2 | MASK_SH1)
#define SELECT_SH3 (MASK_SH3 | SELECT_SH2)
#define SELECT_SH3E (MASK_SH_E | MASK_FPU_SINGLE | SELECT_SH3)
#define SELECT_SH4_NOFPU (MASK_HARD_SH4 | SELECT_SH3)
-#define SELECT_SH4_SINGLE_ONLY (MASK_HARD_SH4 | SELECT_SH3E)
+#define SELECT_SH4_SINGLE_ONLY (MASK_HARD_SH4 | SELECT_SH3E \
+ | MASK_FPU_SINGLE_ONLY)
#define SELECT_SH4 (MASK_SH4 | MASK_SH_E | MASK_HARD_SH4 \
| SELECT_SH3)
#define SELECT_SH4_SINGLE (MASK_FPU_SINGLE | SELECT_SH4)
@@ -282,7 +284,8 @@
/* Reset all target-selection flags. */
#define MASK_ARCH (MASK_SH1 | MASK_SH2 | MASK_SH3 | MASK_SH_E | MASK_SH4 \
| MASK_HARD_SH2A | MASK_HARD_SH2A_DOUBLE | MASK_SH4A \
- | MASK_HARD_SH4 | MASK_FPU_SINGLE | MASK_SH5)
+ | MASK_HARD_SH4 | MASK_FPU_SINGLE | MASK_SH5 \
+ | MASK_FPU_SINGLE_ONLY)
/* This defaults us to big-endian. */
#ifndef TARGET_ENDIAN_DEFAULT
Index: gcc/config/sh/netbsd-elf.h
===================================================================
--- gcc/config/sh/netbsd-elf.h (revision 196758)
+++ gcc/config/sh/netbsd-elf.h (working copy)
@@ -60,7 +60,7 @@
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
- (TARGET_CPU_DEFAULT | MASK_USERMODE | TARGET_ENDIAN_DEFAULT)
+ (TARGET_CPU_DEFAULT | TARGET_ENDIAN_DEFAULT)
/* Define because we use the label and we do not need them. */
#define NO_PROFILE_COUNTERS 1
@@ -96,3 +96,13 @@
#define SH_DIV_STRATEGY_DEFAULT SH_DIV_CALL2
#undef SH_DIV_STR_FOR_SIZE
#define SH_DIV_STR_FOR_SIZE "call2"
+
+#undef SUBTARGET_OVERRIDE_OPTIONS
+#define SUBTARGET_OVERRIDE_OPTIONS \
+ do \
+ { \
+ /* Set -musermode if it hasn't been specified. */ \
+ if (global_options_set.x_TARGET_USERMODE == 0) \
+ TARGET_USERMODE = true; \
+ } \
+ while (0)
Index: gcc/config/sh/sh.md
===================================================================
--- gcc/config/sh/sh.md (revision 196758)
+++ gcc/config/sh/sh.md (working copy)
@@ -1753,7 +1753,7 @@
(clobber (reg:SI PR_REG))
(clobber (reg:SI R4_REG))
(use (match_operand:SI 1 "arith_reg_operand" "r"))]
- "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
+ "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
"jsr @%1%#"
[(set_attr "type" "sfunc")
(set_attr "needs_delay_slot" "yes")])
@@ -1817,7 +1817,7 @@
(clobber (reg:SI R5_REG))
(use (reg:PSI FPSCR_REG))
(use (match_operand:SI 1 "arith_reg_operand" "r"))]
- "TARGET_SH4 && ! TARGET_FPU_SINGLE"
+ "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
"jsr @%1%#"
[(set_attr "type" "sfunc")
(set_attr "fp_mode" "double")
@@ -1836,7 +1836,8 @@
(clobber (reg:SI R4_REG))
(clobber (reg:SI R5_REG))
(use (match_operand:SI 1 "arith_reg_operand" "r"))]
- "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
+ "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
+ && TARGET_FPU_SINGLE"
"jsr @%1%#"
[(set_attr "type" "sfunc")
(set_attr "needs_delay_slot" "yes")])
@@ -1959,7 +1960,7 @@
(clobber (reg:SI R2_REG))
(clobber (reg:SI R3_REG))
(use (match_operand:SI 1 "arith_reg_operand" "r"))]
- "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
+ "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
"jsr @%1%#"
[(set_attr "type" "sfunc")
(set_attr "needs_delay_slot" "yes")])
@@ -2090,7 +2091,7 @@
(clobber (reg:DF DR2_REG))
(use (reg:PSI FPSCR_REG))
(use (match_operand:SI 1 "arith_reg_operand" "r"))]
- "TARGET_SH4 && ! TARGET_FPU_SINGLE"
+ "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
"jsr @%1%#"
[(set_attr "type" "sfunc")
(set_attr "fp_mode" "double")
@@ -2104,7 +2105,8 @@
(clobber (reg:DF DR2_REG))
(clobber (reg:SI R2_REG))
(use (match_operand:SI 1 "arith_reg_operand" "r"))]
- "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
+ "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
+ && TARGET_FPU_SINGLE"
"jsr @%1%#"
[(set_attr "type" "sfunc")
(set_attr "needs_delay_slot" "yes")])
Index: gcc/config/sh/sh.opt
===================================================================
--- gcc/config/sh/sh.opt (revision 196758)
+++ gcc/config/sh/sh.opt (working copy)
@@ -25,6 +25,10 @@
;; Set if the default precision of th FPU is single.
Mask(FPU_SINGLE)
+;; Set if the a double-precision FPU is present but is restricted to
+;; single precision usage only.
+Mask(FPU_SINGLE_ONLY)
+
;; Set if we should generate code using type 2A insns.
Mask(HARD_SH2A)
@@ -332,7 +336,7 @@
Cost to assume for a multiply insn
musermode
-Target Report RejectNegative Mask(USERMODE)
+Target Report RejectNegative Var(TARGET_USERMODE)
Don't generate privileged-mode only code; implies -mno-inline-ic_invalidate if the inline code would not work in user mode.
;; We might want to enable this by default for TARGET_HARD_SH4, because