aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2003-04-01 13:40:11 +0000
committerAldy Hernandez <aldyh@gcc.gnu.org>2003-04-01 13:40:11 +0000
commitd744e06e5edeb7dca7bf021559b3bdfdabe12a28 (patch)
tree8129a959cc2632337ea9823f4d5298efac0ea6e5
parent46e33d43a2f80c82284832820287e118c7e7c65c (diff)
downloadgcc-d744e06e5edeb7dca7bf021559b3bdfdabe12a28.zip
gcc-d744e06e5edeb7dca7bf021559b3bdfdabe12a28.tar.gz
gcc-d744e06e5edeb7dca7bf021559b3bdfdabe12a28.tar.bz2
simd-3.c: New.
* testsuite/gcc.c-torture/execute/simd-3.c: New. * expr.c (expand_expr): Handle VECTOR_CST. (const_vector_from_tree): New. * varasm.c (output_constant): Handle VECTOR_CST. * c-typeck.c (digest_init): Build a vector constant from a VECTOR_TYPE. * config/rs6000/rs6000.c: Remove prototype for easy_vector_constant. (easy_vector_constant): Add mode parameter. Rewrite to handle more easy constants. (rs6000_emit_move): Pass mode to easy_vector_constant. Call emit_easy_vector_insn for SPE V2SI vector constant moves. (emit_easy_vector_insn): New. (easy_vector_same): New. (EASY_VECTOR_15): New macro. (EASY_VECTOR_15_ADD_SELF): New macro. (bdesc_2arg): Rename to xorv2si3. (easy_vector_constant_add_self): New. (input_operand): Allow vector constants. * config/rs6000/rs6000.h (PREDICATE_CODES): Add easy_vector_constant, easy_vector_constant_add_self. (EXTRA_CONSTRAINT): Add 'W'. * config/rs6000/rs6000-protos.h: Add prototype for easy_vector_constant, emit_easy_vector_insn. * config/rs6000/altivec.md (xorv8hi3): New. (xorv16qi3): New. Remove all _const0 patterns. (movv4si_internal): Rewrite to use code. Add vector constant to vector alternative. Add splitter. (movv8hi_internal): Same. (movv16qi_internal): Same. (movv4sf_internal): Same. Change the unspecs for vspltis* to use constants. * config/rs6000/spe.md ("xorv4hi3"): New. ("spe_evxor"): Rename to xorv2si3. ("xorv1di3"): New. Remove all _const0 patterns. (movv2si_internal): Rewrite to use code. Add vector constant to alternatives. Add splitter. (movv4hi_internal): Add vector constant to alternatives. (movv1di_internal): Same. (movv2sf_internal): Same. From-SVN: r65130
-rw-r--r--gcc/ChangeLog53
-rw-r--r--gcc/c-typeck.c8
-rw-r--r--gcc/config/rs6000/altivec.md223
-rw-r--r--gcc/config/rs6000/rs6000-protos.h2
-rw-r--r--gcc/config/rs6000/rs6000.c174
-rw-r--r--gcc/config/rs6000/rs6000.h4
-rw-r--r--gcc/config/rs6000/spe.md85
-rw-r--r--gcc/expr.c43
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/varasm.c17
10 files changed, 453 insertions, 160 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a2ebf09..895acf4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,56 @@
+2003-02-31 Aldy Hernandez <aldyh@redhat.com>
+
+ * testsuite/gcc.c-torture/execute/simd-3.c: New.
+
+ * expr.c (expand_expr): Handle VECTOR_CST.
+ (const_vector_from_tree): New.
+
+ * varasm.c (output_constant): Handle VECTOR_CST.
+
+ * c-typeck.c (digest_init): Build a vector constant from a
+ VECTOR_TYPE.
+
+ * config/rs6000/rs6000.c: Remove prototype for
+ easy_vector_constant.
+ (easy_vector_constant): Add mode parameter. Rewrite to handle
+ more easy constants.
+ (rs6000_emit_move): Pass mode to easy_vector_constant.
+ Call emit_easy_vector_insn for SPE V2SI vector constant moves.
+ (emit_easy_vector_insn): New.
+ (easy_vector_same): New.
+ (EASY_VECTOR_15): New macro.
+ (EASY_VECTOR_15_ADD_SELF): New macro.
+ (bdesc_2arg): Rename to xorv2si3.
+ (easy_vector_constant_add_self): New.
+ (input_operand): Allow vector constants.
+
+ * config/rs6000/rs6000.h (PREDICATE_CODES): Add
+ easy_vector_constant, easy_vector_constant_add_self.
+ (EXTRA_CONSTRAINT): Add 'W'.
+
+ * config/rs6000/rs6000-protos.h: Add prototype for
+ easy_vector_constant, emit_easy_vector_insn.
+
+ * config/rs6000/altivec.md (xorv8hi3): New.
+ (xorv16qi3): New.
+ Remove all _const0 patterns.
+ (movv4si_internal): Rewrite to use code. Add vector constant to
+ vector alternative. Add splitter.
+ (movv8hi_internal): Same.
+ (movv16qi_internal): Same.
+ (movv4sf_internal): Same.
+ Change the unspecs for vspltis* to use constants.
+
+ * config/rs6000/spe.md ("xorv4hi3"): New.
+ ("spe_evxor"): Rename to xorv2si3.
+ ("xorv1di3"): New.
+ Remove all _const0 patterns.
+ (movv2si_internal): Rewrite to use code. Add vector constant to
+ alternatives. Add splitter.
+ (movv4hi_internal): Add vector constant to alternatives.
+ (movv1di_internal): Same.
+ (movv2sf_internal): Same.
+
2003-03-31 Mark Mitchell <mark@codesourcery.com>
PR c/9936
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 8fbcd86..ce37eea 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -4759,6 +4759,14 @@ digest_init (type, init, require_constant)
}
}
+ /* Build a VECTOR_CST from a *constant* vector constructor. If the
+ vector constructor is not constant (e.g. {1,2,3,foo()}) then punt
+ below and handle as a constructor. */
+ if (code == VECTOR_TYPE
+ && comptypes (TREE_TYPE (inside_init), type)
+ && TREE_CONSTANT (inside_init))
+ return build_vector (type, TREE_OPERAND (inside_init, 1));
+
/* Any type can be initialized
from an expression of the same type, optionally with braces. */
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 4632fd5..1d35f80 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -19,6 +19,12 @@
;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
+(define_constants
+ [(UNSPEC_VSPLTISW 141)
+ (UNSPEC_VSPLTISH 140)
+ (UNSPEC_VSPLTISB 139)
+ ])
+
;; Generic LVX load instruction.
(define_insn "altivec_lvx_4si"
[(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
@@ -85,18 +91,37 @@
"{ rs6000_emit_move (operands[0], operands[1], V4SImode); DONE; }")
(define_insn "*movv4si_internal"
- [(set (match_operand:V4SI 0 "nonimmediate_operand" "=m,v,v,o,r,r")
- (match_operand:V4SI 1 "input_operand" "v,m,v,r,o,r"))]
- "TARGET_ALTIVEC"
- "@
- stvx %1,%y0
- lvx %0,%y1
- vor %0,%1,%1
- stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
- lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
- mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
- [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*")
- (set_attr "length" "*,*,*,16,16,16")])
+ [(set (match_operand:V4SI 0 "nonimmediate_operand" "=m,v,v,o,r,r,v")
+ (match_operand:V4SI 1 "input_operand" "v,m,v,r,o,r,W"))]
+ "TARGET_ALTIVEC"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0: return \"stvx %1,%y0\";
+ case 1: return \"lvx %0,%y1\";
+ case 2: return \"vor %0,%1,%1\";
+ case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
+ case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
+ case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+ case 6: return output_vec_const_move (operands);
+ default: abort();
+ }
+}"
+ [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
+ (set_attr "length" "*,*,*,16,16,16,*")])
+
+(define_split
+ [(set (match_operand:V4SI 0 "altivec_register_operand" "")
+ (match_operand:V4SI 1 "easy_vector_constant_add_self" ""))]
+ "TARGET_ALTIVEC && reload_completed"
+ [(set (match_dup 0)
+ (unspec:V4SI [(match_dup 3)] UNSPEC_VSPLTISW))
+ (set (match_dup 0)
+ (plus:V4SI (match_dup 0)
+ (match_dup 0)))]
+ "
+{ operands[3] = GEN_INT (INTVAL (CONST_VECTOR_ELT (operands[1], 0)) >> 1); }")
(define_expand "movv8hi"
[(set (match_operand:V8HI 0 "nonimmediate_operand" "")
@@ -105,18 +130,37 @@
"{ rs6000_emit_move (operands[0], operands[1], V8HImode); DONE; }")
(define_insn "*movv8hi_internal1"
- [(set (match_operand:V8HI 0 "nonimmediate_operand" "=m,v,v,o,r,r")
- (match_operand:V8HI 1 "input_operand" "v,m,v,r,o,r"))]
- "TARGET_ALTIVEC"
- "@
- stvx %1,%y0
- lvx %0,%y1
- vor %0,%1,%1
- stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
- lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
- mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
- [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*")
- (set_attr "length" "*,*,*,16,16,16")])
+ [(set (match_operand:V8HI 0 "nonimmediate_operand" "=m,v,v,o,r,r,v")
+ (match_operand:V8HI 1 "input_operand" "v,m,v,r,o,r,W"))]
+ "TARGET_ALTIVEC"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0: return \"stvx %1,%y0\";
+ case 1: return \"lvx %0,%y1\";
+ case 2: return \"vor %0,%1,%1\";
+ case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
+ case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
+ case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+ case 6: return output_vec_const_move (operands);
+ default: abort ();
+ }
+}"
+ [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
+ (set_attr "length" "*,*,*,16,16,16,*")])
+
+(define_split
+ [(set (match_operand:V8HI 0 "altivec_register_operand" "")
+ (match_operand:V8HI 1 "easy_vector_constant_add_self" ""))]
+ "TARGET_ALTIVEC && reload_completed"
+ [(set (match_dup 0)
+ (unspec:V8HI [(match_dup 3)] UNSPEC_VSPLTISH))
+ (set (match_dup 0)
+ (plus:V8HI (match_dup 0)
+ (match_dup 0)))]
+ "
+{ operands[3] = GEN_INT (INTVAL (CONST_VECTOR_ELT (operands[1], 0)) >> 1); }")
(define_expand "movv16qi"
[(set (match_operand:V16QI 0 "nonimmediate_operand" "")
@@ -125,18 +169,37 @@
"{ rs6000_emit_move (operands[0], operands[1], V16QImode); DONE; }")
(define_insn "*movv16qi_internal1"
- [(set (match_operand:V16QI 0 "nonimmediate_operand" "=m,v,v,o,r,r")
- (match_operand:V16QI 1 "input_operand" "v,m,v,r,o,r"))]
- "TARGET_ALTIVEC"
- "@
- stvx %1,%y0
- lvx %0,%y1
- vor %0,%1,%1
- stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
- lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
- mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
- [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*")
- (set_attr "length" "*,*,*,16,16,16")])
+ [(set (match_operand:V16QI 0 "nonimmediate_operand" "=m,v,v,o,r,r,v")
+ (match_operand:V16QI 1 "input_operand" "v,m,v,r,o,r,W"))]
+ "TARGET_ALTIVEC"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0: return \"stvx %1,%y0\";
+ case 1: return \"lvx %0,%y1\";
+ case 2: return \"vor %0,%1,%1\";
+ case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
+ case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
+ case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+ case 6: return output_vec_const_move (operands);
+ default: abort ();
+ }
+}"
+ [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
+ (set_attr "length" "*,*,*,16,16,16,*")])
+
+(define_split
+ [(set (match_operand:V16QI 0 "altivec_register_operand" "")
+ (match_operand:V16QI 1 "easy_vector_constant_add_self" ""))]
+ "TARGET_ALTIVEC && reload_completed"
+ [(set (match_dup 0)
+ (unspec:V16QI [(match_dup 3)] UNSPEC_VSPLTISB))
+ (set (match_dup 0)
+ (plus:V16QI (match_dup 0)
+ (match_dup 0)))]
+ "
+{ operands[3] = GEN_INT (INTVAL (CONST_VECTOR_ELT (operands[1], 0)) >> 1); }")
(define_expand "movv4sf"
[(set (match_operand:V4SF 0 "nonimmediate_operand" "")
@@ -145,18 +208,25 @@
"{ rs6000_emit_move (operands[0], operands[1], V4SFmode); DONE; }")
(define_insn "*movv4sf_internal1"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "=m,v,v,o,r,r")
- (match_operand:V4SF 1 "input_operand" "v,m,v,r,o,r"))]
- "TARGET_ALTIVEC"
- "@
- stvx %1,%y0
- lvx %0,%y1
- vor %0,%1,%1
- stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
- lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
- mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
- [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*")
- (set_attr "length" "*,*,*,16,16,16")])
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "=m,v,v,o,r,r,v")
+ (match_operand:V4SF 1 "input_operand" "v,m,v,r,o,r,W"))]
+ "TARGET_ALTIVEC"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0: return \"stvx %1,%y0\";
+ case 1: return \"lvx %0,%y1\";
+ case 2: return \"vor %0,%1,%1\";
+ case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
+ case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
+ case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+ case 6: return output_vec_const_move (operands);
+ default: abort ();
+ }
+}"
+ [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
+ (set_attr "length" "*,*,*,16,16,16,*")])
(define_insn "get_vrsave_internal"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -186,36 +256,6 @@
}"
[(set_attr "type" "*")])
-;; Vector clears
-(define_insn "*movv4si_const0"
- [(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
- (match_operand:V4SI 1 "zero_constant" ""))]
- "TARGET_ALTIVEC"
- "vxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "*movv4sf_const0"
- [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
- (match_operand:V4SF 1 "zero_constant" ""))]
-
- "TARGET_ALTIVEC"
- "vxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "*movv8hi_const0"
- [(set (match_operand:V8HI 0 "altivec_register_operand" "=v")
- (match_operand:V8HI 1 "zero_constant" ""))]
- "TARGET_ALTIVEC"
- "vxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "*movv16qi_const0"
- [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
- (match_operand:V16QI 1 "zero_constant" ""))]
- "TARGET_ALTIVEC"
- "vxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
;; Simple binary operations.
(define_insn "addv16qi3"
@@ -1279,6 +1319,7 @@
"vsumsws %0,%1,%2"
[(set_attr "type" "veccomplex")])
+;; Vector xor's
(define_insn "xorv4si3"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(xor:V4SI (match_operand:V4SI 1 "register_operand" "v")
@@ -1287,6 +1328,22 @@
"vxor %0,%1,%2"
[(set_attr "type" "vecsimple")])
+(define_insn "xorv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (xor:V8HI (match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vxor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "xorv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (xor:V16QI (match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vxor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
(define_insn "altivec_vspltb"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
@@ -1294,6 +1351,7 @@
"TARGET_ALTIVEC"
"vspltb %0,%1,%2"
[(set_attr "type" "vecperm")])
+;; End of vector xor's
(define_insn "altivec_vsplth"
[(set (match_operand:V8HI 0 "register_operand" "=v")
@@ -1313,21 +1371,24 @@
(define_insn "altivec_vspltisb"
[(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:QI 1 "immediate_operand" "i")] 139))]
+ (unspec:V16QI [(match_operand:QI 1 "immediate_operand" "i")]
+ UNSPEC_VSPLTISB))]
"TARGET_ALTIVEC"
"vspltisb %0,%1"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vspltish"
[(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:QI 1 "immediate_operand" "i")] 140))]
+ (unspec:V8HI [(match_operand:QI 1 "immediate_operand" "i")]
+ UNSPEC_VSPLTISH))]
"TARGET_ALTIVEC"
"vspltish %0,%1"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vspltisw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:QI 1 "immediate_operand" "i")] 141))]
+ (unspec:V4SI [(match_operand:QI 1 "immediate_operand" "i")]
+ UNSPEC_VSPLTISW))]
"TARGET_ALTIVEC"
"vspltisw %0,%1"
[(set_attr "type" "vecperm")])
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 8dcfd87..3bd3b73 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -54,6 +54,8 @@ extern int got_operand PARAMS ((rtx, enum machine_mode));
extern int got_no_const_operand PARAMS ((rtx, enum machine_mode));
extern int num_insns_constant PARAMS ((rtx, enum machine_mode));
extern int easy_fp_constant PARAMS ((rtx, enum machine_mode));
+extern int easy_vector_constant PARAMS ((rtx, enum machine_mode));
+extern const char *output_vec_const_move PARAMS ((rtx *));
extern int zero_fp_constant PARAMS ((rtx, enum machine_mode));
extern int zero_constant PARAMS ((rtx, enum machine_mode));
extern int volatile_mem_operand PARAMS ((rtx, enum machine_mode));
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index b910520..0de56c1 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -55,6 +55,13 @@ Boston, MA 02111-1307, USA. */
#define TARGET_NO_PROTOTYPE 0
#endif
+#define EASY_VECTOR_15(n, x, y) ((n) >= -16 && (n) <= 15 \
+ && easy_vector_same (x, y))
+
+#define EASY_VECTOR_15_ADD_SELF(n, x, y) ((n) >= 0x10 && (n) <= 0x1e \
+ && !((n) & 1) \
+ && easy_vector_same (x, y))
+
#define min(A,B) ((A) < (B) ? (A) : (B))
#define max(A,B) ((A) > (B) ? (A) : (B))
@@ -266,7 +273,8 @@ static int first_altivec_reg_to_save PARAMS ((void));
static unsigned int compute_vrsave_mask PARAMS ((void));
static void is_altivec_return_reg PARAMS ((rtx, void *));
static rtx generate_set_vrsave PARAMS ((rtx, rs6000_stack_t *, int));
-static int easy_vector_constant PARAMS ((rtx));
+int easy_vector_constant PARAMS ((rtx, enum machine_mode));
+static int easy_vector_same PARAMS ((rtx, enum machine_mode));
static bool is_ev64_opaque_type PARAMS ((tree));
static rtx rs6000_dwarf_register_span PARAMS ((rtx));
@@ -1416,48 +1424,149 @@ easy_fp_constant (op, mode)
abort ();
}
-/* Return 1 if the operand is a CONST_INT and can be put into a
- register with one instruction. */
+/* Return non zero if all elements of a vector have the same value. */
static int
-easy_vector_constant (op)
+easy_vector_same (op, mode)
rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
- rtx elt;
- int units, i;
+ int units, i, cst;
+
+ units = CONST_VECTOR_NUNITS (op);
- if (GET_CODE (op) != CONST_VECTOR)
+ cst = INTVAL (CONST_VECTOR_ELT (op, 0));
+ for (i = 1; i < units; ++i)
+ if (INTVAL (CONST_VECTOR_ELT (op, i)) != cst)
+ break;
+ if (i == units)
+ return 1;
+ return 0;
+}
+
+/* Return 1 if the operand is a CONST_INT and can be put into a
+ register without using memory. */
+
+int
+easy_vector_constant (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int cst, cst2;
+
+ if (GET_CODE (op) != CONST_VECTOR
+ || (!TARGET_ALTIVEC
+ && !TARGET_SPE))
return 0;
- units = CONST_VECTOR_NUNITS (op);
+ if (zero_constant (op, mode)
+ && ((TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
+ || (TARGET_SPE && SPE_VECTOR_MODE (mode))))
+ return 1;
- /* We can generate 0 easily. Look for that. */
- for (i = 0; i < units; ++i)
- {
- elt = CONST_VECTOR_ELT (op, i);
+ if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
+ return 0;
+
+ cst = INTVAL (CONST_VECTOR_ELT (op, 0));
+ cst2 = INTVAL (CONST_VECTOR_ELT (op, 1));
+
+ /* Limit SPE vectors to 15 bits signed. These we can generate with:
+ li r0, CONSTANT1
+ evmergelo r0, r0, r0
+ li r0, CONSTANT2
+
+ I don't know how efficient it would be to allow bigger constants,
+ considering we'll have an extra 'ori' for every 'li'. I doubt 5
+ instructions is better than a 64-bit memory load, but I don't
+ have the e500 timing specs. */
+ if (TARGET_SPE && mode == V2SImode
+ && cst >= -0x7fff && cst <= 0x7fff
+ && cst2 >= -0x7fff && cst <= 0x7fff)
+ return 1;
+
+ if (TARGET_ALTIVEC && EASY_VECTOR_15 (cst, op, mode))
+ return 1;
+
+ if (TARGET_ALTIVEC && EASY_VECTOR_15_ADD_SELF (cst, op, mode))
+ return 1;
+
+ return 0;
+}
+
+/* Same as easy_vector_constant but only for EASY_VECTOR_15_ADD_SELF. */
+
+int
+easy_vector_constant_add_self (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int cst;
- /* We could probably simplify this by just checking for equality
- with CONST0_RTX for the current mode, but let's be safe
- instead. */
+ if (!easy_vector_constant (op, mode))
+ return 0;
+
+ cst = INTVAL (CONST_VECTOR_ELT (op, 0));
+
+ return TARGET_ALTIVEC && EASY_VECTOR_15_ADD_SELF (cst, op, mode);
+}
+
+const char *
+output_vec_const_move (operands)
+ rtx *operands;
+{
+ int cst, cst2;
+ enum machine_mode mode;
+ rtx dest, vec;
+
+ dest = operands[0];
+ vec = operands[1];
- switch (GET_CODE (elt))
+ cst = INTVAL (CONST_VECTOR_ELT (vec, 0));
+ cst2 = INTVAL (CONST_VECTOR_ELT (vec, 1));
+ mode = GET_MODE (dest);
+
+ if (TARGET_ALTIVEC)
+ {
+ if (zero_constant (vec, mode))
+ return "vxor %0,%0,%0";
+ else if (EASY_VECTOR_15 (cst, vec, mode))
{
- case CONST_INT:
- if (INTVAL (elt) != 0)
- return 0;
- break;
- case CONST_DOUBLE:
- if (CONST_DOUBLE_LOW (elt) != 0 || CONST_DOUBLE_HIGH (elt) != 0)
- return 0;
- break;
- default:
- return 0;
+ operands[1] = GEN_INT (cst);
+ switch (mode)
+ {
+ case V4SImode:
+ return "vspltisw %0,%1";
+ case V8HImode:
+ return "vspltish %0,%1";
+ case V16QImode:
+ return "vspltisb %0,%1";
+ default:
+ abort ();
+ }
}
+ else if (EASY_VECTOR_15_ADD_SELF (cst, vec, mode))
+ return "#";
+ else
+ abort ();
}
- /* We could probably generate a few other constants trivially, but
- gcc doesn't generate them yet. FIXME later. */
- return 1;
+ if (TARGET_SPE)
+ {
+ /* Vector constant 0 is handled as a splitter of V2SI, and in the
+ pattern of V1DI, V4HI, and V2SF.
+
+ FIXME: We should probabl return # and add post reload
+ splitters for these, but this way is so easy ;-).
+ */
+ operands[1] = GEN_INT (cst);
+ operands[2] = GEN_INT (cst2);
+ if (cst == cst2)
+ return "li %0,%1\n\tevmergelo %0,%0,%0";
+ else
+ return "li %0,%1\n\tevmergelo %0,%0,%0\n\tli %0,%2";
+ }
+
+ abort ();
}
/* Return 1 if the operand is the constant 0. This works for scalars
@@ -1990,6 +2099,11 @@ input_operand (op, mode)
|| GET_CODE (op) == CONST_DOUBLE))
return 1;
+ /* Allow easy vector constants. */
+ if (GET_CODE (op) == CONST_VECTOR
+ && easy_vector_constant (op, mode))
+ return 1;
+
/* For floating-point or multi-word mode, the only remaining valid type
is a register. */
if (GET_MODE_CLASS (mode) == MODE_FLOAT
@@ -2744,7 +2858,7 @@ rs6000_emit_move (dest, source, mode)
case V2SImode:
case V1DImode:
if (CONSTANT_P (operands[1])
- && !easy_vector_constant (operands[1]))
+ && !easy_vector_constant (operands[1], mode))
operands[1] = force_const_mem (mode, operands[1]);
break;
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index b13c403..0d8085c 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -1292,6 +1292,7 @@ enum reg_class
'S' is a constant that can be placed into a 64-bit mask operand
'T' is a constant that can be placed into a 32-bit mask operand
'U' is for V.4 small data references.
+ 'W' is a vector constant that can be easily generated (no mem refs).
't' is for AND masks that can be performed by two rldic{l,r} insns. */
#define EXTRA_CONSTRAINT(OP, C) \
@@ -1305,6 +1306,7 @@ enum reg_class
&& (fixed_regs[CR0_REGNO] \
|| !logical_operand (OP, DImode)) \
&& !mask64_operand (OP, DImode)) \
+ : (C) == 'W' ? (easy_vector_constant (OP, GET_MODE (OP))) \
: 0)
/* Given an rtx X being reloaded into a reg required to be
@@ -2740,6 +2742,8 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */
{"got_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \
{"got_no_const_operand", {SYMBOL_REF, LABEL_REF}}, \
{"easy_fp_constant", {CONST_DOUBLE}}, \
+ {"easy_vector_constant", {CONST_VECTOR}}, \
+ {"easy_vector_constant_add_self", {CONST_VECTOR}}, \
{"zero_fp_constant", {CONST_DOUBLE}}, \
{"reg_or_mem_operand", {SUBREG, MEM, REG}}, \
{"lwa_operand", {SUBREG, MEM, REG}}, \
diff --git a/gcc/config/rs6000/spe.md b/gcc/config/rs6000/spe.md
index a1ba680..30a07f9 100644
--- a/gcc/config/rs6000/spe.md
+++ b/gcc/config/rs6000/spe.md
@@ -2147,36 +2147,6 @@
[(set_attr "type" "vecstore")
(set_attr "length" "4")])
-;; SPE vector clears
-
-(define_insn "*movv2si_const0"
- [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
- (match_operand:V2SI 1 "zero_constant" ""))]
- "TARGET_SPE"
- "evxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "*movv2sf_const0"
- [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
- (match_operand:V2SF 1 "zero_constant" ""))]
- "TARGET_SPE"
- "evxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "*movv4hi_const0"
- [(set (match_operand:V4HI 0 "gpc_reg_operand" "=r")
- (match_operand:V4HI 1 "zero_constant" ""))]
- "TARGET_SPE"
- "evxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "*movv1di_const0"
- [(set (match_operand:V1DI 0 "gpc_reg_operand" "=r")
- (match_operand:V1DI 1 "zero_constant" ""))]
- "TARGET_SPE"
- "evxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
;; Vector move instructions.
(define_expand "movv2si"
@@ -2185,16 +2155,31 @@
"TARGET_SPE"
"{ rs6000_emit_move (operands[0], operands[1], V2SImode); DONE; }")
-
(define_insn "*movv2si_internal"
- [(set (match_operand:V2SI 0 "nonimmediate_operand" "=m,r,r")
- (match_operand:V2SI 1 "input_operand" "r,m,r"))]
- "TARGET_SPE"
- "@
- evstdd%X0 %1,%y0
- evldd%X1 %0,%y1
- evor %0,%1,%1"
- [(set_attr "type" "vecload,vecload,vecsimple")])
+ [(set (match_operand:V2SI 0 "nonimmediate_operand" "=m,r,r,r")
+ (match_operand:V2SI 1 "input_operand" "r,m,r,W"))]
+ "TARGET_SPE"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0: return \"evstdd%X0 %1,%y0\";
+ case 1: return \"evldd%X1 %0,%y1\";
+ case 2: return \"evor %0,%1,%1\";
+ case 3: return output_vec_const_move (operands);
+ default: abort ();
+ }
+}"
+ [(set_attr "type" "vecload,vecstore,*,*")
+ (set_attr "length" "*,*,*,12")])
+
+(define_split
+ [(set (match_operand:V2SI 0 "register_operand" "")
+ (match_operand:V2SI 1 "zero_constant" ""))]
+ "TARGET_SPE && reload_completed"
+ [(set (match_dup 0)
+ (xor:V2SI (match_dup 0) (match_dup 0)))]
+ "")
(define_expand "movv1di"
[(set (match_operand:V1DI 0 "nonimmediate_operand" "")
@@ -2203,14 +2188,16 @@
"{ rs6000_emit_move (operands[0], operands[1], V1DImode); DONE; }")
(define_insn "*movv1di_internal"
- [(set (match_operand:V1DI 0 "nonimmediate_operand" "=m,r,r")
- (match_operand:V1DI 1 "input_operand" "r,m,r"))]
+ [(set (match_operand:V1DI 0 "nonimmediate_operand" "=m,r,r,r")
+ (match_operand:V1DI 1 "input_operand" "r,m,r,W"))]
"TARGET_SPE"
"@
evstdd%X0 %1,%y0
evldd%X1 %0,%y1
- evor %0,%1,%1"
- [(set_attr "type" "vecload,vecload,vecsimple")])
+ evor %0,%1,%1
+ evxor %0,%0,%0"
+ [(set_attr "type" "vecload,vecstore,*,*")
+ (set_attr "length" "*,*,*,*")])
(define_expand "movv4hi"
[(set (match_operand:V4HI 0 "nonimmediate_operand" "")
@@ -2226,7 +2213,7 @@
evstdd%X0 %1,%y0
evldd%X1 %0,%y1
evor %0,%1,%1"
- [(set_attr "type" "vecload,vecload,vecsimple")])
+ [(set_attr "type" "vecload")])
(define_expand "movv2sf"
[(set (match_operand:V2SF 0 "nonimmediate_operand" "")
@@ -2235,14 +2222,16 @@
"{ rs6000_emit_move (operands[0], operands[1], V2SFmode); DONE; }")
(define_insn "*movv2sf_internal"
- [(set (match_operand:V2SF 0 "nonimmediate_operand" "=m,r,r")
- (match_operand:V2SF 1 "input_operand" "r,m,r"))]
+ [(set (match_operand:V2SF 0 "nonimmediate_operand" "=m,r,r,r")
+ (match_operand:V2SF 1 "input_operand" "r,m,r,W"))]
"TARGET_SPE"
"@
evstdd%X0 %1,%y0
evldd%X1 %0,%y1
- evor %0,%1,%1"
- [(set_attr "type" "vecload,vecload,vecsimple")])
+ evor %0,%1,%1
+ evxor %0,%0,%0"
+ [(set_attr "type" "vecload,vecstore,*,*")
+ (set_attr "length" "*,*,*,*")])
(define_insn "spe_evmwhssfaa"
[(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
diff --git a/gcc/expr.c b/gcc/expr.c
index a957dd7..e9d0ee5 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -155,7 +155,7 @@ static rtx clear_storage_via_libcall PARAMS ((rtx, rtx));
static tree clear_storage_libcall_fn PARAMS ((int));
static rtx compress_float_constant PARAMS ((rtx, rtx));
static rtx get_subtarget PARAMS ((rtx));
-static int is_zeros_p PARAMS ((tree));
+static int is_zeros_p PARAMS ((tree));
static int mostly_zeros_p PARAMS ((tree));
static void store_constructor_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
HOST_WIDE_INT, enum machine_mode,
@@ -175,6 +175,7 @@ static rtx do_store_flag PARAMS ((tree, rtx, enum machine_mode, int));
static void emit_single_push_insn PARAMS ((enum machine_mode, rtx, tree));
#endif
static void do_tablejump PARAMS ((rtx, enum machine_mode, rtx, rtx, rtx));
+static rtx const_vector_from_tree PARAMS ((tree));
/* Record for each mode whether we can move a register directly to or
from an object of that mode in memory. If we can't, we won't try
@@ -6842,6 +6843,9 @@ expand_expr (exp, target, tmode, modifier)
return temp;
+ case VECTOR_CST:
+ return const_vector_from_tree (exp);
+
case CONST_DECL:
return expand_expr (DECL_INITIAL (exp), target, VOIDmode, modifier);
@@ -10329,4 +10333,41 @@ vector_mode_valid_p (mode)
return mov_optab->handlers[innermode].insn_code != CODE_FOR_nothing;
}
+/* Return a CONST_VECTOR rtx for a VECTOR_CST tree. */
+static rtx
+const_vector_from_tree (exp)
+ tree exp;
+{
+ rtvec v;
+ int units, i;
+ tree link, elt;
+ enum machine_mode inner, mode;
+
+ mode = TYPE_MODE (TREE_TYPE (exp));
+
+ if (is_zeros_p (exp))
+ return CONST0_RTX (mode);
+
+ units = GET_MODE_NUNITS (mode);
+ inner = GET_MODE_INNER (mode);
+
+ v = rtvec_alloc (units);
+
+ link = TREE_VECTOR_CST_ELTS (exp);
+ for (i = 0; link; link = TREE_CHAIN (link), ++i)
+ {
+ elt = TREE_VALUE (link);
+
+ if (TREE_CODE (elt) == REAL_CST)
+ RTVEC_ELT (v, i) = CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (elt),
+ inner);
+ else
+ RTVEC_ELT (v, i) = immed_double_const (TREE_INT_CST_LOW (elt),
+ TREE_INT_CST_HIGH (elt),
+ inner);
+ }
+
+ return gen_rtx_raw_CONST_VECTOR (mode, v);
+}
+
#include "gt-expr.h"
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c6196fb..2bae494 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2003-03-01 Aldy Hernandez <aldyh@redhat.com>
+
+ * testsuite/gcc.c-torture/execute/simd-3.c: New.
+
2003-03-31 Mark Mitchell <mark@codesourcery.com>
PR c/9936
diff --git a/gcc/varasm.c b/gcc/varasm.c
index fc6f467..9c93e9b 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -4015,6 +4015,23 @@ output_constant (exp, size, align)
thissize = MIN (TREE_STRING_LENGTH (exp), size);
assemble_string (TREE_STRING_POINTER (exp), thissize);
}
+ else if (TREE_CODE (exp) == VECTOR_CST)
+ {
+ int elt_size;
+ tree link;
+ unsigned int nalign;
+ enum machine_mode inner;
+
+ inner = GET_MODE_INNER (TYPE_MODE (TREE_TYPE (exp)));
+ nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
+
+ elt_size = GET_MODE_UNIT_SIZE (TYPE_MODE (TREE_TYPE (exp)));
+
+ link = TREE_VECTOR_CST_ELTS (exp);
+ output_constant (TREE_VALUE (link), elt_size, align);
+ while ((link = TREE_CHAIN (link)) != NULL)
+ output_constant (TREE_VALUE (link), elt_size, nalign);
+ }
else
abort ();
break;