diff mbox

[MIPS] Target flag and build option to disable indexed memory OPs.

Message ID 6D39441BF12EF246A7ABCE6654B0235380B30E03@HHMAIL01.hh.imgtec.org
State New
Headers show

Commit Message

Matthew Fortune Jan. 19, 2017, 4:12 p.m. UTC
Hi Doug,

I've committed this on your behalf to get the testcases in and also
add the description of when this feature is required.  Thanks for the
patch.  Committed code inline below.

r244640

gcc/

	PR target/78176
	* config.gcc (supported_defaults): Add lxc1-sxc1.
	(with_lxc1_sxc1): Add validation.
	(all_defaults): Add lxc1-sxc1.
	* config/mips/mips.opt (mlxc1-sxc1): New option.
	* gcc/config/mips/mips.h (OPTION_DEFAULT_SPECS): Add a default for
	mlxc1-sxc1.
	(TARGET_CPU_CPP_BUILTINS): Add builtin_define for
	__mips_no_lxc1_sxc1.
	(ISA_HAS_LXC1_SXC1): Gate with mips_lxc1_sxc1.
	* gcc/doc/invoke.texi (-mlxc1-sxc1): Document the new option.
	* doc/install.texi (--with-lxc1-sxc1): Document the new option.

gcc/testsuite/

	* gcc.target/mips/lxc1-sxc1-1.c: New file.
	* gcc.target/mips/lxc1-sxc1-2.c: Likewise.
	* gcc.target/mips/mips.exp (mips_option_groups): Add ghost option
	HAS_LXC1.
	(mips_option_groups): Add -m[no-]lxc1-sxc1.
	(mips-dg-init): Detect default -mno-lxc1-sxc1.
	(mips-dg-options): Handle HAS_LXC1 arch upgrade/downgrade.

Matthew

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@244640 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog                               | 15 ++++++++
 gcc/config.gcc                              | 19 ++++++++-
 gcc/config/mips/mips.h                      |  8 +++-
 gcc/config/mips/mips.opt                    |  4 ++
 gcc/doc/install.texi                        | 19 +++++++++
 gcc/doc/invoke.texi                         |  6 +++
 gcc/testsuite/ChangeLog                     | 11 ++++++
 gcc/testsuite/gcc.target/mips/lxc1-sxc1-1.c | 60 +++++++++++++++++++++++++++++
 gcc/testsuite/gcc.target/mips/lxc1-sxc1-2.c | 60 +++++++++++++++++++++++++++++
 gcc/testsuite/gcc.target/mips/mips.exp      | 12 +++++-
 10 files changed, 209 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/mips/lxc1-sxc1-1.c
 create mode 100644 gcc/testsuite/gcc.target/mips/lxc1-sxc1-2.c

-- 
2.2.1
diff mbox

Patch

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 20b703f..f933e1ad 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@ 
+2017-01-19  Doug Gilmore  <doug.gilmore@imgtec.com>
+
+	PR target/78176
+	* config.gcc (supported_defaults): Add lxc1-sxc1.
+	(with_lxc1_sxc1): Add validation.
+	(all_defaults): Add lxc1-sxc1.
+	* config/mips/mips.opt (mlxc1-sxc1): New option.
+	* gcc/config/mips/mips.h (OPTION_DEFAULT_SPECS): Add a default for
+	mlxc1-sxc1.
+	(TARGET_CPU_CPP_BUILTINS): Add builtin_define for
+	__mips_no_lxc1_sxc1.
+	(ISA_HAS_LXC1_SXC1): Gate with mips_lxc1_sxc1.
+	* gcc/doc/invoke.texi (-mlxc1-sxc1): Document the new option.
+	* doc/install.texi (--with-lxc1-sxc1): Document the new option.
+
 2017-01-19  Richard Biener  <rguenther@suse.de>
 
 	PR tree-optimization/72488
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 90308cd..dd8c08c 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -3940,7 +3940,7 @@  case "${target}" in
 		;;
 
 	mips*-*-*)
-		supported_defaults="abi arch arch_32 arch_64 float fpu nan fp_32 odd_spreg_32 tune tune_32 tune_64 divide llsc mips-plt synci"
+		supported_defaults="abi arch arch_32 arch_64 float fpu nan fp_32 odd_spreg_32 tune tune_32 tune_64 divide llsc mips-plt synci lxc1-sxc1"
 
 		case ${with_float} in
 		"" | soft | hard)
