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. 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 -- Alan Modra Australia Development Lab, IBM