+2017-12-16 Richard Sandiford <richard.sandiford@linaro.org>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
+ * doc/generic.texi (VEC_SERIES_EXPR): Document.
+ * doc/md.texi (vec_series@var{m}): Document.
+ * tree.def (VEC_SERIES_EXPR): New tree code.
+ * tree.h (build_vec_series): Declare.
+ * tree.c (build_vec_series): New function.
+ * cfgexpand.c (expand_debug_expr): Handle VEC_SERIES_EXPR.
+ * tree-pretty-print.c (dump_generic_node): Likewise.
+ * gimple-pretty-print.c (dump_binary_rhs): Likewise.
+ * tree-inline.c (estimate_operator_cost): Likewise.
+ * expr.c (expand_expr_real_2): Likewise.
+ * optabs-tree.c (optab_for_tree_code): Likewise.
+ * tree-cfg.c (verify_gimple_assign_binary): Likewise.
+ * fold-const.c (const_binop): Fold VEC_SERIES_EXPRs of constants.
+ * expmed.c (make_tree): Handle VEC_SERIES.
+ * optabs.def (vec_series_optab): New optab.
+ * optabs.h (expand_vec_series_expr): Declare.
+ * optabs.c (expand_vec_series_expr): New function.
+ * tree-vect-generic.c (expand_vector_operations_1): Check that
+ the operands also have vector type.
+
2017-12-16 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hawyard@arm.com>
David Sherwood <david.sherwood@arm.com>
case VEC_WIDEN_LSHIFT_LO_EXPR:
case VEC_PERM_EXPR:
case VEC_DUPLICATE_EXPR:
+ case VEC_SERIES_EXPR:
return NULL;
/* Misc codes. */
@node Vectors
@subsection Vectors
@tindex VEC_DUPLICATE_EXPR
+@tindex VEC_SERIES_EXPR
@tindex VEC_LSHIFT_EXPR
@tindex VEC_RSHIFT_EXPR
@tindex VEC_WIDEN_MULT_HI_EXPR
This node has a single operand and represents a vector in which every
element is equal to that operand.
+@item VEC_SERIES_EXPR
+This node represents a vector formed from a scalar base and step,
+given as the first and second operands respectively. Element @var{i}
+of the result is equal to @samp{@var{base} + @var{i}*@var{step}}.
+
+This node is restricted to integral types, in order to avoid
+specifying the rounding behavior for floating-point types.
+
@item VEC_LSHIFT_EXPR
@itemx VEC_RSHIFT_EXPR
These nodes represent whole vector left and right shifts, respectively.
This pattern is not allowed to @code{FAIL}.
+@cindex @code{vec_series@var{m}} instruction pattern
+@item @samp{vec_series@var{m}}
+Initialize vector output operand 0 so that element @var{i} is equal to
+operand 1 plus @var{i} times operand 2. In other words, create a linear
+series whose base value is operand 1 and whose step is operand 2.
+
+The vector output has mode @var{m} and the scalar inputs have the mode
+appropriate for one element of @var{m}. This pattern is not used for
+floating-point vectors, in order to avoid having to specify the
+rounding behavior for @var{i} > 1.
+
+This pattern is not allowed to @code{FAIL}.
+
@cindex @code{vec_cmp@var{m}@var{n}} instruction pattern
@item @samp{vec_cmp@var{m}@var{n}}
Output a vector comparison. Operand 0 of mode @var{n} is the destination for
tree elt_tree = make_tree (TREE_TYPE (type), XEXP (op, 0));
return build_vector_from_val (type, elt_tree);
}
+ if (GET_CODE (op) == VEC_SERIES)
+ {
+ tree itype = TREE_TYPE (type);
+ tree base_tree = make_tree (itype, XEXP (op, 0));
+ tree step_tree = make_tree (itype, XEXP (op, 1));
+ return build_vec_series (type, base_tree, step_tree);
+ }
return make_tree (type, op);
}
gcc_assert (target);
return target;
+ case VEC_SERIES_EXPR:
+ expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, modifier);
+ return expand_vec_series_expr (mode, op0, op1, target);
+
case BIT_INSERT_EXPR:
{
unsigned bitpos = tree_to_uhwi (treeop2);
result as argument put those cases that need it here. */
switch (code)
{
+ case VEC_SERIES_EXPR:
+ if (CONSTANT_CLASS_P (arg1)
+ && CONSTANT_CLASS_P (arg2))
+ return build_vec_series (type, arg1, arg2);
+ return NULL_TREE;
+
case COMPLEX_EXPR:
if ((TREE_CODE (arg1) == REAL_CST
&& TREE_CODE (arg2) == REAL_CST)
case VEC_PACK_FIX_TRUNC_EXPR:
case VEC_WIDEN_LSHIFT_HI_EXPR:
case VEC_WIDEN_LSHIFT_LO_EXPR:
+ case VEC_SERIES_EXPR:
for (p = get_tree_code_name (code); *p; p++)
pp_character (buffer, TOUPPER (*p));
pp_string (buffer, " <");
case VEC_DUPLICATE_EXPR:
return vec_duplicate_optab;
+ case VEC_SERIES_EXPR:
+ return vec_series_optab;
+
default:
break;
}
return ops[0].value;
}
+/* Generate VEC_SERIES_EXPR <OP0, OP1>, returning a value of mode VMODE.
+ Use TARGET for the result if nonnull and convenient. */
+
+rtx
+expand_vec_series_expr (machine_mode vmode, rtx op0, rtx op1, rtx target)
+{
+ struct expand_operand ops[3];
+ enum insn_code icode;
+ machine_mode emode = GET_MODE_INNER (vmode);
+
+ icode = direct_optab_handler (vec_series_optab, vmode);
+ gcc_assert (icode != CODE_FOR_nothing);
+
+ create_output_operand (&ops[0], target, vmode);
+ create_input_operand (&ops[1], op0, emode);
+ create_input_operand (&ops[2], op1, emode);
+
+ expand_insn (icode, 3, ops);
+ return ops[0].value;
+}
+
/* Generate insns for a vector comparison into a mask. */
rtx
OPTAB_D (set_thread_pointer_optab, "set_thread_pointer$I$a")
OPTAB_DC (vec_duplicate_optab, "vec_duplicate$a", VEC_DUPLICATE)
+OPTAB_DC (vec_series_optab, "vec_series$a", VEC_SERIES)
/* Generate code for VEC_COND_EXPR. */
extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
+/* Generate code for VEC_SERIES_EXPR. */
+extern rtx expand_vec_series_expr (machine_mode, rtx, rtx, rtx);
+
/* Generate code for MULT_HIGHPART_EXPR. */
extern rtx expand_mult_highpart (machine_mode, rtx, rtx, rtx, bool);
/* Continue with generic binary expression handling. */
break;
+ case VEC_SERIES_EXPR:
+ if (!useless_type_conversion_p (rhs1_type, rhs2_type))
+ {
+ error ("type mismatch in series expression");
+ debug_generic_expr (rhs1_type);
+ debug_generic_expr (rhs2_type);
+ return true;
+ }
+ if (TREE_CODE (lhs_type) != VECTOR_TYPE
+ || !useless_type_conversion_p (TREE_TYPE (lhs_type), rhs1_type))
+ {
+ error ("vector type expected in series expression");
+ debug_generic_expr (lhs_type);
+ return true;
+ }
+ return false;
+
default:
gcc_unreachable ();
}
case VEC_WIDEN_LSHIFT_HI_EXPR:
case VEC_WIDEN_LSHIFT_LO_EXPR:
case VEC_DUPLICATE_EXPR:
+ case VEC_SERIES_EXPR:
return 1;
is_expr = false;
break;
+ case VEC_SERIES_EXPR:
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
case VEC_WIDEN_MULT_EVEN_EXPR:
if (rhs_class == GIMPLE_BINARY_RHS)
rhs2 = gimple_assign_rhs2 (stmt);
- if (TREE_CODE (type) != VECTOR_TYPE)
+ if (!VECTOR_TYPE_P (type)
+ || !VECTOR_TYPE_P (TREE_TYPE (rhs1)))
return;
/* If the vector operation is operating on all same vector elements
}
}
+/* Build a vector series of type TYPE in which element I has the value
+ BASE + I * STEP. The result is a constant if BASE and STEP are constant
+ and a VEC_SERIES_EXPR otherwise. */
+
+tree
+build_vec_series (tree type, tree base, tree step)
+{
+ if (integer_zerop (step))
+ return build_vector_from_val (type, base);
+ if (TREE_CODE (base) == INTEGER_CST && TREE_CODE (step) == INTEGER_CST)
+ {
+ tree_vector_builder builder (type, 1, 3);
+ tree elt1 = wide_int_to_tree (TREE_TYPE (base),
+ wi::to_wide (base) + wi::to_wide (step));
+ tree elt2 = wide_int_to_tree (TREE_TYPE (base),
+ wi::to_wide (elt1) + wi::to_wide (step));
+ builder.quick_push (base);
+ builder.quick_push (elt1);
+ builder.quick_push (elt2);
+ return builder.build ();
+ }
+ return build2 (VEC_SERIES_EXPR, type, base, step);
+}
+
/* Something has messed with the elements of CONSTRUCTOR C after it was built;
calculate TREE_CONSTANT and TREE_SIDE_EFFECTS. */
/* Represents a vector in which every element is equal to operand 0. */
DEFTREECODE (VEC_DUPLICATE_EXPR, "vec_duplicate_expr", tcc_unary, 1)
+/* Vector series created from a start (base) value and a step.
+
+ A = VEC_SERIES_EXPR (B, C)
+
+ means
+
+ for (i = 0; i < N; i++)
+ A[i] = B + C * i; */
+DEFTREECODE (VEC_SERIES_EXPR, "vec_series_expr", tcc_binary, 2)
+
/* Vector conditional expression. It is like COND_EXPR, but with
vector operands.
extern tree make_vector (unsigned, unsigned CXX_MEM_STAT_INFO);
extern tree build_vector_from_ctor (tree, vec<constructor_elt, va_gc> *);
extern tree build_vector_from_val (tree, tree);
+extern tree build_vec_series (tree, tree, tree);
extern void recompute_constructor_flags (tree);
extern void verify_constructor_flags (tree);
extern tree build_constructor (tree, vec<constructor_elt, va_gc> *);