@@ -4063,6 +4063,21 @@  case "${target}" in
 			exit 1
 			;;
 		esac
+
+		case ${with_lxc1_sxc1} in
+		yes)
+			with_lxc1_sxc1=lxc1-sxc1
+			;;
+		no)
+			with_lxc1_sxc1=no-lxc1-sxc1
+			;;
+		"")
+			;;
+		*)
+			echo "Unknown lxc1-sxc1 type used in --with-lxc1-sxc1" 1>&2
+			exit 1
+			;;
+		esac
 		;;
 
 	nds32*-*-*)
@@ -4496,7 +4511,7 @@  case ${target} in
 esac
 
 t=
-all_defaults="abi cpu cpu_32 cpu_64 arch arch_32 arch_64 tune tune_32 tune_64 schedule float mode fpu nan fp_32 odd_spreg_32 divide llsc mips-plt synci tls"
+all_defaults="abi cpu cpu_32 cpu_64 arch arch_32 arch_64 tune tune_32 tune_64 schedule float mode fpu nan fp_32 odd_spreg_32 divide llsc mips-plt synci tls lxc1-sxc1"
 for option in $all_defaults
 do
 	eval "val=\$with_"`echo $option | sed s/-/_/g`
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index fbd7011..4205589 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -637,6 +637,8 @@  struct mips_cpu_info {
 									\
       if (TARGET_CACHE_BUILTIN)						\
 	builtin_define ("__GCC_HAVE_BUILTIN_MIPS_CACHE");		\
+      if (!ISA_HAS_LXC1_SXC1)						\
+	builtin_define ("__mips_no_lxc1_sxc1");				\
     }									\
   while (0)
 
@@ -866,7 +868,8 @@  struct mips_cpu_info {
   {"divide", "%{!mdivide-traps:%{!mdivide-breaks:-mdivide-%(VALUE)}}" }, \
   {"llsc", "%{!mllsc:%{!mno-llsc:-m%(VALUE)}}" }, \
   {"mips-plt", "%{!mplt:%{!mno-plt:-m%(VALUE)}}" }, \
-  {"synci", "%{!msynci:%{!mno-synci:-m%(VALUE)}}" }
+  {"synci", "%{!msynci:%{!mno-synci:-m%(VALUE)}}" },			\
+  {"lxc1-sxc1", "%{!mlxc1-sxc1:%{!mno-lxc1-sxc1:-m%(VALUE)}}" } \
 
 /* A spec that infers the:
    -mnan=2008 setting from a -mips argument,
@@ -1036,7 +1039,8 @@  struct mips_cpu_info {
 
 /* ISA has floating-point indexed load and store instructions
    (LWXC1, LDXC1, SWXC1 and SDXC1).  */
-#define ISA_HAS_LXC1_SXC1	ISA_HAS_FP4
+#define ISA_HAS_LXC1_SXC1	(ISA_HAS_FP4				\
+				 && mips_lxc1_sxc1)
 
 /* ISA has paired-single instructions.  */
 #define ISA_HAS_PAIRED_SINGLE	((ISA_MIPS64				\
diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt
index 2559649..75ebafd 100644
--- a/gcc/config/mips/mips.opt
+++ b/gcc/config/mips/mips.opt
@@ -388,6 +388,10 @@  mlra
 Target Report Var(mips_lra_flag) Init(1) Save
 Use LRA instead of reload.
 
+mlxc1-sxc1
+Target Report Var(mips_lxc1_sxc1) Init(1)
+Use lwxc1/swxc1/ldxc1/sdxc1 instructions where applicable.
+
 mtune=
 Target RejectNegative Joined Var(mips_tune_option) ToLower Enum(mips_arch_opt_value)
 -mtune=PROCESSOR	Optimize the output for PROCESSOR.
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 4793ef8..712b82a 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1375,6 +1375,25 @@  On MIPS targets, make @option{-msynci} the default when no
 On MIPS targets, make @option{-mno-synci} the default when no
 @option{-msynci} option is passed.  This is the default.
 
