summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog36
-rw-r--r--gcc/config/sparc/sparc-c.c7
-rw-r--r--gcc/config/sparc/sparc-modes.def1
-rw-r--r--gcc/config/sparc/sparc.c142
-rw-r--r--gcc/config/sparc/sparc.h2
-rw-r--r--gcc/config/sparc/sparc.md112
-rw-r--r--gcc/config/sparc/sparc.opt4
-rw-r--r--gcc/config/sparc/visintrin.h196
-rw-r--r--gcc/doc/extend.texi45
-rw-r--r--gcc/doc/invoke.texi13
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gcc.target/sparc/cmask.c21
-rw-r--r--gcc/testsuite/gcc.target/sparc/fpadds.c55
-rw-r--r--gcc/testsuite/gcc.target/sparc/fshift.c53
-rw-r--r--gcc/testsuite/gcc.target/sparc/fucmp.c28
-rw-r--r--gcc/testsuite/gcc.target/sparc/vis3misc.c37
16 files changed, 745 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 339e69c2c4f..c6c8322e0aa 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,39 @@
+2011-10-01 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.opt (VIS3): New option.
+ * doc/invoke.texi: Document it.
+ * config/sparc/sparc.h: Force TARGET_VIS3 to zero if assembler is
+ not capable of such instructions.
+ * config/sparc/sparc-c.c (sparc_target_macros): Define __VIS__
+ to 0x300 when TARGET_VIS3.
+ * config/sparc/sparc-modes.def: Create 16-byte vector modes.
+ * config/sparc/sparc.md (UNSPEC_CMASK8, UNSPEC_CMASK16, UNSPEC_CMASK32,
+ UNSPEC_FCHKSM16, UNSPEC_PDISTN, UNSPC_FUCMP): New unspecs.
+ (V64N8, VASS): New mode iterators.
+ (vis3_shift, vis3_addsub_ss): New code iterators.
+ (vbits, vconstr): New mode attributes.
+ (vis3_shift_insn, vis3_addsub_ss_insn): New code attributes.
+ (cmask8<P:mode>_vis, cmask16<P:mode>_vis, cmask32<P:mode>_vis,
+ fchksm16_vis, <vis3_shift_insn><vbits>_vis, pdistn<mode>_vis,
+ fmean16_vis, fpadd64_vis, fpsub64_vis, <vis3_addsub_ss_insn><vbits>_vis,
+ fucmp<code>8<P:mode>_vis): New VIS 3.0 instruction patterns.
+ * config/sparc/sparc.c (sparc_option_override): Set MASK_VIS3 by
+ default when targetting capable cpus. TARGET_VIS3 implies
+ TARGET_VIS2 and TARGET_VIS, and clear them when TARGET_FPU is
+ disabled.
+ (sparc_vis_init_builtins): Emit new VIS 3.0 builtins.
+ (sparc_fold_builtin): Do not eliminate cmask{8,16,32} when result
+ is ignored.
+ * config/sparc/visintrin.h (__vis_cmask8, __vis_cmask16,
+ __vis_cmask32, __vis_fchksm16, __vis_fsll16, __vis_fslas16,
+ __vis_fsrl16, __vis_fsra16, __vis_fsll32, __vis_fslas32,
+ __vis_fsrl32, __vis_fsra32, __vis_pdistn, __vis_fmean16,
+ __vis_fpadd64, __vis_fpsub64, __vis_fpadds16, __vis_fpadds16s,
+ __vis_fpsubs16, __vis_fpsubs16s, __vis_fpadds32, __vis_fpadds32s,
+ __vis_fpsubs32, __vis_fpsubs32s, __vis_fucmple8, __vis_fucmpne8,
+ __vis_fucmpgt8, __vis_fucmpeq8): New VIS 3.0 interfaces.
+ * doc/extend.texi: Document new VIS 3.0 builtins.
+
2011-10-01 Eric Botcazou <ebotcazou@adacore.com>
* ira-color.c (assign_hard_reg): Fix typo.
diff --git a/gcc/config/sparc/sparc-c.c b/gcc/config/sparc/sparc-c.c
index 0f2bee13745..c18797045ae 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_VIS2)
+ if (TARGET_VIS3)
+ {
+ cpp_define (parse_in, "__VIS__=0x300");
+ cpp_define (parse_in, "__VIS=0x300");
+ }
+ else if (TARGET_VIS2)
{
cpp_define (parse_in, "__VIS__=0x200");
cpp_define (parse_in, "__VIS=0x200");
diff --git a/gcc/config/sparc/sparc-modes.def b/gcc/config/sparc/sparc-modes.def
index 6284700867d..ed135ccc1b7 100644
--- a/gcc/config/sparc/sparc-modes.def
+++ b/gcc/config/sparc/sparc-modes.def
@@ -43,5 +43,6 @@ CC_MODE (CCFP);
CC_MODE (CCFPE);
/* Vector modes. */
+VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */
VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */
VECTOR_MODES (INT, 4); /* V4QI V2HI */
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 9863174f904..4df9f6a8088 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -776,9 +776,9 @@ sparc_option_override (void)
/* UltraSPARC T2 */
{ MASK_ISA, MASK_V9|MASK_VIS2},
/* UltraSPARC T3 */
- { MASK_ISA, MASK_V9|MASK_VIS2|MASK_FMAF},
+ { MASK_ISA, MASK_V9|MASK_VIS2|MASK_VIS3|MASK_FMAF},
/* UltraSPARC T4 */
- { MASK_ISA, MASK_V9|MASK_VIS2|MASK_FMAF},
+ { MASK_ISA, MASK_V9|MASK_VIS2|MASK_VIS3|MASK_FMAF},
};
const struct cpu_table *cpu;
unsigned int i;
@@ -861,9 +861,13 @@ sparc_option_override (void)
if (TARGET_VIS2)
target_flags |= MASK_VIS;
- /* Don't allow -mvis, -mvis2, or -mfmaf if FPU is disabled. */
+ /* -mvis3 implies -mvis2 and -mvis */
+ if (TARGET_VIS3)
+ target_flags |= MASK_VIS2 | MASK_VIS;
+
+ /* Don't allow -mvis, -mvis2, -mvis3, or -mfmaf if FPU is disabled. */
if (! TARGET_FPU)
- target_flags &= ~(MASK_VIS | MASK_VIS2 | MASK_FMAF);
+ target_flags &= ~(MASK_VIS | MASK_VIS2 | MASK_VIS3 | MASK_FMAF);
/* -mvis assumes UltraSPARC+, so we are sure v9 instructions
are available.
@@ -9196,6 +9200,10 @@ sparc_vis_init_builtins (void)
tree di_ftype_v8qi_v8qi_di = build_function_type_list (intDI_type_node,
v8qi, v8qi,
intDI_type_node, 0);
+ tree di_ftype_v8qi_v8qi = build_function_type_list (intDI_type_node,
+ v8qi, v8qi, 0);
+ tree si_ftype_v8qi_v8qi = build_function_type_list (intSI_type_node,
+ v8qi, v8qi, 0);
tree di_ftype_di_di = build_function_type_list (intDI_type_node,
intDI_type_node,
intDI_type_node, 0);
@@ -9226,6 +9234,8 @@ sparc_vis_init_builtins (void)
intDI_type_node, 0);
tree di_ftype_void = build_function_type_list (intDI_type_node,
void_type_node, 0);
+ tree void_ftype_si = build_function_type_list (void_type_node,
+ intSI_type_node, 0);
/* Packing and expanding vectors. */
def_builtin ("__builtin_vis_fpack16", CODE_FOR_fpack16_vis,
@@ -9447,6 +9457,102 @@ sparc_vis_init_builtins (void)
def_builtin ("__builtin_vis_bshuffledi", CODE_FOR_bshuffledi_vis,
di_ftype_di_di);
}
+
+ if (TARGET_VIS3)
+ {
+ if (TARGET_ARCH64)
+ {
+ def_builtin ("__builtin_vis_cmask8", CODE_FOR_cmask8di_vis,
+ void_ftype_di);
+ def_builtin ("__builtin_vis_cmask16", CODE_FOR_cmask16di_vis,
+ void_ftype_di);
+ def_builtin ("__builtin_vis_cmask32", CODE_FOR_cmask32di_vis,
+ void_ftype_di);
+ }
+ else
+ {
+ def_builtin ("__builtin_vis_cmask8", CODE_FOR_cmask8si_vis,
+ void_ftype_si);
+ def_builtin ("__builtin_vis_cmask16", CODE_FOR_cmask16si_vis,
+ void_ftype_si);
+ def_builtin ("__builtin_vis_cmask32", CODE_FOR_cmask32si_vis,
+ void_ftype_si);
+ }
+
+ def_builtin_const ("__builtin_vis_fchksm16", CODE_FOR_fchksm16_vis,
+ v4hi_ftype_v4hi_v4hi);
+
+ def_builtin_const ("__builtin_vis_fsll16", CODE_FOR_fsll16_vis,
+ v4hi_ftype_v4hi_v4hi);
+ def_builtin_const ("__builtin_vis_fslas16", CODE_FOR_fslas16_vis,
+ v4hi_ftype_v4hi_v4hi);
+ def_builtin_const ("__builtin_vis_fsrl16", CODE_FOR_fsrl16_vis,
+ v4hi_ftype_v4hi_v4hi);
+ def_builtin_const ("__builtin_vis_fsra16", CODE_FOR_fsra16_vis,
+ v4hi_ftype_v4hi_v4hi);
+ def_builtin_const ("__builtin_vis_fsll32", CODE_FOR_fsll32_vis,
+ v2si_ftype_v2si_v2si);
+ def_builtin_const ("__builtin_vis_fslas32", CODE_FOR_fslas32_vis,
+ v2si_ftype_v2si_v2si);
+ def_builtin_const ("__builtin_vis_fsrl32", CODE_FOR_fsrl32_vis,
+ v2si_ftype_v2si_v2si);
+ def_builtin_const ("__builtin_vis_fsra32", CODE_FOR_fsra32_vis,
+ v2si_ftype_v2si_v2si);
+
+ if (TARGET_ARCH64)
+ def_builtin_const ("__builtin_vis_pdistn", CODE_FOR_pdistndi_vis,
+ di_ftype_v8qi_v8qi);
+ else
+ def_builtin_const ("__builtin_vis_pdistn", CODE_FOR_pdistnsi_vis,
+ si_ftype_v8qi_v8qi);
+
+ def_builtin_const ("__builtin_vis_fmean16", CODE_FOR_fmean16_vis,
+ v4hi_ftype_v4hi_v4hi);
+ def_builtin_const ("__builtin_vis_fpadd64", CODE_FOR_fpadd64_vis,
+ di_ftype_di_di);
+ def_builtin_const ("__builtin_vis_fpsub64", CODE_FOR_fpsub64_vis,
+ di_ftype_di_di);
+
+ def_builtin_const ("__builtin_vis_fpadds16", CODE_FOR_fpadds16_vis,
+ v4hi_ftype_v4hi_v4hi);
+ def_builtin_const ("__builtin_vis_fpadds16s", CODE_FOR_fpadds16s_vis,
+ v2hi_ftype_v2hi_v2hi);
+ def_builtin_const ("__builtin_vis_fpsubs16", CODE_FOR_fpsubs16_vis,
+ v4hi_ftype_v4hi_v4hi);
+ def_builtin_const ("__builtin_vis_fpsubs16s", CODE_FOR_fpsubs16s_vis,
+ v2hi_ftype_v2hi_v2hi);
+ def_builtin_const ("__builtin_vis_fpadds32", CODE_FOR_fpadds32_vis,
+ v2si_ftype_v2si_v2si);
+ def_builtin_const ("__builtin_vis_fpadds32s", CODE_FOR_fpadds32s_vis,
+ v1si_ftype_v1si_v1si);
+ def_builtin_const ("__builtin_vis_fpsubs32", CODE_FOR_fpsubs32_vis,
+ v2si_ftype_v2si_v2si);
+ def_builtin_const ("__builtin_vis_fpsubs32s", CODE_FOR_fpsubs32s_vis,
+ v1si_ftype_v1si_v1si);
+
+ if (TARGET_ARCH64)
+ {
+ def_builtin_const ("__builtin_vis_fucmple8", CODE_FOR_fucmple8di_vis,
+ di_ftype_v8qi_v8qi);
+ def_builtin_const ("__builtin_vis_fucmpne8", CODE_FOR_fucmpne8di_vis,
+ di_ftype_v8qi_v8qi);
+ def_builtin_const ("__builtin_vis_fucmpgt8", CODE_FOR_fucmpgt8di_vis,
+ di_ftype_v8qi_v8qi);
+ def_builtin_const ("__builtin_vis_fucmpeq8", CODE_FOR_fucmpeq8di_vis,
+ di_ftype_v8qi_v8qi);
+ }
+ else
+ {
+ def_builtin_const ("__builtin_vis_fucmple8", CODE_FOR_fucmple8si_vis,
+ si_ftype_v8qi_v8qi);
+ def_builtin_const ("__builtin_vis_fucmpne8", CODE_FOR_fucmpne8si_vis,
+ si_ftype_v8qi_v8qi);
+ def_builtin_const ("__builtin_vis_fucmpgt8", CODE_FOR_fucmpgt8si_vis,
+ si_ftype_v8qi_v8qi);
+ def_builtin_const ("__builtin_vis_fucmpeq8", CODE_FOR_fucmpeq8si_vis,
+ si_ftype_v8qi_v8qi);
+ }
+ }
}
/* Handle TARGET_EXPAND_BUILTIN target hook.
@@ -9608,13 +9714,27 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
tree rtype = TREE_TYPE (TREE_TYPE (fndecl));
enum insn_code icode = (enum insn_code) DECL_FUNCTION_CODE (fndecl);
- if (ignore
- && icode != CODE_FOR_alignaddrsi_vis
- && icode != CODE_FOR_alignaddrdi_vis
- && icode != CODE_FOR_wrgsr_vis
- && icode != CODE_FOR_bmasksi_vis
- && icode != CODE_FOR_bmaskdi_vis)
- return build_zero_cst (rtype);
+ if (ignore)
+ {
+ switch (icode)
+ {
+ case CODE_FOR_alignaddrsi_vis:
+ case CODE_FOR_alignaddrdi_vis:
+ case CODE_FOR_wrgsr_vis:
+ case CODE_FOR_bmasksi_vis:
+ case CODE_FOR_bmaskdi_vis:
+ case CODE_FOR_cmask8si_vis:
+ case CODE_FOR_cmask8di_vis:
+ case CODE_FOR_cmask16si_vis:
+ case CODE_FOR_cmask16di_vis:
+ case CODE_FOR_cmask32si_vis:
+ case CODE_FOR_cmask32di_vis:
+ break;
+
+ default:
+ return build_zero_cst (rtype);
+ }
+ }
switch (icode)
{
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index cccd4446c91..fa943877550 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -1868,6 +1868,8 @@ extern int sparc_indent_opcode;
#define AS_NIAGARA3_FLAG "b"
#undef TARGET_FMAF
#define TARGET_FMAF 0
+#undef TARGET_VIS3
+#define TARGET_VIS3 0
#else
#define AS_NIAGARA3_FLAG "d"
#endif
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 04469558a7c..03158c7f07c 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -80,6 +80,12 @@
(UNSPEC_EDGE32N 74)
(UNSPEC_EDGE32LN 75)
(UNSPEC_BSHUFFLE 76)
+ (UNSPEC_CMASK8 77)
+ (UNSPEC_CMASK16 78)
+ (UNSPEC_CMASK32 79)
+ (UNSPEC_FCHKSM16 80)
+ (UNSPEC_PDISTN 81)
+ (UNSPEC_FUCMP 82)
])
(define_constants
@@ -195,12 +201,16 @@
(define_mode_iterator V64 [DF V2SI V4HI V8QI])
(define_mode_iterator V64I [DI V2SI V4HI V8QI])
+(define_mode_iterator V64N8 [V2SI V4HI])
+
;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this
;; a second register class, EXTRA_FP_REGS, exists for the v9 chip. The name
;; is a bit of a misnomer as it covers all 64 fp regs. The corresponding
;; constraint letter is 'e'. To avoid any confusion, 'e' is used instead of
;; 'f' for all DF/TFmode values, including those that are specific to the v8.
+(define_mode_attr vbits [(V2SI "32") (V4HI "16") (SI "32s") (V2HI "16s")])
+(define_mode_attr vconstr [(V2SI "e") (V4HI "e") (SI "f") (V2HI "f")])
;; Attribute for cpu type.
;; These must match the values for enum processor_type in sparc.h.
@@ -8271,4 +8281,106 @@
"edge32ln\t%r1, %r2, %0"
[(set_attr "type" "edge")])
+;; Conditional moves are possible via fcmpX --> cmaskX -> bshuffle
+(define_insn "cmask8<P:mode>_vis"
+ [(set (reg:DI GSR_REG)
+ (unspec:DI [(match_operand:P 0 "register_operand" "r")
+ (reg:DI GSR_REG)]
+ UNSPEC_CMASK8))]
+ "TARGET_VIS3"
+ "cmask8\t%r0")
+
+(define_insn "cmask16<P:mode>_vis"
+ [(set (reg:DI GSR_REG)
+ (unspec:DI [(match_operand:P 0 "register_operand" "r")
+ (reg:DI GSR_REG)]
+ UNSPEC_CMASK16))]
+ "TARGET_VIS3"
+ "cmask16\t%r0")
+
+(define_insn "cmask32<P:mode>_vis"
+ [(set (reg:DI GSR_REG)
+ (unspec:DI [(match_operand:P 0 "register_operand" "r")
+ (reg:DI GSR_REG)]
+ UNSPEC_CMASK32))]
+ "TARGET_VIS3"
+ "cmask32\t%r0")
+
+(define_insn "fchksm16_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "e")
+ (match_operand:V4HI 2 "register_operand" "e")]
+ UNSPEC_FCHKSM16))]
+ "TARGET_VIS3"
+ "fchksm16\t%1, %2, %0")
+
+(define_code_iterator vis3_shift [ashift ss_ashift lshiftrt ashiftrt])
+(define_code_attr vis3_shift_insn
+ [(ashift "fsll") (ss_ashift "fslas") (lshiftrt "fsrl") (ashiftrt "fsra")])
+
+(define_insn "<vis3_shift_insn><vbits>_vis"
+ [(set (match_operand:V64N8 0 "register_operand" "=<vconstr>")
+ (vis3_shift:V64N8 (match_operand:V64N8 1 "register_operand" "<vconstr>")
+ (match_operand:V64N8 2 "register_operand" "<vconstr>")))]
+ "TARGET_VIS3"
+ "<vis3_shift_insn><vbits>\t%1, %2, %0")
+
+(define_insn "pdistn<mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:V8QI 1 "register_operand" "e")
+ (match_operand:V8QI 2 "register_operand" "e")]
+ UNSPEC_PDISTN))]
+ "TARGET_VIS3"
+ "pdistn\t%1, %2, %0")
+
+(define_insn "fmean16_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (truncate:V4HI
+ (lshiftrt:V4SI
+ (plus:V4SI
+ (plus:V4SI
+ (zero_extend:V4SI
+ (match_operand:V4HI 1 "register_operand" "e"))
+ (zero_extend:V4SI
+ (match_operand:V4HI 2 "register_operand" "e")))
+ (const_vector:V4SI [(const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)]))
+ (const_int 1))))]
+ "TARGET_VIS3"
+ "fmean16\t%1, %2, %0")
+
+(define_insn "fpadd64_vis"
+ [(set (match_operand:DI 0 "register_operand" "=e")
+ (plus:DI (match_operand:DI 1 "register_operand" "e")
+ (match_operand:DI 2 "register_operand" "e")))]
+ "TARGET_VIS3"
+ "fpadd64\t%1, %2, %0")
+
+(define_insn "fpsub64_vis"
+ [(set (match_operand:DI 0 "register_operand" "=e")
+ (minus:DI (match_operand:DI 1 "register_operand" "e")
+ (match_operand:DI 2 "register_operand" "e")))]
+ "TARGET_VIS3"
+ "fpsub64\t%1, %2, %0")
+
+(define_mode_iterator VASS [V4HI V2SI V2HI SI])
+(define_code_iterator vis3_addsub_ss [ss_plus ss_minus])
+(define_code_attr vis3_addsub_ss_insn
+ [(ss_plus "fpadds") (ss_minus "fpsubs")])
+
+(define_insn "<vis3_addsub_ss_insn><vbits>_vis"
+ [(set (match_operand:VASS 0 "register_operand" "=<vconstr>")
+ (vis3_addsub_ss:VASS (match_operand:VASS 1 "register_operand" "<vconstr>")
+ (match_operand:VASS 2 "register_operand" "<vconstr>")))]
+ "TARGET_VIS3"
+ "<vis3_addsub_ss_insn><vbits>\t%1, %2, %0")
+
+(define_insn "fucmp<code>8<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(gcond:V8QI (match_operand:V8QI 1 "register_operand" "e")
+ (match_operand:V8QI 2 "register_operand" "e"))]
+ UNSPEC_FUCMP))]
+ "TARGET_VIS3"
+ "fucmp<code>8\t%1, %2, %0")
+
(include "sync.md")
diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt
index a7b60c838f2..613ae731c8e 100644
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -65,6 +65,10 @@ mvis2
Target Report Mask(VIS2)
Use UltraSPARC Visual Instruction Set version 2.0 extensions
+mvis3
+Target Report Mask(VIS3)
+Use UltraSPARC Visual Instruction Set version 3.0 extensions
+
mfmaf
Target Report Mask(FMAF)
Use UltraSPARC Fused Multiply-Add extensions
diff --git a/gcc/config/sparc/visintrin.h b/gcc/config/sparc/visintrin.h
index 1688301f3d2..32e44e55810 100644
--- a/gcc/config/sparc/visintrin.h
+++ b/gcc/config/sparc/visintrin.h
@@ -431,4 +431,200 @@ __vis_edge32ln (void *__A, void *__B)
return __builtin_vis_edge32ln (__A, __B);
}
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_cmask8 (long __A)
+{
+ return __builtin_vis_cmask8 (__A);
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_cmask16 (long __A)
+{
+ return __builtin_vis_cmask16 (__A);
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_cmask32 (long __A)
+{
+ return __builtin_vis_cmask32 (__A);
+}
+
+extern __inline __v4hi
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fchksm16 (__v4hi __A, __v4hi __B)
+{
+ return __builtin_vis_fchksm16 (__A, __B);
+}
+
+extern __inline __v4hi
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fsll16 (__v4hi __A, __v4hi __B)
+{
+ return __builtin_vis_fsll16 (__A, __B);
+}
+
+extern __inline __v4hi
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fslas16 (__v4hi __A, __v4hi __B)
+{
+ return __builtin_vis_fslas16 (__A, __B);
+}
+
+extern __inline __v4hi
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fsrl16 (__v4hi __A, __v4hi __B)
+{
+ return __builtin_vis_fsrl16 (__A, __B);
+}
+
+extern __inline __v4hi
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fsra16 (__v4hi __A, __v4hi __B)
+{
+ return __builtin_vis_fsra16 (__A, __B);
+}
+
+extern __inline __v2si
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fsll32 (__v2si __A, __v2si __B)
+{
+ return __builtin_vis_fsll32 (__A, __B);
+}
+
+extern __inline __v2si
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fslas32 (__v2si __A, __v2si __B)
+{
+ return __builtin_vis_fslas32 (__A, __B);
+}
+
+extern __inline __v2si
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fsrl32 (__v2si __A, __v2si __B)
+{
+ return __builtin_vis_fsrl32 (__A, __B);
+}
+
+extern __inline __v2si
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fsra32 (__v2si __A, __v2si __B)
+{
+ return __builtin_vis_fsra32 (__A, __B);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_pdistn (__v8qi __A, __v8qi __B)
+{
+ return __builtin_vis_pdistn (__A, __B);
+}
+
+extern __inline __v4hi
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fmean16 (__v4hi __A, __v4hi __B)
+{
+ return __builtin_vis_fmean16 (__A, __B);
+}
+
+extern __inline __i64
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fpadd64 (__i64 __A, __i64 __B)
+{
+ return __builtin_vis_fpadd64 (__A, __B);
+}
+
+extern __inline __i64
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fpsub64 (__i64 __A, __i64 __B)
+{
+ return __builtin_vis_fpsub64 (__A, __B);
+}
+
+extern __inline __v4hi
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fpadds16 (__v4hi __A, __v4hi __B)
+{
+ return __builtin_vis_fpadds16 (__A, __B);
+}
+
+extern __inline __v2hi
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fpadds16s (__v2hi __A, __v2hi __B)
+{
+ return __builtin_vis_fpadds16s (__A, __B);
+}
+
+extern __inline __v4hi
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fpsubs16 (__v4hi __A, __v4hi __B)
+{
+ return __builtin_vis_fpsubs16 (__A, __B);
+}
+
+extern __inline __v2hi
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fpsubs16s (__v2hi __A, __v2hi __B)
+{
+ return __builtin_vis_fpsubs16s (__A, __B);
+}
+
+extern __inline __v2si
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fpadds32 (__v2si __A, __v2si __B)
+{
+ return __builtin_vis_fpadds32 (__A, __B);
+}
+
+extern __inline __v1si
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fpadds32s (__v1si __A, __v1si __B)
+{
+ return __builtin_vis_fpadds32s (__A, __B);
+}
+
+extern __inline __v2si
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fpsubs32 (__v2si __A, __v2si __B)
+{
+ return __builtin_vis_fpsubs32 (__A, __B);
+}
+
+extern __inline __v1si
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fpsubs32s (__v1si __A, __v1si __B)
+{
+ return __builtin_vis_fpsubs32s (__A, __B);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fucmple8 (__v8qi __A, __v8qi __B)
+{
+ return __builtin_vis_fucmple8 (__A, __B);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fucmpne8 (__v8qi __A, __v8qi __B)
+{
+ return __builtin_vis_fucmpne8 (__A, __B);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fucmpgt8 (__v8qi __A, __v8qi __B)
+{
+ return __builtin_vis_fucmpgt8 (__A, __B);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fucmpeq8 (__v8qi __A, __v8qi __B)
+{
+ return __builtin_vis_fucmpeq8 (__A, __B);
+}
+
#endif /* _VISINTRIN_H_INCLUDED */
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 5fe0371df8f..1c688dcf60a 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -13016,8 +13016,8 @@ long __builtin_vis_array16 (long, long);
long __builtin_vis_array32 (long, long);
@end smallexample
-Additionally, when you use the @option{-mvis2} switch, the VIS version
-2.0 built-in functions become available:
+When you use the @option{-mvis2} switch, the VIS version 2.0 built-in
+functions also become available:
@smallexample
long __builtin_vis_bmask (long, long);
@@ -13034,6 +13034,47 @@ long __builtin_vis_edge32n (void *, void *);
long __builtin_vis_edge32ln (void *, void *);
@end smallexample
+When you use the @option{-mvis3} switch, the VIS version 3.0 built-in
+functions also become available:
+
+@smallexample
+void __builtin_vis_cmask8 (long);
+void __builtin_vis_cmask16 (long);
+void __builtin_vis_cmask32 (long);
+
+v4hi __builtin_vis_fchksm16 (v4hi, v4hi);
+
+v4hi __builtin_vis_fsll16 (v4hi, v4hi);
+v4hi __builtin_vis_fslas16 (v4hi, v4hi);
+v4hi __builtin_vis_fsrl16 (v4hi, v4hi);
+v4hi __builtin_vis_fsra16 (v4hi, v4hi);
+v2si __builtin_vis_fsll16 (v2si, v2si);
+v2si __builtin_vis_fslas16 (v2si, v2si);
+v2si __builtin_vis_fsrl16 (v2si, v2si);
+v2si __builtin_vis_fsra16 (v2si, v2si);
+
+long __builtin_vis_pdistn (v8qi, v8qi);
+
+v4hi __builtin_vis_fmean16 (v4hi, v4hi);
+
+int64_t __builtin_vis_fpadd64 (int64_t, int64_t);
+int64_t __builtin_vis_fpsub64 (int64_t, int64_t);
+
+v4hi __builtin_vis_fpadds16 (v4hi, v4hi);
+v2hi __builtin_vis_fpadds16s (v2hi, v2hi);
+v4hi __builtin_vis_fpsubs16 (v4hi, v4hi);
+v2hi __builtin_vis_fpsubs16s (v2hi, v2hi);
+v2si __builtin_vis_fpadds32 (v2si, v2si);
+v1si __builtin_vis_fpadds32s (v1si, v1si);
+v2si __builtin_vis_fpsubs32 (v2si, v2si);
+v1si __builtin_vis_fpsubs32s (v1si, v1si);
+
+long __builtin_vis_fucmple8 (v8qi, v8qi);
+long __builtin_vis_fucmpne8 (v8qi, v8qi);
+long __builtin_vis_fucmpgt8 (v8qi, v8qi);
+long __builtin_vis_fucmpeq8 (v8qi, v8qi);
+@end smallexample
+
@node SPU Built-in Functions
@subsection SPU Built-in Functions
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8e43f823583..bdc745367b3 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -880,7 +880,8 @@ See RS/6000 and PowerPC Options.
-mstack-bias -mno-stack-bias @gol
-munaligned-doubles -mno-unaligned-doubles @gol
-mv8plus -mno-v8plus -mvis -mno-vis @gol
--mvis2 -mno-vis2 -mfmaf -mno-fmaf}
+-mvis2 -mno-vis2 -mvis3 -mno-vis3 @gol
+-mfmaf -mno-fmaf}
@emph{SPU Options}
@gccoptlist{-mwarn-reloc -merror-reloc @gol
@@ -17445,6 +17446,16 @@ default is @option{-mvis2} when targetting a cpu that supports such
instructions, such as UltraSPARC-III and later. Setting @option{-mvis2}
also sets @option{-mvis}.
+@item -mvis3
+@itemx -mno-vis3
+@opindex mvis3
+@opindex mno-vis3
+With @option{-mvis3}, GCC generates code that takes advantage of
+version 3.0 of the UltraSPARC Visual Instruction Set extensions. The
+default is @option{-mvis3} when targetting a cpu that supports such
+instructions, such as niagara-3 and later. Setting @option{-mvis3}
+also sets @option{-mvis2} and @option{-mvis}.
+
@item -mfmaf
@itemx -mno-fmaf
@opindex mfmaf
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 075edfc4008..a43bf9d2111 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2011-10-01 David S. Miller <davem@davemloft.net>
+
+ * gcc.target/sparc/cmask.c: New test.
+ * gcc.target/sparc/fpadds.c: New test.
+ * gcc.target/sparc/fshift.c: New test.
+ * gcc.target/sparc/fucmp.c: New test.
+ * gcc.target/sparc/vis3misc.c: New test.
+
2011-10-01 Janus Weil <janus@gcc.gnu.org>
PR fortran/50585
diff --git a/gcc/testsuite/gcc.target/sparc/cmask.c b/gcc/testsuite/gcc.target/sparc/cmask.c
new file mode 100644
index 00000000000..b3168ec321d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/cmask.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=niagara3 -mvis" } */
+
+void test_cm8 (long x)
+{
+ __builtin_vis_cmask8 (x);
+}
+
+void test_cm16 (long x)
+{
+ __builtin_vis_cmask16 (x);
+}
+
+void test_cm32 (long x)
+{
+ __builtin_vis_cmask32 (x);
+}
+
+/* { dg-final { scan-assembler "cmask8\t%" } } */
+/* { dg-final { scan-assembler "cmask16\t%" } } */
+/* { dg-final { scan-assembler "cmask32\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fpadds.c b/gcc/testsuite/gcc.target/sparc/fpadds.c
new file mode 100644
index 00000000000..d0704e03eda
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/fpadds.c
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=niagara3 -mvis" } */
+typedef int __v2si __attribute__((vector_size(8)));
+typedef int __v1si __attribute__((vector_size(4)));
+typedef short __v4hi __attribute__((vector_size(8)));
+typedef short __v2hi __attribute__((vector_size(4)));
+
+__v4hi test_fpadds16 (__v4hi x, __v4hi y)
+{
+ return __builtin_vis_fpadds16 (x, y);
+}
+
+__v2hi test_fpadds16s (__v2hi x, __v2hi y)
+{
+ return __builtin_vis_fpadds16s (x, y);
+}
+
+__v4hi test_fpsubs16 (__v4hi x, __v4hi y)
+{
+ return __builtin_vis_fpsubs16 (x, y);
+}
+
+__v2hi test_fpsubs16s (__v2hi x, __v2hi y)
+{
+ return __builtin_vis_fpsubs16s (x, y);
+}
+
+__v2si test_fpadds32 (__v2si x, __v2si y)
+{
+ return __builtin_vis_fpadds32 (x, y);
+}
+
+__v1si test_fpadds32s (__v1si x, __v1si y)
+{
+ return __builtin_vis_fpadds32s (x, y);
+}
+
+__v2si test_fpsubs32 (__v2si x, __v2si y)
+{
+ return __builtin_vis_fpsubs32 (x, y);
+}
+
+__v1si test_fpsubs32s (__v1si x, __v1si y)
+{
+ return __builtin_vis_fpsubs32s (x, y);
+}
+
+/* { dg-final { scan-assembler "fpadds16\t%" } } */
+/* { dg-final { scan-assembler "fpadds16s\t%" } } */
+/* { dg-final { scan-assembler "fpsubs16\t%" } } */
+/* { dg-final { scan-assembler "fpsubs16s\t%" } } */
+/* { dg-final { scan-assembler "fpadds32\t%" } } */
+/* { dg-final { scan-assembler "fpadds32s\t%" } } */
+/* { dg-final { scan-assembler "fpsubs32\t%" } } */
+/* { dg-final { scan-assembler "fpsubs32s\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fshift.c b/gcc/testsuite/gcc.target/sparc/fshift.c
new file mode 100644
index 00000000000..a12df0451cb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/fshift.c
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=niagara3 -mvis" } */
+typedef int __v2si __attribute__((vector_size(8)));
+typedef short __v4hi __attribute__((vector_size(8)));
+
+__v4hi test_fsll16 (__v4hi x, __v4hi y)
+{
+ return __builtin_vis_fsll16 (x, y);
+}
+
+__v4hi test_fslas16 (__v4hi x, __v4hi y)
+{
+ return __builtin_vis_fslas16 (x, y);
+}
+
+__v4hi test_fsrl16 (__v4hi x, __v4hi y)
+{
+ return __builtin_vis_fsrl16 (x, y);
+}
+
+__v4hi test_fsra16 (__v4hi x, __v4hi y)
+{
+ return __builtin_vis_fsra16 (x, y);
+}
+
+__v2si test_fsll32 (__v2si x, __v2si y)
+{
+ return __builtin_vis_fsll32 (x, y);
+}
+
+__v2si test_fslas32 (__v2si x, __v2si y)
+{
+ return __builtin_vis_fslas32 (x, y);
+}
+
+__v2si test_fsrl32 (__v2si x, __v2si y)
+{
+ return __builtin_vis_fsrl32 (x, y);
+}
+
+__v2si test_fsra32 (__v2si x, __v2si y)
+{
+ return __builtin_vis_fsra32 (x, y);
+}
+
+/* { dg-final { scan-assembler "fsll16\t%" } } */
+/* { dg-final { scan-assembler "fslas16\t%" } } */
+/* { dg-final { scan-assembler "fsrl16\t%" } } */
+/* { dg-final { scan-assembler "fsra16\t%" } } */
+/* { dg-final { scan-assembler "fsll32\t%" } } */
+/* { dg-final { scan-assembler "fslas32\t%" } } */
+/* { dg-final { scan-assembler "fsrl32\t%" } } */
+/* { dg-final { scan-assembler "fsra32\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fucmp.c b/gcc/testsuite/gcc.target/sparc/fucmp.c
new file mode 100644
index 00000000000..7f291c3e7ed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/fucmp.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=niagara3 -mvis" } */
+typedef unsigned char vec8 __attribute__((vector_size(8)));
+
+long test_fucmple8 (vec8 a, vec8 b)
+{
+ return __builtin_vis_fucmple8 (a, b);
+}
+
+long test_fucmpne8 (vec8 a, vec8 b)
+{
+ return __builtin_vis_fucmpne8 (a, b);
+}
+
+long test_fucmpgt8 (vec8 a, vec8 b)
+{
+ return __builtin_vis_fucmpgt8 (a, b);
+}
+
+long test_fucmpeq8 (vec8 a, vec8 b)
+{
+ return __builtin_vis_fucmpeq8 (a, b);
+}
+
+/* { dg-final { scan-assembler "fucmple8\t%" } } */
+/* { dg-final { scan-assembler "fucmpne8\t%" } } */
+/* { dg-final { scan-assembler "fucmpgt8\t%" } } */
+/* { dg-final { scan-assembler "fucmpeq8\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/vis3misc.c b/gcc/testsuite/gcc.target/sparc/vis3misc.c
new file mode 100644
index 00000000000..8a9535e8fb5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/vis3misc.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=niagara3 -mvis" } */
+typedef int __v2si __attribute__((vector_size(8)));
+typedef short __v4hi __attribute__((vector_size(8)));
+typedef unsigned char __v8qi __attribute__((vector_size(8)));
+typedef long long int64_t;
+
+__v4hi test_fchksm16 (__v4hi x, __v4hi y)
+{
+ return __builtin_vis_fchksm16 (x, y);
+}
+
+long test_pdistn (__v8qi x, __v8qi y)
+{
+ return __builtin_vis_pdistn (x, y);
+}
+
+__v4hi test_fmean16 (__v4hi x, __v4hi y)
+{
+ return __builtin_vis_fmean16 (x, y);
+}
+
+int64_t test_fpadd64 (int64_t x, int64_t y)
+{
+ return __builtin_vis_fpadd64 (x, y);
+}
+
+int64_t test_fpsub64 (int64_t x, int64_t y)
+{
+ return __builtin_vis_fpsub64 (x, y);
+}
+
+/* { dg-final { scan-assembler "fchksm16\t%" } } */
+/* { dg-final { scan-assembler "pdistn\t%" } } */
+/* { dg-final { scan-assembler "fmean16\t%" } } */
+/* { dg-final { scan-assembler "fpadd64\t%" } } */
+/* { dg-final { scan-assembler "fpsub64\t%" } } */