summaryrefslogtreecommitdiff
path: root/gcc/config/rs6000
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/rs6000')
-rw-r--r--gcc/config/rs6000/altivec.md21
-rw-r--r--gcc/config/rs6000/rs6000-protos.h1
-rw-r--r--gcc/config/rs6000/rs6000.c117
3 files changed, 89 insertions, 50 deletions
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 684a5d4c4b9..3e27a1b86c2 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -124,13 +124,14 @@
[(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) (match_dup 3))
(set (match_dup 0)
(plus:V4SI (match_dup 0)
(match_dup 0)))]
"
-{ operands[3] = GEN_INT (INTVAL (CONST_VECTOR_ELT (operands[1], 0)) >> 1); }")
+{
+ operands[3] = gen_easy_vector_constant_add_self (operands[1]);
+}")
(define_expand "movv8hi"
[(set (match_operand:V8HI 0 "nonimmediate_operand" "")
@@ -172,13 +173,14 @@
[(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) (match_dup 3))
(set (match_dup 0)
(plus:V8HI (match_dup 0)
(match_dup 0)))]
"
-{ operands[3] = GEN_INT (INTVAL (CONST_VECTOR_ELT (operands[1], 0)) >> 1); }")
+{
+ operands[3] = gen_easy_vector_constant_add_self (operands[1]);
+}")
(define_expand "movv16qi"
[(set (match_operand:V16QI 0 "nonimmediate_operand" "")
@@ -220,13 +222,14 @@
[(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) (match_dup 3))
(set (match_dup 0)
(plus:V16QI (match_dup 0)
(match_dup 0)))]
"
-{ operands[3] = GEN_INT (INTVAL (CONST_VECTOR_ELT (operands[1], 0)) >> 1); }")
+{
+ operands[3] = gen_easy_vector_constant_add_self (operands[1]);
+}")
(define_expand "movv4sf"
[(set (match_operand:V4SF 0 "nonimmediate_operand" "")
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 5c778e15f05..95a506b4fcc 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -57,6 +57,7 @@ extern int got_no_const_operand (rtx, enum machine_mode);
extern int num_insns_constant (rtx, enum machine_mode);
extern int easy_fp_constant (rtx, enum machine_mode);
extern int easy_vector_constant (rtx, enum machine_mode);
+extern rtx gen_easy_vector_constant_add_self (rtx);
extern const char *output_vec_const_move (rtx *);
extern int zero_fp_constant (rtx, enum machine_mode);
extern int zero_constant (rtx, enum machine_mode);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index c8854b09328..bd649fa5695 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -60,12 +60,9 @@
#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 EASY_VECTOR_15(n) ((n) >= -16 && (n) <= 15)
+#define EASY_VECTOR_15_ADD_SELF(n) ((n) >= 0x10 && (n) <= 0x1e \
+ && !((n) & 1))
#define min(A,B) ((A) < (B) ? (A) : (B))
#define max(A,B) ((A) > (B) ? (A) : (B))
@@ -411,6 +408,7 @@ static void is_altivec_return_reg (rtx, void *);
static rtx generate_set_vrsave (rtx, rs6000_stack_t *, int);
int easy_vector_constant (rtx, enum machine_mode);
static int easy_vector_same (rtx, enum machine_mode);
+static int easy_vector_splat_const (int, enum machine_mode);
static bool is_ev64_opaque_type (tree);
static rtx rs6000_dwarf_register_span (rtx);
static rtx rs6000_legitimize_tls_address (rtx, enum tls_model);
@@ -1677,6 +1675,38 @@ easy_fp_constant (rtx op, enum machine_mode mode)
abort ();
}
+/* Returns the constant for the splat instrunction, if exists. */
+
+static int
+easy_vector_splat_const (int cst, enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case V4SImode:
+ if (EASY_VECTOR_15 (cst)
+ || EASY_VECTOR_15_ADD_SELF (cst))
+ return cst;
+ if ((cst & 0xffff) != ((cst >> 16) & 0xffff))
+ break;
+ cst = cst >> 16;
+ case V8HImode:
+ if (EASY_VECTOR_15 (cst)
+ || EASY_VECTOR_15_ADD_SELF (cst))
+ return cst;
+ if ((cst & 0xff) != ((cst >> 8) & 0xff))
+ break;
+ cst = cst >> 8;
+ case V16QImode:
+ if (EASY_VECTOR_15 (cst)
+ || EASY_VECTOR_15_ADD_SELF (cst))
+ return cst;
+ default:
+ break;
+ }
+ return 0;
+}
+
+
/* Return nonzero if all elements of a vector have the same value. */
static int
@@ -1690,7 +1720,7 @@ easy_vector_same (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
for (i = 1; i < units; ++i)
if (INTVAL (CONST_VECTOR_ELT (op, i)) != cst)
break;
- if (i == units)
+ if (i == units && easy_vector_splat_const (cst, mode))
return 1;
return 0;
}
@@ -1736,31 +1766,14 @@ easy_vector_constant (rtx op, enum machine_mode mode)
&& cst2 >= -0x7fff && cst2 <= 0x7fff)
return 1;
- if (TARGET_ALTIVEC)
- switch (mode)
- {
- case V4SImode:
- if (EASY_VECTOR_15 (cst, op, mode))
- return 1;
- if ((cst & 0xffff) != ((cst >> 16) & 0xffff))
- break;
- cst = cst >> 16;
- case V8HImode:
- if (EASY_VECTOR_15 (cst, op, mode))
- return 1;
- if ((cst & 0xff) != ((cst >> 8) & 0xff))
- break;
- cst = cst >> 8;
- case V16QImode:
- if (EASY_VECTOR_15 (cst, op, mode))
- return 1;
- default:
- break;
- }
-
- if (TARGET_ALTIVEC && EASY_VECTOR_15_ADD_SELF (cst, op, mode))
- return 1;
-
+ if (TARGET_ALTIVEC
+ && easy_vector_same (op, mode))
+ {
+ cst = easy_vector_splat_const (cst, mode);
+ if (EASY_VECTOR_15_ADD_SELF (cst)
+ || EASY_VECTOR_15 (cst))
+ return 1;
+ }
return 0;
}
@@ -1770,13 +1783,31 @@ int
easy_vector_constant_add_self (rtx op, enum machine_mode mode)
{
int cst;
+ if (TARGET_ALTIVEC
+ && GET_CODE (op) == CONST_VECTOR
+ && easy_vector_same (op, mode))
+ {
+ cst = easy_vector_splat_const (INTVAL (CONST_VECTOR_ELT (op, 0)), mode);
+ if (EASY_VECTOR_15_ADD_SELF (cst))
+ return 1;
+ }
+ return 0;
+}
- if (!easy_vector_constant (op, mode))
- return 0;
+/* Generate easy_vector_constant out of a easy_vector_constant_add_self. */
- cst = INTVAL (CONST_VECTOR_ELT (op, 0));
+rtx
+gen_easy_vector_constant_add_self (rtx op)
+{
+ int i, units;
+ rtvec v;
+ units = GET_MODE_NUNITS (GET_MODE (op));
+ v = rtvec_alloc (units);
- return TARGET_ALTIVEC && EASY_VECTOR_15_ADD_SELF (cst, op, mode);
+ for (i = 0; i < units; i++)
+ RTVEC_ELT (v, i) =
+ GEN_INT (INTVAL (CONST_VECTOR_ELT (op, i)) >> 1);
+ return gen_rtx_raw_CONST_VECTOR (GET_MODE (op), v);
}
const char *
@@ -1797,33 +1828,37 @@ output_vec_const_move (rtx *operands)
{
if (zero_constant (vec, mode))
return "vxor %0,%0,%0";
- else if (EASY_VECTOR_15_ADD_SELF (cst, vec, mode))
- return "#";
else if (easy_vector_constant (vec, mode))
{
operands[1] = GEN_INT (cst);
switch (mode)
{
case V4SImode:
- if (EASY_VECTOR_15 (cst, vec, mode))
+ if (EASY_VECTOR_15 (cst))
{
operands[1] = GEN_INT (cst);
return "vspltisw %0,%1";
}
+ else if (EASY_VECTOR_15_ADD_SELF (cst))
+ return "#";
cst = cst >> 16;
case V8HImode:
- if (EASY_VECTOR_15 (cst, vec, mode))
+ if (EASY_VECTOR_15 (cst))
{
operands[1] = GEN_INT (cst);
return "vspltish %0,%1";
}
+ else if (EASY_VECTOR_15_ADD_SELF (cst))
+ return "#";
cst = cst >> 8;
case V16QImode:
- if (EASY_VECTOR_15 (cst, vec, mode))
+ if (EASY_VECTOR_15 (cst))
{
operands[1] = GEN_INT (cst);
return "vspltisb %0,%1";
}
+ else if (EASY_VECTOR_15_ADD_SELF (cst))
+ return "#";
default:
abort ();
}