mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-30 07:14:09 +08:00
Add target specific tile generation algorithm
From-SVN: r257048
This commit is contained in:
parent
066fa0ff72
commit
d5e3c14d8c
@ -1,3 +1,27 @@
|
||||
2017-02-13 Sameera Deshpande <sameera.deshpande@imgtec.com>
|
||||
|
||||
* Makefile.in: Add tree-vect-unified-opts.o in OBJS.
|
||||
* tree-vect-unified-opts.c (ILV_arity_reduction): New function.
|
||||
(EXTR_arity_reduction): Likewise
|
||||
(k_arity_reduction): Likewise
|
||||
(ILV_arity_promotion): Likewise
|
||||
(merge_EXTR_nodes): Likewise
|
||||
(k_arity_promotion): Likewise
|
||||
(k_arity_promotion_reduction): Likewise
|
||||
* tree-vect-unified.c (tree_code_name): Move up in the file.
|
||||
* tree-vect-unified.h (init_stmt_attr_vec): Move to...
|
||||
* tree-vect-unified.c (init_stmt_attr_vec): ...here.
|
||||
* tree-vect-unified.h (free_stmt_attr_vec): Move to...
|
||||
* tree-vect-unified.c (free_stmt_attr_vec): ...here
|
||||
* tree-vect-unified.h (set_stmt_attr): Move to...
|
||||
* tree-vect-unified.c (set_stmt_attr): ...here
|
||||
* tree-vect-unified.h (get_stmt_attr): Move to...
|
||||
* tree-vect-unified.c (get_stmt_attr): ...here
|
||||
(populate_prim_node): Change 2nd argument.
|
||||
(duplicate_prim_node): New function
|
||||
(print_primtree): Likewise.
|
||||
(dump_primtree_node): Likewise.
|
||||
|
||||
2016-07-08 Sameera Deshpande <sameera.deshpande@imgtec.com>
|
||||
|
||||
* Makefile.in: Add tree-vect-unified.o in OBJS.
|
||||
|
@ -1067,7 +1067,12 @@ BUILD_RTL = build/rtl.o build/read-rtl.o build/ggc-none.o \
|
||||
build/print-rtl.o build/hash-table.o
|
||||
BUILD_MD = build/read-md.o
|
||||
BUILD_ERRORS = build/errors.o
|
||||
BUILD_UNITED = build/vec.o build/hash-table.o build/errors.o \
|
||||
build/ggc-none.o \
|
||||
build/tree-vect-unified-common.o build/tree-vect-unified-opts.o
|
||||
|
||||
build/tree-vect-unified-common.o : tree-vect-unified-common.c gtype-desc.h insn-codes.h
|
||||
build/tree-vect-unified-opts.o : tree-vect-unified-opts.c gtype-desc.h insn-codes.h
|
||||
# Specify the directories to be searched for header files.
|
||||
# Both . and srcdir are used, in that order,
|
||||
# so that *config.h will be found in the compilation
|
||||
@ -1206,6 +1211,7 @@ OBJS = \
|
||||
insn-preds.o \
|
||||
insn-recog.o \
|
||||
insn-enums.o \
|
||||
insn-vect-inst-tiles.o \
|
||||
ggc-page.o \
|
||||
alias.o \
|
||||
alloc-pool.o \
|
||||
@ -2207,7 +2213,7 @@ $(common_out_object_file): $(common_out_file)
|
||||
insn-emit.c insn-recog.c insn-extract.c insn-output.c insn-peep.c \
|
||||
insn-attr.h insn-attr-common.h insn-attrtab.c insn-dfatab.c \
|
||||
insn-latencytab.c insn-preds.c gimple-match.c generic-match.c \
|
||||
insn-target-def.h
|
||||
insn-target-def.h insn-vect-inst-tiles.c
|
||||
|
||||
# Dependencies for the md file. The first time through, we just assume
|
||||
# the md file itself and the generated dependency file (in order to get
|
||||
@ -2232,9 +2238,10 @@ simple_rtl_generated_h = insn-attr.h insn-attr-common.h insn-codes.h \
|
||||
|
||||
simple_rtl_generated_c = insn-automata.c insn-emit.c \
|
||||
insn-extract.c insn-output.c \
|
||||
insn-peep.c insn-recog.c
|
||||
insn-peep.c insn-recog.c \
|
||||
insn-vect-inst-tiles.c
|
||||
|
||||
simple_generated_h = $(simple_rtl_generated_h) insn-constants.h
|
||||
simple_generated_h = $(simple_rtl_generated_h) insn-constants.h
|
||||
|
||||
simple_generated_c = $(simple_rtl_generated_c) insn-enums.c
|
||||
|
||||
@ -2602,6 +2609,8 @@ build/read-rtl.o: read-rtl.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
$(GENSUPPORT_H)
|
||||
build/rtl.o: rtl.c $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H) \
|
||||
$(RTL_H) $(GGC_H) errors.h
|
||||
build/tree.o: tree.c $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H) \
|
||||
$(RTL_H) $(GGC_H) errors.h
|
||||
build/vec.o : vec.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(VEC_H) \
|
||||
$(GGC_H) toplev.h $(DIAGNOSTIC_CORE_H)
|
||||
build/hash-table.o : hash-table.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
@ -2655,6 +2664,9 @@ build/gentarget-def.o : gentarget-def.c $(BCONFIG_H) $(SYSTEM_H) \
|
||||
coretypes.h $(GTM_H) $(RTL_BASE_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) \
|
||||
$(HASH_TABLE_H) target-insns.def
|
||||
build/gengenrtl.o : gengenrtl.c $(BCONFIG_H) $(SYSTEM_H) rtl.def
|
||||
build/genvect-inst-tiles.o : genvect-inst-tiles.c $(RTL_BASE_H) $(BCONFIG_H) \
|
||||
$(SYSTEM_H) coretypes.h $(GTM_H) errors.h tree-vect-unified.h \
|
||||
tree-vect-unified-opts.o tree-vect-unified-common.o
|
||||
|
||||
# The gengtype generator program is special: Two versions are built.
|
||||
# One is for the build machine, and one is for the host to allow
|
||||
@ -2732,8 +2744,11 @@ $(genprogmd:%=build/gen%$(build_exeext)): $(BUILD_MD)
|
||||
genprogerr = $(genprogmd) genrtl modes gtype hooks cfn-macros
|
||||
$(genprogerr:%=build/gen%$(build_exeext)): $(BUILD_ERRORS)
|
||||
|
||||
genprogunited = vect-inst-tiles
|
||||
$(genprogunited:%=build/gen%$(build_exeext)): $(BUILD_UNITED)
|
||||
|
||||
# Remaining build programs.
|
||||
genprog = $(genprogerr) check checksum condmd match
|
||||
genprog = $(genprogerr) $(genprogunited) check checksum condmd match
|
||||
|
||||
# These programs need libs over and above what they get from the above list.
|
||||
build/genautomata$(build_exeext) : BUILD_LIBS += -lm
|
||||
|
@ -3468,4 +3468,37 @@ struct GTY(()) machine_function {
|
||||
(TARGET_LOAD_STORE_PAIRS && (TUNE_P5600 || TUNE_I6400) \
|
||||
&& !TARGET_MICROMIPS && !TARGET_FIX_24K)
|
||||
|
||||
#define TARGET_VEC_PERM_CONST_ORDER \
|
||||
{ \
|
||||
{2, 2, 2, "DI", (int[2]){0,2}, 1, "PCKEV.D", "RRR", NULL, NULL}, \
|
||||
{2, 2, 2, "DI", (int[2]){1,3}, 1, "PCKOD.D", "RRR", NULL, NULL}, \
|
||||
\
|
||||
{2, 4, 4, "SI", (int[4]){0,4,2,6}, 1, "ILVEV.W", "RRR", NULL, NULL}, \
|
||||
{2, 4, 4, "SI", (int[4]){1,5,3,7}, 1, "ILVOD.W", "RRR", NULL, NULL}, \
|
||||
{2, 4, 4, "SI", (int[4]){0,2,4,6}, 1, "PCKEV.W", "RRR", NULL, NULL}, \
|
||||
{2, 4, 4, "SI", (int[4]){1,3,5,7}, 1, "PCKOD.W", "RRR", NULL, NULL}, \
|
||||
{2, 4, 4, "SI", (int[4]){2,6,3,7}, 1, "ILVL.W", "RRR", NULL, NULL}, \
|
||||
{2, 4, 4, "SI", (int[4]){0,4,1,5}, 1, "ILVR.W", "RRR", NULL, NULL}, \
|
||||
\
|
||||
{2, 8, 8, "HI", (int[8]){0,8,2,10,4,12,6,14}, 1, "ILVEV.H", "RRR", NULL, NULL}, \
|
||||
{2, 8, 8, "HI", (int[8]){1,9,3,11,5,13,7,15}, 1, "ILVOD.H", "RRR", NULL, NULL}, \
|
||||
{2, 8, 8, "HI", (int[8]){0,2,4,6,8,10,12,14}, 1, "PCKEV.H", "RRR", NULL, NULL}, \
|
||||
{2, 8, 8, "HI", (int[8]){1,3,5,7,9,11,13,15}, 1, "PCKOD.H", "RRR", NULL, NULL}, \
|
||||
{2, 8, 8, "HI", (int[8]){0,8,1,9,2,10,3,11}, 1, "ILVR.H", "RRR", NULL, NULL}, \
|
||||
{2, 8, 8, "HI", (int[8]){4,12,5,13,6,14,7,15}, 1, "ILVL.H", "RRR", NULL, NULL}, \
|
||||
\
|
||||
/*{2, 16, 16, "QI", (int[16]){0,16,2,18,4,20,6,22,8,24,10,26,12,28,14,30}, 1, \
|
||||
"ILVEV.Q", "RRR", NULL, NULL}, \
|
||||
{2, 16, 16, "QI", (int[16]){1,17,3,19,5,21,7,23,9,25,11,27,13,29,15,31}, 1, \
|
||||
"ILVOD.Q", "RRR", NULL, NULL}, \
|
||||
{2, 16, 16, "QI", (int[16]){0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30}, 1, \
|
||||
"PCKEV.Q", "RRR", NULL, NULL}, \
|
||||
{2, 16, 16, "QI", (int[16]){1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31}, 1, \
|
||||
"PCKOD.Q", "RRR", NULL, NULL}, \
|
||||
{2, 16, 16, "QI", (int[16]){8,24,9,25,10,26,11,27,12,28,13,29,14,30,15,31}, 1, \
|
||||
"ILVL.Q", "RRR", NULL, NULL}, \
|
||||
{2, 16, 16, "QI", (int[16]){0,16,1,17,2,18,3,19,4,20,5,21,6,22,7,23}, 1, \
|
||||
"ILVR.Q", "RRR", NULL, NULL}, */\
|
||||
}
|
||||
|
||||
#define MAX_VECTOR_SIZE 16
|
||||
|
@ -358,6 +358,8 @@ typedef void (*gt_pointer_operator) (void *, void *);
|
||||
typedef unsigned char uchar;
|
||||
#endif
|
||||
|
||||
struct vec_perm_order_spec;
|
||||
|
||||
/* Most host source files will require the following headers. */
|
||||
#if !defined (GENERATOR_FILE) && !defined (USED_FOR_TARGET)
|
||||
#include "machmode.h"
|
||||
|
2043
gcc/genvect-inst-tiles.c
Normal file
2043
gcc/genvect-inst-tiles.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -61,7 +61,6 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "builtins.h"
|
||||
#include "params.h"
|
||||
#include "pretty-print.h"
|
||||
#include "pretty-print.h"
|
||||
#else
|
||||
#include "errors.h"
|
||||
#include "machmode.h"
|
||||
@ -78,9 +77,6 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "is-a.h"
|
||||
#include "target.h"
|
||||
#include "tree-core.h"
|
||||
#include "tree-vect-unified.h"
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#include "tree-vect-unified.h"
|
||||
@ -128,7 +124,7 @@ init_primop_node (void)
|
||||
|
||||
struct primop_tree *
|
||||
populate_prim_node (enum primop_code pcode, tree iter_count,
|
||||
struct primop_tree *parent, gimple *stmt)
|
||||
struct primop_tree *parent, gimple *stmt, tree vec_type)
|
||||
{
|
||||
struct primop_tree *ptree;
|
||||
ptree = init_primop_node ();
|
||||
@ -136,7 +132,7 @@ populate_prim_node (enum primop_code pcode, tree iter_count,
|
||||
PT_NODE_OP (ptree) = (int) pcode;
|
||||
PT_PARENT (ptree) = parent;
|
||||
PT_ITER_COUNT (ptree) = iter_count;
|
||||
|
||||
PT_VEC_TYPE (ptree) = vec_type;
|
||||
#ifndef GENERATOR_FILE
|
||||
if (stmt)
|
||||
{
|
||||
@ -154,11 +150,12 @@ populate_prim_node (enum primop_code pcode, tree iter_count,
|
||||
which primtree is being created. */
|
||||
struct primop_tree *
|
||||
create_primTree_combine (enum primop_code pcode, gimple *stmt, int parts,
|
||||
tree iter_count, struct primop_tree *parent)
|
||||
tree iter_count, struct primop_tree *parent,
|
||||
tree vec_type)
|
||||
{
|
||||
struct primop_tree * ptree;
|
||||
|
||||
ptree = populate_prim_node (pcode, iter_count, parent, stmt);
|
||||
ptree = populate_prim_node (pcode, iter_count, parent, stmt, vec_type);
|
||||
PT_OPERAND_SELECTOR (ptree) = -1;
|
||||
PT_DIVISION (ptree) = parts;
|
||||
PT_VAR_STRIDE (ptree) = NULL;
|
||||
@ -183,11 +180,11 @@ create_primTree_combine (enum primop_code pcode, gimple *stmt, int parts,
|
||||
struct primop_tree *
|
||||
create_primTree_partition (enum primop_code pcode, gimple *stmt, int parts,
|
||||
int selector, tree iter_count,
|
||||
struct primop_tree *parent)
|
||||
struct primop_tree *parent, tree vec_type)
|
||||
{
|
||||
struct primop_tree * ptree;
|
||||
|
||||
ptree = populate_prim_node (pcode, iter_count, parent, stmt);
|
||||
ptree = populate_prim_node (pcode, iter_count, parent, stmt, vec_type);
|
||||
PT_OPERAND_SELECTOR (ptree) = selector;
|
||||
PT_DIVISION (ptree) = parts;
|
||||
PT_VAR_STRIDE (ptree) = NULL;
|
||||
|
@ -61,7 +61,6 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "builtins.h"
|
||||
#include "params.h"
|
||||
#include "pretty-print.h"
|
||||
#include "pretty-print.h"
|
||||
#else
|
||||
# include "errors.h"
|
||||
#include "machmode.h"
|
||||
@ -78,8 +77,6 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "is-a.h"
|
||||
#include "target.h"
|
||||
#include "tree-core.h"
|
||||
#include "tree-vect-unified.h"
|
||||
|
||||
#endif
|
||||
|
||||
#include "tree-vect-unified.h"
|
||||
@ -116,12 +113,13 @@ ILV_arity_reduction (struct primop_tree *root, int from_arity, int to_arity)
|
||||
#endif
|
||||
|
||||
new_root = create_primTree_combine (POP_ILV, NULL, to_arity,
|
||||
new_iter_count, PT_PARENT (root));
|
||||
new_iter_count, PT_PARENT (root), PT_VEC_TYPE (root));
|
||||
|
||||
for (i = 0; i < to_arity; i++)
|
||||
{
|
||||
new_child = create_primTree_combine (POP_ILV, NULL,
|
||||
from_arity / to_arity, PT_ITER_COUNT (root), new_root);
|
||||
from_arity / to_arity, PT_ITER_COUNT (root), new_root,
|
||||
PT_VEC_TYPE (root));
|
||||
|
||||
for (j = 0; j < from_arity / to_arity; j++)
|
||||
{
|
||||
@ -173,11 +171,11 @@ EXTR_arity_reduction (struct primop_tree *root, int from_arity, int to_arity)
|
||||
|
||||
new_root = create_primTree_partition (POP_EXTR, NULL, to_arity,
|
||||
(PT_OPERAND_SELECTOR (root) * to_arity / from_arity) % to_arity,
|
||||
new_iter_count, PT_PARENT (root));
|
||||
new_iter_count, PT_PARENT (root), PT_VEC_TYPE (root));
|
||||
|
||||
new_child = create_primTree_partition (POP_EXTR, NULL, from_arity/to_arity,
|
||||
PT_OPERAND_SELECTOR (root) % (from_arity / to_arity),
|
||||
PT_ITER_COUNT (root), new_root);
|
||||
PT_ITER_COUNT (root), new_root, PT_VEC_TYPE (root));
|
||||
|
||||
add_child_at_index (new_child, PT_CHILD (root, 0), 0);
|
||||
|
||||
@ -258,14 +256,14 @@ ILV_arity_promotion (struct primop_tree *root, int from_arity, int to_arity)
|
||||
#endif
|
||||
|
||||
new_root = create_primTree_combine (POP_ILV, NULL, to_arity,
|
||||
new_iter_count, PT_PARENT (root));
|
||||
new_iter_count, PT_PARENT (root), PT_VEC_TYPE (root));
|
||||
for (i = 0; i < to_arity / from_arity; i++)
|
||||
{
|
||||
for (j = 0; j < from_arity; j++)
|
||||
{
|
||||
new_child = create_primTree_partition (POP_EXTR, NULL,
|
||||
to_arity / from_arity, i, PT_ITER_COUNT (root),
|
||||
new_root);
|
||||
new_root, PT_VEC_TYPE (root));
|
||||
add_child_at_index (new_child, PT_CHILD (root, j), 0);
|
||||
tmp = k_arity_promotion_reduction (new_child, to_arity);
|
||||
if (tmp != NULL)
|
||||
@ -313,7 +311,8 @@ merge_EXTR_nodes (struct primop_tree *root, int to_arity)
|
||||
if (iter_node != PT_CHILD (root, 0))
|
||||
{
|
||||
tmp = create_primTree_partition (POP_EXTR, NULL, parts, selector,
|
||||
iter_count, PT_PARENT (root));
|
||||
iter_count, PT_PARENT (root),
|
||||
PT_VEC_TYPE (root));
|
||||
add_child_at_index (tmp, iter_node, 0);
|
||||
return tmp;
|
||||
}
|
||||
@ -520,8 +519,8 @@ int
|
||||
annotate_tree_nodes (struct primop_tree *ptree, int *end,
|
||||
struct primop_tree **leaves)
|
||||
{
|
||||
int key;
|
||||
long long int idx;
|
||||
long long int key;
|
||||
int idx;
|
||||
int length = 0;
|
||||
int i, j;
|
||||
struct primop_tree *temp[150];
|
||||
@ -541,8 +540,8 @@ annotate_tree_nodes (struct primop_tree *ptree, int *end,
|
||||
|
||||
for (i = 0; i < ptree->children.length (); i++)
|
||||
{
|
||||
key = (key | annotate_tree_nodes (PT_CHILD (ptree, i),
|
||||
&length, temp)) << 12;
|
||||
key = (key << 12)
|
||||
| annotate_tree_nodes (PT_CHILD (ptree, i), &length, temp);
|
||||
for (j = 0; j < length; j++)
|
||||
{
|
||||
leaves[(*end)++] = temp[j];
|
||||
@ -575,7 +574,11 @@ unity_redundancy_elimination_2 (struct primop_tree *ptree,
|
||||
bool changed = false;
|
||||
int to_be_matched;
|
||||
struct primop_tree *temp_ptree;
|
||||
int i;
|
||||
int i, j;
|
||||
long long int key;
|
||||
int idx, end;
|
||||
struct primop_tree *leaves[150];
|
||||
struct primtree_hash_table *new_hash;
|
||||
|
||||
*new_ptree = ptree;
|
||||
|
||||
@ -612,14 +615,53 @@ unity_redundancy_elimination_2 (struct primop_tree *ptree,
|
||||
}
|
||||
}
|
||||
|
||||
key = PT_NODE_OP (ptree) << 10;
|
||||
end = 0;
|
||||
for (i = 0; i < (*new_ptree)->children.length (); i++)
|
||||
{
|
||||
changed |= unity_redundancy_elimination_2 (PT_CHILD (*new_ptree, i),
|
||||
&temp_ptree);
|
||||
PT_CHILD (*new_ptree, i) = temp_ptree;
|
||||
PT_PARENT (temp_ptree) = *new_ptree;
|
||||
if (PT_NODE_OP (temp_ptree) == POP_MEMREF
|
||||
|| PT_NODE_OP (temp_ptree) == POP_PH
|
||||
|| PT_NODE_OP (temp_ptree) == POP_CONST)
|
||||
{
|
||||
key = (key | 0xfff) << 12;
|
||||
leaves[end++] = temp_ptree;
|
||||
}
|
||||
else
|
||||
{
|
||||
key = (key << 12) | PT_AUX(temp_ptree);
|
||||
|
||||
for (j = 0;
|
||||
j < primop_hash[PT_AUX(temp_ptree)]->leaves.length ();
|
||||
j++)
|
||||
{
|
||||
leaves[end + j] = primop_hash[PT_AUX(temp_ptree)]->leaves[j];
|
||||
}
|
||||
|
||||
end = end + j;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
idx = lookup_key_in_table (key, leaves, end);
|
||||
|
||||
if (idx == -1)
|
||||
{
|
||||
// Create new entry.
|
||||
new_hash = (struct primtree_hash_table *) xcalloc (1,
|
||||
sizeof (struct primtree_hash_table));
|
||||
new_hash->key = key;
|
||||
new_hash->leaves = vNULL;
|
||||
for (i = 0; i < end; i++)
|
||||
new_hash->leaves.safe_insert (new_hash->leaves.length (), leaves[i]);
|
||||
idx = primop_hash.length ();
|
||||
primop_hash.safe_insert (idx, new_hash);
|
||||
}
|
||||
PT_AUX (*new_ptree) = idx;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
@ -640,13 +682,12 @@ unity_redundancy_elimination (struct primop_tree *ptree)
|
||||
bool changed;
|
||||
|
||||
annotate_tree_nodes (ptree, &end, dummy);
|
||||
|
||||
changed = false;
|
||||
|
||||
do {
|
||||
changed = unity_redundancy_elimination_2 (ptree, &new_ptree);
|
||||
if (ptree == new_ptree)
|
||||
break;
|
||||
//if (ptree == new_ptree)
|
||||
// break;
|
||||
ptree = new_ptree;
|
||||
} while (changed == true);
|
||||
|
||||
|
@ -1559,16 +1559,17 @@ exists_primTree_with_memref (tree base, tree step, bool is_read,
|
||||
|
||||
struct primop_tree *
|
||||
create_primTree_memref (tree base, tree step, bool is_read, int num,
|
||||
tree iter_count, struct primop_tree *parent)
|
||||
tree iter_count, struct primop_tree *parent,
|
||||
tree vec_type)
|
||||
{
|
||||
struct primop_tree * ptree;
|
||||
|
||||
ptree = populate_prim_node (POP_MEMREF, iter_count, parent, NULL);
|
||||
ptree = populate_prim_node (POP_MEMREF, iter_count, parent, NULL, vec_type);
|
||||
|
||||
PT_MEMVAL_BASE (ptree) = unshare_expr (base);
|
||||
PT_MEMVAL_MULT_IDX (ptree) = unshare_expr (step);
|
||||
PT_MEMVAL_IS_READ (ptree) = is_read;
|
||||
|
||||
PT_VEC_TYPE (ptree) = vec_type;
|
||||
if (dump_enabled_p ())
|
||||
{
|
||||
dump_printf_loc (MSG_NOTE, vect_location,
|
||||
@ -1726,18 +1727,19 @@ vectorizable_store (gimple *stmt, struct ITER_node *inode,
|
||||
if (pnode == NULL)
|
||||
{
|
||||
pnode = create_primTree_memref (base, step, false, num,
|
||||
ITER_NODE_NITERS (inode), NULL);
|
||||
ITER_NODE_NITERS (inode), NULL, vec_type);
|
||||
ITER_NODE_LOOP_BODY (inode).safe_insert (
|
||||
ITER_NODE_LOOP_BODY (inode).length (),
|
||||
pnode);
|
||||
pchild1 = create_primTree_combine (POP_ILV, stmt,
|
||||
tree_to_uhwi (step) / num, ITER_NODE_NITERS (inode),
|
||||
pnode);
|
||||
pnode, vec_type);
|
||||
add_child_at_index (pnode, pchild1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pchild1 = get_child_at_index (pnode, 0);
|
||||
gcc_assert (PT_VEC_TYPE (pchild1) == vec_type);
|
||||
}
|
||||
if (def_stmt)
|
||||
{
|
||||
@ -1765,7 +1767,7 @@ vectorizable_store (gimple *stmt, struct ITER_node *inode,
|
||||
}
|
||||
|
||||
add_child_at_index (pchild1, pchild2, tree_to_uhwi (offset) / num);
|
||||
|
||||
gcc_assert (PT_VEC_TYPE (pchild2));
|
||||
return pnode;
|
||||
}
|
||||
|
||||
@ -1843,9 +1845,9 @@ vectorizable_load (gimple *stmt, struct ITER_node *inode,
|
||||
|
||||
pnode = create_primTree_partition (POP_EXTR, stmt,
|
||||
tree_to_uhwi (step) / num,
|
||||
tree_to_uhwi (offset) / num, ITER_NODE_NITERS (inode), parent);
|
||||
tree_to_uhwi (offset) / num, ITER_NODE_NITERS (inode), parent, vec_type);
|
||||
pchild1 = create_primTree_memref (base, step, true, num,
|
||||
ITER_NODE_NITERS (inode), pnode);
|
||||
ITER_NODE_NITERS (inode), pnode, vec_type);
|
||||
add_child_at_index (pnode, pchild1, 0);
|
||||
return pnode;
|
||||
}
|
||||
@ -2390,6 +2392,158 @@ dump_iter_node (struct ITER_node *inode, FILE *fp)
|
||||
pp_flush (&pp);
|
||||
}
|
||||
|
||||
static void
|
||||
reset_aux_field (struct primop_tree *ptree)
|
||||
{
|
||||
int i;
|
||||
PT_AUX (ptree) = -1;
|
||||
if (PT_ARITY (ptree) == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ptree->children.length (); i++)
|
||||
reset_aux_field (get_child_at_index (ptree, i));
|
||||
}
|
||||
|
||||
static int
|
||||
get_transition_state (struct primop_tree *ptree)
|
||||
{
|
||||
int i;
|
||||
vec<int> idx = vNULL;
|
||||
|
||||
/* If the node is non-permute operation, return the state of terminal 'REG' as
|
||||
state of this tree, because non-permute operations are evaluated in
|
||||
registers. */
|
||||
if (PT_NODE_OP (ptree) < MAX_TREE_CODES)
|
||||
{
|
||||
return get_REG_terminal_state (GET_MODE_SIZE (TYPE_MODE (PT_VEC_TYPE (ptree))));
|
||||
}
|
||||
|
||||
/* We need not handle POP_PH as it is only for tile construction. POP_CONCAT
|
||||
and POP_SPLT are now represented using POP_ILV and POP_EXTR for now. Hence
|
||||
these operators need not be handled here. POP_MEMREF and POP_CONST are
|
||||
leaf nodes, and won't be passed to this function. POP_INV for loop
|
||||
invariants, POP_COLLAPSE for reduction operation and POP_ITER for loop or
|
||||
vec_size_reduction operation need TODO. */
|
||||
|
||||
switch (PT_NODE_OP (ptree))
|
||||
{
|
||||
case POP_ILV:
|
||||
for (i = 0; i < ptree->children.length (); i++)
|
||||
{
|
||||
idx.safe_insert(idx.length (),
|
||||
PT_AUX (get_child_at_index (ptree, i)));
|
||||
}
|
||||
|
||||
return transition_state_for_ilv (PT_DIVISION (ptree), idx);
|
||||
|
||||
case POP_EXTR:
|
||||
return transition_state_for_extr (PT_DIVISION (ptree),
|
||||
PT_OPERAND_SELECTOR (ptree),
|
||||
PT_AUX (get_child_at_index (ptree, 0)));
|
||||
|
||||
default:
|
||||
gcc_assert (!"Operator not handled.");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool
|
||||
label_permute_tree (struct primop_tree *ptree)
|
||||
{
|
||||
bool ret = true;
|
||||
int i;
|
||||
|
||||
if (PT_ARITY (ptree) == 0)
|
||||
{
|
||||
switch (PT_NODE_OP (ptree))
|
||||
{
|
||||
case POP_MEMREF:
|
||||
PT_AUX (ptree) = get_REG_terminal_state (GET_MODE_SIZE (TYPE_MODE (PT_VEC_TYPE (ptree))));
|
||||
printf ("tree : %d >> state : %d\n", PT_PID (ptree), PT_AUX (ptree));
|
||||
break;
|
||||
case POP_CONST:
|
||||
PT_AUX (ptree) = get_CONST_terminal_state ();
|
||||
printf ("tree : %d >> state : %d\n", PT_PID (ptree), PT_AUX (ptree));
|
||||
break;
|
||||
default:
|
||||
gcc_assert (0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (i = 0; i < ptree->children.length (); i++)
|
||||
{
|
||||
ret |= label_permute_tree (get_child_at_index (ptree, i));
|
||||
if (ret == false)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (PT_NODE_OP (ptree) == POP_MEMREF)
|
||||
PT_AUX (ptree) = PT_AUX (get_child_at_index (ptree, 0));
|
||||
else
|
||||
PT_AUX (ptree) = get_transition_state (ptree);
|
||||
printf ("tree : %d >> state : %d\n", PT_PID (ptree), PT_AUX (ptree));
|
||||
|
||||
if (PT_AUX (ptree) == -1)
|
||||
{
|
||||
printf ("\n labeled to REG\n");
|
||||
PT_AUX (ptree) = (get_REG_terminal_state (GET_MODE_SIZE (TYPE_MODE (PT_VEC_TYPE (ptree)))));
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("%d\t", PT_AUX (ptree));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
reduce_permute_tree (struct primop_tree *ptree, int goal_nt)
|
||||
{
|
||||
int rule_no;
|
||||
int i;
|
||||
|
||||
// if (PT_AUX (ptree) == get_REG_terminal_state ())
|
||||
// reduce_permute_tree(ptree, 0);
|
||||
rule_no = get_rule_number (ptree, goal_nt);
|
||||
if (rule_no == -1) {
|
||||
printf ("\n Matched to default rule : %d\n", PT_PID (ptree));
|
||||
} else if (is_NT2T_rule (rule_no)) {
|
||||
printf ("Terminal matched.\n");
|
||||
} else {
|
||||
printf ("\n Rule matched: %d.\t State matched: %d.\n", rule_no, PT_AUX (ptree));
|
||||
print_permute_order (rule_no);
|
||||
if (PT_ARITY (ptree) != 0 && PT_NODE_OP (ptree) == POP_MEMREF)
|
||||
return reduce_permute_tree (PT_CHILD (ptree, 0), goal_nt);
|
||||
for (i = 0; i < PT_ARITY (ptree); i++)
|
||||
{
|
||||
reduce_permute_tree (PT_CHILD (ptree, i), get_child_nt (PT_AUX (ptree), rule_no, i));
|
||||
}
|
||||
}
|
||||
|
||||
return true;//(rule_no >= 0);
|
||||
|
||||
}
|
||||
|
||||
static bool
|
||||
unified_perm_tree_code_generation (struct ITER_node *inode)
|
||||
{
|
||||
int i;
|
||||
bool ret = false;
|
||||
struct primop_tree *tmp_tree;
|
||||
|
||||
for (i = 0; i < (ITER_NODE_LOOP_BODY (inode)).length (); i++)
|
||||
{
|
||||
tmp_tree = (ITER_NODE_LOOP_BODY (inode))[i];
|
||||
reset_aux_field (tmp_tree);
|
||||
ret = label_permute_tree (tmp_tree);
|
||||
if (ret == true)
|
||||
ret = reduce_permute_tree (tmp_tree, get_REG_terminal_state (GET_MODE_SIZE (TYPE_MODE (PT_VEC_TYPE (tmp_tree)))));
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Function vectorize_loops_using_uniop.
|
||||
|
||||
Entry point to autovectorization using unified representation:
|
||||
@ -2420,6 +2574,7 @@ vectorize_loops_using_uniop (void)
|
||||
//iter_node = NULL;
|
||||
|
||||
init_stmt_attr_vec ();
|
||||
unif_vect_init_funct ();
|
||||
|
||||
FOR_EACH_LOOP (loop, 0)
|
||||
if (loop->dont_vectorize)
|
||||
@ -2527,6 +2682,35 @@ vectorize_loops_using_uniop (void)
|
||||
dump_iter_node (tmp_iter_node, alt_dump_file);
|
||||
}
|
||||
|
||||
worklist = vNULL;
|
||||
worklist = (ITER_NODE_LOOP_BODY (tmp_iter_node)).copy ();
|
||||
for (i = 0; i < worklist.length (); i++)
|
||||
{
|
||||
gcc_assert (worklist.iterate (i, &tmp_tree));
|
||||
tmp_tree = unity_redundancy_elimination (tmp_tree);
|
||||
|
||||
ITER_NODE_LOOP_BODY (tmp_iter_node)[i] = tmp_tree;
|
||||
}
|
||||
|
||||
if (dump_enabled_p ())
|
||||
{
|
||||
dump_printf (MSG_NOTE, "\nUnity redundancy elimination applied.\n");
|
||||
if (dump_file)
|
||||
dump_iter_node (tmp_iter_node, dump_file);
|
||||
if (alt_dump_file)
|
||||
dump_iter_node (tmp_iter_node, alt_dump_file);
|
||||
}
|
||||
|
||||
//unified_vecsize_reduction (tmp_iter_node);
|
||||
|
||||
if (dump_enabled_p ())
|
||||
{
|
||||
dump_printf (MSG_NOTE, "\nVector size reduction applied.\n");
|
||||
if (dump_file)
|
||||
dump_iter_node (tmp_iter_node, dump_file);
|
||||
if (alt_dump_file)
|
||||
dump_iter_node (tmp_iter_node, alt_dump_file);
|
||||
}
|
||||
gimple *loop_vectorized_call = vect_loop_vectorized_call (loop);
|
||||
/* If the loop is vectorized, set uid of stmts within scalar loop to
|
||||
0. This change is needed if transform phase uses this loop info. */
|
||||
@ -2535,6 +2719,8 @@ vectorize_loops_using_uniop (void)
|
||||
|
||||
/* TODO: Insert call to transformation entry point. */
|
||||
|
||||
unified_perm_tree_code_generation (tmp_iter_node);
|
||||
|
||||
num_vectorized_loops++;
|
||||
/* Now that the loop has been vectorized, allow it to be unrolled
|
||||
etc. */
|
||||
|
@ -224,6 +224,7 @@ struct primop_tree {
|
||||
} phval;
|
||||
} u;
|
||||
int aux;
|
||||
// vec<int> aux1;
|
||||
};
|
||||
|
||||
#define PT_PID(x) (x)->pid
|
||||
@ -250,6 +251,7 @@ struct primop_tree {
|
||||
#define PT_MEMVAL_MULT_IDX(x) (x)->u.memval.mult_idx
|
||||
#define PT_MEMVAL_IS_READ(x) (x)->u.memval.is_read
|
||||
#define PT_AUX(x) (x)->aux
|
||||
//#define PT_AUX1(x) (x)->aux1
|
||||
#define PT_PH_IDX(x) (x)->u.phval.index
|
||||
#define PT_PH_TYPE(x) (x)->u.phval.type
|
||||
//struct ITER_node *iter_node;
|
||||
@ -285,6 +287,51 @@ static const char *const tree_code_name[] = {
|
||||
#undef DEFTREECODE
|
||||
#undef END_OF_BASE_TREE_CODES
|
||||
|
||||
/* TARGET_VEC_PERM_CONST_ORDER - If defined, this target hook points to an array
|
||||
of "struct vec_perm_order_spec" specifying various permute orders supported
|
||||
by the target architecture. */
|
||||
|
||||
struct vec_perm_order_spec
|
||||
{
|
||||
/* Number of operands in permute order specified. */
|
||||
int num_opd;
|
||||
|
||||
/* Vector size of input permute order. */
|
||||
int in_vec_size;
|
||||
|
||||
/* Vector size of resultant permute order. It can be identified from the size
|
||||
of perm_order, however, if by mistake, this field is not defined properly,
|
||||
can lead to errors. Hence, taking that as input. */
|
||||
int out_vec_size;
|
||||
|
||||
/* Input type name. */
|
||||
char *type;
|
||||
|
||||
/* Permute order of operands. */
|
||||
int *perm_order;
|
||||
|
||||
/* Cost of permute operation. */
|
||||
int cost;
|
||||
|
||||
/* Name of permute operation for debugging purpose. */
|
||||
char *op_name;
|
||||
|
||||
/* The constraints on input and output operands of this instruction.
|
||||
Restricting these to R,M or I for register, memory and integer constant
|
||||
respectively. This is needed for reduction rules to be generated for BURS
|
||||
tree. It should have comma separated list - with num_opd + 1 listings. */
|
||||
char * opd_constraint;
|
||||
|
||||
/* Condition under which the instruction can be emitted. Thinking of
|
||||
something like condition part in define_insn. */
|
||||
char * cond;
|
||||
|
||||
/* PRIMOP_TREE constructed after tile construction. */
|
||||
struct primop_tree *ptree;
|
||||
};
|
||||
|
||||
|
||||
|
||||
extern unsigned int vectorize_loops_using_uniop (void);
|
||||
extern struct primop_tree * analyze_and_create_ptree (struct primop_tree *,
|
||||
gimple *, struct ITER_node *);
|
||||
@ -295,16 +342,16 @@ extern struct primop_tree * k_arity_promotion_reduction (struct primop_tree *,
|
||||
int);
|
||||
extern struct primop_tree * init_primop_node (void);
|
||||
extern struct primop_tree * populate_prim_node (enum primop_code, tree,
|
||||
struct primop_tree *, gimple *);
|
||||
struct primop_tree *, gimple *, tree);
|
||||
extern struct primop_tree * exists_primTree_with_memref (tree, tree, bool,
|
||||
struct ITER_node *);
|
||||
extern struct primop_tree * create_primTree_memref (tree, tree, bool, int, tree,
|
||||
struct primop_tree *);
|
||||
struct primop_tree *, tree);
|
||||
extern struct primop_tree * create_primTree_combine (enum primop_code, gimple *,
|
||||
int, tree, struct primop_tree *);
|
||||
int, tree, struct primop_tree *, tree);
|
||||
extern struct primop_tree * create_primTree_partition (enum primop_code,
|
||||
gimple *, int, int, tree,
|
||||
struct primop_tree *);
|
||||
struct primop_tree *, tree);
|
||||
extern void add_child_at_index (struct primop_tree *, struct primop_tree *,
|
||||
int);
|
||||
extern struct primop_tree * get_child_at_index (struct primop_tree *, int);
|
||||
@ -316,6 +363,16 @@ extern void free_stmt_attr_vec (void);
|
||||
extern inline void set_stmt_attr (gimple *, struct stmt_attr *);
|
||||
extern inline struct stmt_attr *get_stmt_attr (gimple *);
|
||||
extern struct primop_tree * unity_redundancy_elimination (struct primop_tree *);
|
||||
|
||||
extern void unif_vect_init_funct (void);
|
||||
extern vec<int> transition_state_for_extr (int, int, int);
|
||||
extern vec<int> transition_state_for_ilv (int, vec<int>);
|
||||
extern int get_REG_terminal_state (int);
|
||||
extern bool is_NT2T_rule (int);
|
||||
extern int get_CONST_terminal_state ();
|
||||
extern int get_MEM_terminal_state ();
|
||||
//extern int get_goal_nonterminal_state (int);
|
||||
extern int get_rule_number (struct primop_tree *, int);
|
||||
extern void print_permute_order (int);
|
||||
extern int get_child_nt (int, int, int);
|
||||
#endif
|
||||
|
||||
|
18
gcc/vec.h
18
gcc/vec.h
@ -486,7 +486,7 @@ public:
|
||||
static size_t embedded_size (unsigned);
|
||||
void embedded_init (unsigned, unsigned = 0, unsigned = 0);
|
||||
void quick_grow (unsigned len);
|
||||
void quick_grow_cleared (unsigned len);
|
||||
void quick_grow_cleared (unsigned len, int = 0);
|
||||
|
||||
/* vec class can access our internal data and functions. */
|
||||
template <typename, typename, typename> friend struct vec;
|
||||
@ -1089,13 +1089,13 @@ vec<T, A, vl_embed>::quick_grow (unsigned len)
|
||||
|
||||
template<typename T, typename A>
|
||||
inline void
|
||||
vec<T, A, vl_embed>::quick_grow_cleared (unsigned len)
|
||||
vec<T, A, vl_embed>::quick_grow_cleared (unsigned len, int val)
|
||||
{
|
||||
unsigned oldlen = length ();
|
||||
size_t sz = sizeof (T) * (len - oldlen);
|
||||
quick_grow (len);
|
||||
if (sz != 0)
|
||||
memset (&(address ()[oldlen]), 0, sz);
|
||||
memset (&(address ()[oldlen]), val, sz);
|
||||
}
|
||||
|
||||
|
||||
@ -1235,9 +1235,9 @@ public:
|
||||
T &pop (void);
|
||||
void truncate (unsigned);
|
||||
void safe_grow (unsigned CXX_MEM_STAT_INFO);
|
||||
void safe_grow_cleared (unsigned CXX_MEM_STAT_INFO);
|
||||
void safe_grow_cleared (unsigned CXX_MEM_STAT_INFO, int = 0);
|
||||
void quick_grow (unsigned);
|
||||
void quick_grow_cleared (unsigned);
|
||||
void quick_grow_cleared (unsigned, int = 0);
|
||||
void quick_insert (unsigned, const T &);
|
||||
void safe_insert (unsigned, const T & CXX_MEM_STAT_INFO);
|
||||
void ordered_remove (unsigned);
|
||||
@ -1604,13 +1604,13 @@ vec<T, va_heap, vl_ptr>::safe_grow (unsigned len MEM_STAT_DECL)
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len MEM_STAT_DECL)
|
||||
vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len MEM_STAT_DECL, int val)
|
||||
{
|
||||
unsigned oldlen = length ();
|
||||
size_t sz = sizeof (T) * (len - oldlen);
|
||||
safe_grow (len PASS_MEM_STAT);
|
||||
if (sz != 0)
|
||||
memset (&(address ()[oldlen]), 0, sz);
|
||||
memset (&(address ()[oldlen]), val, sz);
|
||||
}
|
||||
|
||||
|
||||
@ -1632,10 +1632,10 @@ vec<T, va_heap, vl_ptr>::quick_grow (unsigned len)
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
vec<T, va_heap, vl_ptr>::quick_grow_cleared (unsigned len)
|
||||
vec<T, va_heap, vl_ptr>::quick_grow_cleared (unsigned len, int val)
|
||||
{
|
||||
gcc_checking_assert (m_vec);
|
||||
m_vec->quick_grow_cleared (len);
|
||||
m_vec->quick_grow_cleared (len, val);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user