This is patch #2 of my series for improving the PowerPC internal memory support. It assumes patch #1 has been applied.
This patch moves the rs6000_move_128bit function from rs6000.c to a new file, rs6000-output.c. The third patch will create a rs6000_move_64bit function and change both 32-bit and 64-bit movdi to call it, instead of having all of the instructions be literals. I will also likely add improvements to setting the reg_addr address masks for offsetable addresses. The fourth patch will like move movdd and movdf to call rs6000_move_64bit as well. I tested this on a little endian power8 system and there were no regressions. 2018-03-14 Michael Meissner <meiss...@linux.vnet.ibm.com> * config.gcc (powerpc*-*-*): Add rs6000-output.o to extra_objs. * config/rs6000/t-rs6000 (rs6000-output.o): Add build rule. * config/rs6000/rs6000.c (rs6000_output_move_128bit): Move to rs6000-output.c. (rs6000_move_128bit_ok_p): Likewise. (rs6000_split_128bit_ok_p): Likewise. * config/rs6000/rs6000-output.c (rs6000_output_move_128bit): Likewise. to rs6000-output.c. (rs6000_move_128bit_ok_p): Likewise. (rs6000_split_128bit_ok_p): Likewise. -- Michael Meissner, IBM IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA email: meiss...@linux.vnet.ibm.com, phone: +1 (978) 899-4797
Index: gcc/config.gcc =================================================================== --- gcc/config.gcc (revision 258531) +++ gcc/config.gcc (working copy) @@ -466,7 +466,7 @@ powerpc*-*-*spe*) ;; powerpc*-*-*) cpu_type=rs6000 - extra_objs="rs6000-string.o rs6000-p8swap.o" + extra_objs="rs6000-string.o rs6000-p8swap.o rs6000-output.o" extra_headers="ppc-asm.h altivec.h htmintrin.h htmxlintrin.h" extra_headers="${extra_headers} bmi2intrin.h bmiintrin.h" extra_headers="${extra_headers} xmmintrin.h mm_malloc.h emmintrin.h" Index: gcc/config/rs6000/t-rs6000 =================================================================== --- gcc/config/rs6000/t-rs6000 (revision 258530) +++ gcc/config/rs6000/t-rs6000 (working copy) @@ -30,6 +30,10 @@ rs6000-string.o: $(srcdir)/config/rs6000 $(COMPILE) $< $(POSTCOMPILE) +rs6000-output.o: $(srcdir)/config/rs6000/rs6000-output.c + $(COMPILE) $< + $(POSTCOMPILE) + rs6000-p8swap.o: $(srcdir)/config/rs6000/rs6000-p8swap.c $(COMPILE) $< $(POSTCOMPILE) Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 258535) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -20921,205 +20921,6 @@ rs6000_debug_can_change_mode_class (mach return ret; } -/* Return a string to do a move operation of 128 bits of data. */ - -const char * -rs6000_output_move_128bit (rtx operands[]) -{ - rtx dest = operands[0]; - rtx src = operands[1]; - machine_mode mode = GET_MODE (dest); - int dest_regno; - int src_regno; - bool dest_gpr_p, dest_fp_p, dest_vmx_p, dest_vsx_p; - bool src_gpr_p, src_fp_p, src_vmx_p, src_vsx_p; - - if (REG_P (dest)) - { - dest_regno = REGNO (dest); - dest_gpr_p = INT_REGNO_P (dest_regno); - dest_fp_p = FP_REGNO_P (dest_regno); - dest_vmx_p = ALTIVEC_REGNO_P (dest_regno); - dest_vsx_p = dest_fp_p | dest_vmx_p; - } - else - { - dest_regno = -1; - dest_gpr_p = dest_fp_p = dest_vmx_p = dest_vsx_p = false; - } - - if (REG_P (src)) - { - src_regno = REGNO (src); - src_gpr_p = INT_REGNO_P (src_regno); - src_fp_p = FP_REGNO_P (src_regno); - src_vmx_p = ALTIVEC_REGNO_P (src_regno); - src_vsx_p = src_fp_p | src_vmx_p; - } - else - { - src_regno = -1; - src_gpr_p = src_fp_p = src_vmx_p = src_vsx_p = false; - } - - /* Register moves. */ - if (dest_regno >= 0 && src_regno >= 0) - { - if (dest_gpr_p) - { - if (src_gpr_p) - return "#"; - - if (TARGET_DIRECT_MOVE_128 && src_vsx_p) - return (WORDS_BIG_ENDIAN - ? "mfvsrd %0,%x1\n\tmfvsrld %L0,%x1" - : "mfvsrd %L0,%x1\n\tmfvsrld %0,%x1"); - - else if (TARGET_VSX && TARGET_DIRECT_MOVE && src_vsx_p) - return "#"; - } - - else if (TARGET_VSX && dest_vsx_p) - { - if (src_vsx_p) - return "xxlor %x0,%x1,%x1"; - - else if (TARGET_DIRECT_MOVE_128 && src_gpr_p) - return (WORDS_BIG_ENDIAN - ? "mtvsrdd %x0,%1,%L1" - : "mtvsrdd %x0,%L1,%1"); - - else if (TARGET_DIRECT_MOVE && src_gpr_p) - return "#"; - } - - else if (TARGET_ALTIVEC && dest_vmx_p && src_vmx_p) - return "vor %0,%1,%1"; - - else if (dest_fp_p && src_fp_p) - return "#"; - } - - /* Loads. */ - else if (dest_regno >= 0 && MEM_P (src)) - { - if (dest_gpr_p) - { - if (TARGET_QUAD_MEMORY && quad_load_store_p (dest, src)) - return "lq %0,%1"; - else - return "#"; - } - - else if (TARGET_ALTIVEC && dest_vmx_p - && altivec_indexed_or_indirect_operand (src, mode)) - return "lvx %0,%y1"; - - else if (TARGET_VSX && dest_vsx_p) - { - if (mode_supports_dq_form (mode) - && quad_address_p (XEXP (src, 0), mode, true)) - return "lxv %x0,%1"; - - else if (TARGET_P9_VECTOR) - return "lxvx %x0,%y1"; - - else if (mode == V16QImode || mode == V8HImode || mode == V4SImode) - return "lxvw4x %x0,%y1"; - - else - return "lxvd2x %x0,%y1"; - } - - else if (TARGET_ALTIVEC && dest_vmx_p) - return "lvx %0,%y1"; - - else if (dest_fp_p) - return "#"; - } - - /* Stores. */ - else if (src_regno >= 0 && MEM_P (dest)) - { - if (src_gpr_p) - { - if (TARGET_QUAD_MEMORY && quad_load_store_p (dest, src)) - return "stq %1,%0"; - else - return "#"; - } - - else if (TARGET_ALTIVEC && src_vmx_p - && altivec_indexed_or_indirect_operand (src, mode)) - return "stvx %1,%y0"; - - else if (TARGET_VSX && src_vsx_p) - { - if (mode_supports_dq_form (mode) - && quad_address_p (XEXP (dest, 0), mode, true)) - return "stxv %x1,%0"; - - else if (TARGET_P9_VECTOR) - return "stxvx %x1,%y0"; - - else if (mode == V16QImode || mode == V8HImode || mode == V4SImode) - return "stxvw4x %x1,%y0"; - - else - return "stxvd2x %x1,%y0"; - } - - else if (TARGET_ALTIVEC && src_vmx_p) - return "stvx %1,%y0"; - - else if (src_fp_p) - return "#"; - } - - /* Constants. */ - else if (dest_regno >= 0 - && (GET_CODE (src) == CONST_INT - || GET_CODE (src) == CONST_WIDE_INT - || GET_CODE (src) == CONST_DOUBLE - || GET_CODE (src) == CONST_VECTOR)) - { - if (dest_gpr_p) - return "#"; - - else if ((dest_vmx_p && TARGET_ALTIVEC) - || (dest_vsx_p && TARGET_VSX)) - return output_vec_const_move (operands); - } - - fatal_insn ("Bad 128-bit move", gen_rtx_SET (dest, src)); -} - -/* Validate a 128-bit move. */ -bool -rs6000_move_128bit_ok_p (rtx operands[]) -{ - machine_mode mode = GET_MODE (operands[0]); - return (gpc_reg_operand (operands[0], mode) - || gpc_reg_operand (operands[1], mode)); -} - -/* Return true if a 128-bit move needs to be split. */ -bool -rs6000_split_128bit_ok_p (rtx operands[]) -{ - if (!reload_completed) - return false; - - if (!gpr_or_gpr_p (operands[0], operands[1])) - return false; - - if (quad_load_store_p (operands[0], operands[1])) - return false; - - return true; -} - - /* Given a comparison operation, return the bit number in CCR to test. We know this is a valid comparison. Index: gcc/config/rs6000/rs6000-output.c =================================================================== --- gcc/config/rs6000/rs6000-output.c (revision 0) +++ gcc/config/rs6000/rs6000-output.c (revision 0) @@ -0,0 +1,246 @@ +/* Subroutines used to emit code and split insns for PowerPC. + Copyright (C) 2018 Free Software Foundation, Inc. + Contributed by Richard Kenner (ken...@vlsi1.ultra.nyu.edu) + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#define IN_TARGET_CODE 1 + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "backend.h" +#include "rtl.h" +#include "tree.h" +#include "memmodel.h" +#include "tm_p.h" +#include "expmed.h" +#include "optabs.h" +#include "regs.h" +#include "ira.h" +#include "recog.h" +#include "insn-attr.h" +#include "flags.h" +#include "print-tree.h" +#include "fold-const.h" +#include "stringpool.h" +#include "attribs.h" +#include "varasm.h" +#include "explow.h" +#include "expr.h" +#include "output.h" +#include "target.h" +#include "tm-constrs.h" + + +/* Return a string to do a move operation of 128 bits of data. */ + +const char * +rs6000_output_move_128bit (rtx operands[]) +{ + rtx dest = operands[0]; + rtx src = operands[1]; + machine_mode mode = GET_MODE (dest); + int dest_regno; + int src_regno; + bool dest_gpr_p, dest_fp_p, dest_vmx_p, dest_vsx_p; + bool src_gpr_p, src_fp_p, src_vmx_p, src_vsx_p; + + if (REG_P (dest)) + { + dest_regno = REGNO (dest); + dest_gpr_p = INT_REGNO_P (dest_regno); + dest_fp_p = FP_REGNO_P (dest_regno); + dest_vmx_p = ALTIVEC_REGNO_P (dest_regno); + dest_vsx_p = dest_fp_p | dest_vmx_p; + } + else + { + dest_regno = -1; + dest_gpr_p = dest_fp_p = dest_vmx_p = dest_vsx_p = false; + } + + if (REG_P (src)) + { + src_regno = REGNO (src); + src_gpr_p = INT_REGNO_P (src_regno); + src_fp_p = FP_REGNO_P (src_regno); + src_vmx_p = ALTIVEC_REGNO_P (src_regno); + src_vsx_p = src_fp_p | src_vmx_p; + } + else + { + src_regno = -1; + src_gpr_p = src_fp_p = src_vmx_p = src_vsx_p = false; + } + + /* Register moves. */ + if (dest_regno >= 0 && src_regno >= 0) + { + if (dest_gpr_p) + { + if (src_gpr_p) + return "#"; + + if (TARGET_DIRECT_MOVE_128 && src_vsx_p) + return (WORDS_BIG_ENDIAN + ? "mfvsrd %0,%x1\n\tmfvsrld %L0,%x1" + : "mfvsrd %L0,%x1\n\tmfvsrld %0,%x1"); + + else if (TARGET_VSX && TARGET_DIRECT_MOVE && src_vsx_p) + return "#"; + } + + else if (TARGET_VSX && dest_vsx_p) + { + if (src_vsx_p) + return "xxlor %x0,%x1,%x1"; + + else if (TARGET_DIRECT_MOVE_128 && src_gpr_p) + return (WORDS_BIG_ENDIAN + ? "mtvsrdd %x0,%1,%L1" + : "mtvsrdd %x0,%L1,%1"); + + else if (TARGET_DIRECT_MOVE && src_gpr_p) + return "#"; + } + + else if (TARGET_ALTIVEC && dest_vmx_p && src_vmx_p) + return "vor %0,%1,%1"; + + else if (dest_fp_p && src_fp_p) + return "#"; + } + + /* Loads. */ + else if (dest_regno >= 0 && MEM_P (src)) + { + if (dest_gpr_p) + { + if (TARGET_QUAD_MEMORY && quad_load_store_p (dest, src)) + return "lq %0,%1"; + else + return "#"; + } + + else if (TARGET_ALTIVEC && dest_vmx_p + && altivec_indexed_or_indirect_operand (src, mode)) + return "lvx %0,%y1"; + + else if (TARGET_VSX && dest_vsx_p) + { + if (mode_supports_dq_form (mode) + && quad_address_p (XEXP (src, 0), mode, true)) + return "lxv %x0,%1"; + + else if (TARGET_P9_VECTOR) + return "lxvx %x0,%y1"; + + else if (mode == V16QImode || mode == V8HImode || mode == V4SImode) + return "lxvw4x %x0,%y1"; + + else + return "lxvd2x %x0,%y1"; + } + + else if (TARGET_ALTIVEC && dest_vmx_p) + return "lvx %0,%y1"; + + else if (dest_fp_p) + return "#"; + } + + /* Stores. */ + else if (src_regno >= 0 && MEM_P (dest)) + { + if (src_gpr_p) + { + if (TARGET_QUAD_MEMORY && quad_load_store_p (dest, src)) + return "stq %1,%0"; + else + return "#"; + } + + else if (TARGET_ALTIVEC && src_vmx_p + && altivec_indexed_or_indirect_operand (src, mode)) + return "stvx %1,%y0"; + + else if (TARGET_VSX && src_vsx_p) + { + if (mode_supports_dq_form (mode) + && quad_address_p (XEXP (dest, 0), mode, true)) + return "stxv %x1,%0"; + + else if (TARGET_P9_VECTOR) + return "stxvx %x1,%y0"; + + else if (mode == V16QImode || mode == V8HImode || mode == V4SImode) + return "stxvw4x %x1,%y0"; + + else + return "stxvd2x %x1,%y0"; + } + + else if (TARGET_ALTIVEC && src_vmx_p) + return "stvx %1,%y0"; + + else if (src_fp_p) + return "#"; + } + + /* Constants. */ + else if (dest_regno >= 0 + && (GET_CODE (src) == CONST_INT + || GET_CODE (src) == CONST_WIDE_INT + || GET_CODE (src) == CONST_DOUBLE + || GET_CODE (src) == CONST_VECTOR)) + { + if (dest_gpr_p) + return "#"; + + else if ((dest_vmx_p && TARGET_ALTIVEC) + || (dest_vsx_p && TARGET_VSX)) + return output_vec_const_move (operands); + } + + fatal_insn ("Bad 128-bit move", gen_rtx_SET (dest, src)); +} + +/* Validate a 128-bit move. */ +bool +rs6000_move_128bit_ok_p (rtx operands[]) +{ + machine_mode mode = GET_MODE (operands[0]); + return (gpc_reg_operand (operands[0], mode) + || gpc_reg_operand (operands[1], mode)); +} + +/* Return true if a 128-bit move needs to be split. */ +bool +rs6000_split_128bit_ok_p (rtx operands[]) +{ + if (!reload_completed) + return false; + + if (!gpr_or_gpr_p (operands[0], operands[1])) + return false; + + if (quad_load_store_p (operands[0], operands[1])) + return false; + + return true; +}