+@item --with-lxc1-sxc1
+On MIPS targets, make @option{-mlxc1-sxc1} the default when no
+@option{-mno-lxc1-sxc1} option is passed.  This is the default.
+
+@item --without-lxc1-sxc1
+On MIPS targets, make @option{-mno-lxc1-sxc1} the default when no
+@option{-mlxc1-sxc1} option is passed.  The indexed load/store
+instructions are not directly a problem but can lead to unexpected
+behaviour when deployed in an application intended for a 32-bit address
+space but run on a 64-bit processor.  The issue is seen because all
+known MIPS 64-bit Linux kernels execute o32 and n32 applications
+with 64-bit addressing enabled which affects the overflow behaviour
+of the indexed addressing mode.  GCC will assume that ordinary
+32-bit arithmetic overflow behaviour is the same whether performed
+as an @code{addu} instruction or as part of the address calculation
+in @code{lwxc1} type instructions.  This assumption holds true in a
+pure 32-bit environment and can hold true in a 64-bit environment if
+the address space is accurately set to be 32-bit for o32 and n32.
+
 @item --with-mips-plt
 On MIPS targets, make use of copy relocations and PLTs.
 These features are extensions to the traditional
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 82cb1b5..a13a450 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -19932,6 +19932,12 @@  it is unused.
 
 This optimization is off by default at all optimization levels.
 
+@item -mlxc1-sxc1
+@itemx -mno-lxc1-sxc1
+@opindex mlxc1-sxc1
+When applicable, enable (disable) the generation of @code{lwxc1},
+@code{swxc1}, @code{ldxc1}, @code{sdxc1} instructions.  Enabled by default.
+
 @end table
 
 @node MMIX Options
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e0e0bd5..0ba8f93 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,14 @@ 
+2017-01-19  Matthew Fortune  <matthew.fortune@imgtec.com>
+
+	PR target/78176
+	* gcc.target/mips/lxc1-sxc1-1.c: New file.
+	* gcc.target/mips/lxc1-sxc1-2.c: Likewise.
+	* gcc.target/mips/mips.exp (mips_option_groups): Add ghost option
+	HAS_LXC1.
+	(mips_option_groups): Add -m[no-]lxc1-sxc1.
+	(mips-dg-init): Detect default -mno-lxc1-sxc1.
+	(mips-dg-options): Handle HAS_LXC1 arch upgrade/downgrade.
+
 2017-01-19  Andre Vehreschild  <vehre@gcc.gnu.org>
 
 	PR fortran/70696
