Commit 96038623 by David Edelsohn Committed by Revital Eres

Support for PowerPC 750CL paired-single instructions

Co-Authored-By: Revital Eres <eres@il.ibm.com>

From-SVN: r127954
parent 6e03b280
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> 2007-08-30 Ollie Wild <aaw@google.com>
* c-opts.c (c_common_handle_option): Support -fno-directives-only. * c-opts.c (c_common_handle_option): Support -fno-directives-only.
......
...@@ -312,7 +312,7 @@ mips*-*-*) ...@@ -312,7 +312,7 @@ mips*-*-*)
;; ;;
powerpc*-*-*) powerpc*-*-*)
cpu_type=rs6000 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 need_64bit_hwint=yes
case x$with_cpu in case x$with_cpu in
xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[3456]|xpower6x|xrs64a) xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[3456]|xpower6x|xrs64a)
...@@ -1936,6 +1936,11 @@ powerpc-*-linux*spe*) ...@@ -1936,6 +1936,11 @@ powerpc-*-linux*spe*)
extra_options="${extra_options} rs6000/sysv4.opt" 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" 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*) powerpc-*-linux*)
tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h" tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h"
extra_options="${extra_options} rs6000/sysv4.opt" extra_options="${extra_options} rs6000/sysv4.opt"
......
/* 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
/* 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 */
;; 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")])
...@@ -815,6 +815,12 @@ static void altivec_init_builtins (void); ...@@ -815,6 +815,12 @@ static void altivec_init_builtins (void);
static void rs6000_common_init_builtins (void); static void rs6000_common_init_builtins (void);
static void rs6000_init_libfuncs (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, static void enable_mask_for_builtins (struct builtin_description *, int,
enum rs6000_builtins, enum rs6000_builtins,
enum rs6000_builtins); enum rs6000_builtins);
...@@ -1224,12 +1230,14 @@ rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode) ...@@ -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. */ This excludes the 32-bit decimal float mode for now. */
if (FP_REGNO_P (regno)) if (FP_REGNO_P (regno))
return return
(SCALAR_FLOAT_MODE_P (mode) ((SCALAR_FLOAT_MODE_P (mode)
&& (mode != TDmode || (regno % 2) == 0) && (mode != TDmode || (regno % 2) == 0)
&& mode != SDmode && mode != SDmode
&& FP_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1)) && FP_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1))
|| (GET_MODE_CLASS (mode) == MODE_INT || (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. */ /* The CR register can only hold CC modes. */
if (CR_REGNO_P (regno)) if (CR_REGNO_P (regno))
...@@ -6594,7 +6602,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) ...@@ -6594,7 +6602,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
static void static void
def_builtin (int mask, const char *name, tree type, int code) 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]) if (rs6000_builtin_decls[code])
abort (); abort ();
...@@ -6648,6 +6656,15 @@ static const struct builtin_description bdesc_3arg[] = ...@@ -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_nmsub", ALTIVEC_BUILTIN_VEC_NMSUB },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_perm", ALTIVEC_BUILTIN_VEC_PERM }, { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_perm", ALTIVEC_BUILTIN_VEC_PERM },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sel", ALTIVEC_BUILTIN_VEC_SEL }, { 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). */ /* DST operations: void foo (void *, const int, const char). */
...@@ -6909,6 +6926,17 @@ static struct builtin_description bdesc_2arg[] = ...@@ -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_sums", ALTIVEC_BUILTIN_VEC_SUMS },
{ MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_xor", ALTIVEC_BUILTIN_VEC_XOR }, { 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. */ /* Place holder, leave as first spe builtin. */
{ 0, CODE_FOR_spe_evaddw, "__builtin_spe_evaddw", SPE_BUILTIN_EVADDW }, { 0, CODE_FOR_spe_evaddw, "__builtin_spe_evaddw", SPE_BUILTIN_EVADDW },
{ 0, CODE_FOR_spe_evand, "__builtin_spe_evand", SPE_BUILTIN_EVAND }, { 0, CODE_FOR_spe_evand, "__builtin_spe_evand", SPE_BUILTIN_EVAND },
...@@ -7122,6 +7150,15 @@ static struct builtin_description bdesc_spe_evsel[] = ...@@ -7122,6 +7150,15 @@ static struct builtin_description bdesc_spe_evsel[] =
{ 0, CODE_FOR_spe_evfststeq, "__builtin_spe_evsel_fststeq", SPE_BUILTIN_EVSEL_FSTSTEQ }, { 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. */ /* ABS* operations. */
static const struct builtin_description bdesc_abs[] = static const struct builtin_description bdesc_abs[] =
...@@ -7210,7 +7247,13 @@ static struct builtin_description bdesc_1arg[] = ...@@ -7210,7 +7247,13 @@ static struct builtin_description bdesc_1arg[] =
{ 0, CODE_FOR_spe_evsubfumiaaw, "__builtin_spe_evsubfumiaaw", SPE_BUILTIN_EVSUBFUMIAAW }, { 0, CODE_FOR_spe_evsubfumiaaw, "__builtin_spe_evsubfumiaaw", SPE_BUILTIN_EVSUBFUMIAAW },
/* Place-holder. Leave as last unary SPE builtin. */ /* 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 static rtx
...@@ -7445,6 +7488,52 @@ altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode, ...@@ -7445,6 +7488,52 @@ altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode,
} }
static rtx 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) altivec_expand_lv_builtin (enum insn_code icode, tree exp, rtx target)
{ {
rtx pat, addr; rtx pat, addr;
...@@ -7524,6 +7613,47 @@ spe_expand_stv_builtin (enum insn_code icode, tree exp) ...@@ -7524,6 +7613,47 @@ spe_expand_stv_builtin (enum insn_code icode, tree exp)
} }
static rtx 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) altivec_expand_stv_builtin (enum insn_code icode, tree exp)
{ {
tree arg0 = CALL_EXPR_ARG (exp, 0); tree arg0 = CALL_EXPR_ARG (exp, 0);
...@@ -8071,6 +8201,39 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp) ...@@ -8071,6 +8201,39 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
return NULL_RTX; 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 /* Binops that need to be initialized manually, but can be expanded
automagically by rs6000_expand_binop_builtin. */ automagically by rs6000_expand_binop_builtin. */
static struct builtin_description bdesc_2arg_spe[] = static struct builtin_description bdesc_2arg_spe[] =
...@@ -8237,6 +8400,78 @@ spe_expand_builtin (tree exp, rtx target, bool *expandedp) ...@@ -8237,6 +8400,78 @@ spe_expand_builtin (tree exp, rtx target, bool *expandedp)
} }
static rtx 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) spe_expand_predicate_builtin (enum insn_code icode, tree exp, rtx target)
{ {
rtx pat, scratch, tmp; rtx pat, scratch, tmp;
...@@ -8476,8 +8711,15 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, ...@@ -8476,8 +8711,15 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
if (success) if (success)
return ret; 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. */ /* Handle simple unary operations. */
d = (struct builtin_description *) bdesc_1arg; d = (struct builtin_description *) bdesc_1arg;
...@@ -8603,11 +8845,13 @@ rs6000_init_builtins (void) ...@@ -8603,11 +8845,13 @@ rs6000_init_builtins (void)
get_identifier ("__vector __pixel"), get_identifier ("__vector __pixel"),
pixel_V8HI_type_node)); pixel_V8HI_type_node));
if (TARGET_PAIRED_FLOAT)
paired_init_builtins ();
if (TARGET_SPE) if (TARGET_SPE)
spe_init_builtins (); spe_init_builtins ();
if (TARGET_ALTIVEC) if (TARGET_ALTIVEC)
altivec_init_builtins (); altivec_init_builtins ();
if (TARGET_ALTIVEC || TARGET_SPE) if (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT)
rs6000_common_init_builtins (); rs6000_common_init_builtins ();
#if TARGET_XCOFF #if TARGET_XCOFF
...@@ -8865,6 +9109,62 @@ spe_init_builtins (void) ...@@ -8865,6 +9109,62 @@ spe_init_builtins (void)
} }
static 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) altivec_init_builtins (void)
{ {
const struct builtin_description *d; const struct builtin_description *d;
...@@ -9226,6 +9526,11 @@ rs6000_common_init_builtins (void) ...@@ -9226,6 +9526,11 @@ rs6000_common_init_builtins (void)
const struct builtin_description *d; const struct builtin_description *d;
size_t i; 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 tree v4sf_ftype_v4sf_v4sf_v16qi
= build_function_type_list (V4SF_type_node, = build_function_type_list (V4SF_type_node,
V4SF_type_node, V4SF_type_node, V4SF_type_node, V4SF_type_node,
...@@ -9258,11 +9563,17 @@ rs6000_common_init_builtins (void) ...@@ -9258,11 +9563,17 @@ rs6000_common_init_builtins (void)
opaque_V2SI_type_node, opaque_V2SI_type_node,
opaque_V2SI_type_node, NULL_TREE); 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, = build_function_type_list (opaque_V2SF_type_node,
opaque_V2SF_type_node, opaque_V2SF_type_node,
opaque_V2SF_type_node, NULL_TREE); 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 tree v2si_ftype_int_int
= build_function_type_list (opaque_V2SI_type_node, = build_function_type_list (opaque_V2SI_type_node,
integer_type_node, integer_type_node, integer_type_node, integer_type_node,
...@@ -9276,10 +9587,14 @@ rs6000_common_init_builtins (void) ...@@ -9276,10 +9587,14 @@ rs6000_common_init_builtins (void)
= build_function_type_list (opaque_V2SI_type_node, = build_function_type_list (opaque_V2SI_type_node,
opaque_V2SI_type_node, NULL_TREE); opaque_V2SI_type_node, NULL_TREE);
tree v2sf_ftype_v2sf tree v2sf_ftype_v2sf_spe
= build_function_type_list (opaque_V2SF_type_node, = build_function_type_list (opaque_V2SF_type_node,
opaque_V2SF_type_node, NULL_TREE); 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 tree v2sf_ftype_v2si
= build_function_type_list (opaque_V2SF_type_node, = build_function_type_list (opaque_V2SF_type_node,
opaque_V2SI_type_node, NULL_TREE); opaque_V2SI_type_node, NULL_TREE);
...@@ -9466,6 +9781,9 @@ rs6000_common_init_builtins (void) ...@@ -9466,6 +9781,9 @@ rs6000_common_init_builtins (void)
case V16QImode: case V16QImode:
type = v16qi_ftype_v16qi_v16qi_v16qi; type = v16qi_ftype_v16qi_v16qi_v16qi;
break; break;
case V2SFmode:
type = v2sf_ftype_v2sf_v2sf_v2sf;
break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
...@@ -9575,7 +9893,10 @@ rs6000_common_init_builtins (void) ...@@ -9575,7 +9893,10 @@ rs6000_common_init_builtins (void)
type = v2si_ftype_v2si_v2si; type = v2si_ftype_v2si_v2si;
break; break;
case V2SFmode: case V2SFmode:
if (TARGET_PAIRED_FLOAT)
type = v2sf_ftype_v2sf_v2sf; type = v2sf_ftype_v2sf_v2sf;
else
type = v2sf_ftype_v2sf_v2sf_spe;
break; break;
case SImode: case SImode:
type = int_ftype_int_int; type = int_ftype_int_int;
...@@ -9714,7 +10035,12 @@ rs6000_common_init_builtins (void) ...@@ -9714,7 +10035,12 @@ rs6000_common_init_builtins (void)
else if (mode0 == V2SImode && mode1 == V2SImode) else if (mode0 == V2SImode && mode1 == V2SImode)
type = v2si_ftype_v2si; type = v2si_ftype_v2si;
else if (mode0 == V2SFmode && mode1 == V2SFmode) else if (mode0 == V2SFmode && mode1 == V2SFmode)
{
if (TARGET_PAIRED_FLOAT)
type = v2sf_ftype_v2sf; type = v2sf_ftype_v2sf;
else
type = v2sf_ftype_v2sf_spe;
}
else if (mode0 == V2SFmode && mode1 == V2SImode) else if (mode0 == V2SFmode && mode1 == V2SImode)
type = v2sf_ftype_v2si; type = v2sf_ftype_v2si;
else if (mode0 == V2SImode && mode1 == V2SFmode) else if (mode0 == V2SImode && mode1 == V2SFmode)
...@@ -21094,6 +21420,9 @@ static bool ...@@ -21094,6 +21420,9 @@ static bool
rs6000_vector_mode_supported_p (enum machine_mode mode) 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)) if (TARGET_SPE && SPE_VECTOR_MODE (mode))
return true; return true;
......
...@@ -56,6 +56,10 @@ ...@@ -56,6 +56,10 @@
#define PPC405_ERRATUM77 0 #define PPC405_ERRATUM77 0
#endif #endif
#ifndef TARGET_PAIRED_FLOAT
#define TARGET_PAIRED_FLOAT 0
#endif
/* Common ASM definitions used by ASM_SPEC among the various targets /* Common ASM definitions used by ASM_SPEC among the various targets
for handling -mcpu=xxx switches. */ for handling -mcpu=xxx switches. */
#define ASM_CPU_SPEC \ #define ASM_CPU_SPEC \
...@@ -472,6 +476,7 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops; ...@@ -472,6 +476,7 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
#define UNITS_PER_FP_WORD 8 #define UNITS_PER_FP_WORD 8
#define UNITS_PER_ALTIVEC_WORD 16 #define UNITS_PER_ALTIVEC_WORD 16
#define UNITS_PER_SPE_WORD 8 #define UNITS_PER_SPE_WORD 8
#define UNITS_PER_PAIRED_WORD 8
/* Type used for ptrdiff_t, as a string used in a declaration. */ /* Type used for ptrdiff_t, as a string used in a declaration. */
#define PTRDIFF_TYPE "int" #define PTRDIFF_TYPE "int"
...@@ -555,8 +560,10 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops; ...@@ -555,8 +560,10 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
#define LOCAL_ALIGNMENT(TYPE, ALIGN) \ #define LOCAL_ALIGNMENT(TYPE, ALIGN) \
((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \ ((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \
(TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 : \ (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 : \
(TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \ ((TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \
&& SPE_VECTOR_MODE (TYPE_MODE (TYPE))) ? 64 : ALIGN) && 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. */ /* Alignment of field after `int : 0' in a structure. */
#define EMPTY_FIELD_BOUNDARY 32 #define EMPTY_FIELD_BOUNDARY 32
...@@ -595,7 +602,8 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops; ...@@ -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 Align vectors to 128 bits. Align SPE vectors and E500 v2 doubles to
64 bits. */ 64 bits. */
#define DATA_ALIGNMENT(TYPE, ALIGN) \ #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 \ : (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 \
: TREE_CODE (TYPE) == ARRAY_TYPE \ : TREE_CODE (TYPE) == ARRAY_TYPE \
&& TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
...@@ -831,6 +839,9 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops; ...@@ -831,6 +839,9 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
/* SPE SIMD registers are just the GPRs. */ /* SPE SIMD registers are just the GPRs. */
#define SPE_SIMD_REGNO_P(N) ((N) <= 31) #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. */ /* True if register is the XER register. */
#define XER_REGNO_P(N) ((N) == XER_REGNO) #define XER_REGNO_P(N) ((N) == XER_REGNO)
...@@ -859,9 +870,13 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops; ...@@ -859,9 +870,13 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
|| (MODE) == V1DImode \ || (MODE) == V1DImode \
|| (MODE) == V2SImode) || (MODE) == V2SImode)
#define PAIRED_VECTOR_MODE(MODE) \
((MODE) == V2SFmode)
#define UNITS_PER_SIMD_WORD \ #define UNITS_PER_SIMD_WORD \
(TARGET_ALTIVEC ? UNITS_PER_ALTIVEC_WORD \ (TARGET_ALTIVEC ? UNITS_PER_ALTIVEC_WORD \
: (TARGET_SPE ? UNITS_PER_SPE_WORD : UNITS_PER_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 /* Value is TRUE if hard register REGNO can hold a value of
machine-mode MODE. */ machine-mode MODE. */
...@@ -2949,6 +2964,35 @@ enum rs6000_builtins ...@@ -2949,6 +2964,35 @@ enum rs6000_builtins
SPE_BUILTIN_MFSPEFSCR, SPE_BUILTIN_MFSPEFSCR,
SPE_BUILTIN_BRINC, 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 RS6000_BUILTIN_COUNT
}; };
......
...@@ -14568,3 +14568,4 @@ ...@@ -14568,3 +14568,4 @@
(include "altivec.md") (include "altivec.md")
(include "spe.md") (include "spe.md")
(include "dfp.md") (include "dfp.md")
(include "paired.md")
...@@ -201,6 +201,10 @@ mspe ...@@ -201,6 +201,10 @@ mspe
Target Var(rs6000_spe) Target Var(rs6000_spe)
Generate SPE SIMD instructions on E500 Generate SPE SIMD instructions on E500
mpaired
Target Var(rs6000_paired_float)
Generate PPC750CL paired-single instructions
mspe= mspe=
Target RejectNegative Joined Target RejectNegative Joined
-mspe=yes/no Deprecated option. Use -mspe/-mno-spe instead -mspe=yes/no Deprecated option. Use -mspe/-mno-spe instead
......
...@@ -2678,7 +2678,7 @@ ...@@ -2678,7 +2678,7 @@
(define_expand "movv2sf" (define_expand "movv2sf"
[(set (match_operand:V2SF 0 "nonimmediate_operand" "") [(set (match_operand:V2SF 0 "nonimmediate_operand" "")
(match_operand:V2SF 1 "any_operand" ""))] (match_operand:V2SF 1 "any_operand" ""))]
"TARGET_SPE" "TARGET_SPE || TARGET_PAIRED_FLOAT"
"{ rs6000_emit_move (operands[0], operands[1], V2SFmode); DONE; }") "{ rs6000_emit_move (operands[0], operands[1], V2SFmode); DONE; }")
(define_insn "*movv2sf_internal" (define_insn "*movv2sf_internal"
......
...@@ -704,6 +704,7 @@ See RS/6000 and PowerPC Options. ...@@ -704,6 +704,7 @@ See RS/6000 and PowerPC Options.
-misel=yes -misel=no @gol -misel=yes -misel=no @gol
-mspe -mno-spe @gol -mspe -mno-spe @gol
-mspe=yes -mspe=no @gol -mspe=yes -mspe=no @gol
-mpaired @gol
-mvrsave -mno-vrsave @gol -mvrsave -mno-vrsave @gol
-mmulhw -mno-mulhw @gol -mmulhw -mno-mulhw @gol
-mdlmzb -mno-dlmzb @gol -mdlmzb -mno-dlmzb @gol
...@@ -12582,6 +12583,13 @@ This switch has been deprecated. Use @option{-misel} and ...@@ -12582,6 +12583,13 @@ This switch has been deprecated. Use @option{-misel} and
This switch enables or disables the generation of SPE simd This switch enables or disables the generation of SPE simd
instructions. 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} @item -mspe=@var{yes/no}
This option has been deprecated. Use @option{-mspe} and This option has been deprecated. Use @option{-mspe} and
@option{-mno-spe} instead. @option{-mno-spe} instead.
......
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> 2007-08-30 Ollie Wild <aaw@google.com>
g++.dg/conversion/ptrmem2.C: New test. g++.dg/conversion/ptrmem2.C: New test.
/* { 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);
}
/* { 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);
}
/* { 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);
}
/* { 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);
}
/* { 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);
}
/* { 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);
}
/* { 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);
}
/* { 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment