Commit 26277d41 by Paolo Bonzini Committed by Paolo Bonzini

tree-cfg.c (gimplify_val): Move from tree-complex.c.

2004-07-22  Paolo Bonzini  <bonzini@gnu.org>

	* tree-cfg.c (gimplify_val): Move from tree-complex.c.
	(gimplify_build1): Move from tree-complex.c do_unop.
	(gimplify_build2): Move from tree-complex.c do_binop.
	(gimplify_build3): New.
	* tree-complex.c (gimplify_val, do_unop, do_binop): Remove.
	Adjust throughout to call the functions above.
	* tree-flow.h: Declare the functions above.
	* tree-nested.c (gimplify_val): Rename to...
	(tsi_gimplify_val): ... this.

	* Makefile.in (tree_complex.o): Update dependencies.
	(stor-layout.o): Depend on regs.h.
	* c-common.c (handle_vector_size_attribute): Update for
	vector types without corresponding vector modes.
	* expr.c (expand_expr): Treat VECTOR_CST's like CONSTRUCTORS if
	a corresponding vector mode is not available.
	* print-tree.c (print_node): Print nunits for vector types
	* regclass.c (have_regs_of_mode): New.
	(init_reg_sets_1): Initialize it and use it instead
	of allocatable_regs_of_mode.
	* regs.h (have_regs_of_mode): Declare it.
	* stor-layout.c (layout_type): Pick a mode for vector types.
	* tree-complex.c (build_word_mode_vector_type, tree_vec_extract,
	build_replicated_const, do_unop, do_binop, do_plus_minus,
	do_negate, expand_vector_piecewise, expand_vector_parallel,
	expand_vector_addition, expand_vector_operations_1,
	expand_vector_operations, tree_lower_operations,
	pass_lower_vector_ssa, pass_pre_expand): New.
	(expand_complex_operations, pass_lower_complex): Remove.
	* tree-optimize.c (init_tree_optimization_passes): Adjust
	pass ordering for changes in tree-complex.c.
	* tree-pass.h: Declare new passes.
	* tree.c (finish_vector_type): Remove.
	(make_vector_type): New.
	(build_vector_type_for_mode, build_vector_type): Rewritten.
	* tree.def (VECTOR_TYPE): Document where the number of
	subparts is stored.
	* tree.h (TYPE_VECTOR_SUBPARTS): Use TYPE_PRECISION field.
	(make_vector): Remove declaration.

From-SVN: r85039
parent 727a31fa
2004-07-22 Paolo Bonzini <bonzini@gnu.org>
* tree-cfg.c (gimplify_val): Move from tree-complex.c.
(gimplify_build1): Move from tree-complex.c do_unop.
(gimplify_build2): Move from tree-complex.c do_binop.
(gimplify_build3): New.
* tree-complex.c (gimplify_val, do_unop, do_binop): Remove.
Adjust throughout to call the functions above.
* tree-flow.h: Declare the functions above.
* tree-nested.c (gimplify_val): Rename to...
(tsi_gimplify_val): ... this.
* Makefile.in (tree_complex.o): Update dependencies.
(stor-layout.o): Depend on regs.h.
* c-common.c (handle_vector_size_attribute): Update for
vector types without corresponding vector modes.
* expr.c (expand_expr): Treat VECTOR_CST's like CONSTRUCTORS if
a corresponding vector mode is not available.
* print-tree.c (print_node): Print nunits for vector types
* regclass.c (have_regs_of_mode): New.
(init_reg_sets_1): Initialize it and use it instead
of allocatable_regs_of_mode.
* regs.h (have_regs_of_mode): Declare it.
* stor-layout.c (layout_type): Pick a mode for vector types.
* tree-complex.c (build_word_mode_vector_type, tree_vec_extract,
build_replicated_const, do_unop, do_binop, do_plus_minus,
do_negate, expand_vector_piecewise, expand_vector_parallel,
expand_vector_addition, expand_vector_operations_1,
expand_vector_operations, tree_lower_operations,
pass_lower_vector_ssa, pass_pre_expand): New.
(expand_complex_operations, pass_lower_complex): Remove.
* tree-optimize.c (init_tree_optimization_passes): Adjust
pass ordering for changes in tree-complex.c.
* tree-pass.h: Declare new passes.
* tree.c (finish_vector_type): Remove.
(make_vector_type): New.
(build_vector_type_for_mode, build_vector_type): Rewritten.
* tree.def (VECTOR_TYPE): Document where the number of
subparts is stored.
* tree.h (TYPE_VECTOR_SUBPARTS): Use TYPE_PRECISION field.
(make_vector): Remove declaration.
2004-07-21 Richard Henderson <rth@redhat.com>
* gimple-low.c (expand_var_p): Don't look at TREE_ADDRESSABLE,
......
......@@ -1585,7 +1585,7 @@ print-tree.o : print-tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H
$(GGC_H) langhooks.h real.h
stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(FLAGS_H) function.h $(EXPR_H) $(RTL_H) toplev.h $(GGC_H) $(TM_P_H) $(TARGET_H) \
langhooks.h
langhooks.h $(REGS_H)
tree-alias-type.o: tree-alias-type.c tree-alias-type.h $(SYSTEM_H) $(CONFIG_H) \
$(GGC_H) $(TM_H) coretypes.h $(VARRAY_H)
tree-alias-ander.o: tree-alias-ander.c tree-alias-ander.h $(SYSTEM_H) \
......@@ -1922,7 +1922,8 @@ tree-sra.o : tree-sra.c $(CONFIG_H) system.h errors.h $(TREE_H) $(RTL_H) \
langhooks.h tree-pass.h $(FLAGS_H) $(EXPR_H)
tree-complex.o : tree-complex.c $(CONFIG_H) system.h $(TREE_H) \
$(TM_H) $(TREE_FLOW_H) $(TREE_GIMPLE_H) tree-iterator.h tree-pass.h \
$(FLAGS_H)
$(FLAGS_H) $(OPTABS_H) $(RTL_H) $(MACHMODE_H) $(EXPR_H) \
langhooks.h $(FLAGS_H) $(DIAGNOSTIC_H)
df.o : df.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
insn-config.h $(RECOG_H) function.h $(REGS_H) alloc-pool.h hard-reg-set.h \
$(BASIC_BLOCK_H) $(DF_H)
......
......@@ -4783,7 +4783,7 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
bool *no_add_attrs)
{
unsigned HOST_WIDE_INT vecsize, nunits;
enum machine_mode mode, orig_mode, new_mode;
enum machine_mode orig_mode;
tree type = *node, new_type, size;
*no_add_attrs = true;
......@@ -4832,28 +4832,13 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
/* Calculate how many units fit in the vector. */
nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
/* Find a suitably sized vector. */
new_mode = VOIDmode;
for (mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_mode) == MODE_INT
? MODE_VECTOR_INT
: MODE_VECTOR_FLOAT);
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
if (vecsize == GET_MODE_SIZE (mode)
&& nunits == (unsigned HOST_WIDE_INT) GET_MODE_NUNITS (mode))
{
new_mode = mode;
break;
}
if (new_mode == VOIDmode)
if (nunits & (nunits - 1))
{
error ("no vector mode with the size and type specified could be found");
error ("number of components of the vector not a power of two");
return NULL_TREE;
}
new_type = build_vector_type_for_mode (type, new_mode);
new_type = build_vector_type (type, nunits);
/* Build back pointers if needed. */
*node = reconstruct_complex_type (*node, new_type);
......
......@@ -628,6 +628,89 @@ expand_cmplxdiv_wide (rtx real0, rtx real1, rtx imag0, rtx imag1, rtx realr,
return 1;
}
/* Return the optab used for computing the operation given by
the tree code, CODE. This function is not always usable (for
example, it cannot give complete results for multiplication
or division) but probably ought to be relied on more widely
throughout the expander. */
optab
optab_for_tree_code (enum tree_code code, tree type)
{
bool trapv;
switch (code)
{
case BIT_AND_EXPR:
return and_optab;
case BIT_IOR_EXPR:
return ior_optab;
case BIT_NOT_EXPR:
return one_cmpl_optab;
case BIT_XOR_EXPR:
return xor_optab;
case TRUNC_MOD_EXPR:
case CEIL_MOD_EXPR:
case FLOOR_MOD_EXPR:
case ROUND_MOD_EXPR:
return TYPE_UNSIGNED (type) ? umod_optab : smod_optab;
case RDIV_EXPR:
case TRUNC_DIV_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
case LSHIFT_EXPR:
return ashl_optab;
case RSHIFT_EXPR:
return TYPE_UNSIGNED (type) ? lshr_optab : ashr_optab;
case LROTATE_EXPR:
return rotl_optab;
case RROTATE_EXPR:
return rotr_optab;
case MAX_EXPR:
return TYPE_UNSIGNED (type) ? umax_optab : smax_optab;
case MIN_EXPR:
return TYPE_UNSIGNED (type) ? umin_optab : smin_optab;
default:
break;
}
trapv = flag_trapv && INTEGRAL_TYPE_P (type) && !TYPE_UNSIGNED (type);
switch (code)
{
case PLUS_EXPR:
return trapv ? addv_optab : add_optab;
case MINUS_EXPR:
return trapv ? subv_optab : sub_optab;
case MULT_EXPR:
return trapv ? smulv_optab : smul_optab;
case NEGATE_EXPR:
return trapv ? negv_optab : neg_optab;
case ABS_EXPR:
return trapv ? absv_optab : abs_optab;
default:
return NULL;
}
}
/* Wrapper around expand_binop which takes an rtx code to specify
the operation to perform, not an optab pointer. All other
arguments are the same. */
......@@ -2804,7 +2887,8 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
}
/* If there is no negate operation, try doing a subtract from zero.
The US Software GOFAST library needs this. */
The US Software GOFAST library needs this. FIXME: This is *wrong*
for floating-point operations due to negative zeros! */
if (unoptab->code == NEG)
{
rtx temp;
......
......@@ -454,6 +454,10 @@ enum can_compare_purpose
ccp_store_flag
};
/* Return the optab used for computing the given operation on the type
given by the second argument. */
extern optab optab_for_tree_code (enum tree_code, tree);
/* Nonzero if a compare of mode MODE can be done straightforwardly
(without splitting it into pieces). */
extern int can_compare_p (enum rtx_code, enum machine_mode,
......
......@@ -537,6 +537,8 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
print_node (file, "values", TYPE_VALUES (node), indent + 4);
else if (TREE_CODE (node) == ARRAY_TYPE || TREE_CODE (node) == SET_TYPE)
print_node (file, "domain", TYPE_DOMAIN (node), indent + 4);
else if (TREE_CODE (node) == VECTOR_TYPE)
fprintf (file, " nunits %d", (int) TYPE_VECTOR_SUBPARTS (node));
else if (TREE_CODE (node) == RECORD_TYPE
|| TREE_CODE (node) == UNION_TYPE
|| TREE_CODE (node) == QUAL_UNION_TYPE)
......
......@@ -191,6 +191,10 @@ const char * reg_names[] = REGISTER_NAMES;
enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER];
/* 1 if there is a register of given mode. */
bool have_regs_of_mode [MAX_MACHINE_MODE];
/* 1 if class does contain register of given mode. */
static char contains_reg_of_mode [N_REG_CLASSES] [MAX_MACHINE_MODE];
......@@ -305,7 +309,6 @@ init_reg_sets_1 (void)
{
unsigned int i, j;
unsigned int /* enum machine_mode */ m;
char allocatable_regs_of_mode [MAX_MACHINE_MODE];
/* This macro allows the fixed or call-used registers
and the register classes to depend on target flags. */
......@@ -469,8 +472,8 @@ init_reg_sets_1 (void)
SET_HARD_REG_BIT (regs_invalidated_by_call, i);
}
memset (have_regs_of_mode, 0, sizeof (have_regs_of_mode));
memset (contains_reg_of_mode, 0, sizeof (contains_reg_of_mode));
memset (allocatable_regs_of_mode, 0, sizeof (allocatable_regs_of_mode));
for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)
for (i = 0; i < N_REG_CLASSES; i++)
if ((unsigned) CLASS_MAX_NREGS (i, m) <= reg_class_size[i])
......@@ -479,7 +482,7 @@ init_reg_sets_1 (void)
&& HARD_REGNO_MODE_OK (j, m))
{
contains_reg_of_mode [i][m] = 1;
allocatable_regs_of_mode [m] = 1;
have_regs_of_mode [m] = 1;
break;
}
......@@ -487,7 +490,7 @@ init_reg_sets_1 (void)
and take the maximum cost of moving any subset to any other. */
for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)
if (allocatable_regs_of_mode [m])
if (have_regs_of_mode [m])
{
for (i = 0; i < N_REG_CLASSES; i++)
if (contains_reg_of_mode [i][m])
......
......@@ -163,6 +163,10 @@ extern char regs_ever_live[FIRST_PSEUDO_REGISTER];
extern char regs_asm_clobbered[FIRST_PSEUDO_REGISTER];
/* Vector indexed by machine mode saying whether there are regs of that mode. */
extern bool have_regs_of_mode [MAX_MACHINE_MODE];
/* For each hard register, the widest mode object that it can contain.
This will be a MODE_INT mode if the register can hold integers. Otherwise
it will be a MODE_FLOAT or a MODE_CC mode, whichever is valid for the
......
......@@ -34,6 +34,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "ggc.h"
#include "target.h"
#include "langhooks.h"
#include "regs.h"
/* Set to one when set_sizetype has been called. */
static int sizetype_set;
......@@ -1582,10 +1583,52 @@ layout_type (tree type)
break;
case VECTOR_TYPE:
TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
break;
{
int nunits = TYPE_VECTOR_SUBPARTS (type);
tree nunits_tree = build_int_2 (nunits, 0);
tree innertype = TREE_TYPE (type);
if (nunits & (nunits - 1))
abort ();
/* Find an appropriate mode for the vector type. */
if (TYPE_MODE (type) == VOIDmode)
{
enum machine_mode innermode = TYPE_MODE (innertype);
enum machine_mode mode;
/* First, look for a supported vector type. */
if (GET_MODE_CLASS (innermode) == MODE_FLOAT)
mode = MIN_MODE_VECTOR_FLOAT;
else
mode = MIN_MODE_VECTOR_INT;
for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode))
if (GET_MODE_NUNITS (mode) == nunits
&& GET_MODE_INNER (mode) == innermode
&& VECTOR_MODE_SUPPORTED_P (mode))
break;
/* For integers, try mapping it to a same-sized scalar mode. */
if (mode == VOIDmode
&& GET_MODE_CLASS (innermode) == MODE_INT)
mode = mode_for_size (nunits * GET_MODE_BITSIZE (innermode),
MODE_INT, 0);
if (mode == VOIDmode || !have_regs_of_mode[mode])
TYPE_MODE (type) = BLKmode;
else
TYPE_MODE (type) = mode;
}
TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
TYPE_SIZE_UNIT (type) = int_const_binop (MULT_EXPR,
TYPE_SIZE_UNIT (innertype),
nunits_tree, 0);
TYPE_SIZE (type) = int_const_binop (MULT_EXPR, TYPE_SIZE (innertype),
nunits_tree, 0);
break;
}
case VOID_TYPE:
/* This is an incomplete type and so doesn't have a size. */
......
......@@ -4793,6 +4793,79 @@ struct tree_opt_pass pass_split_crit_edges =
0, /* todo_flags_start */
TODO_dump_func, /* todo_flags_finish */
};
/* Return EXP if it is a valid GIMPLE rvalue, else gimplify it into
a temporary, make sure and register it to be renamed if necessary,
and finally return the temporary. Put the statements to compute
EXP before the current statement in BSI. */
tree
gimplify_val (block_stmt_iterator *bsi, tree type, tree exp)
{
tree t, new_stmt, orig_stmt;
if (is_gimple_val (exp))
return exp;
t = make_rename_temp (type, NULL);
new_stmt = build (MODIFY_EXPR, type, t, exp);
orig_stmt = bsi_stmt (*bsi);
SET_EXPR_LOCUS (new_stmt, EXPR_LOCUS (orig_stmt));
TREE_BLOCK (new_stmt) = TREE_BLOCK (orig_stmt);
bsi_insert_before (bsi, new_stmt, BSI_SAME_STMT);
return t;
}
/* Build a ternary operation and gimplify it. Emit code before BSI.
Return the gimple_val holding the result. */
tree
gimplify_build3 (block_stmt_iterator *bsi, enum tree_code code,
tree type, tree a, tree b, tree c)
{
tree ret;
ret = fold (build3 (code, type, a, b, c));
STRIP_NOPS (ret);
return gimplify_val (bsi, type, ret);
}
/* Build a binary operation and gimplify it. Emit code before BSI.
Return the gimple_val holding the result. */
tree
gimplify_build2 (block_stmt_iterator *bsi, enum tree_code code,
tree type, tree a, tree b)
{
tree ret;
ret = fold (build2 (code, type, a, b));
STRIP_NOPS (ret);
return gimplify_val (bsi, type, ret);
}
/* Build a unary operation and gimplify it. Emit code before BSI.
Return the gimple_val holding the result. */
tree
gimplify_build1 (block_stmt_iterator *bsi, enum tree_code code, tree type,
tree a)
{
tree ret;
ret = fold (build1 (code, type, a));
STRIP_NOPS (ret);
return gimplify_val (bsi, type, ret);
}
/* Emit return warnings. */
......
......@@ -496,6 +496,13 @@ extern tree tree_block_label (basic_block bb);
extern void extract_true_false_edges_from_block (basic_block, edge *, edge *);
extern bool tree_purge_dead_eh_edges (basic_block);
extern bool tree_purge_all_dead_eh_edges (bitmap);
extern tree gimplify_val (block_stmt_iterator *, tree, tree);
extern tree gimplify_build1 (block_stmt_iterator *, enum tree_code,
tree, tree);
extern tree gimplify_build2 (block_stmt_iterator *, enum tree_code,
tree, tree, tree);
extern tree gimplify_build3 (block_stmt_iterator *, enum tree_code,
tree, tree, tree, tree);
/* In tree-pretty-print.c. */
extern void dump_generic_bb (FILE *, basic_block, int, int);
......
......@@ -373,7 +373,7 @@ init_tmp_var (struct nesting_info *info, tree exp, tree_stmt_iterator *tsi)
/* Similarly, but only do so to force EXP to satisfy is_gimple_val. */
static tree
gimplify_val (struct nesting_info *info, tree exp, tree_stmt_iterator *tsi)
tsi_gimplify_val (struct nesting_info *info, tree exp, tree_stmt_iterator *tsi)
{
if (is_gimple_val (exp))
return exp;
......@@ -790,7 +790,7 @@ convert_nonlocal_reference (tree *tp, int *walk_subtrees, void *data)
where we only accept variables (and min_invariant, presumably),
then compute the address into a temporary. */
if (save_val_only)
*tp = gimplify_val (wi->info, t, &wi->tsi);
*tp = tsi_gimplify_val (wi->info, t, &wi->tsi);
}
}
break;
......@@ -904,7 +904,7 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
/* If we are in a context where we only accept values, then
compute the address into a temporary. */
if (save_val_only)
*tp = gimplify_val (wi->info, t, &wi->tsi);
*tp = tsi_gimplify_val (wi->info, t, &wi->tsi);
}
}
break;
......@@ -1041,7 +1041,7 @@ convert_nl_goto_reference (tree *tp, int *walk_subtrees, void *data)
field = get_nl_goto_field (i);
x = get_frame_field (info, target_context, field, &wi->tsi);
x = build_addr (x);
x = gimplify_val (info, x, &wi->tsi);
x = tsi_gimplify_val (info, x, &wi->tsi);
arg = tree_cons (NULL, x, NULL);
x = build_addr (new_label);
arg = tree_cons (NULL, x, arg);
......@@ -1139,7 +1139,7 @@ convert_tramp_reference (tree *tp, int *walk_subtrees, void *data)
/* Compute the address of the field holding the trampoline. */
x = get_frame_field (info, target_context, x, &wi->tsi);
x = build_addr (x);
x = gimplify_val (info, x, &wi->tsi);
x = tsi_gimplify_val (info, x, &wi->tsi);
arg = tree_cons (NULL, x, NULL);
/* Do machine-specific ugliness. Normally this will involve
......
......@@ -299,6 +299,7 @@ init_tree_optimization_passes (void)
NEXT_PASS (pass_lower_cf);
NEXT_PASS (pass_lower_eh);
NEXT_PASS (pass_build_cfg);
NEXT_PASS (pass_pre_expand);
NEXT_PASS (pass_tree_profile);
NEXT_PASS (pass_init_datastructures);
NEXT_PASS (pass_all_optimizations);
......@@ -325,7 +326,6 @@ init_tree_optimization_passes (void)
NEXT_PASS (pass_tail_recursion);
NEXT_PASS (pass_ch);
NEXT_PASS (pass_profile);
NEXT_PASS (pass_lower_complex);
NEXT_PASS (pass_sra);
NEXT_PASS (DUP_PASS (pass_rename_ssa_copies));
NEXT_PASS (DUP_PASS (pass_dominator));
......
......@@ -120,7 +120,8 @@ extern struct tree_opt_pass pass_may_alias;
extern struct tree_opt_pass pass_split_crit_edges;
extern struct tree_opt_pass pass_pre;
extern struct tree_opt_pass pass_profile;
extern struct tree_opt_pass pass_lower_complex;
extern struct tree_opt_pass pass_pre_expand;
extern struct tree_opt_pass pass_lower_vector_ssa;
extern struct tree_opt_pass pass_fold_builtins;
extern struct tree_opt_pass pass_early_warn_uninitialized;
extern struct tree_opt_pass pass_late_warn_uninitialized;
......
......@@ -111,7 +111,7 @@ static void set_type_quals (tree, int);
static int type_hash_eq (const void *, const void *);
static hashval_t type_hash_hash (const void *);
static void print_type_hash_statistics (void);
static void finish_vector_type (tree);
static tree make_vector_type (tree, int, enum machine_mode);
static int type_hash_marked_p (const void *);
static unsigned int type_hash_list (tree, hashval_t);
static unsigned int attribute_hash_list (tree, hashval_t);
......@@ -5279,18 +5279,23 @@ tree_operand_check_failed (int idx, enum tree_code code, const char *file,
}
#endif /* ENABLE_TREE_CHECKING */
/* For a new vector type node T, build the information necessary for
debugging output. */
/* Create a new vector type node holding SUBPARTS units of type INNERTYPE,
and mapped to the machine mode MODE. Initialize its fields and build
the information necessary for debugging output. */
static void
finish_vector_type (tree t)
static tree
make_vector_type (tree innertype, int nunits, enum machine_mode mode)
{
tree t = make_node (VECTOR_TYPE);
TREE_TYPE (t) = innertype;
TYPE_VECTOR_SUBPARTS (t) = nunits;
TYPE_MODE (t) = mode;
layout_type (t);
{
tree index = build_int_2 (TYPE_VECTOR_SUBPARTS (t) - 1, 0);
tree array = build_array_type (TREE_TYPE (t),
build_index_type (index));
tree index = build_int_2 (nunits - 1, 0);
tree array = build_array_type (innertype, build_index_type (index));
tree rt = make_node (RECORD_TYPE);
TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array);
......@@ -5303,6 +5308,8 @@ finish_vector_type (tree t)
numbers equal. */
TYPE_UID (rt) = TYPE_UID (t);
}
return t;
}
static tree
......@@ -5521,36 +5528,39 @@ reconstruct_complex_type (tree type, tree bottom)
return outer;
}
/* Returns a vector tree node given a vector mode and inner type. */
/* Returns a vector tree node given a mode (integer, vector, or BLKmode) and
the inner type. */
tree
build_vector_type_for_mode (tree innertype, enum machine_mode mode)
{
tree t;
t = make_node (VECTOR_TYPE);
TREE_TYPE (t) = innertype;
TYPE_MODE (t) = mode;
finish_vector_type (t);
return t;
}
int nunits;
/* Similarly, but takes inner type and units. */
if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
|| GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
nunits = GET_MODE_NUNITS (mode);
tree
build_vector_type (tree innertype, int nunits)
{
enum machine_mode innermode = TYPE_MODE (innertype);
enum machine_mode mode;
else if (GET_MODE_CLASS (mode) == MODE_INT)
{
/* Check that there are no leftover bits. */
if (GET_MODE_BITSIZE (mode) % TREE_INT_CST_LOW (TYPE_SIZE (innertype)))
abort ();
if (GET_MODE_CLASS (innermode) == MODE_FLOAT)
mode = MIN_MODE_VECTOR_FLOAT;
nunits = GET_MODE_BITSIZE (mode)
/ TREE_INT_CST_LOW (TYPE_SIZE (innertype));
}
else
mode = MIN_MODE_VECTOR_INT;
abort ();
for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode))
if (GET_MODE_NUNITS (mode) == nunits && GET_MODE_INNER (mode) == innermode)
return build_vector_type_for_mode (innertype, mode);
return make_vector_type (innertype, nunits, mode);
}
return NULL_TREE;
/* Similarly, but takes the inner type and number of units, which must be
a power of two. */
tree
build_vector_type (tree innertype, int nunits)
{
return make_vector_type (innertype, nunits, VOIDmode);
}
/* Given an initializer INIT, return TRUE if INIT is zero or some
......
......@@ -151,7 +151,8 @@ DEFTREECODE (REAL_TYPE, "real_type", 't', 0)
DEFTREECODE (COMPLEX_TYPE, "complex_type", 't', 0)
/* Vector types. The TREE_TYPE field is the data type of the vector
elements. */
elements. The TYPE_PRECISION field is the number of subparts of
the vector. */
DEFTREECODE (VECTOR_TYPE, "vector_type", 't', 0)
/* C enums. The type node looks just like an INTEGER_TYPE node.
......
......@@ -1516,7 +1516,7 @@ struct tree_block GTY(())
/* For a VECTOR_TYPE, this is the number of sub-parts of the vector. */
#define TYPE_VECTOR_SUBPARTS(VECTOR_TYPE) \
GET_MODE_NUNITS (VECTOR_TYPE_CHECK (VECTOR_TYPE)->type.mode)
(VECTOR_TYPE_CHECK (VECTOR_TYPE)->type.precision)
/* Indicates that objects of this type must be initialized by calling a
function when they are created. */
......@@ -3480,7 +3480,6 @@ extern void expand_function_start (tree);
extern void expand_pending_sizes (tree);
extern void recompute_tree_invarant_for_addr_expr (tree);
extern bool needs_to_live_in_memory (tree);
extern tree make_vector (enum machine_mode, tree, int);
extern tree reconstruct_complex_type (tree, tree);
extern int real_onep (tree);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment