@@ -19,20 +19,21 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
-(define_code_iterator SUBST [ashift lshiftrt rotate])
+(define_code_iterator SUBST [ashift lshiftrt rotate ashiftrt])
+(define_mode_iterator DSI_VI [SI DI V2QI V4QI V8QI V16QI V2HI V4HI V8HI V2SI V4SI V2DI])
; This expands an register/immediate operand to a register+immediate
; operand to draw advantage of the address style operand format
; providing a addition for free.
(define_subst "addr_style_op_subst"
- [(set (match_operand:DSI 0 "" "")
- (SUBST:DSI (match_operand:DSI 1 "" "")
- (match_operand:SI 2 "" "")))]
+ [(set (match_operand:DSI_VI 0 "" "")
+ (SUBST:DSI_VI (match_operand:DSI_VI 1 "" "")
+ (match_operand:SI 2 "" "")))]
""
[(set (match_dup 0)
- (SUBST:DSI (match_dup 1)
- (plus:SI (match_operand:SI 2 "register_operand" "a")
- (match_operand 3 "const_int_operand" "n"))))])
+ (SUBST:DSI_VI (match_dup 1)
+ (plus:SI (match_operand:SI 2 "register_operand" "a")
+ (match_operand 3 "const_int_operand" "n"))))])
; Use this in the insn name.
(define_subst_attr "addr_style_op" "addr_style_op_subst" "" "_plus")
@@ -307,44 +307,81 @@
; vec_store_lanes?
+; vec_set is supposed to *modify* an existing vector so operand 0 is
+; duplicated as input operand.
+(define_expand "vec_set<mode>"
+ [(set (match_operand:V 0 "register_operand" "")
+ (unspec:V [(match_operand:<non_vec> 1 "general_operand" "")
+ (match_operand:SI 2 "shift_count_or_setmem_operand" "")
+ (match_dup 0)]
+ UNSPEC_VEC_SET))]
+ "TARGET_VX")
+
; FIXME: Support also vector mode operands for 1
; FIXME: A target memory operand seems to be useful otherwise we end
; up with vl vlvgg vst. Shouldn't the middle-end be able to handle
; that itself?
(define_insn "*vec_set<mode>"
- [(set (match_operand:V 0 "register_operand" "=v, v,v")
- (unspec:V [(match_operand:<non_vec> 1 "general_operand" "d,QR,K")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y, I,I")
- (match_operand:V 3 "register_operand" "0, 0,0")]
+ [(set (match_operand:V 0 "register_operand" "=v,v,v,v")
+ (unspec:V [(match_operand:<non_vec> 1 "general_operand" "d,d,QR,K")
+ (match_operand:SI 2 "nonmemory_operand" "a,n,I,I")
+ (match_operand:V 3 "register_operand" "0,0,0,0")]
UNSPEC_VEC_SET))]
- "TARGET_VX"
+ "TARGET_VX
+ && (!CONST_INT_P (operands[2])
+ || UINTVAL (operands[2]) < GET_MODE_NUNITS (<V:MODE>mode))"
"@
- vlvg<bhfgq>\t%v0,%1,%Y2
+ vlvg<bhfgq>\t%v0,%1,0(%2)
+ vlvg<bhfgq>\t%v0,%1,%2
vle<bhfgq>\t%v0,%1,%2
vlei<bhfgq>\t%v0,%1,%2"
- [(set_attr "op_type" "VRS,VRX,VRI")])
+ [(set_attr "op_type" "VRS,VRS,VRX,VRI")])
+
+(define_insn "*vec_set<mode>_plus"
+ [(set (match_operand:V 0 "register_operand" "=v")
+ (unspec:V [(match_operand:<non_vec> 1 "general_operand" "d")
+ (plus:SI (match_operand:SI 2 "register_operand" "a")
+ (match_operand:SI 4 "const_int_operand" "n"))
+ (match_operand:V 3 "register_operand" "0")]
+ UNSPEC_VEC_SET))]
+ "TARGET_VX"
+ "vlvg<bhfgq>\t%v0,%1,%4(%2)"
+ [(set_attr "op_type" "VRS")])
-; vec_set is supposed to *modify* an existing vector so operand 0 is
-; duplicated as input operand.
-(define_expand "vec_set<mode>"
- [(set (match_operand:V 0 "register_operand" "")
- (unspec:V [(match_operand:<non_vec> 1 "general_operand" "")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "")
- (match_dup 0)]
- UNSPEC_VEC_SET))]
- "TARGET_VX")
; FIXME: Support also vector mode operands for 0
; FIXME: This should be (vec_select ..) or something but it does only allow constant selectors :(
; This is used via RTL standard name as well as for expanding the builtin
-(define_insn "vec_extract<mode>"
- [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "=d,QR")
- (unspec:<non_vec> [(match_operand:V 1 "register_operand" " v, v")
- (match_operand:SI 2 "shift_count_or_setmem_operand" " Y, I")]
+(define_expand "vec_extract<mode>"
+ [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "")
+ (unspec:<non_vec> [(match_operand:V 1 "register_operand" "")
+ (match_operand:SI 2 "shift_count_or_setmem_operand" "")]
UNSPEC_VEC_EXTRACT))]
+ "TARGET_VX")
+
+(define_insn "*vec_extract<mode>"
+ [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "=d,d,QR")
+ (unspec:<non_vec> [(match_operand:V 1 "register_operand" "v,v, v")
+ (match_operand:SI 2 "nonmemory_operand" "a,n, I")]
+ UNSPEC_VEC_EXTRACT))]
+ "TARGET_VX
+ && (!CONST_INT_P (operands[2])
+ || UINTVAL (operands[2]) < GET_MODE_NUNITS (<V:MODE>mode))"
+ "@
+ vlgv<bhfgq>\t%0,%v1,0(%2)
+ vlgv<bhfgq>\t%0,%v1,%2
+ vste<bhfgq>\t%v1,%0,%2"
+ [(set_attr "op_type" "VRS,VRS,VRX")])
+
+(define_insn "*vec_extract<mode>_plus"
+ [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "=d,QR")
+ (unspec:<non_vec> [(match_operand:V 1 "register_operand" "v, v")
+ (plus:SI (match_operand:SI 2 "nonmemory_operand" "a, I")
+ (match_operand:SI 3 "const_int_operand" "n, I"))]
+ UNSPEC_VEC_EXTRACT))]
"TARGET_VX"
"@
- vlgv<bhfgq>\t%0,%v1,%Y2
+ vlgv<bhfgq>\t%0,%v1,%3(%2)
vste<bhfgq>\t%v1,%0,%2"
[(set_attr "op_type" "VRS,VRX")])
@@ -667,17 +704,6 @@
[(set_attr "op_type" "VRR")])
-; Vector rotate instructions
-
-; Each vector element rotated by a scalar
-; verllb, verllh, verllf, verllg
-(define_insn "rotl<mode>3"
- [(set (match_operand:VI 0 "register_operand" "=v")
- (rotate:VI (match_operand:VI 1 "register_operand" "v")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
- "TARGET_VX"
- "verll<bhfgq>\t%v0,%v1,%Y2"
- [(set_attr "op_type" "VRS")])
; Each vector element rotated by the corresponding vector element
; verllvb, verllvh, verllvf, verllvg
@@ -690,35 +716,33 @@
[(set_attr "op_type" "VRR")])
-; Shift each element by scalar value
+; Vector rotate and shift by scalar instructions
-; veslb, veslh, veslf, veslg
-(define_insn "ashl<mode>3"
- [(set (match_operand:VI 0 "register_operand" "=v")
- (ashift:VI (match_operand:VI 1 "register_operand" "v")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
- "TARGET_VX"
- "vesl<bhfgq>\t%v0,%v1,%Y2"
- [(set_attr "op_type" "VRS")])
+(define_code_iterator VEC_SHIFTS [ashift ashiftrt lshiftrt rotate])
+(define_code_attr vec_shifts_name [(ashift "ashl") (ashiftrt "ashr")
+ (lshiftrt "lshr") (rotate "rotl")])
+(define_code_attr vec_shifts_mnem [(ashift "vesl") (ashiftrt "vesra")
+ (lshiftrt "vesrl") (rotate "verll")])
-; vesrab, vesrah, vesraf, vesrag
-(define_insn "ashr<mode>3"
- [(set (match_operand:VI 0 "register_operand" "=v")
- (ashiftrt:VI (match_operand:VI 1 "register_operand" "v")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
- "TARGET_VX"
- "vesra<bhfgq>\t%v0,%v1,%Y2"
- [(set_attr "op_type" "VRS")])
+; Each vector element rotated by a scalar
+(define_expand "<vec_shifts_name><mode>3"
+ [(set (match_operand:VI 0 "register_operand" "")
+ (VEC_SHIFTS:VI (match_operand:VI 1 "register_operand" "")
+ (match_operand:SI 2 "shift_count_or_setmem_operand" "")))]
+ "TARGET_VX")
+; verllb, verllh, verllf, verllg
+; veslb, veslh, veslf, veslg
+; vesrab, vesrah, vesraf, vesrag
; vesrlb, vesrlh, vesrlf, vesrlg
-(define_insn "lshr<mode>3"
- [(set (match_operand:VI 0 "register_operand" "=v")
- (lshiftrt:VI (match_operand:VI 1 "register_operand" "v")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
- "TARGET_VX"
- "vesrl<bhfgq>\t%v0,%v1,%Y2"
- [(set_attr "op_type" "VRS")])
-
+(define_insn "*<vec_shifts_name><mode>3<addr_style_op>"
+ [(set (match_operand:VI 0 "register_operand" "=v,v")
+ (VEC_SHIFTS:VI (match_operand:VI 1 "register_operand" "v,v")
+ (match_operand:SI 2 "nonmemory_operand" "a,n")))]
+ "TARGET_VX"
+ "<vec_shifts_mnem><bhfgq>\t%v0,%v1,%Y2"
+ [(set_attr "enabled" "*,<addr_style_op_enabled>")
+ (set_attr "op_type" "VRS")])
; Shift each element by corresponding vector element