aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/sparc
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-09-30 07:54:07 +0000
committerDavid S. Miller <davem@gcc.gnu.org>2011-09-30 00:54:07 -0700
commitc4728c6b20436826e469927a76fa12b89f7cf11e (patch)
treeef2752591fdb528a5b9df11ad312ebf11a2712dd /gcc/config/sparc
parent3aaedee02143cb24a313a147f787d4211844a042 (diff)
downloadgcc-c4728c6b20436826e469927a76fa12b89f7cf11e.zip
gcc-c4728c6b20436826e469927a76fa12b89f7cf11e.tar.gz
gcc-c4728c6b20436826e469927a76fa12b89f7cf11e.tar.bz2
Add sparc VIS 2.0 builtins, intrinsics, and option to control them.
gcc/ * config/sparc/sparc.opt (VIS2): New option. * doc/invoke.texi: Document it. * config/sparc/sparc.md (UNSPEC_EDGE8N, UNSPEC_EDGE8LN, UNSPEC_EDGE16N, UNSPEC_EDGE16LN, UNSPEC_EDGE32N, UNSPEC_EDGE32LN, UNSPEC_BSHUFFLE): New unspecs. (define_attr type): New insn type 'edgen'. (bmask<P:mode>_vis, bshuffle<V64I:mode>_vis, edge8n<P:mode>_vis, edge8ln<P:mode>_vis, edge16n<P:mode>_vis, edge16ln<P:mode>_vis, edge32n<P:mode>_vis, edge32ln<P:mode>_vis): New insn VIS 2.0 patterns. * niagara.md: Handle edgen. * niagara2.md: Likewise. * ultra1_2.md: Likewise. * ultra3.md: Likewise. * config/sparc/sparc-c.c (sparc_target_macros): Define __VIS__ to 0x200 when TARGET_VIS2. * config/sparc/sparc.c (sparc_option_override): Set MASK_VIS2 by default when targetting capable cpus. TARGET_VIS2 implies TARGET_VIS, clear and it when TARGET_FPU is disabled. (sparc_vis_init_builtins): Emit new VIS 2.0 builtins. (sparc_expand_builtin): Fix predicate indexing when builtin returns void. (sparc_fold_builtin): Do not eliminate bmask when result is ignored. * config/sparc/visintrin.h (__vis_bmask, __vis_bshuffledi, __vis_bshufflev2si, __vis_bshufflev4hi, __vis_bshufflev8qi, __vis_edge8n, __vis_edge8ln, __vis_edge16n, __vis_edge16ln, __vis_edge32n, __vis_edge32ln): New VIS 2.0 interfaces. * doc/extend.texi: Document new VIS 2.0 builtins. gcc/testsuite/ * gcc.target/sparc/bmaskbshuf.c: New test. * gcc.target/sparc/edgen.c: New test. From-SVN: r179376
Diffstat (limited to 'gcc/config/sparc')
-rw-r--r--gcc/config/sparc/niagara.md2
-rw-r--r--gcc/config/sparc/niagara2.md4
-rw-r--r--gcc/config/sparc/sparc-c.c7
-rw-r--r--gcc/config/sparc/sparc.c77
-rw-r--r--gcc/config/sparc/sparc.md85
-rw-r--r--gcc/config/sparc/sparc.opt6
-rw-r--r--gcc/config/sparc/ultra1_2.md2
-rw-r--r--gcc/config/sparc/ultra3.md2
-rw-r--r--gcc/config/sparc/visintrin.h77
9 files changed, 244 insertions, 18 deletions
diff --git a/gcc/config/sparc/niagara.md b/gcc/config/sparc/niagara.md
index a75088b..c7a2245 100644
--- a/gcc/config/sparc/niagara.md
+++ b/gcc/config/sparc/niagara.md
@@ -114,5 +114,5 @@
*/
(define_insn_reservation "niag_vis" 8
(and (eq_attr "cpu" "niagara")
- (eq_attr "type" "fga,fgm_pack,fgm_mul,fgm_cmp,fgm_pdist,edge,gsr,array"))
+ (eq_attr "type" "fga,fgm_pack,fgm_mul,fgm_cmp,fgm_pdist,edge,edgen,gsr,array"))
"niag_pipe*8")
diff --git a/gcc/config/sparc/niagara2.md b/gcc/config/sparc/niagara2.md
index f261ac1..fa07bec 100644
--- a/gcc/config/sparc/niagara2.md
+++ b/gcc/config/sparc/niagara2.md
@@ -111,10 +111,10 @@
(define_insn_reservation "niag2_vis" 6
(and (eq_attr "cpu" "niagara2")
- (eq_attr "type" "fga,fgm_pack,fgm_mul,fgm_cmp,fgm_pdist,edge,array,gsr"))
+ (eq_attr "type" "fga,fgm_pack,fgm_mul,fgm_cmp,fgm_pdist,edge,edgen,array,gsr"))
"niag2_pipe*6")
(define_insn_reservation "niag3_vis" 9
(and (eq_attr "cpu" "niagara3")
- (eq_attr "type" "fga,fgm_pack,fgm_mul,fgm_cmp,fgm_pdist,edge,array,gsr"))
+ (eq_attr "type" "fga,fgm_pack,fgm_mul,fgm_cmp,fgm_pdist,edge,edgen,array,gsr"))
"niag2_pipe*9")
diff --git a/gcc/config/sparc/sparc-c.c b/gcc/config/sparc/sparc-c.c
index 6e30950..0f2bee1 100644
--- a/gcc/config/sparc/sparc-c.c
+++ b/gcc/config/sparc/sparc-c.c
@@ -45,7 +45,12 @@ sparc_target_macros (void)
cpp_assert (parse_in, "machine=sparc");
}
- if (TARGET_VIS)
+ if (TARGET_VIS2)
+ {
+ cpp_define (parse_in, "__VIS__=0x200");
+ cpp_define (parse_in, "__VIS=0x200");
+ }
+ else if (TARGET_VIS)
{
cpp_define (parse_in, "__VIS__=0x100");
cpp_define (parse_in, "__VIS=0x100");
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index c8c0677..9863174 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -769,16 +769,16 @@ sparc_option_override (void)
/* UltraSPARC III */
/* ??? Check if %y issue still holds true. */
{ MASK_ISA,
- MASK_V9|MASK_DEPRECATED_V8_INSNS},
+ MASK_V9|MASK_DEPRECATED_V8_INSNS|MASK_VIS2},
/* UltraSPARC T1 */
{ MASK_ISA,
MASK_V9|MASK_DEPRECATED_V8_INSNS},
/* UltraSPARC T2 */
- { MASK_ISA, MASK_V9},
+ { MASK_ISA, MASK_V9|MASK_VIS2},
/* UltraSPARC T3 */
- { MASK_ISA, MASK_V9 | MASK_FMAF},
+ { MASK_ISA, MASK_V9|MASK_VIS2|MASK_FMAF},
/* UltraSPARC T4 */
- { MASK_ISA, MASK_V9 | MASK_FMAF},
+ { MASK_ISA, MASK_V9|MASK_VIS2|MASK_FMAF},
};
const struct cpu_table *cpu;
unsigned int i;
@@ -857,9 +857,13 @@ sparc_option_override (void)
if (target_flags_explicit & MASK_FPU)
target_flags = (target_flags & ~MASK_FPU) | fpu;
- /* Don't allow -mvis or -mfmaf if FPU is disabled. */
+ /* -mvis2 implies -mvis */
+ if (TARGET_VIS2)
+ target_flags |= MASK_VIS;
+
+ /* Don't allow -mvis, -mvis2, or -mfmaf if FPU is disabled. */
if (! TARGET_FPU)
- target_flags &= ~(MASK_VIS | MASK_FMAF);
+ target_flags &= ~(MASK_VIS | MASK_VIS2 | MASK_FMAF);
/* -mvis assumes UltraSPARC+, so we are sure v9 instructions
are available.
@@ -9300,6 +9304,21 @@ sparc_vis_init_builtins (void)
di_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge32l", CODE_FOR_edge32ldi_vis,
di_ftype_ptr_ptr);
+ if (TARGET_VIS2)
+ {
+ def_builtin_const ("__builtin_vis_edge8n", CODE_FOR_edge8ndi_vis,
+ di_ftype_ptr_ptr);
+ def_builtin_const ("__builtin_vis_edge8ln", CODE_FOR_edge8lndi_vis,
+ di_ftype_ptr_ptr);
+ def_builtin_const ("__builtin_vis_edge16n", CODE_FOR_edge16ndi_vis,
+ di_ftype_ptr_ptr);
+ def_builtin_const ("__builtin_vis_edge16ln", CODE_FOR_edge16lndi_vis,
+ di_ftype_ptr_ptr);
+ def_builtin_const ("__builtin_vis_edge32n", CODE_FOR_edge32ndi_vis,
+ di_ftype_ptr_ptr);
+ def_builtin_const ("__builtin_vis_edge32ln", CODE_FOR_edge32lndi_vis,
+ di_ftype_ptr_ptr);
+ }
}
else
{
@@ -9315,6 +9334,21 @@ sparc_vis_init_builtins (void)
si_ftype_ptr_ptr);
def_builtin_const ("__builtin_vis_edge32l", CODE_FOR_edge32lsi_vis,
si_ftype_ptr_ptr);
+ if (TARGET_VIS2)
+ {
+ def_builtin_const ("__builtin_vis_edge8n", CODE_FOR_edge8nsi_vis,
+ si_ftype_ptr_ptr);
+ def_builtin_const ("__builtin_vis_edge8ln", CODE_FOR_edge8lnsi_vis,
+ si_ftype_ptr_ptr);
+ def_builtin_const ("__builtin_vis_edge16n", CODE_FOR_edge16nsi_vis,
+ si_ftype_ptr_ptr);
+ def_builtin_const ("__builtin_vis_edge16ln", CODE_FOR_edge16lnsi_vis,
+ si_ftype_ptr_ptr);
+ def_builtin_const ("__builtin_vis_edge32n", CODE_FOR_edge32nsi_vis,
+ si_ftype_ptr_ptr);
+ def_builtin_const ("__builtin_vis_edge32ln", CODE_FOR_edge32lnsi_vis,
+ si_ftype_ptr_ptr);
+ }
}
/* Pixel compare. */
@@ -9394,6 +9428,25 @@ sparc_vis_init_builtins (void)
def_builtin_const ("__builtin_vis_array32", CODE_FOR_array32si_vis,
si_ftype_si_si);
}
+
+ if (TARGET_VIS2)
+ {
+ /* Byte mask and shuffle */
+ if (TARGET_ARCH64)
+ def_builtin ("__builtin_vis_bmask", CODE_FOR_bmaskdi_vis,
+ di_ftype_di_di);
+ else
+ def_builtin ("__builtin_vis_bmask", CODE_FOR_bmasksi_vis,
+ si_ftype_si_si);
+ def_builtin ("__builtin_vis_bshufflev4hi", CODE_FOR_bshufflev4hi_vis,
+ v4hi_ftype_v4hi_v4hi);
+ def_builtin ("__builtin_vis_bshufflev8qi", CODE_FOR_bshufflev8qi_vis,
+ v8qi_ftype_v8qi_v8qi);
+ def_builtin ("__builtin_vis_bshufflev2si", CODE_FOR_bshufflev2si_vis,
+ v2si_ftype_v2si_v2si);
+ def_builtin ("__builtin_vis_bshuffledi", CODE_FOR_bshuffledi_vis,
+ di_ftype_di_di);
+ }
}
/* Handle TARGET_EXPAND_BUILTIN target hook.
@@ -9428,16 +9481,18 @@ sparc_expand_builtin (tree exp, rtx target,
FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
{
const struct insn_operand_data *insn_op;
+ int idx;
if (arg == error_mark_node)
return NULL_RTX;
arg_count++;
- insn_op = &insn_data[icode].operand[arg_count - !nonvoid];
+ idx = arg_count - !nonvoid;
+ insn_op = &insn_data[icode].operand[idx];
op[arg_count] = expand_normal (arg);
- if (! (*insn_data[icode].operand[arg_count].predicate) (op[arg_count],
- insn_op->mode))
+ if (! (*insn_data[icode].operand[idx].predicate) (op[arg_count],
+ insn_op->mode))
op[arg_count] = copy_to_mode_reg (insn_op->mode, op[arg_count]);
}
@@ -9556,7 +9611,9 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
if (ignore
&& icode != CODE_FOR_alignaddrsi_vis
&& icode != CODE_FOR_alignaddrdi_vis
- && icode != CODE_FOR_wrgsr_vis)
+ && icode != CODE_FOR_wrgsr_vis
+ && icode != CODE_FOR_bmasksi_vis
+ && icode != CODE_FOR_bmaskdi_vis)
return build_zero_cst (rtype);
switch (icode)
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 2def8d1..0446955 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -72,6 +72,14 @@
(UNSPEC_SP_SET 60)
(UNSPEC_SP_TEST 61)
+
+ (UNSPEC_EDGE8N 70)
+ (UNSPEC_EDGE8LN 71)
+ (UNSPEC_EDGE16N 72)
+ (UNSPEC_EDGE16LN 73)
+ (UNSPEC_EDGE32N 74)
+ (UNSPEC_EDGE32LN 75)
+ (UNSPEC_BSHUFFLE 76)
])
(define_constants
@@ -240,7 +248,7 @@
fpcmp,
fpmul,fpdivs,fpdivd,
fpsqrts,fpsqrtd,
- fga,fgm_pack,fgm_mul,fgm_pdist,fgm_cmp,edge,gsr,array,
+ fga,fgm_pack,fgm_mul,fgm_pdist,fgm_cmp,edge,edgen,gsr,array,
cmove,
ialuX,
multi,savew,flushw,iflush,trap"
@@ -8188,4 +8196,79 @@
"array32\t%r1, %r2, %0"
[(set_attr "type" "array")])
+(define_insn "bmask<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (plus:P (match_operand:P 1 "register_operand" "rJ")
+ (match_operand:P 2 "register_operand" "rJ")))
+ (clobber (reg:SI GSR_REG))]
+ "TARGET_VIS2"
+ "bmask\t%r1, %r2, %0"
+ [(set_attr "type" "array")])
+
+(define_insn "bshuffle<V64I:mode>_vis"
+ [(set (match_operand:V64I 0 "register_operand" "=e")
+ (unspec:V64I [(match_operand:V64I 1 "register_operand" "e")
+ (match_operand:V64I 2 "register_operand" "e")]
+ UNSPEC_BSHUFFLE))
+ (use (reg:SI GSR_REG))]
+ "TARGET_VIS2"
+ "bshuffle\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+;; VIS 2.0 adds edge variants which do not set the condition codes
+(define_insn "edge8n<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_operand" "rJ")
+ (match_operand:P 2 "register_operand" "rJ")]
+ UNSPEC_EDGE8N))]
+ "TARGET_VIS2"
+ "edge8n\t%r1, %r2, %0"
+ [(set_attr "type" "edgen")])
+
+(define_insn "edge8ln<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_operand" "rJ")
+ (match_operand:P 2 "register_operand" "rJ")]
+ UNSPEC_EDGE8LN))]
+ "TARGET_VIS2"
+ "edge8ln\t%r1, %r2, %0"
+ [(set_attr "type" "edgen")])
+
+(define_insn "edge16n<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_operand" "rJ")
+ (match_operand:P 2 "register_operand" "rJ")]
+ UNSPEC_EDGE16N))]
+ "TARGET_VIS2"
+ "edge16n\t%r1, %r2, %0"
+ [(set_attr "type" "edgen")])
+
+(define_insn "edge16ln<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_operand" "rJ")
+ (match_operand:P 2 "register_operand" "rJ")]
+ UNSPEC_EDGE16LN))]
+ "TARGET_VIS2"
+ "edge16ln\t%r1, %r2, %0"
+ [(set_attr "type" "edgen")])
+
+(define_insn "edge32n<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_operand" "rJ")
+ (match_operand:P 2 "register_operand" "rJ")]
+ UNSPEC_EDGE32N))]
+ "TARGET_VIS2"
+ "edge32n\t%r1, %r2, %0"
+ [(set_attr "type" "edgen")])
+
+(define_insn "edge32ln<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_operand" "rJ")
+ (match_operand:P 2 "register_operand" "rJ")]
+ UNSPEC_EDGE32LN))]
+ "TARGET_VIS2"
+ "edge32ln\t%r1, %r2, %0"
+ [(set_attr "type" "edge")])
+
(include "sync.md")
diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt
index 6be6a75..a7b60c8 100644
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -59,7 +59,11 @@ Compile for V8+ ABI
mvis
Target Report Mask(VIS)
-Use UltraSPARC Visual Instruction Set extensions
+Use UltraSPARC Visual Instruction Set version 1.0 extensions
+
+mvis2
+Target Report Mask(VIS2)
+Use UltraSPARC Visual Instruction Set version 2.0 extensions
mfmaf
Target Report Mask(FMAF)
diff --git a/gcc/config/sparc/ultra1_2.md b/gcc/config/sparc/ultra1_2.md
index 4600205..9cdebab 100644
--- a/gcc/config/sparc/ultra1_2.md
+++ b/gcc/config/sparc/ultra1_2.md
@@ -94,7 +94,7 @@
(define_insn_reservation "us1_simple_ieu1" 1
(and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "compare,edge,array"))
+ (eq_attr "type" "compare,edge,edgen,array"))
"us1_ieu1 + us1_slot012")
(define_insn_reservation "us1_ialuX" 1
diff --git a/gcc/config/sparc/ultra3.md b/gcc/config/sparc/ultra3.md
index c6a9f89..c891e35 100644
--- a/gcc/config/sparc/ultra3.md
+++ b/gcc/config/sparc/ultra3.md
@@ -56,7 +56,7 @@
(define_insn_reservation "us3_array" 2
(and (eq_attr "cpu" "ultrasparc3")
- (eq_attr "type" "array"))
+ (eq_attr "type" "array,edgen"))
"us3_ms + us3_slotany, nothing")
;; ??? Not entirely accurate.
diff --git a/gcc/config/sparc/visintrin.h b/gcc/config/sparc/visintrin.h
index 3bef099..1688301 100644
--- a/gcc/config/sparc/visintrin.h
+++ b/gcc/config/sparc/visintrin.h
@@ -354,4 +354,81 @@ __vis_array32 (long __A, long __B)
return __builtin_vis_array32 (__A, __B);
}
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_bmask (long __A, long __B)
+{
+ return __builtin_vis_bmask (__A, __B);
+}
+
+extern __inline __i64
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_bshuffledi (__i64 __A, __i64 __B)
+{
+ return __builtin_vis_bshuffledi (__A, __B);
+}
+
+extern __inline __v2si
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_bshufflev2si (__v2si __A, __v2si __B)
+{
+ return __builtin_vis_bshufflev2si (__A, __B);
+}
+
+extern __inline __v4hi
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_bshufflev4hi (__v4hi __A, __v4hi __B)
+{
+ return __builtin_vis_bshufflev4hi (__A, __B);
+}
+
+extern __inline __v8qi
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_bshufflev8qi (__v8qi __A, __v8qi __B)
+{
+ return __builtin_vis_bshufflev8qi (__A, __B);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_edge8n (void *__A, void *__B)
+{
+ return __builtin_vis_edge8n (__A, __B);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_edge8ln (void *__A, void *__B)
+{
+ return __builtin_vis_edge8ln (__A, __B);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_edge16n (void *__A, void *__B)
+{
+ return __builtin_vis_edge16n (__A, __B);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_edge16ln (void *__A, void *__B)
+{
+ return __builtin_vis_edge16ln (__A, __B);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_edge32n (void *__A, void *__B)
+{
+ return __builtin_vis_edge32n (__A, __B);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_edge32ln (void *__A, void *__B)
+{
+ return __builtin_vis_edge32ln (__A, __B);
+}
+
#endif /* _VISINTRIN_H_INCLUDED */