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:
Devang Patel 2004-09-03 20:27:01 -07:00 committed by Devang Patel
parent 48d0dd7520
commit 40923b202d
15 changed files with 1299 additions and 14 deletions

View file

@ -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:

View file

@ -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) \

View file

@ -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)

View file

@ -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 *);

View file

@ -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

View file

@ -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.

View file

@ -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.

View 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" } } */

View 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" } } */

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;