diff options
author | revitale <revitale@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-08-31 05:26:38 +0000 |
---|---|---|
committer | revitale <revitale@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-08-31 05:26:38 +0000 |
commit | a9de045e3994baa4e0ccb0bc3055e7ef3e697cd7 (patch) | |
tree | f6b30b9a0ef62545c6daf229e0c8c8eff0aa2a72 | |
parent | e5ead12a0cb23e024117b90a912c24efd36f995a (diff) | |
download | gcc-a9de045e3994baa4e0ccb0bc3055e7ef3e697cd7.tar.gz |
Support for PowerPC 750CL paired-single instructions
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@127954 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 36 | ||||
-rw-r--r-- | gcc/config.gcc | 7 | ||||
-rw-r--r-- | gcc/config/rs6000/750cl.h | 23 | ||||
-rw-r--r-- | gcc/config/rs6000/paired.h | 77 | ||||
-rw-r--r-- | gcc/config/rs6000/paired.md | 355 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 351 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.h | 56 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 1 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.opt | 4 | ||||
-rw-r--r-- | gcc/config/rs6000/spe.md | 2 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/paired-1.c | 33 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/paired-2.c | 35 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/paired-3.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/paired-4.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/paired-5.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/paired-6.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/paired-7.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/ppc-paired.c | 44 |
20 files changed, 1195 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 99766dca081..483728dd3e6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,39 @@ +2007-08-31 David Edelsohn <edelsohn@gnu.org> + Revital Eres <eres@il.ibm.com> + + * doc/invoke.texi (-mpaired): Document flag. + * config.gcc: Include paired.h in powerpc extra_headers and + 750cl.h in powerpc-*-linux*paired*. + * config/rs6000/rs6000.opt (-mpaired): New flag. + * config/rs6000/rs6000.c (paired_init_builtins, + paired_expand_builtin, paired_expand_lv_builtin, + paired_expand_stv_builtin, paired_expand_predicate_builtin): + New functions to support the paired single builtin functions. + (rs6000_hard_regno_mode_ok): Handle PAIRED_VECTOR_MODE. + (def_builtin, bdesc_3arg, bdesc_2arg, bdesc_1arg): Add paired + single builtins. + (bdesc_paired_preds): New structure for paired predicate + instructions. + (rs6000_expand_builtin): Expand paired single builtins. + (rs6000_init_builtins): Init paired single builtins. + (rs6000_common_init_builtins): Add v2sf_ftype_v2sf_v2sf_v2sf. + Rename v2sf_ftype_v2sf_v2sf to v2sf_ftype_v2sf_v2sf_spe + and v2sf_ftype_v2sf_spe to v2sf_ftype_v2sf. Add new types + v2sf_ftype_v2sf_v2sf and v2sf_ftype_v2sf. + (rs6000_vector_mode_supported_p): Support paired vector mode. + * config/rs6000/rs6000.h: (UNITS_PER_PAIRED_WORD, + PAIRED_VECTOR_MODE, PAIRED_SIMD_REGNO_P, TARGET_PAIRED_FLOAT): + New. + (LOCAL_ALIGNMENT): Handle PAIRED_VECTOR_MODE. + (DATA_ALIGNMENT): Likewise. + (UNITS_PER_SIMD_WORD): Handle PAIRED_VECTOR_MODE. + (rs6000_builtins): Add PAIRED builtins. + * config/rs6000/rs6000.md: Include paired.md. + * config/rs6000/paired.h: New. + * config/rs6000/paired.md: New. + * config/rs6000/750cl.h: New. + * config/rs6000/spe.md: Recognize movv2sf instruction for 750cl. + 2007-08-30 Ollie Wild <aaw@google.com> * c-opts.c (c_common_handle_option): Support -fno-directives-only. diff --git a/gcc/config.gcc b/gcc/config.gcc index 6665eb70370..9f6c0262cb9 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -312,7 +312,7 @@ mips*-*-*) ;; powerpc*-*-*) cpu_type=rs6000 - extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h" + extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h" need_64bit_hwint=yes case x$with_cpu in xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[3456]|xpower6x|xrs64a) @@ -1936,6 +1936,11 @@ powerpc-*-linux*spe*) extra_options="${extra_options} rs6000/sysv4.opt" tmake_file="rs6000/t-fprules rs6000/t-fprules-softfp soft-fp/t-softfp rs6000/t-ppcos ${tmake_file} rs6000/t-ppccomm" ;; +powerpc-*-linux*paired*) + tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/linux.h rs6000/750cl.h" + extra_options="${extra_options} rs6000/sysv4.opt" + tmake_file="rs6000/t-fprules rs6000/t-fprules-softfp soft-fp/t-softfp rs6000/t-ppcos ${tmake_file} rs6000/t-ppccomm" + ;; powerpc-*-linux*) tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h" extra_options="${extra_options} rs6000/sysv4.opt" diff --git a/gcc/config/rs6000/750cl.h b/gcc/config/rs6000/750cl.h new file mode 100644 index 00000000000..d01761b2ae2 --- /dev/null +++ b/gcc/config/rs6000/750cl.h @@ -0,0 +1,23 @@ +/* Enable 750cl paired single support. + Copyright (C) 2007 Free Software Foundation, Inc. + Contributed by Revital Eres (eres@il.ibm.com) + 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 2, 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 COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#undef TARGET_PAIRED_FLOAT +#define TARGET_PAIRED_FLOAT rs6000_paired_float + diff --git a/gcc/config/rs6000/paired.h b/gcc/config/rs6000/paired.h new file mode 100644 index 00000000000..e70d0fa878f --- /dev/null +++ b/gcc/config/rs6000/paired.h @@ -0,0 +1,77 @@ +/* PowerPC 750CL user include file. + Copyright (C) 2007 Free Software Foundation, Inc. + Contributed by Revital Eres (eres@il.ibm.com). + + 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 2, 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 COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/* As a special exception, if you include this header file into source + files compiled by GCC, this header file does not by itself cause + the resulting executable to be covered by the GNU General Public + License. This exception does not however invalidate any other + reasons why the executable file might be covered by the GNU General + Public License. */ + +#ifndef _PAIRED_H +#define _PAIRED_H + +#define vector __attribute__((vector_size(8))) + +#define paired_msub __builtin_paired_msub +#define paired_madd __builtin_paired_madd +#define paired_nmsub __builtin_paired_nmsub +#define paired_nmadd __builtin_paired_nmadd +#define paired_sum0 __builtin_paired_sum0 +#define paired_sum1 __builtin_paired_sum1 +#define paired_div __builtin_paired_divv2sf3 +#define paired_add __builtin_paired_addv2sf3 +#define paired_sub __builtin_paired_subv2sf3 +#define paired_mul __builtin_paired_mulv2sf3 +#define paired_muls0 __builtin_paired_muls0 +#define paired_muls1 __builtin_paired_muls1 +#define paired_madds0 __builtin_paired_madds0 +#define paired_madds1 __builtin_paired_madds1 +#define paired_merge00 __builtin_paired_merge00 +#define paired_merge01 __builtin_paired_merge01 +#define paired_merge10 __builtin_paired_merge10 +#define paired_merge11 __builtin_paired_merge11 +#define paired_abs __builtin_paired_absv2sf2 +#define paired_nabs __builtin_paired_nabsv2sf2 +#define paired_neg __builtin_paired_negv2sf2 +#define paired_sqrt __builtin_paired_sqrtv2sf2 +#define paired_res __builtin_paired_resv2sf2 +#define paired_stx __builtin_paired_stx +#define paired_lx __builtin_paired_lx +#define paired_cmpu0 __builtin_paired_cmpu0 +#define paired_cmpu1 __builtin_paired_cmpu1 + +/* Condition register codes for Paired predicates. */ +#define LT 0 +#define GT 1 +#define EQ 2 +#define UN 3 + +#define paired_cmpu0_un(a,b) __builtin_paired_cmpu0 (UN, (a), (b)) +#define paired_cmpu0_eq(a,b) __builtin_paired_cmpu0 (EQ, (a), (b)) +#define paired_cmpu0_lt(a,b) __builtin_paired_cmpu0 (LT, (a), (b)) +#define paired_cmpu0_gt(a,b) __builtin_paired_cmpu0 (GT, (a), (b)) +#define paired_cmpu1_un(a,b) __builtin_paired_cmpu1 (UN, (a), (b)) +#define paired_cmpu1_eq(a,b) __builtin_paired_cmpu1 (EQ, (a), (b)) +#define paired_cmpu1_lt(a,b) __builtin_paired_cmpu1 (LT, (a), (b)) +#define paired_cmpu1_gt(a,b) __builtin_paired_cmpu1 (GT, (a), (b)) + +#endif /* _PAIRED_H */ diff --git a/gcc/config/rs6000/paired.md b/gcc/config/rs6000/paired.md new file mode 100644 index 00000000000..ad3001d884c --- /dev/null +++ b/gcc/config/rs6000/paired.md @@ -0,0 +1,355 @@ +;; PowerPC paired single and double hummer description +;; Copyright (C) 2007 +;; Free Software Foundation, Inc. +;; Contributed by David Edelsohn <edelsohn@gnu.org> and Revital Eres +;; <eres@il.ibm.com> + +;; 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 2, 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 COPYING. If not, write to the +;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +;; MA 02110-1301, USA. + + +(define_insn "negv2sf2" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (neg:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")))] + "TARGET_PAIRED_FLOAT" + "ps_neg %0,%1" + [(set_attr "type" "fp")]) + +(define_insn "sqrtv2sf2" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (sqrt:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")))] + "TARGET_PAIRED_FLOAT" + "ps_rsqrte %0,%1" + [(set_attr "type" "fp")]) + +(define_insn "absv2sf2" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (abs:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")))] + "TARGET_PAIRED_FLOAT" + "ps_abs %0,%1" + [(set_attr "type" "fp")]) + +(define_insn "nabsv2sf2" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (neg:V2SF (abs:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f"))))] + "TARGET_PAIRED_FLOAT" + "ps_nabs %0,%1" + [(set_attr "type" "fp")]) + +(define_insn "addv2sf3" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (plus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f") + (match_operand:V2SF 2 "gpc_reg_operand" "f")))] + "TARGET_PAIRED_FLOAT" + "ps_add %0,%1,%2" + [(set_attr "type" "fp")]) + +(define_insn "subv2sf3" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (minus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f") + (match_operand:V2SF 2 "gpc_reg_operand" "f")))] + "TARGET_PAIRED_FLOAT" + "ps_sub %0,%1,%2" + [(set_attr "type" "fp")]) + +(define_insn "mulv2sf3" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f") + (match_operand:V2SF 2 "gpc_reg_operand" "f")))] + "TARGET_PAIRED_FLOAT" + "ps_mul %0,%1,%2" + [(set_attr "type" "fp")]) + +(define_insn "resv2sf2" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))] + "TARGET_PAIRED_FLOAT && flag_finite_math_only" + "ps_res %0,%1" + [(set_attr "type" "fp")]) + +(define_insn "divv2sf3" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (div:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f") + (match_operand:V2SF 2 "gpc_reg_operand" "f")))] + "TARGET_PAIRED_FLOAT" + "ps_div %0,%1,%2" + [(set_attr "type" "sdiv")]) + +(define_insn "paired_madds0" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (vec_concat:V2SF + (plus:SF (mult:SF (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f") + (parallel [(const_int 0)])) + (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f") + (parallel [(const_int 0)]))) + (vec_select:SF (match_operand:V2SF 3 "gpc_reg_operand" "f") + (parallel [(const_int 0)]))) + (plus:SF (mult:SF (vec_select:SF (match_dup 1) + (parallel [(const_int 1)])) + (vec_select:SF (match_dup 2) + (parallel [(const_int 0)]))) + (vec_select:SF (match_dup 3) + (parallel [(const_int 1)])))))] + "TARGET_PAIRED_FLOAT && TARGET_FUSED_MADD" + "ps_madds0 %0,%1,%2,%3" + [(set_attr "type" "fp")]) + +(define_insn "paired_madds1" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (vec_concat:V2SF + (plus:SF (mult:SF (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f") + (parallel [(const_int 0)])) + (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f") + (parallel [(const_int 1)]))) + (vec_select:SF (match_operand:V2SF 3 "gpc_reg_operand" "f") + (parallel [(const_int 0)]))) + (plus:SF (mult:SF (vec_select:SF (match_dup 1) + (parallel [(const_int 1)])) + (vec_select:SF (match_dup 2) + (parallel [(const_int 1)]))) + (vec_select:SF (match_dup 3) + (parallel [(const_int 1)])))))] + "TARGET_PAIRED_FLOAT && TARGET_FUSED_MADD" + "ps_madds1 %0,%1,%2,%3" + [(set_attr "type" "fp")]) + +(define_insn "paired_madd" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (plus:V2SF (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f") + (match_operand:V2SF 2 "gpc_reg_operand" "f")) + (match_operand:V2SF 3 "gpc_reg_operand" "f")))] + "TARGET_PAIRED_FLOAT && TARGET_FUSED_MADD" + "ps_madd %0,%1,%2,%3" + [(set_attr "type" "fp")]) + +(define_insn "paired_msub" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (minus:V2SF (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f") + (match_operand:V2SF 2 "gpc_reg_operand" "f")) + (match_operand:V2SF 3 "gpc_reg_operand" "f")))] + "TARGET_PAIRED_FLOAT && TARGET_FUSED_MADD" + "ps_msub %0,%1,%2,%3" + [(set_attr "type" "fp")]) + +(define_insn "paired_nmadd" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (neg:V2SF (plus:V2SF (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f") + (match_operand:V2SF 2 "gpc_reg_operand" "f")) + (match_operand:V2SF 3 "gpc_reg_operand" "f"))))] + "TARGET_PAIRED_FLOAT && TARGET_FUSED_MADD + && HONOR_SIGNED_ZEROS (SFmode)" + "ps_nmadd %0,%1,%2,%3" + [(set_attr "type" "fp")]) + +(define_insn "paired_nmsub" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (neg:V2SF (minus:V2SF (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f") + (match_operand:V2SF 2 "gpc_reg_operand" "f")) + (match_operand:V2SF 3 "gpc_reg_operand" "f"))))] + "TARGET_PAIRED_FLOAT && TARGET_FUSED_MADD + && HONOR_SIGNED_ZEROS (DFmode)" + "ps_nmsub %0,%1,%2,%3" + [(set_attr "type" "dmul")]) + +(define_insn "selv2sf4" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (vec_concat:V2SF + (if_then_else:SF (ge (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f") + (parallel [(const_int 0)])) + (match_operand:SF 4 "zero_fp_constant" "F")) + (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f") + (parallel [(const_int 0)])) + (vec_select:SF (match_operand:V2SF 3 "gpc_reg_operand" "f") + (parallel [(const_int 0)]))) + (if_then_else:SF (ge (vec_select:SF (match_dup 1) + (parallel [(const_int 1)])) + (match_dup 4)) + (vec_select:SF (match_dup 2) + (parallel [(const_int 1)])) + (vec_select:SF (match_dup 3) + (parallel [(const_int 1)])))))] + + "TARGET_PAIRED_FLOAT" + "ps_sel %0,%1,%2,%3" + [(set_attr "type" "fp")]) + +(define_insn "*movv2sf_paired" + [(set (match_operand:V2SF 0 "nonimmediate_operand" "=Z,f,f,o,r,r,v") + (match_operand:V2SF 1 "input_operand" "f,Z,f,r,o,r,W"))] + "TARGET_PAIRED_FLOAT + && (register_operand (operands[0], V2SFmode) + || register_operand (operands[1], V2SFmode))" +{ + switch (which_alternative) + { + case 0: return "psq_stx %1,%y0,0,0"; + case 1: return "psq_lx %0,%y1,0,0"; + case 2: return "ps_mr %0,%1"; + case 3: return "#"; + case 4: return "#"; + case 5: return "#"; + case 6: return output_vec_const_move (operands); + default: gcc_unreachable (); + } +} + [(set_attr "type" "fpstore,fpload,fp,*,*,*,*")]) + +(define_insn "paired_stx" + [(set (match_operand:V2SF 0 "memory_operand" "=Z") + (match_operand:V2SF 1 "gpc_reg_operand" "f"))] + "TARGET_PAIRED_FLOAT" + "psq_stx %1,%y0,0,0" + [(set_attr "type" "fpstore")]) + +(define_insn "paired_lx" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (match_operand:V2SF 1 "memory_operand" "Z"))] + "TARGET_PAIRED_FLOAT" + "psq_lx %0,%y1,0,0" + [(set_attr "type" "fpload")]) + + +(define_split + [(set (match_operand:V2SF 0 "nonimmediate_operand" "") + (match_operand:V2SF 1 "input_operand" ""))] + "TARGET_PAIRED_FLOAT && reload_completed + && gpr_or_gpr_p (operands[0], operands[1])" + [(pc)] + { + rs6000_split_multireg_move (operands[0], operands[1]); DONE; + }) + +(define_insn "paired_cmpu0" + [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") + (compare:CCFP (vec_select:SF + (match_operand:V2SF 1 "gpc_reg_operand" "f") + (parallel [(const_int 0)])) + (vec_select:SF + (match_operand:V2SF 2 "gpc_reg_operand" "f") + (parallel [(const_int 0)]))))] + "TARGET_PAIRED_FLOAT" + "ps_cmpu0 %0,%1,%2" + [(set_attr "type" "fpcompare")]) + +(define_insn "paired_cmpu1" + [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") + (compare:CCFP (vec_select:SF + (match_operand:V2SF 1 "gpc_reg_operand" "f") + (parallel [(const_int 1)])) + (vec_select:SF + (match_operand:V2SF 2 "gpc_reg_operand" "f") + (parallel [(const_int 1)]))))] + "TARGET_PAIRED_FLOAT" + "ps_cmpu1 %0,%1,%2" + [(set_attr "type" "fpcompare")]) + +(define_insn "paired_merge00" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (vec_concat:V2SF + (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f") + (parallel [(const_int 0)])) + (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f") + (parallel [(const_int 0)]))))] + "TARGET_PAIRED_FLOAT" + "ps_merge00 %0, %1, %2" + [(set_attr "type" "fp")]) + +(define_insn "paired_merge01" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (vec_concat:V2SF + (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f") + (parallel [(const_int 0)])) + (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f") + (parallel [(const_int 1)]))))] + "TARGET_PAIRED_FLOAT" + "ps_merge01 %0, %1, %2" + [(set_attr "type" "fp")]) + +(define_insn "paired_merge10" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (vec_concat:V2SF + (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f") + (parallel [(const_int 1)])) + (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f") + (parallel [(const_int 0)]))))] + "TARGET_PAIRED_FLOAT" + "ps_merge10 %0, %1, %2" + [(set_attr "type" "fp")]) + +(define_insn "paired_merge11" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (vec_concat:V2SF + (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f") + (parallel [(const_int 1)])) + (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f") + (parallel [(const_int 1)]))))] + "TARGET_PAIRED_FLOAT" + "ps_merge11 %0, %1, %2" + [(set_attr "type" "fp")]) + +(define_insn "paired_sum0" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (vec_concat:V2SF (plus:SF (vec_select:SF + (match_operand:V2SF 1 "gpc_reg_operand" "f") + (parallel [(const_int 0)])) + (vec_select:SF + (match_operand:V2SF 2 "gpc_reg_operand" "f") + (parallel [(const_int 1)]))) + (vec_select:SF + (match_operand:V2SF 3 "gpc_reg_operand" "f") + (parallel [(const_int 1)]))))] + "TARGET_PAIRED_FLOAT" + "ps_sum0 %0,%1,%2,%3" + [(set_attr "type" "fp")]) + +(define_insn "paired_sum1" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (vec_concat:V2SF (vec_select:SF + (match_operand:V2SF 2 "gpc_reg_operand" "f") + (parallel [(const_int 1)])) + (plus:SF (vec_select:SF + (match_operand:V2SF 1 "gpc_reg_operand" "f") + (parallel [(const_int 0)])) + (vec_select:SF + (match_operand:V2SF 3 "gpc_reg_operand" "f") + (parallel [(const_int 1)])))))] + "TARGET_PAIRED_FLOAT" + "ps_sum1 %0,%1,%2,%3" + [(set_attr "type" "fp")]) + +(define_insn "paired_muls0" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (mult:V2SF (match_operand:V2SF 2 "gpc_reg_operand" "f") + (vec_duplicate:V2SF + (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f") + (parallel [(const_int 0)])))))] + "TARGET_PAIRED_FLOAT" + "ps_muls0 %0, %1, %2" + [(set_attr "type" "fp")]) + + +(define_insn "paired_muls1" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (mult:V2SF (match_operand:V2SF 2 "gpc_reg_operand" "f") + (vec_duplicate:V2SF + (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f") + (parallel [(const_int 1)])))))] + "TARGET_PAIRED_FLOAT" + "ps_muls1 %0, %1, %2" + [(set_attr "type" "fp")]) + + diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 010b532993e..03660b7ff07 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -815,6 +815,12 @@ static void altivec_init_builtins (void); static void rs6000_common_init_builtins (void); static void rs6000_init_libfuncs (void); +static void paired_init_builtins (void); +static rtx paired_expand_builtin (tree, rtx, bool *); +static rtx paired_expand_lv_builtin (enum insn_code, tree, rtx); +static rtx paired_expand_stv_builtin (enum insn_code, tree); +static rtx paired_expand_predicate_builtin (enum insn_code, tree, rtx); + static void enable_mask_for_builtins (struct builtin_description *, int, enum rs6000_builtins, enum rs6000_builtins); @@ -1224,12 +1230,14 @@ rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode) This excludes the 32-bit decimal float mode for now. */ if (FP_REGNO_P (regno)) return - (SCALAR_FLOAT_MODE_P (mode) + ((SCALAR_FLOAT_MODE_P (mode) && (mode != TDmode || (regno % 2) == 0) && mode != SDmode && FP_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1)) || (GET_MODE_CLASS (mode) == MODE_INT - && GET_MODE_SIZE (mode) == UNITS_PER_FP_WORD); + && GET_MODE_SIZE (mode) == UNITS_PER_FP_WORD) + || (PAIRED_SIMD_REGNO_P (regno) && TARGET_PAIRED_FLOAT + && PAIRED_VECTOR_MODE (mode))); /* The CR register can only hold CC modes. */ if (CR_REGNO_P (regno)) @@ -6594,7 +6602,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) static void def_builtin (int mask, const char *name, tree type, int code) { - if (mask & target_flags) + if ((mask & target_flags) || TARGET_PAIRED_FLOAT) { if (rs6000_builtin_decls[code]) abort (); @@ -6648,6 +6656,15 @@ static const struct builtin_description bdesc_3arg[] = { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_nmsub", ALTIVEC_BUILTIN_VEC_NMSUB }, { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_perm", ALTIVEC_BUILTIN_VEC_PERM }, { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sel", ALTIVEC_BUILTIN_VEC_SEL }, + + { 0, CODE_FOR_paired_msub, "__builtin_paired_msub", PAIRED_BUILTIN_MSUB }, + { 0, CODE_FOR_paired_madd, "__builtin_paired_madd", PAIRED_BUILTIN_MADD }, + { 0, CODE_FOR_paired_madds0, "__builtin_paired_madds0", PAIRED_BUILTIN_MADDS0 }, + { 0, CODE_FOR_paired_madds1, "__builtin_paired_madds1", PAIRED_BUILTIN_MADDS1 }, + { 0, CODE_FOR_paired_nmsub, "__builtin_paired_nmsub", PAIRED_BUILTIN_NMSUB }, + { 0, CODE_FOR_paired_nmadd, "__builtin_paired_nmadd", PAIRED_BUILTIN_NMADD }, + { 0, CODE_FOR_paired_sum0, "__builtin_paired_sum0", PAIRED_BUILTIN_SUM0 }, + { 0, CODE_FOR_paired_sum1, "__builtin_paired_sum1", PAIRED_BUILTIN_SUM1 }, }; /* DST operations: void foo (void *, const int, const char). */ @@ -6909,6 +6926,17 @@ static struct builtin_description bdesc_2arg[] = { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sums", ALTIVEC_BUILTIN_VEC_SUMS }, { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_xor", ALTIVEC_BUILTIN_VEC_XOR }, + { 0, CODE_FOR_divv2sf3, "__builtin_paired_divv2sf3", PAIRED_BUILTIN_DIVV2SF3 }, + { 0, CODE_FOR_addv2sf3, "__builtin_paired_addv2sf3", PAIRED_BUILTIN_ADDV2SF3 }, + { 0, CODE_FOR_subv2sf3, "__builtin_paired_subv2sf3", PAIRED_BUILTIN_SUBV2SF3 }, + { 0, CODE_FOR_mulv2sf3, "__builtin_paired_mulv2sf3", PAIRED_BUILTIN_MULV2SF3 }, + { 0, CODE_FOR_paired_muls0, "__builtin_paired_muls0", PAIRED_BUILTIN_MULS0 }, + { 0, CODE_FOR_paired_muls1, "__builtin_paired_muls1", PAIRED_BUILTIN_MULS1 }, + { 0, CODE_FOR_paired_merge00, "__builtin_paired_merge00", PAIRED_BUILTIN_MERGE00 }, + { 0, CODE_FOR_paired_merge01, "__builtin_paired_merge01", PAIRED_BUILTIN_MERGE01 }, + { 0, CODE_FOR_paired_merge10, "__builtin_paired_merge10", PAIRED_BUILTIN_MERGE10 }, + { 0, CODE_FOR_paired_merge11, "__builtin_paired_merge11", PAIRED_BUILTIN_MERGE11 }, + /* Place holder, leave as first spe builtin. */ { 0, CODE_FOR_spe_evaddw, "__builtin_spe_evaddw", SPE_BUILTIN_EVADDW }, { 0, CODE_FOR_spe_evand, "__builtin_spe_evand", SPE_BUILTIN_EVAND }, @@ -7122,6 +7150,15 @@ static struct builtin_description bdesc_spe_evsel[] = { 0, CODE_FOR_spe_evfststeq, "__builtin_spe_evsel_fststeq", SPE_BUILTIN_EVSEL_FSTSTEQ }, }; +/* PAIRED predicates. */ +static const struct builtin_description bdesc_paired_preds[] = +{ + /* Place-holder. Leave as first. */ + { 0, CODE_FOR_paired_cmpu0, "__builtin_paired_cmpu0", PAIRED_BUILTIN_CMPU0 }, + /* Place-holder. Leave as last. */ + { 0, CODE_FOR_paired_cmpu1, "__builtin_paired_cmpu1", PAIRED_BUILTIN_CMPU1 }, +}; + /* ABS* operations. */ static const struct builtin_description bdesc_abs[] = @@ -7210,7 +7247,13 @@ static struct builtin_description bdesc_1arg[] = { 0, CODE_FOR_spe_evsubfumiaaw, "__builtin_spe_evsubfumiaaw", SPE_BUILTIN_EVSUBFUMIAAW }, /* Place-holder. Leave as last unary SPE builtin. */ - { 0, CODE_FOR_spe_evsubfusiaaw, "__builtin_spe_evsubfusiaaw", SPE_BUILTIN_EVSUBFUSIAAW } + { 0, CODE_FOR_spe_evsubfusiaaw, "__builtin_spe_evsubfusiaaw", SPE_BUILTIN_EVSUBFUSIAAW }, + + { 0, CODE_FOR_absv2sf2, "__builtin_paired_absv2sf2", PAIRED_BUILTIN_ABSV2SF2 }, + { 0, CODE_FOR_nabsv2sf2, "__builtin_paired_nabsv2sf2", PAIRED_BUILTIN_NABSV2SF2 }, + { 0, CODE_FOR_negv2sf2, "__builtin_paired_negv2sf2", PAIRED_BUILTIN_NEGV2SF2 }, + { 0, CODE_FOR_sqrtv2sf2, "__builtin_paired_sqrtv2sf2", PAIRED_BUILTIN_SQRTV2SF2 }, + { 0, CODE_FOR_resv2sf2, "__builtin_paired_resv2sf2", PAIRED_BUILTIN_RESV2SF2 } }; static rtx @@ -7445,6 +7488,52 @@ altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode, } static rtx +paired_expand_lv_builtin (enum insn_code icode, tree exp, rtx target) +{ + rtx pat, addr; + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); + enum machine_mode tmode = insn_data[icode].operand[0].mode; + enum machine_mode mode0 = Pmode; + enum machine_mode mode1 = Pmode; + rtx op0 = expand_normal (arg0); + rtx op1 = expand_normal (arg1); + + if (icode == CODE_FOR_nothing) + /* Builtin not supported on this processor. */ + return 0; + + /* If we got invalid arguments bail out before generating bad rtl. */ + if (arg0 == error_mark_node || arg1 == error_mark_node) + return const0_rtx; + + if (target == 0 + || GET_MODE (target) != tmode + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + op1 = copy_to_mode_reg (mode1, op1); + + if (op0 == const0_rtx) + { + addr = gen_rtx_MEM (tmode, op1); + } + else + { + op0 = copy_to_mode_reg (mode0, op0); + addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op0, op1)); + } + + pat = GEN_FCN (icode) (target, addr); + + if (! pat) + return 0; + emit_insn (pat); + + return target; +} + +static rtx altivec_expand_lv_builtin (enum insn_code icode, tree exp, rtx target) { rtx pat, addr; @@ -7524,6 +7613,47 @@ spe_expand_stv_builtin (enum insn_code icode, tree exp) } static rtx +paired_expand_stv_builtin (enum insn_code icode, tree exp) +{ + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); + tree arg2 = CALL_EXPR_ARG (exp, 2); + rtx op0 = expand_normal (arg0); + rtx op1 = expand_normal (arg1); + rtx op2 = expand_normal (arg2); + rtx pat, addr; + enum machine_mode tmode = insn_data[icode].operand[0].mode; + enum machine_mode mode1 = Pmode; + enum machine_mode mode2 = Pmode; + + /* Invalid arguments. Bail before doing anything stoopid! */ + if (arg0 == error_mark_node + || arg1 == error_mark_node + || arg2 == error_mark_node) + return const0_rtx; + + if (! (*insn_data[icode].operand[1].predicate) (op0, tmode)) + op0 = copy_to_mode_reg (tmode, op0); + + op2 = copy_to_mode_reg (mode2, op2); + + if (op1 == const0_rtx) + { + addr = gen_rtx_MEM (tmode, op2); + } + else + { + op1 = copy_to_mode_reg (mode1, op1); + addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op1, op2)); + } + + pat = GEN_FCN (icode) (addr, op0); + if (pat) + emit_insn (pat); + return NULL_RTX; +} + +static rtx altivec_expand_stv_builtin (enum insn_code icode, tree exp) { tree arg0 = CALL_EXPR_ARG (exp, 0); @@ -8071,6 +8201,39 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp) return NULL_RTX; } +/* Expand the builtin in EXP and store the result in TARGET. Store + true in *EXPANDEDP if we found a builtin to expand. */ +static rtx +paired_expand_builtin (tree exp, rtx target, bool * expandedp) +{ + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); + unsigned int fcode = DECL_FUNCTION_CODE (fndecl); + struct builtin_description *d; + size_t i; + + *expandedp = true; + + switch (fcode) + { + case PAIRED_BUILTIN_STX: + return paired_expand_stv_builtin (CODE_FOR_paired_stx, exp); + case PAIRED_BUILTIN_LX: + return paired_expand_lv_builtin (CODE_FOR_paired_lx, exp, target); + default: + break; + /* Fall through. */ + } + + /* Expand the paired predicates. */ + d = (struct builtin_description *) bdesc_paired_preds; + for (i = 0; i < ARRAY_SIZE (bdesc_paired_preds); i++, d++) + if (d->code == fcode) + return paired_expand_predicate_builtin (d->icode, exp, target); + + *expandedp = false; + return NULL_RTX; +} + /* Binops that need to be initialized manually, but can be expanded automagically by rs6000_expand_binop_builtin. */ static struct builtin_description bdesc_2arg_spe[] = @@ -8237,6 +8400,78 @@ spe_expand_builtin (tree exp, rtx target, bool *expandedp) } static rtx +paired_expand_predicate_builtin (enum insn_code icode, tree exp, rtx target) +{ + rtx pat, scratch, tmp; + tree form = CALL_EXPR_ARG (exp, 0); + tree arg0 = CALL_EXPR_ARG (exp, 1); + tree arg1 = CALL_EXPR_ARG (exp, 2); + rtx op0 = expand_normal (arg0); + rtx op1 = expand_normal (arg1); + enum machine_mode mode0 = insn_data[icode].operand[1].mode; + enum machine_mode mode1 = insn_data[icode].operand[2].mode; + int form_int; + enum rtx_code code; + + if (TREE_CODE (form) != INTEGER_CST) + { + error ("argument 1 of __builtin_paired_predicate must be a constant"); + return const0_rtx; + } + else + form_int = TREE_INT_CST_LOW (form); + + gcc_assert (mode0 == mode1); + + if (arg0 == error_mark_node || arg1 == error_mark_node) + return const0_rtx; + + if (target == 0 + || GET_MODE (target) != SImode + || !(*insn_data[icode].operand[0].predicate) (target, SImode)) + target = gen_reg_rtx (SImode); + if (!(*insn_data[icode].operand[1].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + if (!(*insn_data[icode].operand[2].predicate) (op1, mode1)) + op1 = copy_to_mode_reg (mode1, op1); + + scratch = gen_reg_rtx (CCFPmode); + + pat = GEN_FCN (icode) (scratch, op0, op1); + if (!pat) + return const0_rtx; + + emit_insn (pat); + + switch (form_int) + { + /* LT bit. */ + case 0: + code = LT; + break; + /* GT bit. */ + case 1: + code = GT; + break; + /* EQ bit. */ + case 2: + code = EQ; + break; + /* UN bit. */ + case 3: + emit_insn (gen_move_from_CR_ov_bit (target, scratch)); + return target; + default: + error ("argument 1 of __builtin_paired_predicate is out of range"); + return const0_rtx; + } + + tmp = gen_rtx_fmt_ee (code, SImode, scratch, const0_rtx); + emit_move_insn (target, tmp); + return target; +} + +static rtx spe_expand_predicate_builtin (enum insn_code icode, tree exp, rtx target) { rtx pat, scratch, tmp; @@ -8476,8 +8711,15 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, if (success) return ret; } + if (TARGET_PAIRED_FLOAT) + { + ret = paired_expand_builtin (exp, target, &success); + + if (success) + return ret; + } - gcc_assert (TARGET_ALTIVEC || TARGET_SPE); + gcc_assert (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT); /* Handle simple unary operations. */ d = (struct builtin_description *) bdesc_1arg; @@ -8603,11 +8845,13 @@ rs6000_init_builtins (void) get_identifier ("__vector __pixel"), pixel_V8HI_type_node)); + if (TARGET_PAIRED_FLOAT) + paired_init_builtins (); if (TARGET_SPE) spe_init_builtins (); if (TARGET_ALTIVEC) altivec_init_builtins (); - if (TARGET_ALTIVEC || TARGET_SPE) + if (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT) rs6000_common_init_builtins (); #if TARGET_XCOFF @@ -8865,6 +9109,62 @@ spe_init_builtins (void) } static void +paired_init_builtins (void) +{ + struct builtin_description *d; + size_t i; + tree endlink = void_list_node; + + tree int_ftype_int_v2sf_v2sf + = build_function_type + (integer_type_node, + tree_cons (NULL_TREE, integer_type_node, + tree_cons (NULL_TREE, V2SF_type_node, + tree_cons (NULL_TREE, V2SF_type_node, + endlink)))); + tree pcfloat_type_node = + build_pointer_type (build_qualified_type + (float_type_node, TYPE_QUAL_CONST)); + + tree v2sf_ftype_long_pcfloat = build_function_type_list (V2SF_type_node, + long_integer_type_node, + pcfloat_type_node, + NULL_TREE); + tree void_ftype_v2sf_long_pcfloat = + build_function_type_list (void_type_node, + V2SF_type_node, + long_integer_type_node, + pcfloat_type_node, + NULL_TREE); + + + def_builtin (0, "__builtin_paired_lx", v2sf_ftype_long_pcfloat, + PAIRED_BUILTIN_LX); + + + def_builtin (0, "__builtin_paired_stx", void_ftype_v2sf_long_pcfloat, + PAIRED_BUILTIN_STX); + + /* Predicates. */ + d = (struct builtin_description *) bdesc_paired_preds; + for (i = 0; i < ARRAY_SIZE (bdesc_paired_preds); ++i, d++) + { + tree type; + + switch (insn_data[d->icode].operand[1].mode) + { + case V2SFmode: + type = int_ftype_int_v2sf_v2sf; + break; + default: + gcc_unreachable (); + } + + def_builtin (d->mask, d->name, type, d->code); + } +} + +static void altivec_init_builtins (void) { const struct builtin_description *d; @@ -9226,6 +9526,11 @@ rs6000_common_init_builtins (void) const struct builtin_description *d; size_t i; + tree v2sf_ftype_v2sf_v2sf_v2sf + = build_function_type_list (V2SF_type_node, + V2SF_type_node, V2SF_type_node, + V2SF_type_node, NULL_TREE); + tree v4sf_ftype_v4sf_v4sf_v16qi = build_function_type_list (V4SF_type_node, V4SF_type_node, V4SF_type_node, @@ -9258,11 +9563,17 @@ rs6000_common_init_builtins (void) opaque_V2SI_type_node, opaque_V2SI_type_node, NULL_TREE); - tree v2sf_ftype_v2sf_v2sf + tree v2sf_ftype_v2sf_v2sf_spe = build_function_type_list (opaque_V2SF_type_node, opaque_V2SF_type_node, opaque_V2SF_type_node, NULL_TREE); + tree v2sf_ftype_v2sf_v2sf + = build_function_type_list (V2SF_type_node, + V2SF_type_node, + V2SF_type_node, NULL_TREE); + + tree v2si_ftype_int_int = build_function_type_list (opaque_V2SI_type_node, integer_type_node, integer_type_node, @@ -9276,10 +9587,14 @@ rs6000_common_init_builtins (void) = build_function_type_list (opaque_V2SI_type_node, opaque_V2SI_type_node, NULL_TREE); - tree v2sf_ftype_v2sf + tree v2sf_ftype_v2sf_spe = build_function_type_list (opaque_V2SF_type_node, opaque_V2SF_type_node, NULL_TREE); + tree v2sf_ftype_v2sf + = build_function_type_list (V2SF_type_node, + V2SF_type_node, NULL_TREE); + tree v2sf_ftype_v2si = build_function_type_list (opaque_V2SF_type_node, opaque_V2SI_type_node, NULL_TREE); @@ -9466,6 +9781,9 @@ rs6000_common_init_builtins (void) case V16QImode: type = v16qi_ftype_v16qi_v16qi_v16qi; break; + case V2SFmode: + type = v2sf_ftype_v2sf_v2sf_v2sf; + break; default: gcc_unreachable (); } @@ -9574,8 +9892,11 @@ rs6000_common_init_builtins (void) case V2SImode: type = v2si_ftype_v2si_v2si; break; - case V2SFmode: - type = v2sf_ftype_v2sf_v2sf; + case V2SFmode: + if (TARGET_PAIRED_FLOAT) + type = v2sf_ftype_v2sf_v2sf; + else + type = v2sf_ftype_v2sf_v2sf_spe; break; case SImode: type = int_ftype_int_int; @@ -9714,7 +10035,12 @@ rs6000_common_init_builtins (void) else if (mode0 == V2SImode && mode1 == V2SImode) type = v2si_ftype_v2si; else if (mode0 == V2SFmode && mode1 == V2SFmode) - type = v2sf_ftype_v2sf; + { + if (TARGET_PAIRED_FLOAT) + type = v2sf_ftype_v2sf; + else + type = v2sf_ftype_v2sf_spe; + } else if (mode0 == V2SFmode && mode1 == V2SImode) type = v2sf_ftype_v2si; else if (mode0 == V2SImode && mode1 == V2SFmode) @@ -21094,6 +21420,9 @@ static bool rs6000_vector_mode_supported_p (enum machine_mode mode) { + if (TARGET_PAIRED_FLOAT && PAIRED_VECTOR_MODE (mode)) + return true; + if (TARGET_SPE && SPE_VECTOR_MODE (mode)) return true; diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 4ba955f4c82..b7dced33aad 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -56,6 +56,10 @@ #define PPC405_ERRATUM77 0 #endif +#ifndef TARGET_PAIRED_FLOAT +#define TARGET_PAIRED_FLOAT 0 +#endif + /* Common ASM definitions used by ASM_SPEC among the various targets for handling -mcpu=xxx switches. */ #define ASM_CPU_SPEC \ @@ -472,6 +476,7 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops; #define UNITS_PER_FP_WORD 8 #define UNITS_PER_ALTIVEC_WORD 16 #define UNITS_PER_SPE_WORD 8 +#define UNITS_PER_PAIRED_WORD 8 /* Type used for ptrdiff_t, as a string used in a declaration. */ #define PTRDIFF_TYPE "int" @@ -555,8 +560,10 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops; #define LOCAL_ALIGNMENT(TYPE, ALIGN) \ ((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \ (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 : \ - (TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \ - && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) ? 64 : ALIGN) + ((TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \ + && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) || (TARGET_PAIRED_FLOAT \ + && TREE_CODE (TYPE) == VECTOR_TYPE \ + && PAIRED_VECTOR_MODE (TYPE_MODE (TYPE)))) ? 64 : ALIGN) /* Alignment of field after `int : 0' in a structure. */ #define EMPTY_FIELD_BOUNDARY 32 @@ -595,7 +602,8 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops; Align vectors to 128 bits. Align SPE vectors and E500 v2 doubles to 64 bits. */ #define DATA_ALIGNMENT(TYPE, ALIGN) \ - (TREE_CODE (TYPE) == VECTOR_TYPE ? (TARGET_SPE_ABI ? 64 : 128) \ + (TREE_CODE (TYPE) == VECTOR_TYPE ? ((TARGET_SPE_ABI \ + || TARGET_PAIRED_FLOAT) ? 64 : 128) \ : (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 \ : TREE_CODE (TYPE) == ARRAY_TYPE \ && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ @@ -831,6 +839,9 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops; /* SPE SIMD registers are just the GPRs. */ #define SPE_SIMD_REGNO_P(N) ((N) <= 31) +/* PAIRED SIMD registers are just the FPRs. */ +#define PAIRED_SIMD_REGNO_P(N) ((N) >= 32 && (N) <= 63) + /* True if register is the XER register. */ #define XER_REGNO_P(N) ((N) == XER_REGNO) @@ -859,9 +870,13 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops; || (MODE) == V1DImode \ || (MODE) == V2SImode) -#define UNITS_PER_SIMD_WORD \ - (TARGET_ALTIVEC ? UNITS_PER_ALTIVEC_WORD \ - : (TARGET_SPE ? UNITS_PER_SPE_WORD : UNITS_PER_WORD)) +#define PAIRED_VECTOR_MODE(MODE) \ + ((MODE) == V2SFmode) + +#define UNITS_PER_SIMD_WORD \ + (TARGET_ALTIVEC ? UNITS_PER_ALTIVEC_WORD \ + : (TARGET_SPE ? UNITS_PER_SPE_WORD : (TARGET_PAIRED_FLOAT ? \ + UNITS_PER_PAIRED_WORD : UNITS_PER_WORD))) /* Value is TRUE if hard register REGNO can hold a value of machine-mode MODE. */ @@ -2949,6 +2964,35 @@ enum rs6000_builtins SPE_BUILTIN_MFSPEFSCR, SPE_BUILTIN_BRINC, + /* PAIRED builtins. */ + PAIRED_BUILTIN_DIVV2SF3, + PAIRED_BUILTIN_ABSV2SF2, + PAIRED_BUILTIN_NEGV2SF2, + PAIRED_BUILTIN_SQRTV2SF2, + PAIRED_BUILTIN_ADDV2SF3, + PAIRED_BUILTIN_SUBV2SF3, + PAIRED_BUILTIN_RESV2SF2, + PAIRED_BUILTIN_MULV2SF3, + PAIRED_BUILTIN_MSUB, + PAIRED_BUILTIN_MADD, + PAIRED_BUILTIN_NMSUB, + PAIRED_BUILTIN_NMADD, + PAIRED_BUILTIN_NABSV2SF2, + PAIRED_BUILTIN_SUM0, + PAIRED_BUILTIN_SUM1, + PAIRED_BUILTIN_MULS0, + PAIRED_BUILTIN_MULS1, + PAIRED_BUILTIN_MERGE00, + PAIRED_BUILTIN_MERGE01, + PAIRED_BUILTIN_MERGE10, + PAIRED_BUILTIN_MERGE11, + PAIRED_BUILTIN_MADDS0, + PAIRED_BUILTIN_MADDS1, + PAIRED_BUILTIN_STX, + PAIRED_BUILTIN_LX, + PAIRED_BUILTIN_CMPU0, + PAIRED_BUILTIN_CMPU1, + RS6000_BUILTIN_COUNT }; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 4bc71128278..e3505d1e5ae 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -14568,3 +14568,4 @@ (include "altivec.md") (include "spe.md") (include "dfp.md") +(include "paired.md") diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index cfa123ab4b0..49800633935 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -201,6 +201,10 @@ mspe Target Var(rs6000_spe) Generate SPE SIMD instructions on E500 +mpaired +Target Var(rs6000_paired_float) +Generate PPC750CL paired-single instructions + mspe= Target RejectNegative Joined -mspe=yes/no Deprecated option. Use -mspe/-mno-spe instead diff --git a/gcc/config/rs6000/spe.md b/gcc/config/rs6000/spe.md index b7b2fef8eab..1b66343bab2 100644 --- a/gcc/config/rs6000/spe.md +++ b/gcc/config/rs6000/spe.md @@ -2678,7 +2678,7 @@ (define_expand "movv2sf" [(set (match_operand:V2SF 0 "nonimmediate_operand" "") (match_operand:V2SF 1 "any_operand" ""))] - "TARGET_SPE" + "TARGET_SPE || TARGET_PAIRED_FLOAT" "{ rs6000_emit_move (operands[0], operands[1], V2SFmode); DONE; }") (define_insn "*movv2sf_internal" diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 1646df305cb..61b7f72493d 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -704,6 +704,7 @@ See RS/6000 and PowerPC Options. -misel=yes -misel=no @gol -mspe -mno-spe @gol -mspe=yes -mspe=no @gol +-mpaired @gol -mvrsave -mno-vrsave @gol -mmulhw -mno-mulhw @gol -mdlmzb -mno-dlmzb @gol @@ -12582,6 +12583,13 @@ This switch has been deprecated. Use @option{-misel} and This switch enables or disables the generation of SPE simd instructions. +@item -mpaired +@itemx -mno-paired +@opindex mpaired +@opindex mno-paired +This switch enables or disables the generation of PAIRED simd +instructions. + @item -mspe=@var{yes/no} This option has been deprecated. Use @option{-mspe} and @option{-mno-spe} instead. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 80f20333b70..f3d9fd7a417 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2007-08-31 David Edelsohn <edelsohn@gnu.org> + Revital Eres <eres@il.ibm.com> + + * gcc.target/powerpc/paired-1.c: New test. + * gcc.target/powerpc/paired-2.c: New test. + * gcc.target/powerpc/paired-3.c: New test. + * gcc.target/powerpc/paired-4.c: New test. + * gcc.target/powerpc/paired-5.c: New test. + * gcc.target/powerpc/paired-6.c: New test. + * gcc.target/powerpc/paired-7.c: New test. + * gcc.target/powerpc/ppc-paired.c: New test. + 2007-08-30 Ollie Wild <aaw@google.com> g++.dg/conversion/ptrmem2.C: New test. diff --git a/gcc/testsuite/gcc.target/powerpc/paired-1.c b/gcc/testsuite/gcc.target/powerpc/paired-1.c new file mode 100644 index 00000000000..641a8e022f8 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/paired-1.c @@ -0,0 +1,33 @@ +/* { dg-do compile { target powerpc-*-linux*paired* } } */ +/* { dg-options "-mpaired -m32 -ffinite-math-only " } */ + +/* Test PowerPC PAIRED extensions. */ + +#include <paired.h> + +static float in1[2] __attribute__ ((aligned (8))) = +{6.0, 7.0}; +static float in2[2] __attribute__ ((aligned (8))) = +{4.0, 3.0}; + +static float out[2] __attribute__ ((aligned (8))); + +vector float a, b, c, d; +void +test_api () +{ + b = paired_lx (0, in1); + c = paired_lx (0, in2); + + a = paired_sub (b, c); + + paired_stx (a, 0, out); +} + +int +main () +{ + test_api (); + return (0); +} + diff --git a/gcc/testsuite/gcc.target/powerpc/paired-2.c b/gcc/testsuite/gcc.target/powerpc/paired-2.c new file mode 100644 index 00000000000..ef409027fd2 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/paired-2.c @@ -0,0 +1,35 @@ +/* { dg-do compile { target powerpc-*-linux*paired* } } */ +/* { dg-options "-mpaired -m32 -ffinite-math-only" } */ + +/* Test PowerPC PAIRED extensions. */ + +#include <paired.h> +#include <stdlib.h> + +static float out[2] __attribute__ ((aligned (8))); + +vector float b = { 3.0, 8.0 }; +vector float c = { 3.0, 5.0 }; + +vector float a = { 0.0, 0.0 }; +void +test_api () +{ + + if (paired_cmpu0_eq (b, c)) + { + a = paired_sub (b, c); + paired_stx (a, 0, out); + } + + if ((out[1]) != 3.0) + abort (); +} + +int +main () +{ + test_api (); + return (0); +} + diff --git a/gcc/testsuite/gcc.target/powerpc/paired-3.c b/gcc/testsuite/gcc.target/powerpc/paired-3.c new file mode 100644 index 00000000000..756d6e111fc --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/paired-3.c @@ -0,0 +1,34 @@ +/* { dg-do compile { target powerpc-*-linux*paired* } } */ +/* { dg-options "-mpaired -m32 -ffinite-math-only" } */ + +/* Test PowerPC PAIRED extensions. */ + +#include <paired.h> +#include <stdlib.h> + +static float out[2] __attribute__ ((aligned (8))); + +vector float b = { 2.0, 8.0 }; +vector float c = { 3.0, 5.0 }; + +vector float a = { 0.0, 0.0 }; +void +test_api () +{ + + if (paired_cmpu0_lt (b, c)) + { + a = paired_add (b, c); + paired_stx (a, 0, out); + } + if ((out[0] != 5.0) || (out[1] != 13.0)) + abort (); +} + +int +main () +{ + test_api (); + return (0); +} + diff --git a/gcc/testsuite/gcc.target/powerpc/paired-4.c b/gcc/testsuite/gcc.target/powerpc/paired-4.c new file mode 100644 index 00000000000..3d5c1549bc0 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/paired-4.c @@ -0,0 +1,34 @@ +/* { dg-do compile { target powerpc-*-linux*paired* } } */ +/* { dg-options "-mpaired -m32 -ffinite-math-only" } */ + +/* Test PowerPC PAIRED extensions. */ + +#include <paired.h> +#include <stdlib.h> + +static float out[2] __attribute__ ((aligned (8))); + +vector float b = { 3.0, 8.0 }; +vector float c = { 2.0, 5.0 }; + +vector float a = { 0.0, 0.0 }; +void +test_api () +{ + + if (paired_cmpu0_gt (b, c)) + { + a = paired_add (b, c); + paired_stx (a, 0, out); + } + if ((out[0] != 5.0) || (out[1] != 13.0)) + abort (); +} + +int +main () +{ + test_api (); + return (0); +} + diff --git a/gcc/testsuite/gcc.target/powerpc/paired-5.c b/gcc/testsuite/gcc.target/powerpc/paired-5.c new file mode 100644 index 00000000000..df3bb444184 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/paired-5.c @@ -0,0 +1,34 @@ +/* { dg-do compile { target powerpc-*-linux*paired* } } */ +/* { dg-options "-mpaired -m32 -ffinite-math-only" } */ + +/* Test PowerPC PAIRED extensions. */ + +#include <paired.h> +#include <stdlib.h> + +static float out[2] __attribute__ ((aligned (8))); + +vector float b = { 3.0, 5.0 }; +vector float c = { 2.0, 5.0 }; + +vector float a = { 0.0, 0.0 }; +void +test_api () +{ + + if (paired_cmpu1_eq (b, c)) + { + a = paired_add (b, c); + paired_stx (a, 0, out); + } + if ((out[0] != 5.0) || (out[1] != 10.0)) + abort (); +} + +int +main () +{ + test_api (); + return (0); +} + diff --git a/gcc/testsuite/gcc.target/powerpc/paired-6.c b/gcc/testsuite/gcc.target/powerpc/paired-6.c new file mode 100644 index 00000000000..0d6ab52e9a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/paired-6.c @@ -0,0 +1,34 @@ +/* { dg-do compile { target powerpc-*-linux*paired* } } */ +/* { dg-options "-mpaired -m32 -ffinite-math-only" } */ + +/* Test PowerPC PAIRED extensions. */ + +#include <paired.h> +#include <stdlib.h> + +static float out[2] __attribute__ ((aligned (8))); + +vector float b = { 3.0, 5.0 }; +vector float c = { 2.0, 6.0 }; + +vector float a = { 0.0, 0.0 }; +void +test_api () +{ + + if (paired_cmpu1_lt (b, c)) + { + a = paired_add (b, c); + paired_stx (a, 0, out); + } + if ((out[0] != 5.0) || (out[1] != 11.0)) + abort (); +} + +int +main () +{ + test_api (); + return (0); +} + diff --git a/gcc/testsuite/gcc.target/powerpc/paired-7.c b/gcc/testsuite/gcc.target/powerpc/paired-7.c new file mode 100644 index 00000000000..aa1edd033c0 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/paired-7.c @@ -0,0 +1,34 @@ +/* { dg-do compile { target powerpc-*-linux*paired* } } */ +/* { dg-options "-mpaired -m32 -ffinite-math-only" } */ + +/* Test PowerPC PAIRED extensions. */ + +#include <paired.h> +#include <stdlib.h> + +static float out[2] __attribute__ ((aligned (8))); + +vector float b = { 2.0, 8.0 }; +vector float c = { 3.0, 6.0 }; + +vector float a = { 0.0, 0.0 }; +void +test_api () +{ + + if (paired_cmpu1_gt (b, c)) + { + a = paired_add (b, c); + paired_stx (a, 0, out); + } + if ((out[0] != 5.0) || (out[1] != 14.0)) + abort (); +} + +int +main () +{ + test_api (); + return (0); +} + diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-paired.c b/gcc/testsuite/gcc.target/powerpc/ppc-paired.c new file mode 100644 index 00000000000..f6f3b6e5bab --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/ppc-paired.c @@ -0,0 +1,44 @@ +/* { dg-do compile { target powerpc-*-linux*paired* } } */ +/* { dg-options "-mpaired -m32 -ffinite-math-only" } */ + +/* Test PowerPC PAIRED extensions. */ + +#include <paired.h> + +vector float a, b, c, d; + +void +test_api () +{ + b = paired_msub (b, c, d); + b = paired_madd (b, c, d); + b = paired_nmadd (b, c, d); + b = paired_nmsub (b, c, d); + b = paired_sum0 (a, b, c); + b = paired_sum1 (a, b, c); + b = paired_div (b, c); + b = paired_add (a, c); + b = paired_sub (a, c); + b = paired_mul (a, c); + b = paired_neg (a); + b = paired_muls0 (a, c); + b = paired_muls1 (a, c); + b = paired_madds0 (a, c, d); + b = paired_madds1 (a, c, d); + b = paired_merge00 (a, c); + b = paired_merge01 (a, c); + b = paired_merge10 (a, c); + b = paired_merge11 (a, c); + b = paired_abs (a); + b = paired_nabs (a); + b = paired_sqrt (a); + b = paired_res (a); +} + +int +main (void) +{ + test_api (); + return 0; +} + |