@@ -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" "")]
@@ -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;
+})
@@ -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")
@@ -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)
@@ -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 */
@@ -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[]);
@@ -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
@@ -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")
@@ -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;
})
@@ -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")])