diff --git a/gcc/testsuite/gcc.target/mips/lxc1-sxc1-1.c b/gcc/testsuite/gcc.target/mips/lxc1-sxc1-1.c
new file mode 100644
index 0000000..f455eb8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/lxc1-sxc1-1.c
@@ -0,0 +1,60 @@ 
+/* { dg-options "(HAS_LXC1) -mno-lxc1-sxc1" } */
+/* { dg-final { scan-assembler-not "\tldxc1\t" } } */
+/* { dg-final { scan-assembler-not "\tsdxc1\t" } } */
+
+#ifndef __mips_no_lxc1_sxc1
+#error missing definition of __mips_no_lxc1_sxc1
+#endif
+
+double ldexp(double x, int exp);
+
+typedef struct
+{
+  double** rows;
+} d_mat_struct;
+
+typedef d_mat_struct d_mat_t[1];
+
+#define d_mat_entry(mat,i,j) (*((mat)->rows[i] + (j)))
+
+double __attribute__((noinline))
+ldxc1_test (int kappa, int zeros, double ctt, int* expo, d_mat_t r, double* s)
+{
+  int kappa2 = kappa;
+  double tmp = 0.0;
+
+  do
+    {
+      kappa--;
+      if (kappa > zeros + 1)
+	{
+	  tmp = d_mat_entry(r, kappa - 1, kappa - 1) * ctt;
+	  tmp = ldexp(tmp, (expo[kappa - 1] - expo[kappa2]));
+	}
+    }
+  while ((kappa >= zeros + 2) && (s[kappa - 1] <= tmp));
+
+  return tmp;
+}
+
+#define SIZE 20
+
+int main(void)
+{
+  int kappa = SIZE - 1;
+  int zeros = 1;
+  double ctt = 2;
+
+  int expo[SIZE] = {0};
+  double s[SIZE] = {0};
+  double rows_data[SIZE][SIZE] = {0};
+  double* rows[SIZE];
+
+  for (int i = 0; i < SIZE; i++)
+    rows[i] = rows_data[i];
+
+  d_mat_t r = { rows };
+
+  ldxc1_test(kappa, zeros, ctt, expo, r, s);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/mips/lxc1-sxc1-2.c b/gcc/testsuite/gcc.target/mips/lxc1-sxc1-2.c
new file mode 100644
index 0000000..dfbf6b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/lxc1-sxc1-2.c
@@ -0,0 +1,60 @@ 
+/* { dg-options "(HAS_LXC1) -mlxc1-sxc1" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler "\tldxc1\t" } } */
+
+#ifdef __mips_no_lxc1_sxc1
+#error unexpected definition of __mips_no_lxc1_sxc1
+#endif
+
+double ldexp(double x, int exp);
+
+typedef struct
+{
+  double** rows;
+} d_mat_struct;
+
+typedef d_mat_struct d_mat_t[1];
+
+#define d_mat_entry(mat,i,j) (*((mat)->rows[i] + (j)))
+
+double __attribute__((noinline))
+ldxc1_test (int kappa, int zeros, double ctt, int* expo, d_mat_t r, double* s)
+{
+  int kappa2 = kappa;
+  double tmp = 0.0;
+
+  do
+    {
+      kappa--;
+      if (kappa > zeros + 1)
+	{
+	  tmp = d_mat_entry(r, kappa - 1, kappa - 1) * ctt;
+	  tmp = ldexp(tmp, (expo[kappa - 1] - expo[kappa2]));
+	}
+    }
+  while ((kappa >= zeros + 2) && (s[kappa - 1] <= tmp));
+
+  return tmp;
+}
+
+#define SIZE 20
+
+int main(void)
+{
+  int kappa = SIZE - 1;
+  int zeros = 1;
+  double ctt = 2;
+
+  int expo[SIZE] = {0};
+  double s[SIZE] = {0};
+  double rows_data[SIZE][SIZE] = {0};
+  double* rows[SIZE];
+
+  for (int i = 0; i < SIZE; i++)
+    rows[i] = rows_data[i];
+
+  d_mat_t r = { rows };
+
+  ldxc1_test(kappa, zeros, ctt, expo, r, s);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp
index b2f4e18..5296a15f 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -258,6 +258,7 @@  set mips_option_groups {
     madd "HAS_MADD"
     maddps "HAS_MADDPS"
     lsa "(|!)HAS_LSA"
+    lxc1 "HAS_LXC1"
     section_start "-Wl,--section-start=.*"
     frame-header "-mframe-header-opt|-mno-frame-header-opt"
     stack-protector "-fstack-protector"
@@ -282,6 +283,7 @@  foreach option {
     gpopt
     local-sdata
     long-calls
+    lxc1-sxc1
     paired-single
     plt
     shared
@@ -855,6 +857,12 @@  proc mips-dg-init {} {
 	    "-mno-smartmips",
 	    #endif
 
+	    #ifdef __mips_no_lxc1_sxc1
+	    "-mno-lxc1-sxc1",
+	    #else
+	    "-mlxc1-sxc1"
+	    #endif
+
 	    #ifdef __mips_synci
 	    "-msynci",
 	    #else
@@ -1173,7 +1181,8 @@  proc mips-dg-options { args } {
 	#
 	#
 	} elseif { $isa < 4
-		   && [mips_have_test_option_p options "HAS_MOVN"] } {
+		   && ([mips_have_test_option_p options "HAS_LXC1"]
+		       || [mips_have_test_option_p options "HAS_MOVN"]) } {
 	    mips_make_test_option options "-mips4"
         # We need MIPS III or higher for:
 	#
@@ -1214,6 +1223,7 @@  proc mips-dg-options { args } {
 		       || [mips_have_test_option_p options "-mfp32"]
 		       || [mips_have_test_option_p options "-mfix-r10000"]
 		       || [mips_have_test_option_p options "NOT_HAS_DMUL"]
+		       || [mips_have_test_option_p options "HAS_LXC1"]
 		       || [mips_have_test_option_p options "HAS_MOVN"]
 		       || [mips_have_test_option_p options "HAS_MADD"]
 		       || [mips_have_test_option_p options "-mpaired-single"]