This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH 4/6] rs6000: Cleanup interleave/even_odd/vec_perm.
- From: Richard Henderson <rth at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: richard dot earnshaw at arm dot com, ramana dot radhakrishnan at linaro dot org, jakub at redhat dot com, dje dot gcc at gmail dot com, sje at cup dot hp dot com, rdsandiford at googlemail dot com, mingjie dot xing at gmail dot com, meissner at linux dot vnet dot ibm dot com
- Date: Thu, 8 Dec 2011 13:06:21 -0800
- Subject: [PATCH 4/6] rs6000: Cleanup interleave/even_odd/vec_perm.
- References: <1323378383-9824-1-git-send-email-rth@redhat.com>
Put merge-type insns in standard (vec_select (vec_concat)) form.
Delete vec_extract_{even,odd} patterns.
Delete or rename vec_interleave_{high,low} patterns.
Add vec_perm_const patterns for SPE, VSX, and Paired-Single.
---
gcc/config/rs6000/altivec.md | 368 +++++++---------------------------
gcc/config/rs6000/paired.md | 116 ++++-------
gcc/config/rs6000/predicates.md | 10 +
gcc/config/rs6000/rs6000-builtin.def | 8 +-
gcc/config/rs6000/rs6000-modes.def | 10 +-
gcc/config/rs6000/rs6000-protos.h | 3 +
gcc/config/rs6000/rs6000.c | 160 +++++++++++++++-
gcc/config/rs6000/spe.md | 58 +++---
gcc/config/rs6000/vector.md | 74 +------
gcc/config/rs6000/vsx.md | 151 +++++++++-----
10 files changed, 431 insertions(+), 527 deletions(-)
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 7797b65..54ca369 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -327,7 +327,7 @@
(define_insn "*altivec_addv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(plus:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")))]
+ (match_operand:V4SF 2 "register_operand" "v")))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vaddfp %0,%1,%2"
[(set_attr "type" "vecfloat")])
@@ -764,202 +764,112 @@
(define_insn "altivec_vmrghb"
[(set (match_operand:V16QI 0 "register_operand" "=v")
- (vec_merge:V16QI (vec_select:V16QI (match_operand:V16QI 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)
- (const_int 4)
- (const_int 12)
- (const_int 5)
- (const_int 13)
- (const_int 6)
- (const_int 14)
- (const_int 7)
- (const_int 15)]))
- (vec_select:V16QI (match_operand:V16QI 2 "register_operand" "v")
- (parallel [(const_int 8)
- (const_int 0)
- (const_int 9)
- (const_int 1)
- (const_int 10)
- (const_int 2)
- (const_int 11)
- (const_int 3)
- (const_int 12)
- (const_int 4)
- (const_int 13)
- (const_int 5)
- (const_int 14)
- (const_int 6)
- (const_int 15)
- (const_int 7)]))
- (const_int 21845)))]
+ (vec_select:V16QI
+ (vec_concat:V32QI
+ (match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v"))
+ (parallel [(const_int 0) (const_int 16)
+ (const_int 1) (const_int 17)
+ (const_int 2) (const_int 18)
+ (const_int 3) (const_int 19)
+ (const_int 4) (const_int 20)
+ (const_int 5) (const_int 21)
+ (const_int 6) (const_int 22)
+ (const_int 7) (const_int 23)])))]
"TARGET_ALTIVEC"
"vmrghb %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vmrghh"
[(set (match_operand:V8HI 0 "register_operand" "=v")
- (vec_merge:V8HI (vec_select:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (parallel [(const_int 0)
- (const_int 4)
- (const_int 1)
- (const_int 5)
- (const_int 2)
- (const_int 6)
- (const_int 3)
- (const_int 7)]))
- (vec_select:V8HI (match_operand:V8HI 2 "register_operand" "v")
- (parallel [(const_int 4)
- (const_int 0)
- (const_int 5)
- (const_int 1)
- (const_int 6)
- (const_int 2)
- (const_int 7)
- (const_int 3)]))
- (const_int 85)))]
+ (vec_select:V8HI
+ (vec_concat:V16HI
+ (match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "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"
"vmrghh %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vmrghw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (vec_merge:V4SI (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "v")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (const_int 5)))]
+ (vec_select:V4SI
+ (vec_concat:V8SI
+ (match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v"))
+ (parallel [(const_int 0) (const_int 4)
+ (const_int 1) (const_int 5)])))]
"VECTOR_MEM_ALTIVEC_P (V4SImode)"
"vmrghw %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "*altivec_vmrghsf"
[(set (match_operand:V4SF 0 "register_operand" "=v")
- (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (const_int 5)))]
+ (vec_select:V4SF
+ (vec_concat:V8SF
+ (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v"))
+ (parallel [(const_int 0) (const_int 4)
+ (const_int 1) (const_int 5)])))]
"VECTOR_MEM_ALTIVEC_P (V4SFmode)"
"vmrghw %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vmrglb"
[(set (match_operand:V16QI 0 "register_operand" "=v")
- (vec_merge:V16QI (vec_select:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (parallel [(const_int 8)
- (const_int 0)
- (const_int 9)
- (const_int 1)
- (const_int 10)
- (const_int 2)
- (const_int 11)
- (const_int 3)
- (const_int 12)
- (const_int 4)
- (const_int 13)
- (const_int 5)
- (const_int 14)
- (const_int 6)
- (const_int 15)
- (const_int 7)]))
- (vec_select:V16QI (match_operand:V16QI 2 "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)
- (const_int 4)
- (const_int 12)
- (const_int 5)
- (const_int 13)
- (const_int 6)
- (const_int 14)
- (const_int 7)
- (const_int 15)]))
- (const_int 21845)))]
+ (vec_select:V16QI
+ (vec_concat:V32QI
+ (match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v"))
+ (parallel [(const_int 8) (const_int 24)
+ (const_int 9) (const_int 25)
+ (const_int 10) (const_int 26)
+ (const_int 11) (const_int 27)
+ (const_int 12) (const_int 28)
+ (const_int 13) (const_int 29)
+ (const_int 14) (const_int 30)
+ (const_int 15) (const_int 31)])))]
"TARGET_ALTIVEC"
"vmrglb %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vmrglh"
[(set (match_operand:V8HI 0 "register_operand" "=v")
- (vec_merge:V8HI (vec_select:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (parallel [(const_int 4)
- (const_int 0)
- (const_int 5)
- (const_int 1)
- (const_int 6)
- (const_int 2)
- (const_int 7)
- (const_int 3)]))
- (vec_select:V8HI (match_operand:V8HI 2 "register_operand" "v")
- (parallel [(const_int 0)
- (const_int 4)
- (const_int 1)
- (const_int 5)
- (const_int 2)
- (const_int 6)
- (const_int 3)
- (const_int 7)]))
- (const_int 85)))]
+ (vec_select:V8HI
+ (vec_concat:V16HI
+ (match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "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"
"vmrglh %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vmrglw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (vec_merge:V4SI
- (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "v")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (const_int 5)))]
+ (vec_select:V4SI
+ (vec_concat:V8SI
+ (match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v"))
+ (parallel [(const_int 2) (const_int 6)
+ (const_int 3) (const_int 7)])))]
"VECTOR_MEM_ALTIVEC_P (V4SImode)"
"vmrglw %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "*altivec_vmrglsf"
[(set (match_operand:V4SF 0 "register_operand" "=v")
- (vec_merge:V4SF
- (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (const_int 5)))]
+ (vec_select:V4SF
+ (vec_concat:V8SF
+ (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v"))
+ (parallel [(const_int 2) (const_int 6)
+ (const_int 3) (const_int 7)])))]
"VECTOR_MEM_ALTIVEC_P (V4SFmode)"
"vmrglw %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -1332,7 +1242,7 @@
(define_insn "*altivec_vrfiz"
[(set (match_operand:V4SF 0 "register_operand" "=v")
- (fix:V4SF (match_operand:V4SF 1 "register_operand" "v")))]
+ (fix:V4SF (match_operand:V4SF 1 "register_operand" "v")))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
"vrfiz %0,%1"
[(set_attr "type" "vecfloat")])
@@ -1507,7 +1417,7 @@
(define_insn "altivec_vupkhsb"
[(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")]
+ (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")]
UNSPEC_VUPKHSB))]
"TARGET_ALTIVEC"
"vupkhsb %0,%1"
@@ -1515,7 +1425,7 @@
(define_insn "altivec_vupkhpx"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
UNSPEC_VUPKHPX))]
"TARGET_ALTIVEC"
"vupkhpx %0,%1"
@@ -1523,7 +1433,7 @@
(define_insn "altivec_vupkhsh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
UNSPEC_VUPKHSH))]
"TARGET_ALTIVEC"
"vupkhsh %0,%1"
@@ -1531,7 +1441,7 @@
(define_insn "altivec_vupklsb"
[(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")]
+ (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")]
UNSPEC_VUPKLSB))]
"TARGET_ALTIVEC"
"vupklsb %0,%1"
@@ -1539,7 +1449,7 @@
(define_insn "altivec_vupklpx"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
UNSPEC_VUPKLPX))]
"TARGET_ALTIVEC"
"vupklpx %0,%1"
@@ -1547,7 +1457,7 @@
(define_insn "altivec_vupklsh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
UNSPEC_VUPKLSH))]
"TARGET_ALTIVEC"
"vupklsh %0,%1"
@@ -2442,140 +2352,6 @@
"stvrxl %1,%y0"
[(set_attr "type" "vecstore")])
-;; ??? This is still used directly by vector.md
-(define_expand "vec_extract_evenv4si"
- [(set (match_operand:V4SI 0 "register_operand" "")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "")
- (match_operand:V4SI 2 "register_operand" "")]
- UNSPEC_EXTEVEN_V4SI))]
- "TARGET_ALTIVEC"
- "
-{
- rtx mask = gen_reg_rtx (V16QImode);
- rtvec v = rtvec_alloc (16);
-
- RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, 0);
- RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, 1);
- RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, 2);
- RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, 3);
- RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, 8);
- RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, 9);
- RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, 10);
- RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, 11);
- RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, 18);
- RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, 19);
- RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, 24);
- RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, 25);
- RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, 26);
- RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, 27);
- emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
- emit_insn (gen_altivec_vperm_v4si (operands[0], operands[1], operands[2], mask));
-
- DONE;
-}")
-
-;; ??? This is still used directly by vector.md
-(define_expand "vec_extract_evenv4sf"
- [(set (match_operand:V4SF 0 "register_operand" "")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "")
- (match_operand:V4SF 2 "register_operand" "")]
- UNSPEC_EXTEVEN_V4SF))]
- "TARGET_ALTIVEC"
- "
-{
- rtx mask = gen_reg_rtx (V16QImode);
- rtvec v = rtvec_alloc (16);
-
- RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, 0);
- RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, 1);
- RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, 2);
- RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, 3);
- RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, 8);
- RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, 9);
- RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, 10);
- RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, 11);
- RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, 18);
- RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, 19);
- RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, 24);
- RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, 25);
- RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, 26);
- RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, 27);
- emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
- emit_insn (gen_altivec_vperm_v4sf (operands[0], operands[1], operands[2], mask));
-
- DONE;
-}")
-
-(define_insn "vpkuhum_nomode"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand 1 "register_operand" "v")
- (match_operand 2 "register_operand" "v")]
- UNSPEC_VPKUHUM))]
- "TARGET_ALTIVEC"
- "vpkuhum %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "vpkuwum_nomode"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand 1 "register_operand" "v")
- (match_operand 2 "register_operand" "v")]
- UNSPEC_VPKUWUM))]
- "TARGET_ALTIVEC"
- "vpkuwum %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_expand "vec_extract_oddv8hi"
- [(set (match_operand:V8HI 0 "register_operand" "")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "")
- (match_operand:V8HI 2 "register_operand" "")]
- UNSPEC_EXTODD_V8HI))]
- "TARGET_ALTIVEC"
- "
-{
- emit_insn (gen_vpkuwum_nomode (operands[0], operands[1], operands[2]));
- DONE;
-}")
-
-(define_expand "vec_extract_oddv16qi"
- [(set (match_operand:V16QI 0 "register_operand" "")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "")
- (match_operand:V16QI 2 "register_operand" "")]
- UNSPEC_EXTODD_V16QI))]
- "TARGET_ALTIVEC"
- "
-{
- emit_insn (gen_vpkuhum_nomode (operands[0], operands[1], operands[2]));
- DONE;
-}")
-
-(define_expand "vec_interleave_high<mode>"
- [(set (match_operand:VI 0 "register_operand" "")
- (unspec:VI [(match_operand:VI 1 "register_operand" "")
- (match_operand:VI 2 "register_operand" "")]
- UNSPEC_INTERHI))]
- "TARGET_ALTIVEC"
- "
-{
- emit_insn (gen_altivec_vmrgh<VI_char> (operands[0], operands[1], operands[2]));
- DONE;
-}")
-
-(define_expand "vec_interleave_low<mode>"
- [(set (match_operand:VI 0 "register_operand" "")
- (unspec:VI [(match_operand:VI 1 "register_operand" "")
- (match_operand:VI 2 "register_operand" "")]
- UNSPEC_INTERLO))]
- "TARGET_ALTIVEC"
- "
-{
- emit_insn (gen_altivec_vmrgl<VI_char> (operands[0], operands[1], operands[2]));
- DONE;
-}")
-
(define_expand "vec_unpacks_float_hi_v8hi"
[(set (match_operand:V4SF 0 "register_operand" "")
(unspec:V4SF [(match_operand:V8HI 1 "register_operand" "")]
diff --git a/gcc/config/rs6000/paired.md b/gcc/config/rs6000/paired.md
index f0bf7f9..c52d90f 100644
--- a/gcc/config/rs6000/paired.md
+++ b/gcc/config/rs6000/paired.md
@@ -272,48 +272,61 @@
(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)]))))]
+ (vec_select:V2SF
+ (vec_concat:V4SF
+ (match_operand:V2SF 1 "gpc_reg_operand" "f")
+ (match_operand:V2SF 2 "gpc_reg_operand" "f"))
+ (parallel [(const_int 0) (const_int 2)])))]
"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)]))))]
+ (vec_select:V2SF
+ (vec_concat:V4SF
+ (match_operand:V2SF 1 "gpc_reg_operand" "f")
+ (match_operand:V2SF 2 "gpc_reg_operand" "f"))
+ (parallel [(const_int 0) (const_int 3)])))]
"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)]))))]
+ (vec_select:V2SF
+ (vec_concat:V4SF
+ (match_operand:V2SF 1 "gpc_reg_operand" "f")
+ (match_operand:V2SF 2 "gpc_reg_operand" "f"))
+ (parallel [(const_int 1) (const_int 2)])))]
"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)]))))]
+ (vec_select:V2SF
+ (vec_concat:V4SF
+ (match_operand:V2SF 1 "gpc_reg_operand" "f")
+ (match_operand:V2SF 2 "gpc_reg_operand" "f"))
+ (parallel [(const_int 1) (const_int 3)])))]
"TARGET_PAIRED_FLOAT"
"ps_merge11 %0, %1, %2"
[(set_attr "type" "fp")])
+(define_expand "vec_perm_constv2sf"
+ [(match_operand:V2SF 0 "gpc_reg_operand" "")
+ (match_operand:V2SF 1 "gpc_reg_operand" "")
+ (match_operand:V2SF 2 "gpc_reg_operand" "")
+ (match_operand:V2SI 3 "" "")]
+ "TARGET_PAIRED_FLOAT"
+{
+ if (paired_expand_vec_perm_const (operands))
+ DONE;
+ else
+ FAIL;
+})
+
(define_insn "paired_sum0"
[(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
(vec_concat:V2SF (plus:SF (vec_select:SF
@@ -439,55 +452,6 @@
DONE;
})
-(define_expand "vec_interleave_highv2sf"
- [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
- (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "f")
- (match_operand:V2SF 2 "gpc_reg_operand" "f")]
- UNSPEC_INTERHI_V2SF))]
- "TARGET_PAIRED_FLOAT"
- "
-{
- emit_insn (gen_paired_merge00 (operands[0], operands[1], operands[2]));
- DONE;
-}")
-
-(define_expand "vec_interleave_lowv2sf"
- [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
- (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "f")
- (match_operand:V2SF 2 "gpc_reg_operand" "f")]
- UNSPEC_INTERLO_V2SF))]
- "TARGET_PAIRED_FLOAT"
- "
-{
- emit_insn (gen_paired_merge11 (operands[0], operands[1], operands[2]));
- DONE;
-}")
-
-(define_expand "vec_extract_evenv2sf"
- [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
- (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "f")
- (match_operand:V2SF 2 "gpc_reg_operand" "f")]
- UNSPEC_EXTEVEN_V2SF))]
- "TARGET_PAIRED_FLOAT"
- "
-{
- emit_insn (gen_paired_merge00 (operands[0], operands[1], operands[2]));
- DONE;
-}")
-
-(define_expand "vec_extract_oddv2sf"
- [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
- (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "f")
- (match_operand:V2SF 2 "gpc_reg_operand" "f")]
- UNSPEC_EXTODD_V2SF))]
- "TARGET_PAIRED_FLOAT"
- "
-{
- emit_insn (gen_paired_merge11 (operands[0], operands[1], operands[2]));
- DONE;
-}")
-
-
(define_expand "reduc_splus_v2sf"
[(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
(match_operand:V2SF 1 "gpc_reg_operand" "f"))]
@@ -516,12 +480,10 @@
(match_operand:V2SF 1 "gpc_reg_operand" "f")
(match_operand:V2SF 2 "gpc_reg_operand" "f")))]
"TARGET_PAIRED_FLOAT && flag_unsafe_math_optimizations"
- "
{
- if (paired_emit_vector_cond_expr (operands[0], operands[1], operands[2],
- operands[3], operands[4], operands[5]))
- DONE;
- else
- FAIL;
-}")
-
+ if (paired_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+ operands[3], operands[4], operands[5]))
+ DONE;
+ else
+ FAIL;
+})
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index e407eda..29dd18d 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -112,6 +112,16 @@
(and (match_code "const_int")
(match_test "INTVAL (op) > 0 && exact_log2 (INTVAL (op)) >= 0")))
+;; Match op = 0 or op = 1.
+(define_predicate "const_0_to_1_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 0, 1)")))
+
+;; Match op = 2 or op = 3.
+(define_predicate "const_2_to_3_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 2, 3)")))
+
;; Return 1 if op is a register that is not special.
(define_predicate "gpc_reg_operand"
(and (match_operand 0 "register_operand")
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index 25880ea..776350b 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -984,10 +984,10 @@ BU_VSX_2 (XXMRGHW_4SF, "xxmrghw", CONST, vsx_xxmrghw_v4sf)
BU_VSX_2 (XXMRGHW_4SI, "xxmrghw_4si", CONST, vsx_xxmrghw_v4si)
BU_VSX_2 (XXMRGLW_4SF, "xxmrglw", CONST, vsx_xxmrglw_v4sf)
BU_VSX_2 (XXMRGLW_4SI, "xxmrglw_4si", CONST, vsx_xxmrglw_v4si)
-BU_VSX_2 (VEC_MERGEL_V2DF, "mergel_2df", CONST, vec_interleave_lowv2df)
-BU_VSX_2 (VEC_MERGEL_V2DI, "mergel_2di", CONST, vec_interleave_lowv2di)
-BU_VSX_2 (VEC_MERGEH_V2DF, "mergeh_2df", CONST, vec_interleave_highv2df)
-BU_VSX_2 (VEC_MERGEH_V2DI, "mergeh_2di", CONST, vec_interleave_highv2di)
+BU_VSX_2 (VEC_MERGEL_V2DF, "mergel_2df", CONST, vsx_mergel_v2df)
+BU_VSX_2 (VEC_MERGEL_V2DI, "mergel_2di", CONST, vsx_mergel_v2di)
+BU_VSX_2 (VEC_MERGEH_V2DF, "mergeh_2df", CONST, vsx_mergeh_v2df)
+BU_VSX_2 (VEC_MERGEH_V2DI, "mergeh_2di", CONST, vsx_mergeh_v2di)
/* VSX abs builtin functions. */
BU_VSX_A (XVABSDP, "xvabsdp", CONST, absv2df2)
diff --git a/gcc/config/rs6000/rs6000-modes.def b/gcc/config/rs6000/rs6000-modes.def
index 724c947..f72f40d 100644
--- a/gcc/config/rs6000/rs6000-modes.def
+++ b/gcc/config/rs6000/rs6000-modes.def
@@ -34,8 +34,10 @@ CC_MODE (CCFP);
CC_MODE (CCEQ);
/* Vector modes. */
-VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */
-VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */
+VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */
+VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */
+VECTOR_MODES (INT, 32); /* V32QI V16HI V8SI V4DI */
VECTOR_MODE (INT, DI, 1);
-VECTOR_MODES (FLOAT, 8); /* V4HF V2SF */
-VECTOR_MODES (FLOAT, 16); /* V8HF V4SF V2DF */
+VECTOR_MODES (FLOAT, 8); /* V4HF V2SF */
+VECTOR_MODES (FLOAT, 16); /* V8HF V4SF V2DF */
+VECTOR_MODES (FLOAT, 32); /* V16HF V8SF V4DF */
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index f2ed084..7dfc187 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -56,6 +56,9 @@ extern void paired_expand_vector_init (rtx, rtx);
extern void rs6000_expand_vector_set (rtx, rtx, int);
extern void rs6000_expand_vector_extract (rtx, rtx, int);
extern bool altivec_expand_vec_perm_const (rtx op[4]);
+extern bool paired_expand_vec_perm_const (rtx op[4]);
+extern void rs6000_expand_extract_even (rtx, rtx, rtx);
+extern void rs6000_expand_interleave (rtx, rtx, rtx, bool);
extern void build_mask64_2_operands (rtx, rtx *);
extern int expand_block_clear (rtx[]);
extern int expand_block_move (rtx[]);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 9be155d..8be6b3a 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1661,6 +1661,8 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P rs6000_legitimate_constant_p
+#undef TARGET_VECTORIZE_VEC_PERM_CONST_OK
+#define TARGET_VECTORIZE_VEC_PERM_CONST_OK rs6000_vectorize_vec_perm_const_ok
/* Simplifications for entries below. */
@@ -4723,7 +4725,7 @@ rs6000_expand_vector_init (rtx target, rtx vals)
copy_to_reg (XVECEXP (vals, 0, 3))));
emit_insn (gen_vsx_xvcvdpsp (flt_even, dbl_even));
emit_insn (gen_vsx_xvcvdpsp (flt_odd, dbl_odd));
- emit_insn (gen_vec_extract_evenv4sf (target, flt_even, flt_odd));
+ rs6000_expand_extract_even (target, flt_even, flt_odd);
}
return;
}
@@ -26377,6 +26379,162 @@ altivec_expand_vec_perm_const (rtx operands[4])
return false;
}
+/* Expand a Paired Single, VSX Permute Doubleword, or SPE constant permutation.
+ Return true if we match an efficient implementation. */
+
+static bool
+paired_expand_vec_perm_const_1 (rtx target, rtx op0, rtx op1,
+ unsigned char perm0, unsigned char perm1)
+{
+ rtx x;
+
+ /* If both selectors come from the same operand, fold to single op. */
+ if ((perm0 & 2) == (perm1 & 2))
+ {
+ if (perm0 & 2)
+ op0 = op1;
+ else
+ op1 = op0;
+ }
+ /* If both operands are equal, fold to simpler permutation. */
+ if (rtx_equal_p (op0, op1))
+ {
+ perm0 = perm0 & 1;
+ perm1 = (perm1 & 1) + 2;
+ }
+ /* If the first selector comes from the second operand, swap. */
+ else if (perm0 & 2)
+ {
+ if (perm1 & 2)
+ return false;
+ perm0 -= 2;
+ perm1 += 2;
+ x = op0, op0 = op1, op1 = x;
+ }
+ /* If the second selector does not come from the second operand, fail. */
+ else if ((perm1 & 2) == 0)
+ return false;
+
+ /* Success! */
+ if (target != NULL)
+ {
+ enum machine_mode vmode, dmode;
+ rtvec v;
+
+ vmode = GET_MODE (target);
+ gcc_assert (GET_MODE_NUNITS (vmode) == 2);
+ dmode = mode_for_vector (GET_MODE_INNER (vmode), 4);
+
+ x = gen_rtx_VEC_CONCAT (dmode, op0, op1);
+ v = gen_rtvec (2, GEN_INT (perm0), GEN_INT (perm1));
+ x = gen_rtx_VEC_SELECT (vmode, x, gen_rtx_PARALLEL (VOIDmode, v));
+ emit_insn (gen_rtx_SET (VOIDmode, target, x));
+ }
+ return true;
+}
+
+bool
+paired_expand_vec_perm_const (rtx operands[4])
+{
+ rtx target, op0, op1, sel;
+ unsigned char perm0, perm1;
+
+ target = operands[0];
+ op0 = operands[1];
+ op1 = operands[2];
+ sel = operands[3];
+
+ /* Unpack the constant selector. */
+ perm0 = INTVAL (XVECEXP (sel, 0, 0)) & 3;
+ perm1 = INTVAL (XVECEXP (sel, 0, 1)) & 3;
+
+ return paired_expand_vec_perm_const_1 (target, op0, op1, perm0, perm1);
+}
+
+/* Test whether a constant permutation is supported. */
+
+static bool
+rs6000_vectorize_vec_perm_const_ok (enum machine_mode vmode,
+ const unsigned char *sel)
+{
+ rtx op0, op1;
+
+ /* AltiVec can handle arbitrary permutations. */
+ if (TARGET_ALTIVEC)
+ return true;
+
+ /* ??? Do we ever have VSX without AltiVec? If so, then we need to
+ check for both xxpermdi and xxmrg[hl]w. The former can be done
+ with paired_expand_vec_perm_const_1 above; the latter would need
+ other matching. */
+
+ if (TARGET_PAIRED_FLOAT && vmode == V2SFmode)
+ ; /* Check for ps_merge* insns. */
+ else if (TARGET_SPE && vmode == V2SImode)
+ ; /* Check for evmerge* insns. */
+ else
+ return false;
+
+ op0 = gen_raw_REG (vmode, LAST_VIRTUAL_REGISTER + 1);
+ op1 = gen_raw_REG (vmode, LAST_VIRTUAL_REGISTER + 2);
+ return paired_expand_vec_perm_const_1 (NULL, op0, op1, sel[0], sel[1]);
+}
+
+/* Expand an extract even operation. */
+
+void
+rs6000_expand_extract_even (rtx target, rtx op0, rtx op1)
+{
+ enum machine_mode vmode = GET_MODE (target);
+ enum machine_mode imode;
+ unsigned i, nelt = GET_MODE_NUNITS (vmode);
+ rtx perm[16], x;
+
+ for (i = 0; i < nelt; i++)
+ perm[i] = GEN_INT (i * 2);
+
+ imode = vmode;
+ if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT)
+ imode = mode_for_vector (mode_for_size (GET_MODE_UNIT_SIZE (vmode),
+ MODE_INT, 0),
+ nelt);
+
+ x = gen_rtx_CONST_VECTOR (imode, gen_rtvec_v (nelt, perm));
+ x = expand_vec_perm (vmode, op0, op1, x, target);
+ if (x != target)
+ emit_move_insn (target, x);
+}
+
+/* Expand a vector interleave operation. */
+
+void
+rs6000_expand_interleave (rtx target, rtx op0, rtx op1, bool highp)
+{
+ enum machine_mode vmode = GET_MODE (target);
+ enum machine_mode imode;
+ unsigned i, high, nelt = GET_MODE_NUNITS (vmode);
+ rtx perm[16], x;
+
+ high = (highp == TARGET_BIG_ENDIAN ? 0 : nelt);
+
+ for (i = 0; i < nelt / 2; i++)
+ {
+ perm[i * 2] = GEN_INT (i + high);
+ perm[i * 2 + 1] = GEN_INT (i + nelt + high);
+ }
+
+ imode = vmode;
+ if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT)
+ imode = mode_for_vector (mode_for_size (GET_MODE_UNIT_SIZE (vmode),
+ MODE_INT, 0),
+ nelt);
+
+ x = gen_rtx_CONST_VECTOR (imode, gen_rtvec_v (nelt, perm));
+ x = expand_vec_perm (vmode, op0, op1, x, target);
+ if (x != target)
+ emit_move_insn (target, x);
+}
+
/* Return an RTX representing where to find the function value of a
function returning MODE. */
static rtx
diff --git a/gcc/config/rs6000/spe.md b/gcc/config/rs6000/spe.md
index d50ad1a..0895e7c 100644
--- a/gcc/config/rs6000/spe.md
+++ b/gcc/config/rs6000/spe.md
@@ -441,12 +441,11 @@
(define_insn "spe_evmergehi"
[(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
- (vec_merge:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
- (vec_select:V2SI
- (match_operand:V2SI 2 "gpc_reg_operand" "r")
- (parallel [(const_int 1)
- (const_int 0)]))
- (const_int 2)))]
+ (vec_select:V2SI
+ (vec_concat:V4SI
+ (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (parallel [(const_int 0) (const_int 2)])))]
"TARGET_SPE"
"evmergehi %0,%1,%2"
[(set_attr "type" "vecsimple")
@@ -454,9 +453,11 @@
(define_insn "spe_evmergehilo"
[(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
- (vec_merge:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
- (match_operand:V2SI 2 "gpc_reg_operand" "r")
- (const_int 2)))]
+ (vec_select:V2SI
+ (vec_concat:V4SI
+ (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (parallel [(const_int 0) (const_int 3)])))]
"TARGET_SPE"
"evmergehilo %0,%1,%2"
[(set_attr "type" "vecsimple")
@@ -464,12 +465,11 @@
(define_insn "spe_evmergelo"
[(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
- (vec_merge:V2SI (vec_select:V2SI
- (match_operand:V2SI 1 "gpc_reg_operand" "r")
- (parallel [(const_int 1)
- (const_int 0)]))
- (match_operand:V2SI 2 "gpc_reg_operand" "r")
- (const_int 2)))]
+ (vec_select:V2SI
+ (vec_concat:V4SI
+ (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (parallel [(const_int 1) (const_int 3)])))]
"TARGET_SPE"
"evmergelo %0,%1,%2"
[(set_attr "type" "vecsimple")
@@ -477,20 +477,30 @@
(define_insn "spe_evmergelohi"
[(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
- (vec_merge:V2SI (vec_select:V2SI
- (match_operand:V2SI 1 "gpc_reg_operand" "r")
- (parallel [(const_int 1)
- (const_int 0)]))
- (vec_select:V2SI
- (match_operand:V2SI 2 "gpc_reg_operand" "r")
- (parallel [(const_int 1)
- (const_int 0)]))
- (const_int 2)))]
+ (vec_select:V2SI
+ (vec_concat:V4SI
+ (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (parallel [(const_int 1) (const_int 2)])))]
"TARGET_SPE"
"evmergelohi %0,%1,%2"
[(set_attr "type" "vecsimple")
(set_attr "length" "4")])
+(define_expand "vec_perm_constv2si"
+ [(match_operand:V2SI 0 "gpc_reg_operand" "")
+ (match_operand:V2SI 1 "gpc_reg_operand" "")
+ (match_operand:V2SI 2 "gpc_reg_operand" "")
+ (match_operand:V2SI 3 "" "")]
+ "TARGET_SPE"
+{
+ /* Yes, this looks a bit funny, but it's the same pattern different modes. */
+ if (paired_expand_vec_perm_const (operands))
+ DONE;
+ else
+ FAIL;
+})
+
(define_insn "spe_evnand"
[(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
(not:V2SI (and:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md
index 4930f8c..bcb23ac 100644
--- a/gcc/config/rs6000/vector.md
+++ b/gcc/config/rs6000/vector.md
@@ -747,62 +747,6 @@
INTVAL (operands[2]));
DONE;
})
-
-;; Interleave patterns
-(define_expand "vec_interleave_highv4sf"
- [(set (match_operand:V4SF 0 "vfloat_operand" "")
- (vec_merge:V4SF
- (vec_select:V4SF (match_operand:V4SF 1 "vfloat_operand" "")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (vec_select:V4SF (match_operand:V4SF 2 "vfloat_operand" "")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (const_int 5)))]
- "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
- "")
-
-(define_expand "vec_interleave_lowv4sf"
- [(set (match_operand:V4SF 0 "vfloat_operand" "")
- (vec_merge:V4SF
- (vec_select:V4SF (match_operand:V4SF 1 "vfloat_operand" "")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (vec_select:V4SF (match_operand:V4SF 2 "vfloat_operand" "")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (const_int 5)))]
- "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
- "")
-
-(define_expand "vec_interleave_high<mode>"
- [(set (match_operand:VEC_64 0 "vfloat_operand" "")
- (vec_concat:VEC_64
- (vec_select:<VEC_base> (match_operand:VEC_64 1 "vfloat_operand" "")
- (parallel [(const_int 0)]))
- (vec_select:<VEC_base> (match_operand:VEC_64 2 "vfloat_operand" "")
- (parallel [(const_int 0)]))))]
- "VECTOR_UNIT_VSX_P (<MODE>mode)"
- "")
-
-(define_expand "vec_interleave_low<mode>"
- [(set (match_operand:VEC_64 0 "vfloat_operand" "")
- (vec_concat:VEC_64
- (vec_select:<VEC_base> (match_operand:VEC_64 1 "vfloat_operand" "")
- (parallel [(const_int 1)]))
- (vec_select:<VEC_base> (match_operand:VEC_64 2 "vfloat_operand" "")
- (parallel [(const_int 1)]))))]
- "VECTOR_UNIT_VSX_P (<MODE>mode)"
- "")
-
;; Convert double word types to single word types
(define_expand "vec_pack_trunc_v2df"
@@ -816,7 +760,7 @@
emit_insn (gen_vsx_xvcvdpsp (r1, operands[1]));
emit_insn (gen_vsx_xvcvdpsp (r2, operands[2]));
- emit_insn (gen_vec_extract_evenv4sf (operands[0], r1, r2));
+ rs6000_expand_extract_even (operands[0], r1, r2);
DONE;
})
@@ -831,7 +775,7 @@
emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1]));
emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2]));
- emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2));
+ rs6000_expand_extract_even (operands[0], r1, r2);
DONE;
})
@@ -846,7 +790,7 @@
emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1]));
emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2]));
- emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2));
+ rs6000_expand_extract_even (operands[0], r1, r2);
DONE;
})
@@ -858,7 +802,7 @@
{
rtx reg = gen_reg_rtx (V4SFmode);
- emit_insn (gen_vec_interleave_highv4sf (reg, operands[1], operands[1]));
+ rs6000_expand_interleave (reg, operands[1], operands[1], true);
emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
DONE;
})
@@ -870,7 +814,7 @@
{
rtx reg = gen_reg_rtx (V4SFmode);
- emit_insn (gen_vec_interleave_lowv4sf (reg, operands[1], operands[1]));
+ rs6000_expand_interleave (reg, operands[1], operands[1], false);
emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
DONE;
})
@@ -882,7 +826,7 @@
{
rtx reg = gen_reg_rtx (V4SImode);
- emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1]));
+ rs6000_expand_interleave (reg, operands[1], operands[1], true);
emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
DONE;
})
@@ -894,7 +838,7 @@
{
rtx reg = gen_reg_rtx (V4SImode);
- emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1]));
+ rs6000_expand_interleave (reg, operands[1], operands[1], false);
emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
DONE;
})
@@ -906,7 +850,7 @@
{
rtx reg = gen_reg_rtx (V4SImode);
- emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1]));
+ rs6000_expand_interleave (reg, operands[1], operands[1], true);
emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
DONE;
})
@@ -918,7 +862,7 @@
{
rtx reg = gen_reg_rtx (V4SImode);
- emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1]));
+ rs6000_expand_interleave (reg, operands[1], operands[1], false);
emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
DONE;
})
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index fb86034..f55f0c6 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -180,7 +180,13 @@
(V4SI "SI")
(V8HI "HI")
(V16QI "QI")])
-
+
+;; Map to a double-sized vector mode
+(define_mode_attr VS_double [(V4SI "V8SI")
+ (V4SF "V8SF")
+ (V2DI "V4DI")
+ (V2DF "V4DF")])
+
;; Constants for creating unspecs
(define_c_enum "unspec"
[UNSPEC_VSX_CONCAT
@@ -195,7 +201,6 @@
UNSPEC_VSX_CVSPUXDS
UNSPEC_VSX_TDIV
UNSPEC_VSX_TSQRT
- UNSPEC_VSX_XXPERMDI
UNSPEC_VSX_SET
UNSPEC_VSX_ROUND_I
UNSPEC_VSX_ROUND_IC
@@ -352,7 +357,7 @@
(define_insn "*vsx_div<mode>3"
[(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
(div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
"x<VSv>div<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_div>")
@@ -1184,39 +1189,89 @@
[(set_attr "length" "4,8")
(set_attr "type" "fp")])
-;; General double word oriented permute, allow the other vector types for
-;; optimizing the permute instruction.
-(define_insn "vsx_xxpermdi_<mode>"
- [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wd,?wa")
- (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wd,wa")
- (match_operand:VSX_L 2 "vsx_register_operand" "wd,wa")
- (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
- UNSPEC_VSX_XXPERMDI))]
+;; Expand the builtin form of xxpermdi to canonical rtl.
+(define_expand "vsx_xxpermdi_<mode>"
+ [(match_operand:VSX_L 0 "vsx_register_operand" "")
+ (match_operand:VSX_L 1 "vsx_register_operand" "")
+ (match_operand:VSX_L 2 "vsx_register_operand" "")
+ (match_operand:QI 3 "u5bit_cint_operand" "")]
"VECTOR_MEM_VSX_P (<MODE>mode)"
- "xxpermdi %x0,%x1,%x2,%3"
- [(set_attr "type" "vecperm")])
+{
+ rtx target = operands[0];
+ rtx op0 = operands[1];
+ rtx op1 = operands[2];
+ int mask = INTVAL (operands[3]);
+ rtx perm0 = GEN_INT ((mask >> 1) & 1);
+ rtx perm1 = GEN_INT ((mask & 1) + 2);
+ rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
+
+ if (<MODE>mode == V2DFmode)
+ gen = gen_vsx_xxpermdi2_v2df_1;
+ else
+ {
+ gen = gen_vsx_xxpermdi2_v2di_1;
+ if (<MODE>mode != V2DImode)
+ {
+ target = gen_lowpart (V2DImode, target);
+ op0 = gen_lowpart (V2DImode, target);
+ op1 = gen_lowpart (V2DImode, target);
+ }
+ }
+ emit_insn (gen (target, op0, op1, perm0, perm1));
+ DONE;
+})
-;; Varient of xxpermdi that is emitted by the vec_interleave functions
-(define_insn "*vsx_xxpermdi2_<mode>"
+(define_insn "vsx_xxpermdi2_<mode>_1"
[(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
- (vec_concat:VSX_D
- (vec_select:<VS_scalar>
- (match_operand:VSX_D 1 "vsx_register_operand" "wd")
- (parallel
- [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
- (vec_select:<VS_scalar>
- (match_operand:VSX_D 3 "vsx_register_operand" "wd")
- (parallel
- [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
+ (vec_select:VSX_D
+ (vec_concat:<VS_double>
+ (match_operand:VSX_D 1 "vsx_register_operand" "wd")
+ (match_operand:VSX_D 2 "vsx_register_operand" "wd"))
+ (parallel [(match_operand 3 "const_0_to_1_operand" "")
+ (match_operand 4 "const_2_to_3_operand" "")])))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
{
- gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1));
- operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
- | (INTVAL (operands[4]) & 1));
- return \"xxpermdi %x0,%x1,%x3,%5\";
+ int mask = (INTVAL (operands[3]) << 1) | (INTVAL (operands[4]) - 2);
+ operands[3] = GEN_INT (mask);
+ return "xxpermdi %x0,%x1,%x2,%3";
}
[(set_attr "type" "vecperm")])
+(define_expand "vec_perm_const<mode>"
+ [(match_operand:VSX_D 0 "vsx_register_operand" "")
+ (match_operand:VSX_D 1 "vsx_register_operand" "")
+ (match_operand:VSX_D 2 "vsx_register_operand" "")
+ (match_operand:V2DI 3 "" "")]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+{
+ /* Yes, this looks a bit funny, but it's the same pattern different modes. */
+ if (paired_expand_vec_perm_const (operands))
+ DONE;
+ else
+ FAIL;
+})
+
+;; Expanders for builtins
+(define_expand "vsx_mergel_<mode>"
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "")
+ (vec_select:VSX_D
+ (vec_concat:<VS_double>
+ (match_operand:VSX_D 1 "vsx_register_operand" "")
+ (match_operand:VSX_D 2 "vsx_register_operand" ""))
+ (parallel [(const_int 1) (const_int 3)])))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "")
+
+(define_expand "vsx_mergeh_<mode>"
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "")
+ (vec_select:VSX_D
+ (vec_concat:<VS_double>
+ (match_operand:VSX_D 1 "vsx_register_operand" "")
+ (match_operand:VSX_D 2 "vsx_register_operand" ""))
+ (parallel [(const_int 0) (const_int 2)])))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
+ "")
+
;; V2DF/V2DI splat
(define_insn "vsx_splat_<mode>"
[(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
@@ -1247,40 +1302,24 @@
;; V4SF/V4SI interleave
(define_insn "vsx_xxmrghw_<mode>"
[(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
- (vec_merge:VSX_W
- (vec_select:VSX_W
- (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (vec_select:VSX_W
- (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (const_int 5)))]
+ (vec_select:VSX_W
+ (vec_concat:<VS_double>
+ (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
+ (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa"))
+ (parallel [(const_int 0) (const_int 4)
+ (const_int 1) (const_int 5)])))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
"xxmrghw %x0,%x1,%x2"
[(set_attr "type" "vecperm")])
(define_insn "vsx_xxmrglw_<mode>"
[(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
- (vec_merge:VSX_W
- (vec_select:VSX_W
- (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (vec_select:VSX_W
- (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (const_int 5)))]
+ (vec_select:VSX_W
+ (vec_concat:<VS_double>
+ (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
+ (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa"))
+ (parallel [(const_int 2) (const_int 6)
+ (const_int 3) (const_int 7)])))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
"xxmrglw %x0,%x1,%x2"
[(set_attr "type" "vecperm")])
--
1.7.7.3