Patchwork lower-subreg and IBM long double

login
register
mail settings
Submitter Alan Modra
Date Aug. 19, 2013, 6:47 a.m.
Message ID <20130819064742.GP4024@bubble.grove.modra.org>
Download mbox | patch
Permalink /patch/268122/
State New
Headers show

Comments

Alan Modra - Aug. 19, 2013, 6:47 a.m.
On Tue, Jun 11, 2013 at 09:56:11AM +0930, Alan Modra wrote:
>[snip] 
> It isn't hard to see why we are going wrong.  IBM long double is
> really a two element array of double, and the rs6000 backend uses
> subregs to access the elements.  The problem is that lower-subreg
> lowers to word_mode, so we get DImode.  word_mode makes sense for most
> targets where subregs of FP modes might be used to narrow an access
> for bit-twiddling operations on the sign bit.  It doesn't make sense
> for us.  We want DFmode for FP operations.  An example is the expander
> used by the testcase.

This is a repost of http://gcc.gnu.org/ml/gcc/2013-06/msg00053.html,
taking into account Joseph's doc review comments and adding a
testcase.  David has already acked the rs6000.c changes.  Bootstrapped
and regression tested powerpc64-linux.  OK to apply?

gcc/
	* rs6000.c (TARGET_INIT_LOWER_SUBREG): Define.
	(rs6000_init_lower_subreg): New function.
	* lower-subreg.c (init_lower_subreg): Call targetm.init_lower_subreg.
	* target.def (init_lower_subreg): New.
	* doc/tm.texi.in (TARGET_INIT_LOWER_SUBREG): Document.
	* doc/tm.texi: Regenerate.
gcc/testsuite/
	* gcc.target/powerpc/fabsl.c: New test.

Patch

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 201834)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -59,6 +59,7 @@ 
 #include "opts.h"
 #include "tree-vectorizer.h"
 #include "dumpfile.h"
+#include "lower-subreg.h"
 #if TARGET_XCOFF
 #include "xcoffout.h"  /* get declarations of xcoff_*_section_name */
 #endif
@@ -1364,6 +1365,8 @@  static const struct attribute_spec rs6000_attribut
 #define TARGET_RTX_COSTS rs6000_rtx_costs
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
+#undef TARGET_INIT_LOWER_SUBREG
+#define TARGET_INIT_LOWER_SUBREG rs6000_init_lower_subreg
 
 #undef TARGET_DWARF_REGISTER_SPAN
 #define TARGET_DWARF_REGISTER_SPAN rs6000_dwarf_register_span
@@ -27971,6 +27974,20 @@  rs6000_memory_move_cost (enum machine_mode mode, r
   return ret;
 }
 
+static void
+rs6000_init_lower_subreg (void *data)
+{
+  if (!TARGET_IEEEQUAD
+      && TARGET_HARD_FLOAT
+      && (TARGET_FPRS || TARGET_E500_DOUBLE)
+      && TARGET_LONG_DOUBLE_128)
+    {
+      struct target_lower_subreg *info = (struct target_lower_subreg *) data;
+      info->x_choices[0].move_modes_to_split[TFmode] = false;
+      info->x_choices[1].move_modes_to_split[TFmode] = false;
+    }
+}
+
 /* Returns a code for a target-specific builtin that implements
    reciprocal of the function, or NULL_TREE if not available.  */
 
Index: gcc/lower-subreg.c
===================================================================
--- gcc/lower-subreg.c	(revision 201834)
+++ gcc/lower-subreg.c	(working copy)
@@ -39,6 +39,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "df.h"
 #include "lower-subreg.h"
+#include "target.h"
 
 #ifdef STACK_GROWS_DOWNWARD
 # undef STACK_GROWS_DOWNWARD
@@ -287,6 +288,9 @@  init_lower_subreg (void)
   if (LOG_COSTS)
     fprintf (stderr, "\nSpeed costs\n===========\n\n");
   compute_costs (true, &rtxes);
+
+  if (targetm.init_lower_subreg)
+    targetm.init_lower_subreg (this_target_lower_subreg);
 }
 
 static bool
Index: gcc/target.def
===================================================================
--- gcc/target.def	(revision 201834)
+++ gcc/target.def	(working copy)
@@ -5110,6 +5110,14 @@  comparison code or operands.",
  void, (int *code, rtx *op0, rtx *op1, bool op0_preserve_value),
  default_canonicalize_comparison)
 
+/* Allow modification of subreg choices.  */
+DEFHOOK
+(init_lower_subreg,
+ "This hook allows modification of the choices the lower_subreg pass \
+will make for particular subreg modes.  @var{data} is a pointer to a \
+@code{struct target_lower_subreg}.",
+ void, (void *data), NULL)
+
 DEFHOOKPOD
 (atomic_test_and_set_trueval,
  "This value should be set if the result written by\
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	(revision 201834)
+++ gcc/doc/tm.texi.in	(working copy)
@@ -4939,6 +4939,8 @@  Define this macro if a non-short-circuit operation
 
 @hook TARGET_ADDRESS_COST
 
+@hook TARGET_INIT_LOWER_SUBREG
+
 @node Scheduling
 @section Adjusting the Instruction Scheduler