[(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" "")
[(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" "")
[(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" "")
#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))
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);
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
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;
}
&& 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;
}
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 *
{
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 ();
}