@@ -1203,17 +1203,18 @@ (define_expand "altivec_vmrghh"
(use (match_operand:V8HI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
- rtx (*fun) (rtx, rtx, rtx) = BYTES_BIG_ENDIAN ? gen_altivec_vmrghh_direct
- : gen_altivec_vmrglh_direct;
- if (!BYTES_BIG_ENDIAN)
- std::swap (operands[1], operands[2]);
- emit_insn (fun (operands[0], operands[1], operands[2]));
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (
+ gen_altivec_vmrghh_direct_be (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (
+ gen_altivec_vmrglh_direct_le (operands[0], operands[2], operands[1]));
DONE;
})
-(define_insn "altivec_vmrghh_direct"
+(define_insn "altivec_vmrghh_direct_be"
[(set (match_operand:V8HI 0 "register_operand" "=v")
- (vec_select:V8HI
+ (vec_select:V8HI
(vec_concat:V16HI
(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v"))
@@ -1221,7 +1222,21 @@ (define_insn "altivec_vmrghh_direct"
(const_int 1) (const_int 9)
(const_int 2) (const_int 10)
(const_int 3) (const_int 11)])))]
- "TARGET_ALTIVEC"
+ "TARGET_ALTIVEC && BYTES_BIG_ENDIAN"
+ "vmrghh %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vmrghh_direct_le"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (vec_select:V8HI
+ (vec_concat:V16HI
+ (match_operand:V8HI 2 "register_operand" "v")
+ (match_operand:V8HI 1 "register_operand" "v"))
+ (parallel [(const_int 4) (const_int 12)
+ (const_int 5) (const_int 13)
+ (const_int 6) (const_int 14)
+ (const_int 7) (const_int 15)])))]
+ "TARGET_ALTIVEC && !BYTES_BIG_ENDIAN"
"vmrghh %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -1344,15 +1359,16 @@ (define_expand "altivec_vmrglh"
(use (match_operand:V8HI 2 "register_operand"))]
"TARGET_ALTIVEC"
{
- rtx (*fun) (rtx, rtx, rtx) = BYTES_BIG_ENDIAN ? gen_altivec_vmrglh_direct
- : gen_altivec_vmrghh_direct;
- if (!BYTES_BIG_ENDIAN)
- std::swap (operands[1], operands[2]);
- emit_insn (fun (operands[0], operands[1], operands[2]));
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (
+ gen_altivec_vmrglh_direct_be (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (
+ gen_altivec_vmrghh_direct_le (operands[0], operands[2], operands[1]));
DONE;
})
-(define_insn "altivec_vmrglh_direct"
+(define_insn "altivec_vmrglh_direct_be"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(vec_select:V8HI
(vec_concat:V16HI
@@ -1362,7 +1378,21 @@ (define_insn "altivec_vmrglh_direct"
(const_int 5) (const_int 13)
(const_int 6) (const_int 14)
(const_int 7) (const_int 15)])))]
- "TARGET_ALTIVEC"
+ "TARGET_ALTIVEC && BYTES_BIG_ENDIAN"
+ "vmrglh %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vmrglh_direct_le"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (vec_select:V8HI
+ (vec_concat:V16HI
+ (match_operand:V8HI 2 "register_operand" "v")
+ (match_operand:V8HI 1 "register_operand" "v"))
+ (parallel [(const_int 0) (const_int 8)
+ (const_int 1) (const_int 9)
+ (const_int 2) (const_int 10)
+ (const_int 3) (const_int 11)])))]
+ "TARGET_ALTIVEC && !BYTES_BIG_ENDIAN"
"vmrglh %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -3831,13 +3861,13 @@ (define_expand "vec_widen_umult_hi_v16qi"
{
emit_insn (gen_altivec_vmuleub (ve, operands[1], operands[2]));
emit_insn (gen_altivec_vmuloub (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrghh_direct (operands[0], ve, vo));
+ emit_insn (gen_altivec_vmrghh (operands[0], ve, vo));
}
else
{
emit_insn (gen_altivec_vmuloub (ve, operands[1], operands[2]));
emit_insn (gen_altivec_vmuleub (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrghh_direct (operands[0], vo, ve));
+ emit_insn (gen_altivec_vmrglh (operands[0], ve, vo));
}
DONE;
})
@@ -3856,13 +3886,13 @@ (define_expand "vec_widen_umult_lo_v16qi"
{
emit_insn (gen_altivec_vmuleub (ve, operands[1], operands[2]));
emit_insn (gen_altivec_vmuloub (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrglh_direct (operands[0], ve, vo));
+ emit_insn (gen_altivec_vmrglh (operands[0], ve, vo));
}
else
{
emit_insn (gen_altivec_vmuloub (ve, operands[1], operands[2]));
emit_insn (gen_altivec_vmuleub (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrglh_direct (operands[0], vo, ve));
+ emit_insn (gen_altivec_vmrghh (operands[0], ve, vo));
}
DONE;
})
@@ -3881,13 +3911,13 @@ (define_expand "vec_widen_smult_hi_v16qi"
{
emit_insn (gen_altivec_vmulesb (ve, operands[1], operands[2]));
emit_insn (gen_altivec_vmulosb (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrghh_direct (operands[0], ve, vo));
+ emit_insn (gen_altivec_vmrghh (operands[0], ve, vo));
}
else
{
emit_insn (gen_altivec_vmulosb (ve, operands[1], operands[2]));
emit_insn (gen_altivec_vmulesb (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrghh_direct (operands[0], vo, ve));
+ emit_insn (gen_altivec_vmrglh (operands[0], ve, vo));
}
DONE;
})
@@ -3906,13 +3936,13 @@ (define_expand "vec_widen_smult_lo_v16qi"
{
emit_insn (gen_altivec_vmulesb (ve, operands[1], operands[2]));
emit_insn (gen_altivec_vmulosb (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrglh_direct (operands[0], ve, vo));
+ emit_insn (gen_altivec_vmrglh (operands[0], ve, vo));
}
else
{
emit_insn (gen_altivec_vmulosb (ve, operands[1], operands[2]));
emit_insn (gen_altivec_vmulesb (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrglh_direct (operands[0], vo, ve));
+ emit_insn (gen_altivec_vmrghh (operands[0], ve, vo));
}
DONE;
})
@@ -23446,8 +23446,8 @@ altivec_expand_vec_perm_const (rtx target, rtx op0, rtx op1,
: CODE_FOR_altivec_vmrglb_direct_le,
{0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23}},
{OPTION_MASK_ALTIVEC,
- BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghh_direct
- : CODE_FOR_altivec_vmrglh_direct,
+ BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghh_direct_be
+ : CODE_FOR_altivec_vmrglh_direct_le,
{0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23}},
{OPTION_MASK_ALTIVEC,
BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghw_direct_v4si_be
@@ -23458,8 +23458,8 @@ altivec_expand_vec_perm_const (rtx target, rtx op0, rtx op1,
: CODE_FOR_altivec_vmrghb_direct_le,
{8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31}},
{OPTION_MASK_ALTIVEC,
- BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglh_direct
- : CODE_FOR_altivec_vmrghh_direct,
+ BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglh_direct_be
+ : CODE_FOR_altivec_vmrghh_direct_le,
{8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31}},
{OPTION_MASK_ALTIVEC,
BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglw_direct_v4si_be
new file mode 100644
@@ -0,0 +1,37 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-require-effective-target vmx_hw } */
+
+/* Test vector merge for 16-bit element size,
+ it will abort if the RTL pattern isn't expected. */
+
+#include "altivec.h"
+
+__attribute__((noipa))
+signed short elem_2 (vector signed short a, vector signed short b)
+{
+ vector signed short c = vec_mergeh (a,b);
+ return vec_extract (c, 2);
+}
+
+__attribute__((noipa))
+unsigned short elem_7 (vector unsigned short a, vector unsigned short b)
+{
+ vector unsigned short c = vec_mergel (a,b);
+ return vec_extract (c, 7);
+}
+
+int
+main ()
+{
+ vector unsigned short v1 = {3, 22, 12, 34, 5, 25, 30, 11};
+ vector unsigned short v2 = {84, 168, 267, 966, 65, 399, 999, 99};
+ signed short x1 = elem_2 ((vector signed short) v1, (vector signed short) v2);
+ unsigned short x2 = elem_7 (v1, v2);
+
+ if (x1 != 22 || x2 != 99)
+ __builtin_abort ();
+
+ return 0;
+}
+