Tree level if-conversion for vectorizer.
* Makefile.in (OBJS-common): Add tree-if-conv.o (tree-if-conv.o): New rule. * cfgloop.c (flow_loop_exit_edges_find): Set EDGE_LOOP_EXIT flag. (get_loop_body_in_bfs_order): New. * cfgloop.h (get_loop_body_in_bfs_order): New. * tree-flow.h (enum move_pos): Move here from .. * tree-ssa-loop-im.c (enum move_pos): here. (movement_possibility): Make externally visible. * tree-optimize.c (init_tree_optimization_passes): New entry for if conversion pass. * tree-pass.h (pass_if_conversion): New. * tree-ssa-operands.c (get_expr_operands): Handle COND_EXPR. * tree-if-conv.c: New file. * doc/passes.texi: Document tree if-conversion pass. * doc/tree-ssa.texi: Same. testsuite: * gcc.dg/tree-ssa/ifc-20040816-1.c: New test. * gcc.dg/tree-ssa/ifc-20040816-2.c: New test. From-SVN: r87073
This commit is contained in:
parent
48d0dd7520
commit
40923b202d
15 changed files with 1299 additions and 14 deletions
|
@ -1,3 +1,21 @@
|
|||
2004-09-03 Devang Patel <dpatel@apple.com>
|
||||
|
||||
* Makefile.in (OBJS-common): Add tree-if-conv.o
|
||||
(tree-if-conv.o): New rule.
|
||||
* cfgloop.c (flow_loop_exit_edges_find): Set EDGE_LOOP_EXIT flag.
|
||||
(get_loop_body_in_bfs_order): New.
|
||||
* cfgloop.h (get_loop_body_in_bfs_order): New.
|
||||
* tree-flow.h (enum move_pos): Move here from ..
|
||||
* tree-ssa-loop-im.c (enum move_pos): here.
|
||||
(movement_possibility): Make externally visible.
|
||||
* tree-optimize.c (init_tree_optimization_passes): New entry for
|
||||
if conversion pass.
|
||||
* tree-pass.h (pass_if_conversion): New.
|
||||
* tree-ssa-operands.c (get_expr_operands): Handle COND_EXPR.
|
||||
* tree-if-conv.c: New file.
|
||||
* doc/passes.texi: Document tree if-conversion pass.
|
||||
* doc/tree-ssa.texi: Same.
|
||||
|
||||
2004-09-03 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR target/14925:
|
||||
|
|
|
@ -887,7 +887,6 @@ C_AND_OBJC_OBJS = attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \
|
|||
C_OBJS = c-parse.o c-lang.o stub-objc.o $(C_AND_OBJC_OBJS)
|
||||
|
||||
# Language-independent object files.
|
||||
|
||||
OBJS-common = \
|
||||
tree-chrec.o tree-scalar-evolution.o tree-data-ref.o \
|
||||
tree-cfg.o tree-dfa.o tree-eh.o tree-ssa.o tree-optimize.o tree-gimple.o \
|
||||
|
@ -900,6 +899,7 @@ OBJS-common = \
|
|||
tree-phinodes.o tree-ssanames.o tree-sra.o tree-complex.o tree-ssa-loop.o \
|
||||
tree-ssa-loop-niter.o tree-ssa-loop-manip.o tree-ssa-threadupdate.o \
|
||||
tree-vectorizer.o tree-ssa-loop-ivcanon.o tree-ssa-propagate.o \
|
||||
tree-if-conv.o \
|
||||
alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \
|
||||
cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o \
|
||||
cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o \
|
||||
|
@ -1688,6 +1688,10 @@ tree-tailcall.o : tree-tailcall.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
|
|||
tree-nested.o: tree-nested.c $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TREE_H) \
|
||||
$(RTL_H) $(TM_P_H) function.h tree-dump.h tree-inline.h tree-iterator.h \
|
||||
tree-gimple.h cgraph.h $(EXPR_H) langhooks.h $(GGC_H) gt-tree-nested.h
|
||||
tree-if-conv.o: tree-if-conv.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(TREE_H) flags.h $(TIMEVAR_H) varray.h $(BASIC_BLOCK_H) $(TREE_FLOW_H) \
|
||||
cfgloop.h $(RTL_H) c-common.h tree-chrec.h tree-data-ref.h \
|
||||
tree-scalar-evolution.h tree-pass.h
|
||||
tree-iterator.o : tree-iterator.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
|
||||
coretypes.h $(GGC_H) tree-iterator.h tree-gimple.h gt-tree-iterator.h
|
||||
tree-dfa.o : tree-dfa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
|
||||
|
|
|
@ -315,7 +315,10 @@ flow_loop_exit_edges_find (struct loop *loop)
|
|||
basic_block dest = e->dest;
|
||||
|
||||
if (!flow_bb_inside_loop_p (loop, dest))
|
||||
loop->exit_edges[num_exits++] = e;
|
||||
{
|
||||
e->flags |= EDGE_LOOP_EXIT;
|
||||
loop->exit_edges[num_exits++] = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
free (bbs);
|
||||
|
@ -1085,6 +1088,60 @@ get_loop_body_in_dom_order (const struct loop *loop)
|
|||
return tovisit;
|
||||
}
|
||||
|
||||
/* Get body of a LOOP in breadth first sort order. */
|
||||
|
||||
basic_block *
|
||||
get_loop_body_in_bfs_order (const struct loop *loop)
|
||||
{
|
||||
basic_block *blocks;
|
||||
basic_block bb;
|
||||
bitmap visited;
|
||||
unsigned int i = 0;
|
||||
unsigned int vc = 1;
|
||||
|
||||
if (!loop->num_nodes)
|
||||
abort ();
|
||||
|
||||
if (loop->latch == EXIT_BLOCK_PTR)
|
||||
abort ();
|
||||
|
||||
blocks = xcalloc (loop->num_nodes, sizeof (basic_block));
|
||||
visited = BITMAP_XMALLOC ();
|
||||
|
||||
bb = loop->header;
|
||||
while (i < loop->num_nodes)
|
||||
{
|
||||
edge e;
|
||||
|
||||
if (!bitmap_bit_p (visited, bb->index))
|
||||
{
|
||||
/* This basic block is now visited */
|
||||
bitmap_set_bit (visited, bb->index);
|
||||
blocks[i++] = bb;
|
||||
}
|
||||
|
||||
for (e = bb->succ; e; e = e->succ_next)
|
||||
{
|
||||
if (flow_bb_inside_loop_p (loop, e->dest))
|
||||
{
|
||||
if (!bitmap_bit_p (visited, e->dest->index))
|
||||
{
|
||||
bitmap_set_bit (visited, e->dest->index);
|
||||
blocks[i++] = e->dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i < vc)
|
||||
abort ();
|
||||
|
||||
bb = blocks[vc++];
|
||||
}
|
||||
|
||||
BITMAP_XFREE (visited);
|
||||
return blocks;
|
||||
}
|
||||
|
||||
/* Gets exit edges of a LOOP, returning their number in N_EDGES. */
|
||||
edge *
|
||||
get_loop_exit_edges (const struct loop *loop, unsigned int *n_edges)
|
||||
|
|
|
@ -272,6 +272,7 @@ extern unsigned get_loop_level (const struct loop *);
|
|||
/* Loops & cfg manipulation. */
|
||||
extern basic_block *get_loop_body (const struct loop *);
|
||||
extern basic_block *get_loop_body_in_dom_order (const struct loop *);
|
||||
extern basic_block *get_loop_body_in_bfs_order (const struct loop *);
|
||||
extern edge *get_loop_exit_edges (const struct loop *, unsigned *);
|
||||
extern unsigned num_loop_branches (const struct loop *);
|
||||
|
||||
|
|
|
@ -385,6 +385,15 @@ The optimizations also use various utility functions contained in
|
|||
@file{tree-ssa-loop-manip.c}, @file{cfgloop.c}, @file{cfgloopanal.c} and
|
||||
@file{cfgloopmanip.c}.
|
||||
|
||||
@item Tree level if-conversion for vectorizer
|
||||
|
||||
This pass applies if-conversion to simple loops to help vectorizer.
|
||||
We identify if convertable loops, if-convert statements and merge
|
||||
basic blocks in one big block. The idea is to present loop in such
|
||||
form so that vectorizer can have one to one mapping between statements
|
||||
and available vector operations. This patch re-introduces COND_EXPR
|
||||
at GIMPLE level. This pass is located in @file{tree-if-conv.c}.
|
||||
|
||||
@item Conditional constant propagation
|
||||
|
||||
This pass relaxes a lattice of values in order to identify those
|
||||
|
|
|
@ -260,6 +260,9 @@ becomes
|
|||
a = T1;
|
||||
@end smallexample
|
||||
|
||||
Tree level if-conversion pass re-introduces @code{?:} expression, if appropriate.
|
||||
It is used to vectorize loops with conditions using vector conditional operations.
|
||||
|
||||
Note that in GIMPLE, @code{if} statements are also represented using
|
||||
@code{COND_EXPR}, as described below.
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2004-09-03 Devang Patel <dpatel@apple.com>
|
||||
|
||||
* gcc.dg/tree-ssa/ifc-20040816-1.c: New test.
|
||||
* gcc.dg/tree-ssa/ifc-20040816-2.c: New test.
|
||||
|
||||
2004-09-03 Jan Beulich <jbeulich@novell.com>
|
||||
|
||||
* g++.dg/abi/bitfield5.C: Use -mno-ms-bitfields.
|
||||
|
|
36
gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-1.c
Normal file
36
gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-1.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-c -O2 -fdump-tree-ifcvt-stats" { target *-*-* } } */
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define N 16
|
||||
#define MAX 42
|
||||
|
||||
extern void abort(void);
|
||||
|
||||
int main1 ()
|
||||
{
|
||||
int A[N] = {36,39,42,45,43,32,21,12,23,34,45,56,67,78,89,11};
|
||||
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < N; i++)
|
||||
{
|
||||
j = A[i];
|
||||
A[i] = ( j >= MAX ? MAX : 0);
|
||||
}
|
||||
|
||||
/* check results: */
|
||||
for (i = 0; i < N; i++)
|
||||
{
|
||||
if (A[i] > MAX)
|
||||
abort ();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
|
37
gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-2.c
Normal file
37
gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-2.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-c -O2 -fdump-tree-ifcvt-stats" { target *-*-* } } */
|
||||
|
||||
typedef float afloat __attribute__ ((__aligned__(16)));
|
||||
void foo(const afloat * __restrict__ zr_in,
|
||||
const afloat * __restrict__ zi_in,
|
||||
const afloat * __restrict__ zk_in,
|
||||
afloat * __restrict__ zr_out,
|
||||
afloat * __restrict__ zi_out,
|
||||
afloat * __restrict__ zk_out,
|
||||
float cr, float ci)
|
||||
{
|
||||
unsigned int pi;
|
||||
float tmp_r, tmp_i, tmp_k;
|
||||
for (pi = 0; pi < (512)*(512); pi++) {
|
||||
float zr = zr_in[pi];
|
||||
float zi = zi_in[pi];
|
||||
float zk = zk_in[pi];
|
||||
|
||||
if (zr*zr + zi*zi >= 4.0f) {
|
||||
tmp_r = zr;
|
||||
tmp_i = zi;
|
||||
tmp_k = zk;
|
||||
} else {
|
||||
tmp_r = (zr*zr - zi*zi + cr);
|
||||
tmp_i = (2 * zr * zi + ci);
|
||||
tmp_k = zk + 1.0f;
|
||||
}
|
||||
zr_out[pi] = tmp_r;
|
||||
zi_out[pi] = tmp_i;
|
||||
zk_out[pi] = tmp_k;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
|
||||
|
|
@ -654,6 +654,22 @@ bool for_each_index (tree *, bool (*) (tree, tree *, void *), void *);
|
|||
void create_iv (tree, tree, tree, struct loop *, block_stmt_iterator *, bool,
|
||||
tree *, tree *);
|
||||
|
||||
/* In tree-ssa-loop-im.c */
|
||||
/* The possibilities of statement movement. */
|
||||
|
||||
enum move_pos
|
||||
{
|
||||
MOVE_IMPOSSIBLE, /* No movement -- side effect expression. */
|
||||
MOVE_PRESERVE_EXECUTION, /* Must not cause the non-executed statement
|
||||
become executed -- memory accesses, ... */
|
||||
MOVE_POSSIBLE /* Unlimited movement. */
|
||||
};
|
||||
extern enum move_pos movement_possibility (tree);
|
||||
|
||||
/* In tree-if-conv.c */
|
||||
bool tree_if_conversion (struct loop *, bool);
|
||||
|
||||
|
||||
/* In tree-flow-inline.h */
|
||||
static inline int phi_arg_from_edge (tree, edge);
|
||||
static inline bool is_call_clobbered (tree);
|
||||
|
|
1102
gcc/tree-if-conv.c
Normal file
1102
gcc/tree-if-conv.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -368,6 +368,7 @@ init_tree_optimization_passes (void)
|
|||
NEXT_PASS (pass_loop_init);
|
||||
NEXT_PASS (pass_lim);
|
||||
NEXT_PASS (pass_iv_canon);
|
||||
NEXT_PASS (pass_if_conversion);
|
||||
NEXT_PASS (pass_vectorize);
|
||||
NEXT_PASS (pass_complete_unroll);
|
||||
NEXT_PASS (pass_loop_done);
|
||||
|
|
|
@ -110,6 +110,7 @@ extern struct tree_opt_pass pass_loop;
|
|||
extern struct tree_opt_pass pass_loop_init;
|
||||
extern struct tree_opt_pass pass_lim;
|
||||
extern struct tree_opt_pass pass_iv_canon;
|
||||
extern struct tree_opt_pass pass_if_conversion;
|
||||
extern struct tree_opt_pass pass_vectorize;
|
||||
extern struct tree_opt_pass pass_complete_unroll;
|
||||
extern struct tree_opt_pass pass_loop_done;
|
||||
|
|
|
@ -47,16 +47,6 @@ struct depend
|
|||
struct depend *next;
|
||||
};
|
||||
|
||||
/* The possibilities of statement movement. */
|
||||
|
||||
enum move_pos
|
||||
{
|
||||
MOVE_IMPOSSIBLE, /* No movement -- side effect expression. */
|
||||
MOVE_PRESERVE_EXECUTION, /* Must not cause the non-executed statement
|
||||
become executed -- memory accesses, ... */
|
||||
MOVE_POSSIBLE /* Unlimited movement. */
|
||||
};
|
||||
|
||||
/* The auxiliary data kept for each statement. */
|
||||
|
||||
struct lim_aux_data
|
||||
|
@ -170,7 +160,7 @@ for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
|
|||
because it may trap), return MOVE_PRESERVE_EXECUTION.
|
||||
Otherwise return MOVE_IMPOSSIBLE. */
|
||||
|
||||
static enum move_pos
|
||||
enum move_pos
|
||||
movement_possibility (tree stmt)
|
||||
{
|
||||
tree lhs, rhs;
|
||||
|
|
|
@ -625,7 +625,6 @@ finalize_ssa_vuses (vuse_optype *old_ops_p)
|
|||
return vuse_ops;
|
||||
}
|
||||
|
||||
|
||||
/* Return a new v_must_def operand vector for STMT, comparing to OLD_OPS_P. */
|
||||
|
||||
static v_must_def_optype
|
||||
|
@ -1081,6 +1080,12 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
|
|||
get_call_expr_operands (stmt, expr);
|
||||
return;
|
||||
|
||||
case COND_EXPR:
|
||||
get_expr_operands (stmt, &COND_EXPR_COND (expr), opf_none);
|
||||
get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none);
|
||||
get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
|
||||
return;
|
||||
|
||||
case MODIFY_EXPR:
|
||||
{
|
||||
int subflags;
|
||||
|
|
Loading…
Add table
Reference in a new issue