fix pr46851 and pr60340: remove unmaintained omega dependence test
Regstrapped on amd64-linux. 2015-07-18 Sebastian Pop <s.pop@samsung.com> PR middle-end/46851 PR middle-end/60340 * Makefile.in: Removed omega.o. * common.opt: Remove flag fcheck-data-deps. * doc/invoke.texi: Remove documentation for fcheck-data-deps and its associated params: omega-max-vars, omega-max-geqs, omega-max-eqs, omega-max-wild-cards, omega-hash-table-size, omega-max-keys, omega-eliminate-redundant-constraints. * doc/loop.texi: Remove all the section on Omega. * graphite-blocking.c: Include missing params.h: it used to be included through tree-data-ref.h and omega.h. * graphite-isl-ast-to-gimple.c: Same. * graphite-optimize-isl.c: Same. * graphite-sese-to-poly.c: Same. * graphite.c: Same. * omega.c: Remove. * omega.h: Remove. * params.def: Removed PARAM_OMEGA_MAX_VARS, PARAM_OMEGA_MAX_GEQS, PARAM_OMEGA_MAX_EQS, PARAM_OMEGA_MAX_WILD_CARDS, PARAM_OMEGA_HASH_TABLE_SIZE, PARAM_OMEGA_MAX_KEYS, and PARAM_OMEGA_ELIMINATE_REDUNDANT_CONSTRAINTS. * passes.def: Remove pass_check_data_deps. * tree-data-ref.c (dump_affine_function): Declare DEBUG_FUNCTION. (dump_conflict_function): Same. (dump_subscript): Same. (print_direction_vector): Same. (print_dir_vectors): Same. (print_lambda_vector): Same. (print_dist_vectors): Same. (dump_data_dependence_relation): Same. (dump_data_dependence_relations): Same. (dump_dist_dir_vectors): Same. (dump_ddrs): Same. (init_omega_eq_with_af): Removed. (omega_extract_distance_vectors): Removed. (omega_setup_subscript): Removed. (init_omega_for_ddr_1): Removed. (init_omega_for_ddr): Removed. (ddr_consistent_p): Removed. (compute_affine_dependence): Do not use omega to check data dependences. (compute_data_dependences_for_bb): Removed. (analyze_all_data_dependences): Removed. (tree_check_data_deps): Removed. * tree-data-ref.h: Do not include omega.h. (compute_data_dependences_for_bb): Removed. (tree_check_data_deps): Removed. * tree-ssa-loop.c (pass_check_data_deps): Removed. (make_pass_check_data_deps): Removed. * tree-ssa-phiopt.c: Include params.h. * tree-vect-data-refs.c: Same. * tree-vect-slp.c: Same. testsuite/ * gcc.dg/tree-ssa/pr42327.c: Removed. * g++.dg/other/pr35011.C: Removed. From-SVN: r225979
This commit is contained in:
parent
ca4b5dbd8a
commit
49b8fe6c1a
|
@ -1,3 +1,58 @@
|
|||
2015-07-18 Sebastian Pop <s.pop@samsung.com>
|
||||
|
||||
PR middle-end/46851
|
||||
PR middle-end/60340
|
||||
* Makefile.in: Removed omega.o.
|
||||
* common.opt: Document flag fcheck-data-deps as deprecated.
|
||||
* doc/invoke.texi: Remove documentation for fcheck-data-deps and
|
||||
its associated params: omega-max-vars, omega-max-geqs,
|
||||
omega-max-eqs, omega-max-wild-cards, omega-hash-table-size,
|
||||
omega-max-keys, omega-eliminate-redundant-constraints.
|
||||
* doc/loop.texi: Remove all the section on Omega.
|
||||
* graphite-blocking.c: Include missing params.h: it used to be
|
||||
included through tree-data-ref.h and omega.h.
|
||||
* graphite-isl-ast-to-gimple.c: Same.
|
||||
* graphite-optimize-isl.c: Same.
|
||||
* graphite-sese-to-poly.c: Same.
|
||||
* graphite.c: Same.
|
||||
* omega.c: Remove.
|
||||
* omega.h: Remove.
|
||||
* params.def: Removed PARAM_OMEGA_MAX_VARS, PARAM_OMEGA_MAX_GEQS,
|
||||
PARAM_OMEGA_MAX_EQS, PARAM_OMEGA_MAX_WILD_CARDS,
|
||||
PARAM_OMEGA_HASH_TABLE_SIZE, PARAM_OMEGA_MAX_KEYS, and
|
||||
PARAM_OMEGA_ELIMINATE_REDUNDANT_CONSTRAINTS.
|
||||
* passes.def: Remove pass_check_data_deps.
|
||||
* tree-data-ref.c (dump_affine_function): Declare DEBUG_FUNCTION.
|
||||
(dump_conflict_function): Same.
|
||||
(dump_subscript): Same.
|
||||
(print_direction_vector): Same.
|
||||
(print_dir_vectors): Same.
|
||||
(print_lambda_vector): Same.
|
||||
(print_dist_vectors): Same.
|
||||
(dump_data_dependence_relation): Same.
|
||||
(dump_data_dependence_relations): Same.
|
||||
(dump_dist_dir_vectors): Same.
|
||||
(dump_ddrs): Same.
|
||||
(init_omega_eq_with_af): Removed.
|
||||
(omega_extract_distance_vectors): Removed.
|
||||
(omega_setup_subscript): Removed.
|
||||
(init_omega_for_ddr_1): Removed.
|
||||
(init_omega_for_ddr): Removed.
|
||||
(ddr_consistent_p): Removed.
|
||||
(compute_affine_dependence): Do not use omega to check data
|
||||
dependences.
|
||||
(compute_data_dependences_for_bb): Removed.
|
||||
(analyze_all_data_dependences): Removed.
|
||||
(tree_check_data_deps): Removed.
|
||||
* tree-data-ref.h: Do not include omega.h.
|
||||
(compute_data_dependences_for_bb): Removed.
|
||||
(tree_check_data_deps): Removed.
|
||||
* tree-ssa-loop.c (pass_check_data_deps): Removed.
|
||||
(make_pass_check_data_deps): Removed.
|
||||
* tree-ssa-phiopt.c: Include params.h.
|
||||
* tree-vect-data-refs.c: Same.
|
||||
* tree-vect-slp.c: Same.
|
||||
|
||||
2015-07-18 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
* config/i386/i386.md (pushsf splitter): Pass curr_insn to
|
||||
|
|
|
@ -1347,7 +1347,6 @@ OBJS = \
|
|||
mcf.o \
|
||||
mode-switching.o \
|
||||
modulo-sched.o \
|
||||
omega.o \
|
||||
omp-low.o \
|
||||
optabs.o \
|
||||
options-save.o \
|
||||
|
|
|
@ -987,7 +987,7 @@ Save registers around function calls
|
|||
|
||||
fcheck-data-deps
|
||||
Common Report Var(flag_check_data_deps)
|
||||
Compare the results of several data dependence analyzers.
|
||||
This switch is deprecated; do not use.
|
||||
|
||||
fcheck-new
|
||||
Common Var(flag_check_new)
|
||||
|
|
|
@ -385,7 +385,7 @@ Objective-C and Objective-C++ Dialects}.
|
|||
-fauto-inc-dec -fbranch-probabilities @gol
|
||||
-fbranch-target-load-optimize -fbranch-target-load-optimize2 @gol
|
||||
-fbtr-bb-exclusive -fcaller-saves @gol
|
||||
-fcheck-data-deps -fcombine-stack-adjustments -fconserve-stack @gol
|
||||
-fcombine-stack-adjustments -fconserve-stack @gol
|
||||
-fcompare-elim -fcprop-registers -fcrossjumping @gol
|
||||
-fcse-follow-jumps -fcse-skip-blocks -fcx-fortran-rules @gol
|
||||
-fcx-limited-range @gol
|
||||
|
@ -8812,11 +8812,6 @@ be parallelized. Parallelize all the loops that can be analyzed to
|
|||
not contain loop carried dependences without checking that it is
|
||||
profitable to parallelize the loops.
|
||||
|
||||
@item -fcheck-data-deps
|
||||
@opindex fcheck-data-deps
|
||||
Compare the results of several data dependence analyzers. This option
|
||||
is used for debugging the data dependence analyzers.
|
||||
|
||||
@item -ftree-loop-if-convert
|
||||
@opindex ftree-loop-if-convert
|
||||
Attempt to transform conditional jumps in the innermost loops to
|
||||
|
@ -10475,34 +10470,6 @@ Large expressions slow the analyzer.
|
|||
Bound on the complexity of the expressions in the scalar evolutions analyzer.
|
||||
Complex expressions slow the analyzer.
|
||||
|
||||
@item omega-max-vars
|
||||
The maximum number of variables in an Omega constraint system.
|
||||
The default value is 128.
|
||||
|
||||
@item omega-max-geqs
|
||||
The maximum number of inequalities in an Omega constraint system.
|
||||
The default value is 256.
|
||||
|
||||
@item omega-max-eqs
|
||||
The maximum number of equalities in an Omega constraint system.
|
||||
The default value is 128.
|
||||
|
||||
@item omega-max-wild-cards
|
||||
The maximum number of wildcard variables that the Omega solver is
|
||||
able to insert. The default value is 18.
|
||||
|
||||
@item omega-hash-table-size
|
||||
The size of the hash table in the Omega solver. The default value is
|
||||
550.
|
||||
|
||||
@item omega-max-keys
|
||||
The maximal number of keys used by the Omega solver. The default
|
||||
value is 500.
|
||||
|
||||
@item omega-eliminate-redundant-constraints
|
||||
When set to 1, use expensive methods to eliminate all redundant
|
||||
constraints. The default value is 0.
|
||||
|
||||
@item vect-max-version-for-alignment-checks
|
||||
The maximum number of run-time checks that can be performed when
|
||||
doing loop versioning for alignment in the vectorizer.
|
||||
|
|
|
@ -25,7 +25,6 @@ variable analysis and number of iterations analysis).
|
|||
* loop-iv:: Induction variables on RTL.
|
||||
* Number of iterations:: Number of iterations analysis.
|
||||
* Dependency analysis:: Data dependency analysis.
|
||||
* Omega:: A solver for linear programming problems.
|
||||
@end menu
|
||||
|
||||
@node Loop representation
|
||||
|
@ -602,33 +601,3 @@ maximum verbosity the details of a data dependence relations array,
|
|||
direction vectors for a data dependence relations array, and
|
||||
@code{dump_data_references} prints the details of the data references
|
||||
contained in a data reference array.
|
||||
|
||||
|
||||
@node Omega
|
||||
@section Omega a solver for linear programming problems
|
||||
@cindex Omega a solver for linear programming problems
|
||||
|
||||
The data dependence analysis contains several solvers triggered
|
||||
sequentially from the less complex ones to the more sophisticated.
|
||||
For ensuring the consistency of the results of these solvers, a data
|
||||
dependence check pass has been implemented based on two different
|
||||
solvers. The second method that has been integrated to GCC is based
|
||||
on the Omega dependence solver, written in the 1990's by William Pugh
|
||||
and David Wonnacott. Data dependence tests can be formulated using a
|
||||
subset of the Presburger arithmetics that can be translated to linear
|
||||
constraint systems. These linear constraint systems can then be
|
||||
solved using the Omega solver.
|
||||
|
||||
The Omega solver is using Fourier-Motzkin's algorithm for variable
|
||||
elimination: a linear constraint system containing @code{n} variables
|
||||
is reduced to a linear constraint system with @code{n-1} variables.
|
||||
The Omega solver can also be used for solving other problems that can
|
||||
be expressed under the form of a system of linear equalities and
|
||||
inequalities. The Omega solver is known to have an exponential worst
|
||||
case, also known under the name of ``omega nightmare'' in the
|
||||
literature, but in practice, the omega test is known to be efficient
|
||||
for the common data dependence tests.
|
||||
|
||||
The interface used by the Omega solver for describing the linear
|
||||
programming problems is described in @file{omega.h}, and the solver is
|
||||
@code{omega_solve_problem}.
|
||||
|
|
|
@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "cfghooks.h"
|
||||
#include "tree.h"
|
||||
#include "gimple.h"
|
||||
#include "params.h"
|
||||
#include "fold-const.h"
|
||||
#include "gimple-iterator.h"
|
||||
#include "tree-ssa-loop.h"
|
||||
|
|
|
@ -44,6 +44,7 @@ extern "C" {
|
|||
#include "cfghooks.h"
|
||||
#include "tree.h"
|
||||
#include "gimple.h"
|
||||
#include "params.h"
|
||||
#include "fold-const.h"
|
||||
#include "gimple-iterator.h"
|
||||
#include "tree-ssa-loop.h"
|
||||
|
|
|
@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "cfgloop.h"
|
||||
#include "tree-data-ref.h"
|
||||
#include "graphite-poly.h"
|
||||
#include "params.h"
|
||||
|
||||
static isl_union_set *
|
||||
scop_get_domains (scop_p scop ATTRIBUTE_UNUSED)
|
||||
|
|
|
@ -47,6 +47,7 @@ extern "C" {
|
|||
#include "tree.h"
|
||||
#include "gimple.h"
|
||||
#include "ssa.h"
|
||||
#include "params.h"
|
||||
#include "fold-const.h"
|
||||
#include "gimple-iterator.h"
|
||||
#include "gimplify.h"
|
||||
|
|
|
@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "diagnostic-core.h"
|
||||
#include "cfgloop.h"
|
||||
#include "tree-pass.h"
|
||||
#include "params.h"
|
||||
|
||||
#ifdef HAVE_isl
|
||||
#include "cfghooks.h"
|
||||
|
|
5524
gcc/omega.c
5524
gcc/omega.c
File diff suppressed because it is too large
Load Diff
341
gcc/omega.h
341
gcc/omega.h
|
@ -1,341 +0,0 @@
|
|||
/* Source code for an implementation of the Omega test, an integer
|
||||
programming algorithm for dependence analysis, by William Pugh,
|
||||
appeared in Supercomputing '91 and CACM Aug 92.
|
||||
|
||||
This code has no license restrictions, and is considered public
|
||||
domain.
|
||||
|
||||
Changes copyright (C) 2005-2015 Free Software Foundation, Inc.
|
||||
Contributed by Sebastian Pop <sebastian.pop@inria.fr>
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
|
||||
#ifndef GCC_OMEGA_H
|
||||
#define GCC_OMEGA_H
|
||||
|
||||
#include "params.h"
|
||||
|
||||
#define OMEGA_MAX_VARS PARAM_VALUE (PARAM_OMEGA_MAX_VARS)
|
||||
#define OMEGA_MAX_GEQS PARAM_VALUE (PARAM_OMEGA_MAX_GEQS)
|
||||
#define OMEGA_MAX_EQS PARAM_VALUE (PARAM_OMEGA_MAX_EQS)
|
||||
|
||||
#define pos_infinity (0x7ffffff)
|
||||
#define neg_infinity (-0x7ffffff)
|
||||
|
||||
/* Results of the Omega solver. */
|
||||
enum omega_result {
|
||||
omega_false = 0,
|
||||
omega_true = 1,
|
||||
|
||||
/* Value returned when the solver is unable to determine an
|
||||
answer. */
|
||||
omega_unknown = 2,
|
||||
|
||||
/* Value used for asking the solver to simplify the system. */
|
||||
omega_simplify = 3
|
||||
};
|
||||
|
||||
/* Values used for labeling equations. Private (not used outside the
|
||||
solver). */
|
||||
enum omega_eqn_color {
|
||||
omega_black = 0,
|
||||
omega_red = 1
|
||||
};
|
||||
|
||||
/* Structure for equations. */
|
||||
typedef struct eqn_d
|
||||
{
|
||||
int key;
|
||||
int touched;
|
||||
enum omega_eqn_color color;
|
||||
|
||||
/* Array of coefficients for the equation. The layout of the data
|
||||
is as follows: coef[0] is the constant, coef[i] for 1 <= i <=
|
||||
OMEGA_MAX_VARS, are the coefficients for each dimension. Examples:
|
||||
the equation 0 = 9 + x + 0y + 5z is encoded as [9 1 0 5], the
|
||||
inequality 0 <= -8 + x + 2y + 3z is encoded as [-8 1 2 3]. */
|
||||
int *coef;
|
||||
} *eqn;
|
||||
|
||||
typedef struct omega_pb_d
|
||||
{
|
||||
/* The number of variables in the system of equations. */
|
||||
int num_vars;
|
||||
|
||||
/* Safe variables are not eliminated during the Fourier-Motzkin
|
||||
simplification of the system. Safe variables are all those
|
||||
variables that are placed at the beginning of the array of
|
||||
variables: PB->var[1, ..., SAFE_VARS]. PB->var[0] is not used,
|
||||
as PB->eqs[x]->coef[0] represents the constant of the equation. */
|
||||
int safe_vars;
|
||||
|
||||
/* Number of elements in eqs[]. */
|
||||
int num_eqs;
|
||||
/* Number of elements in geqs[]. */
|
||||
int num_geqs;
|
||||
/* Number of elements in subs[]. */
|
||||
int num_subs;
|
||||
|
||||
int hash_version;
|
||||
bool variables_initialized;
|
||||
bool variables_freed;
|
||||
|
||||
/* Index or name of variables. Negative integers are reserved for
|
||||
wildcard variables. Maps the index of variables in the original
|
||||
problem to the new index of the variable. The index for a
|
||||
variable in the coef array of an equation can change as some
|
||||
variables are eliminated. */
|
||||
int *var;
|
||||
|
||||
int *forwarding_address;
|
||||
|
||||
/* Inequalities in the system of constraints. */
|
||||
eqn geqs;
|
||||
|
||||
/* Equations in the system of constraints. */
|
||||
eqn eqs;
|
||||
|
||||
/* A map of substituted variables. */
|
||||
eqn subs;
|
||||
} *omega_pb;
|
||||
|
||||
extern void omega_initialize (void);
|
||||
extern omega_pb omega_alloc_problem (int, int);
|
||||
extern enum omega_result omega_solve_problem (omega_pb, enum omega_result);
|
||||
extern enum omega_result omega_simplify_problem (omega_pb);
|
||||
extern enum omega_result omega_simplify_approximate (omega_pb);
|
||||
extern enum omega_result omega_constrain_variable_sign (omega_pb,
|
||||
enum omega_eqn_color,
|
||||
int, int);
|
||||
extern void debug (omega_pb_d &ref);
|
||||
extern void debug (omega_pb_d *ptr);
|
||||
extern void debug_omega_problem (omega_pb);
|
||||
extern void omega_print_problem (FILE *, omega_pb);
|
||||
extern void omega_print_red_equations (FILE *, omega_pb);
|
||||
extern int omega_count_red_equations (omega_pb);
|
||||
extern void omega_pretty_print_problem (FILE *, omega_pb);
|
||||
extern void omega_unprotect_variable (omega_pb, int var);
|
||||
extern void omega_negate_geq (omega_pb, int);
|
||||
extern void omega_convert_eq_to_geqs (omega_pb, int eq);
|
||||
extern void omega_print_eqn (FILE *, omega_pb, eqn, bool, int);
|
||||
extern bool omega_problem_has_red_equations (omega_pb);
|
||||
extern enum omega_result omega_eliminate_redundant (omega_pb, bool);
|
||||
extern void omega_eliminate_red (omega_pb, bool);
|
||||
extern void omega_constrain_variable_value (omega_pb, enum omega_eqn_color,
|
||||
int, int);
|
||||
extern bool omega_query_variable (omega_pb, int, int *, int *);
|
||||
extern int omega_query_variable_signs (omega_pb, int, int, int, int,
|
||||
int, int, bool *, int *);
|
||||
extern bool omega_query_variable_bounds (omega_pb, int, int *, int *);
|
||||
extern void (*omega_when_reduced) (omega_pb);
|
||||
extern void omega_no_procedure (omega_pb);
|
||||
|
||||
/* Return true when variable I in problem PB is a wildcard. */
|
||||
|
||||
static inline bool
|
||||
omega_wildcard_p (omega_pb pb, int i)
|
||||
{
|
||||
return (pb->var[i] < 0);
|
||||
}
|
||||
|
||||
/* Return true when variable I in problem PB is a safe variable. */
|
||||
|
||||
static inline bool
|
||||
omega_safe_var_p (omega_pb pb, int i)
|
||||
{
|
||||
/* The constant of an equation is not a variable. */
|
||||
gcc_assert (0 < i);
|
||||
return (i <= pb->safe_vars);
|
||||
}
|
||||
|
||||
/* Print to FILE equality E from PB. */
|
||||
|
||||
static inline void
|
||||
omega_print_eq (FILE *file, omega_pb pb, eqn e)
|
||||
{
|
||||
omega_print_eqn (file, pb, e, false, 0);
|
||||
}
|
||||
|
||||
/* Print to FILE inequality E from PB. */
|
||||
|
||||
static inline void
|
||||
omega_print_geq (FILE *file, omega_pb pb, eqn e)
|
||||
{
|
||||
omega_print_eqn (file, pb, e, true, 0);
|
||||
}
|
||||
|
||||
/* Print to FILE inequality E from PB. */
|
||||
|
||||
static inline void
|
||||
omega_print_geq_extra (FILE *file, omega_pb pb, eqn e)
|
||||
{
|
||||
omega_print_eqn (file, pb, e, true, 1);
|
||||
}
|
||||
|
||||
/* E1 = E2, make a copy of E2 into E1. Equations contain S variables. */
|
||||
|
||||
static inline void
|
||||
omega_copy_eqn (eqn e1, eqn e2, int s)
|
||||
{
|
||||
e1->key = e2->key;
|
||||
e1->touched = e2->touched;
|
||||
e1->color = e2->color;
|
||||
|
||||
memcpy (e1->coef, e2->coef, (s + 1) * sizeof (int));
|
||||
}
|
||||
|
||||
/* Initialize E = 0. Equation E contains S variables. */
|
||||
|
||||
static inline void
|
||||
omega_init_eqn_zero (eqn e, int s)
|
||||
{
|
||||
e->key = 0;
|
||||
e->touched = 0;
|
||||
e->color = omega_black;
|
||||
|
||||
memset (e->coef, 0, (s + 1) * sizeof (int));
|
||||
}
|
||||
|
||||
/* Allocate N equations with S variables. */
|
||||
|
||||
static inline eqn
|
||||
omega_alloc_eqns (int s, int n)
|
||||
{
|
||||
int i;
|
||||
eqn res = (eqn) (xcalloc (n, sizeof (struct eqn_d)));
|
||||
|
||||
for (i = n - 1; i >= 0; i--)
|
||||
{
|
||||
res[i].coef = (int *) (xcalloc (OMEGA_MAX_VARS + 1, sizeof (int)));
|
||||
omega_init_eqn_zero (&res[i], s);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Free N equations from array EQ. */
|
||||
|
||||
static inline void
|
||||
omega_free_eqns (eqn eq, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = n - 1; i >= 0; i--)
|
||||
free (eq[i].coef);
|
||||
|
||||
free (eq);
|
||||
}
|
||||
|
||||
/* Returns true when E is an inequality with a single variable. */
|
||||
|
||||
static inline bool
|
||||
single_var_geq (eqn e, int nv ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return (e->key != 0
|
||||
&& -OMEGA_MAX_VARS <= e->key && e->key <= OMEGA_MAX_VARS);
|
||||
}
|
||||
|
||||
/* Allocate a new equality with all coefficients 0, and tagged with
|
||||
COLOR. Return the index of this equality in problem PB. */
|
||||
|
||||
static inline int
|
||||
omega_add_zero_eq (omega_pb pb, enum omega_eqn_color color)
|
||||
{
|
||||
int idx = pb->num_eqs++;
|
||||
|
||||
gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
|
||||
omega_init_eqn_zero (&pb->eqs[idx], pb->num_vars);
|
||||
pb->eqs[idx].color = color;
|
||||
return idx;
|
||||
}
|
||||
|
||||
/* Allocate a new inequality with all coefficients 0, and tagged with
|
||||
COLOR. Return the index of this inequality in problem PB. */
|
||||
|
||||
static inline int
|
||||
omega_add_zero_geq (omega_pb pb, enum omega_eqn_color color)
|
||||
{
|
||||
int idx = pb->num_geqs;
|
||||
|
||||
pb->num_geqs++;
|
||||
gcc_assert (pb->num_geqs <= OMEGA_MAX_GEQS);
|
||||
omega_init_eqn_zero (&pb->geqs[idx], pb->num_vars);
|
||||
pb->geqs[idx].touched = 1;
|
||||
pb->geqs[idx].color = color;
|
||||
return idx;
|
||||
}
|
||||
|
||||
/* Initialize variables for problem PB. */
|
||||
|
||||
static inline void
|
||||
omega_initialize_variables (omega_pb pb)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = pb->num_vars; i >= 0; i--)
|
||||
pb->forwarding_address[i] = pb->var[i] = i;
|
||||
|
||||
pb->variables_initialized = true;
|
||||
}
|
||||
|
||||
/* Free problem PB. */
|
||||
|
||||
static inline void
|
||||
omega_free_problem (omega_pb pb)
|
||||
{
|
||||
free (pb->var);
|
||||
free (pb->forwarding_address);
|
||||
omega_free_eqns (pb->geqs, OMEGA_MAX_GEQS);
|
||||
omega_free_eqns (pb->eqs, OMEGA_MAX_EQS);
|
||||
omega_free_eqns (pb->subs, OMEGA_MAX_VARS + 1);
|
||||
free (pb);
|
||||
}
|
||||
|
||||
/* Copy omega problems: P1 = P2. */
|
||||
|
||||
static inline void
|
||||
omega_copy_problem (omega_pb p1, omega_pb p2)
|
||||
{
|
||||
int e, i;
|
||||
|
||||
p1->num_vars = p2->num_vars;
|
||||
p1->hash_version = p2->hash_version;
|
||||
p1->variables_initialized = p2->variables_initialized;
|
||||
p1->variables_freed = p2->variables_freed;
|
||||
p1->safe_vars = p2->safe_vars;
|
||||
p1->num_eqs = p2->num_eqs;
|
||||
p1->num_subs = p2->num_subs;
|
||||
p1->num_geqs = p2->num_geqs;
|
||||
|
||||
for (e = p2->num_eqs - 1; e >= 0; e--)
|
||||
omega_copy_eqn (&(p1->eqs[e]), &(p2->eqs[e]), p2->num_vars);
|
||||
|
||||
for (e = p2->num_geqs - 1; e >= 0; e--)
|
||||
omega_copy_eqn (&(p1->geqs[e]), &(p2->geqs[e]), p2->num_vars);
|
||||
|
||||
for (e = p2->num_subs - 1; e >= 0; e--)
|
||||
omega_copy_eqn (&(p1->subs[e]), &(p2->subs[e]), p2->num_vars);
|
||||
|
||||
for (i = p2->num_vars; i >= 0; i--)
|
||||
p1->var[i] = p2->var[i];
|
||||
|
||||
for (i = OMEGA_MAX_VARS; i >= 0; i--)
|
||||
p1->forwarding_address[i] = p2->forwarding_address[i];
|
||||
}
|
||||
|
||||
#endif /* GCC_OMEGA_H */
|
|
@ -525,41 +525,6 @@ DEFPARAM(PARAM_SCEV_MAX_EXPR_COMPLEXITY,
|
|||
"Bound on the complexity of the expressions in the scalar evolutions analyzer",
|
||||
10, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_OMEGA_MAX_VARS,
|
||||
"omega-max-vars",
|
||||
"Bound on the number of variables in Omega constraint systems",
|
||||
128, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_OMEGA_MAX_GEQS,
|
||||
"omega-max-geqs",
|
||||
"Bound on the number of inequalities in Omega constraint systems",
|
||||
256, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_OMEGA_MAX_EQS,
|
||||
"omega-max-eqs",
|
||||
"Bound on the number of equalities in Omega constraint systems",
|
||||
128, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_OMEGA_MAX_WILD_CARDS,
|
||||
"omega-max-wild-cards",
|
||||
"Bound on the number of wild cards in Omega constraint systems",
|
||||
18, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_OMEGA_HASH_TABLE_SIZE,
|
||||
"omega-hash-table-size",
|
||||
"Bound on the size of the hash table in Omega constraint systems",
|
||||
550, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_OMEGA_MAX_KEYS,
|
||||
"omega-max-keys",
|
||||
"Bound on the number of keys in Omega constraint systems",
|
||||
500, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_OMEGA_ELIMINATE_REDUNDANT_CONSTRAINTS,
|
||||
"omega-eliminate-redundant-constraints",
|
||||
"When set to 1, use expensive methods to eliminate all redundant constraints",
|
||||
0, 0, 1)
|
||||
|
||||
DEFPARAM(PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS,
|
||||
"vect-max-version-for-alignment-checks",
|
||||
"Bound on number of runtime checks inserted by the vectorizer's loop versioning for alignment check",
|
||||
|
|
|
@ -233,7 +233,6 @@ along with GCC; see the file COPYING3. If not see
|
|||
NEXT_PASS (pass_tree_unswitch);
|
||||
NEXT_PASS (pass_scev_cprop);
|
||||
NEXT_PASS (pass_record_bounds);
|
||||
NEXT_PASS (pass_check_data_deps);
|
||||
NEXT_PASS (pass_loop_distribution);
|
||||
NEXT_PASS (pass_copy_prop);
|
||||
NEXT_PASS (pass_graphite);
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2015-07-18 Sebastian Pop <s.pop@samsung.com>
|
||||
|
||||
PR middle-end/46851
|
||||
PR middle-end/60340
|
||||
* gcc.dg/tree-ssa/pr42327.c: Removed.
|
||||
* g++.dg/other/pr35011.C: Removed.
|
||||
|
||||
2015-07-17 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR target/66906
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-O3 -fcheck-data-deps" }
|
||||
|
||||
double foo(const double* p0, const double* p1, const double* q0)
|
||||
{
|
||||
double d;
|
||||
for (; p0 != p1; ++p0, ++q0)
|
||||
d += *p0 * *q0;
|
||||
return d;
|
||||
}
|
||||
|
||||
struct A
|
||||
{
|
||||
double x[3];
|
||||
const double* begin() const { return x; }
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
A a0, a1;
|
||||
double d;
|
||||
B(const A&);
|
||||
};
|
||||
|
||||
B::B(const A& a) : a0(a), a1(a), d(foo(a0.begin(), a0.begin()+3, a1.begin()))
|
||||
{}
|
|
@ -1,7 +0,0 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O1 -fcheck-data-deps" } */
|
||||
|
||||
void foo(char *str)
|
||||
{
|
||||
while (*str != 0) *str++ = 0;
|
||||
}
|
|
@ -249,7 +249,7 @@ debug (data_reference *ptr)
|
|||
|
||||
/* Dumps the affine function described by FN to the file OUTF. */
|
||||
|
||||
static void
|
||||
DEBUG_FUNCTION void
|
||||
dump_affine_function (FILE *outf, affine_fn fn)
|
||||
{
|
||||
unsigned i;
|
||||
|
@ -266,7 +266,7 @@ dump_affine_function (FILE *outf, affine_fn fn)
|
|||
|
||||
/* Dumps the conflict function CF to the file OUTF. */
|
||||
|
||||
static void
|
||||
DEBUG_FUNCTION void
|
||||
dump_conflict_function (FILE *outf, conflict_function *cf)
|
||||
{
|
||||
unsigned i;
|
||||
|
@ -290,7 +290,7 @@ dump_conflict_function (FILE *outf, conflict_function *cf)
|
|||
|
||||
/* Dump function for a SUBSCRIPT structure. */
|
||||
|
||||
static void
|
||||
DEBUG_FUNCTION void
|
||||
dump_subscript (FILE *outf, struct subscript *subscript)
|
||||
{
|
||||
conflict_function *cf = SUB_CONFLICTS_IN_A (subscript);
|
||||
|
@ -322,7 +322,7 @@ dump_subscript (FILE *outf, struct subscript *subscript)
|
|||
|
||||
/* Print the classic direction vector DIRV to OUTF. */
|
||||
|
||||
static void
|
||||
DEBUG_FUNCTION void
|
||||
print_direction_vector (FILE *outf,
|
||||
lambda_vector dirv,
|
||||
int length)
|
||||
|
@ -367,7 +367,7 @@ print_direction_vector (FILE *outf,
|
|||
|
||||
/* Print a vector of direction vectors. */
|
||||
|
||||
static void
|
||||
DEBUG_FUNCTION void
|
||||
print_dir_vectors (FILE *outf, vec<lambda_vector> dir_vects,
|
||||
int length)
|
||||
{
|
||||
|
@ -380,7 +380,7 @@ print_dir_vectors (FILE *outf, vec<lambda_vector> dir_vects,
|
|||
|
||||
/* Print out a vector VEC of length N to OUTFILE. */
|
||||
|
||||
static inline void
|
||||
DEBUG_FUNCTION void
|
||||
print_lambda_vector (FILE * outfile, lambda_vector vector, int n)
|
||||
{
|
||||
int i;
|
||||
|
@ -392,7 +392,7 @@ print_lambda_vector (FILE * outfile, lambda_vector vector, int n)
|
|||
|
||||
/* Print a vector of distance vectors. */
|
||||
|
||||
static void
|
||||
DEBUG_FUNCTION void
|
||||
print_dist_vectors (FILE *outf, vec<lambda_vector> dist_vects,
|
||||
int length)
|
||||
{
|
||||
|
@ -405,7 +405,7 @@ print_dist_vectors (FILE *outf, vec<lambda_vector> dist_vects,
|
|||
|
||||
/* Dump function for a DATA_DEPENDENCE_RELATION structure. */
|
||||
|
||||
static void
|
||||
DEBUG_FUNCTION void
|
||||
dump_data_dependence_relation (FILE *outf,
|
||||
struct data_dependence_relation *ddr)
|
||||
{
|
||||
|
@ -488,7 +488,7 @@ debug_data_dependence_relation (struct data_dependence_relation *ddr)
|
|||
|
||||
/* Dump into FILE all the dependence relations from DDRS. */
|
||||
|
||||
void
|
||||
DEBUG_FUNCTION void
|
||||
dump_data_dependence_relations (FILE *file,
|
||||
vec<ddr_p> ddrs)
|
||||
{
|
||||
|
@ -528,7 +528,7 @@ debug_data_dependence_relations (vec<ddr_p> ddrs)
|
|||
dependence vectors, or in other words the number of loops in the
|
||||
considered nest. */
|
||||
|
||||
static void
|
||||
DEBUG_FUNCTION void
|
||||
dump_dist_dir_vectors (FILE *file, vec<ddr_p> ddrs)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
@ -558,7 +558,7 @@ dump_dist_dir_vectors (FILE *file, vec<ddr_p> ddrs)
|
|||
|
||||
/* Dumps the data dependence relations DDRS in FILE. */
|
||||
|
||||
static void
|
||||
DEBUG_FUNCTION void
|
||||
dump_ddrs (FILE *file, vec<ddr_p> ddrs)
|
||||
{
|
||||
unsigned int i;
|
||||
|
@ -3682,531 +3682,6 @@ access_functions_are_affine_or_constant_p (const struct data_reference *a,
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Initializes an equation for an OMEGA problem using the information
|
||||
contained in the ACCESS_FUN. Returns true when the operation
|
||||
succeeded.
|
||||
|
||||
PB is the omega constraint system.
|
||||
EQ is the number of the equation to be initialized.
|
||||
OFFSET is used for shifting the variables names in the constraints:
|
||||
a constrain is composed of 2 * the number of variables surrounding
|
||||
dependence accesses. OFFSET is set either to 0 for the first n variables,
|
||||
then it is set to n.
|
||||
ACCESS_FUN is expected to be an affine chrec. */
|
||||
|
||||
static bool
|
||||
init_omega_eq_with_af (omega_pb pb, unsigned eq,
|
||||
unsigned int offset, tree access_fun,
|
||||
struct data_dependence_relation *ddr)
|
||||
{
|
||||
switch (TREE_CODE (access_fun))
|
||||
{
|
||||
case POLYNOMIAL_CHREC:
|
||||
{
|
||||
tree left = CHREC_LEFT (access_fun);
|
||||
tree right = CHREC_RIGHT (access_fun);
|
||||
int var = CHREC_VARIABLE (access_fun);
|
||||
unsigned var_idx;
|
||||
|
||||
if (TREE_CODE (right) != INTEGER_CST)
|
||||
return false;
|
||||
|
||||
var_idx = index_in_loop_nest (var, DDR_LOOP_NEST (ddr));
|
||||
pb->eqs[eq].coef[offset + var_idx + 1] = int_cst_value (right);
|
||||
|
||||
/* Compute the innermost loop index. */
|
||||
DDR_INNER_LOOP (ddr) = MAX (DDR_INNER_LOOP (ddr), var_idx);
|
||||
|
||||
if (offset == 0)
|
||||
pb->eqs[eq].coef[var_idx + DDR_NB_LOOPS (ddr) + 1]
|
||||
+= int_cst_value (right);
|
||||
|
||||
switch (TREE_CODE (left))
|
||||
{
|
||||
case POLYNOMIAL_CHREC:
|
||||
return init_omega_eq_with_af (pb, eq, offset, left, ddr);
|
||||
|
||||
case INTEGER_CST:
|
||||
pb->eqs[eq].coef[0] += int_cst_value (left);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
case INTEGER_CST:
|
||||
pb->eqs[eq].coef[0] += int_cst_value (access_fun);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* As explained in the comments preceding init_omega_for_ddr, we have
|
||||
to set up a system for each loop level, setting outer loops
|
||||
variation to zero, and current loop variation to positive or zero.
|
||||
Save each lexico positive distance vector. */
|
||||
|
||||
static void
|
||||
omega_extract_distance_vectors (omega_pb pb,
|
||||
struct data_dependence_relation *ddr)
|
||||
{
|
||||
int eq, geq;
|
||||
unsigned i, j;
|
||||
struct loop *loopi, *loopj;
|
||||
enum omega_result res;
|
||||
|
||||
/* Set a new problem for each loop in the nest. The basis is the
|
||||
problem that we have initialized until now. On top of this we
|
||||
add new constraints. */
|
||||
for (i = 0; i <= DDR_INNER_LOOP (ddr)
|
||||
&& DDR_LOOP_NEST (ddr).iterate (i, &loopi); i++)
|
||||
{
|
||||
int dist = 0;
|
||||
omega_pb copy = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr),
|
||||
DDR_NB_LOOPS (ddr));
|
||||
|
||||
omega_copy_problem (copy, pb);
|
||||
|
||||
/* For all the outer loops "loop_j", add "dj = 0". */
|
||||
for (j = 0; j < i && DDR_LOOP_NEST (ddr).iterate (j, &loopj); j++)
|
||||
{
|
||||
eq = omega_add_zero_eq (copy, omega_black);
|
||||
copy->eqs[eq].coef[j + 1] = 1;
|
||||
}
|
||||
|
||||
/* For "loop_i", add "0 <= di". */
|
||||
geq = omega_add_zero_geq (copy, omega_black);
|
||||
copy->geqs[geq].coef[i + 1] = 1;
|
||||
|
||||
/* Reduce the constraint system, and test that the current
|
||||
problem is feasible. */
|
||||
res = omega_simplify_problem (copy);
|
||||
if (res == omega_false
|
||||
|| res == omega_unknown
|
||||
|| copy->num_geqs > (int) DDR_NB_LOOPS (ddr))
|
||||
goto next_problem;
|
||||
|
||||
for (eq = 0; eq < copy->num_subs; eq++)
|
||||
if (copy->subs[eq].key == (int) i + 1)
|
||||
{
|
||||
dist = copy->subs[eq].coef[0];
|
||||
goto found_dist;
|
||||
}
|
||||
|
||||
if (dist == 0)
|
||||
{
|
||||
/* Reinitialize problem... */
|
||||
omega_copy_problem (copy, pb);
|
||||
for (j = 0; j < i && DDR_LOOP_NEST (ddr).iterate (j, &loopj); j++)
|
||||
{
|
||||
eq = omega_add_zero_eq (copy, omega_black);
|
||||
copy->eqs[eq].coef[j + 1] = 1;
|
||||
}
|
||||
|
||||
/* ..., but this time "di = 1". */
|
||||
eq = omega_add_zero_eq (copy, omega_black);
|
||||
copy->eqs[eq].coef[i + 1] = 1;
|
||||
copy->eqs[eq].coef[0] = -1;
|
||||
|
||||
res = omega_simplify_problem (copy);
|
||||
if (res == omega_false
|
||||
|| res == omega_unknown
|
||||
|| copy->num_geqs > (int) DDR_NB_LOOPS (ddr))
|
||||
goto next_problem;
|
||||
|
||||
for (eq = 0; eq < copy->num_subs; eq++)
|
||||
if (copy->subs[eq].key == (int) i + 1)
|
||||
{
|
||||
dist = copy->subs[eq].coef[0];
|
||||
goto found_dist;
|
||||
}
|
||||
}
|
||||
|
||||
found_dist:;
|
||||
/* Save the lexicographically positive distance vector. */
|
||||
if (dist >= 0)
|
||||
{
|
||||
lambda_vector dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
|
||||
lambda_vector dir_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
|
||||
|
||||
dist_v[i] = dist;
|
||||
|
||||
for (eq = 0; eq < copy->num_subs; eq++)
|
||||
if (copy->subs[eq].key > 0)
|
||||
{
|
||||
dist = copy->subs[eq].coef[0];
|
||||
dist_v[copy->subs[eq].key - 1] = dist;
|
||||
}
|
||||
|
||||
for (j = 0; j < DDR_NB_LOOPS (ddr); j++)
|
||||
dir_v[j] = dir_from_dist (dist_v[j]);
|
||||
|
||||
save_dist_v (ddr, dist_v);
|
||||
save_dir_v (ddr, dir_v);
|
||||
}
|
||||
|
||||
next_problem:;
|
||||
omega_free_problem (copy);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is called for each subscript of a tuple of data references:
|
||||
insert an equality for representing the conflicts. */
|
||||
|
||||
static bool
|
||||
omega_setup_subscript (tree access_fun_a, tree access_fun_b,
|
||||
struct data_dependence_relation *ddr,
|
||||
omega_pb pb, bool *maybe_dependent)
|
||||
{
|
||||
int eq;
|
||||
tree type = signed_type_for_types (TREE_TYPE (access_fun_a),
|
||||
TREE_TYPE (access_fun_b));
|
||||
tree fun_a = chrec_convert (type, access_fun_a, NULL);
|
||||
tree fun_b = chrec_convert (type, access_fun_b, NULL);
|
||||
tree difference = chrec_fold_minus (type, fun_a, fun_b);
|
||||
tree minus_one;
|
||||
|
||||
/* When the fun_a - fun_b is not constant, the dependence is not
|
||||
captured by the classic distance vector representation. */
|
||||
if (TREE_CODE (difference) != INTEGER_CST)
|
||||
return false;
|
||||
|
||||
/* ZIV test. */
|
||||
if (ziv_subscript_p (fun_a, fun_b) && !integer_zerop (difference))
|
||||
{
|
||||
/* There is no dependence. */
|
||||
*maybe_dependent = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
minus_one = build_int_cst (type, -1);
|
||||
fun_b = chrec_fold_multiply (type, fun_b, minus_one);
|
||||
|
||||
eq = omega_add_zero_eq (pb, omega_black);
|
||||
if (!init_omega_eq_with_af (pb, eq, DDR_NB_LOOPS (ddr), fun_a, ddr)
|
||||
|| !init_omega_eq_with_af (pb, eq, 0, fun_b, ddr))
|
||||
/* There is probably a dependence, but the system of
|
||||
constraints cannot be built: answer "don't know". */
|
||||
return false;
|
||||
|
||||
/* GCD test. */
|
||||
if (DDR_NB_LOOPS (ddr) != 0 && pb->eqs[eq].coef[0]
|
||||
&& !int_divides_p (lambda_vector_gcd
|
||||
((lambda_vector) &(pb->eqs[eq].coef[1]),
|
||||
2 * DDR_NB_LOOPS (ddr)),
|
||||
pb->eqs[eq].coef[0]))
|
||||
{
|
||||
/* There is no dependence. */
|
||||
*maybe_dependent = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Helper function, same as init_omega_for_ddr but specialized for
|
||||
data references A and B. */
|
||||
|
||||
static bool
|
||||
init_omega_for_ddr_1 (struct data_reference *dra, struct data_reference *drb,
|
||||
struct data_dependence_relation *ddr,
|
||||
omega_pb pb, bool *maybe_dependent)
|
||||
{
|
||||
unsigned i;
|
||||
int ineq;
|
||||
struct loop *loopi;
|
||||
unsigned nb_loops = DDR_NB_LOOPS (ddr);
|
||||
|
||||
/* Insert an equality per subscript. */
|
||||
for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
|
||||
{
|
||||
if (!omega_setup_subscript (DR_ACCESS_FN (dra, i), DR_ACCESS_FN (drb, i),
|
||||
ddr, pb, maybe_dependent))
|
||||
return false;
|
||||
else if (*maybe_dependent == false)
|
||||
{
|
||||
/* There is no dependence. */
|
||||
DDR_ARE_DEPENDENT (ddr) = chrec_known;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert inequalities: constraints corresponding to the iteration
|
||||
domain, i.e. the loops surrounding the references "loop_x" and
|
||||
the distance variables "dx". The layout of the OMEGA
|
||||
representation is as follows:
|
||||
- coef[0] is the constant
|
||||
- coef[1..nb_loops] are the protected variables that will not be
|
||||
removed by the solver: the "dx"
|
||||
- coef[nb_loops + 1, 2*nb_loops] are the loop variables: "loop_x".
|
||||
*/
|
||||
for (i = 0; i <= DDR_INNER_LOOP (ddr)
|
||||
&& DDR_LOOP_NEST (ddr).iterate (i, &loopi); i++)
|
||||
{
|
||||
HOST_WIDE_INT nbi = max_stmt_executions_int (loopi);
|
||||
|
||||
/* 0 <= loop_x */
|
||||
ineq = omega_add_zero_geq (pb, omega_black);
|
||||
pb->geqs[ineq].coef[i + nb_loops + 1] = 1;
|
||||
|
||||
/* 0 <= loop_x + dx */
|
||||
ineq = omega_add_zero_geq (pb, omega_black);
|
||||
pb->geqs[ineq].coef[i + nb_loops + 1] = 1;
|
||||
pb->geqs[ineq].coef[i + 1] = 1;
|
||||
|
||||
if (nbi != -1)
|
||||
{
|
||||
/* loop_x <= nb_iters */
|
||||
ineq = omega_add_zero_geq (pb, omega_black);
|
||||
pb->geqs[ineq].coef[i + nb_loops + 1] = -1;
|
||||
pb->geqs[ineq].coef[0] = nbi;
|
||||
|
||||
/* loop_x + dx <= nb_iters */
|
||||
ineq = omega_add_zero_geq (pb, omega_black);
|
||||
pb->geqs[ineq].coef[i + nb_loops + 1] = -1;
|
||||
pb->geqs[ineq].coef[i + 1] = -1;
|
||||
pb->geqs[ineq].coef[0] = nbi;
|
||||
|
||||
/* A step "dx" bigger than nb_iters is not feasible, so
|
||||
add "0 <= nb_iters + dx", */
|
||||
ineq = omega_add_zero_geq (pb, omega_black);
|
||||
pb->geqs[ineq].coef[i + 1] = 1;
|
||||
pb->geqs[ineq].coef[0] = nbi;
|
||||
/* and "dx <= nb_iters". */
|
||||
ineq = omega_add_zero_geq (pb, omega_black);
|
||||
pb->geqs[ineq].coef[i + 1] = -1;
|
||||
pb->geqs[ineq].coef[0] = nbi;
|
||||
}
|
||||
}
|
||||
|
||||
omega_extract_distance_vectors (pb, ddr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Sets up the Omega dependence problem for the data dependence
|
||||
relation DDR. Returns false when the constraint system cannot be
|
||||
built, ie. when the test answers "don't know". Returns true
|
||||
otherwise, and when independence has been proved (using one of the
|
||||
trivial dependence test), set MAYBE_DEPENDENT to false, otherwise
|
||||
set MAYBE_DEPENDENT to true.
|
||||
|
||||
Example: for setting up the dependence system corresponding to the
|
||||
conflicting accesses
|
||||
|
||||
| loop_i
|
||||
| loop_j
|
||||
| A[i, i+1] = ...
|
||||
| ... A[2*j, 2*(i + j)]
|
||||
| endloop_j
|
||||
| endloop_i
|
||||
|
||||
the following constraints come from the iteration domain:
|
||||
|
||||
0 <= i <= Ni
|
||||
0 <= i + di <= Ni
|
||||
0 <= j <= Nj
|
||||
0 <= j + dj <= Nj
|
||||
|
||||
where di, dj are the distance variables. The constraints
|
||||
representing the conflicting elements are:
|
||||
|
||||
i = 2 * (j + dj)
|
||||
i + 1 = 2 * (i + di + j + dj)
|
||||
|
||||
For asking that the resulting distance vector (di, dj) be
|
||||
lexicographically positive, we insert the constraint "di >= 0". If
|
||||
"di = 0" in the solution, we fix that component to zero, and we
|
||||
look at the inner loops: we set a new problem where all the outer
|
||||
loop distances are zero, and fix this inner component to be
|
||||
positive. When one of the components is positive, we save that
|
||||
distance, and set a new problem where the distance on this loop is
|
||||
zero, searching for other distances in the inner loops. Here is
|
||||
the classic example that illustrates that we have to set for each
|
||||
inner loop a new problem:
|
||||
|
||||
| loop_1
|
||||
| loop_2
|
||||
| A[10]
|
||||
| endloop_2
|
||||
| endloop_1
|
||||
|
||||
we have to save two distances (1, 0) and (0, 1).
|
||||
|
||||
Given two array references, refA and refB, we have to set the
|
||||
dependence problem twice, refA vs. refB and refB vs. refA, and we
|
||||
cannot do a single test, as refB might occur before refA in the
|
||||
inner loops, and the contrary when considering outer loops: ex.
|
||||
|
||||
| loop_0
|
||||
| loop_1
|
||||
| loop_2
|
||||
| T[{1,+,1}_2][{1,+,1}_1] // refA
|
||||
| T[{2,+,1}_2][{0,+,1}_1] // refB
|
||||
| endloop_2
|
||||
| endloop_1
|
||||
| endloop_0
|
||||
|
||||
refB touches the elements in T before refA, and thus for the same
|
||||
loop_0 refB precedes refA: ie. the distance vector (0, 1, -1)
|
||||
but for successive loop_0 iterations, we have (1, -1, 1)
|
||||
|
||||
The Omega solver expects the distance variables ("di" in the
|
||||
previous example) to come first in the constraint system (as
|
||||
variables to be protected, or "safe" variables), the constraint
|
||||
system is built using the following layout:
|
||||
|
||||
"cst | distance vars | index vars".
|
||||
*/
|
||||
|
||||
static bool
|
||||
init_omega_for_ddr (struct data_dependence_relation *ddr,
|
||||
bool *maybe_dependent)
|
||||
{
|
||||
omega_pb pb;
|
||||
bool res = false;
|
||||
|
||||
*maybe_dependent = true;
|
||||
|
||||
if (same_access_functions (ddr))
|
||||
{
|
||||
unsigned j;
|
||||
lambda_vector dir_v;
|
||||
|
||||
/* Save the 0 vector. */
|
||||
save_dist_v (ddr, lambda_vector_new (DDR_NB_LOOPS (ddr)));
|
||||
dir_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
|
||||
for (j = 0; j < DDR_NB_LOOPS (ddr); j++)
|
||||
dir_v[j] = dir_equal;
|
||||
save_dir_v (ddr, dir_v);
|
||||
|
||||
/* Save the dependences carried by outer loops. */
|
||||
pb = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr), DDR_NB_LOOPS (ddr));
|
||||
res = init_omega_for_ddr_1 (DDR_A (ddr), DDR_B (ddr), ddr, pb,
|
||||
maybe_dependent);
|
||||
omega_free_problem (pb);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Omega expects the protected variables (those that have to be kept
|
||||
after elimination) to appear first in the constraint system.
|
||||
These variables are the distance variables. In the following
|
||||
initialization we declare NB_LOOPS safe variables, and the total
|
||||
number of variables for the constraint system is 2*NB_LOOPS. */
|
||||
pb = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr), DDR_NB_LOOPS (ddr));
|
||||
res = init_omega_for_ddr_1 (DDR_A (ddr), DDR_B (ddr), ddr, pb,
|
||||
maybe_dependent);
|
||||
omega_free_problem (pb);
|
||||
|
||||
/* Stop computation if not decidable, or no dependence. */
|
||||
if (res == false || *maybe_dependent == false)
|
||||
return res;
|
||||
|
||||
pb = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr), DDR_NB_LOOPS (ddr));
|
||||
res = init_omega_for_ddr_1 (DDR_B (ddr), DDR_A (ddr), ddr, pb,
|
||||
maybe_dependent);
|
||||
omega_free_problem (pb);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Return true when DDR contains the same information as that stored
|
||||
in DIR_VECTS and in DIST_VECTS, return false otherwise. */
|
||||
|
||||
static bool
|
||||
ddr_consistent_p (FILE *file,
|
||||
struct data_dependence_relation *ddr,
|
||||
vec<lambda_vector> dist_vects,
|
||||
vec<lambda_vector> dir_vects)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
/* If dump_file is set, output there. */
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
file = dump_file;
|
||||
|
||||
if (dist_vects.length () != DDR_NUM_DIST_VECTS (ddr))
|
||||
{
|
||||
lambda_vector b_dist_v;
|
||||
fprintf (file, "\n(Number of distance vectors differ: Banerjee has %d, Omega has %d.\n",
|
||||
dist_vects.length (),
|
||||
DDR_NUM_DIST_VECTS (ddr));
|
||||
|
||||
fprintf (file, "Banerjee dist vectors:\n");
|
||||
FOR_EACH_VEC_ELT (dist_vects, i, b_dist_v)
|
||||
print_lambda_vector (file, b_dist_v, DDR_NB_LOOPS (ddr));
|
||||
|
||||
fprintf (file, "Omega dist vectors:\n");
|
||||
for (i = 0; i < DDR_NUM_DIST_VECTS (ddr); i++)
|
||||
print_lambda_vector (file, DDR_DIST_VECT (ddr, i), DDR_NB_LOOPS (ddr));
|
||||
|
||||
fprintf (file, "data dependence relation:\n");
|
||||
dump_data_dependence_relation (file, ddr);
|
||||
|
||||
fprintf (file, ")\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dir_vects.length () != DDR_NUM_DIR_VECTS (ddr))
|
||||
{
|
||||
fprintf (file, "\n(Number of direction vectors differ: Banerjee has %d, Omega has %d.)\n",
|
||||
dir_vects.length (),
|
||||
DDR_NUM_DIR_VECTS (ddr));
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < DDR_NUM_DIST_VECTS (ddr); i++)
|
||||
{
|
||||
lambda_vector a_dist_v;
|
||||
lambda_vector b_dist_v = DDR_DIST_VECT (ddr, i);
|
||||
|
||||
/* Distance vectors are not ordered in the same way in the DDR
|
||||
and in the DIST_VECTS: search for a matching vector. */
|
||||
FOR_EACH_VEC_ELT (dist_vects, j, a_dist_v)
|
||||
if (lambda_vector_equal (a_dist_v, b_dist_v, DDR_NB_LOOPS (ddr)))
|
||||
break;
|
||||
|
||||
if (j == dist_vects.length ())
|
||||
{
|
||||
fprintf (file, "\n(Dist vectors from the first dependence analyzer:\n");
|
||||
print_dist_vectors (file, dist_vects, DDR_NB_LOOPS (ddr));
|
||||
fprintf (file, "not found in Omega dist vectors:\n");
|
||||
print_dist_vectors (file, DDR_DIST_VECTS (ddr), DDR_NB_LOOPS (ddr));
|
||||
fprintf (file, "data dependence relation:\n");
|
||||
dump_data_dependence_relation (file, ddr);
|
||||
fprintf (file, ")\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < DDR_NUM_DIR_VECTS (ddr); i++)
|
||||
{
|
||||
lambda_vector a_dir_v;
|
||||
lambda_vector b_dir_v = DDR_DIR_VECT (ddr, i);
|
||||
|
||||
/* Direction vectors are not ordered in the same way in the DDR
|
||||
and in the DIR_VECTS: search for a matching vector. */
|
||||
FOR_EACH_VEC_ELT (dir_vects, j, a_dir_v)
|
||||
if (lambda_vector_equal (a_dir_v, b_dir_v, DDR_NB_LOOPS (ddr)))
|
||||
break;
|
||||
|
||||
if (j == dist_vects.length ())
|
||||
{
|
||||
fprintf (file, "\n(Dir vectors from the first dependence analyzer:\n");
|
||||
print_dir_vectors (file, dir_vects, DDR_NB_LOOPS (ddr));
|
||||
fprintf (file, "not found in Omega dir vectors:\n");
|
||||
print_dir_vectors (file, DDR_DIR_VECTS (ddr), DDR_NB_LOOPS (ddr));
|
||||
fprintf (file, "data dependence relation:\n");
|
||||
dump_data_dependence_relation (file, ddr);
|
||||
fprintf (file, ")\n");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* This computes the affine dependence relation between A and B with
|
||||
respect to LOOP_NEST. CHREC_KNOWN is used for representing the
|
||||
independence between two accesses, while CHREC_DONT_KNOW is used
|
||||
|
@ -4239,55 +3714,13 @@ compute_affine_dependence (struct data_dependence_relation *ddr,
|
|||
|
||||
if (access_functions_are_affine_or_constant_p (dra, loop_nest)
|
||||
&& access_functions_are_affine_or_constant_p (drb, loop_nest))
|
||||
{
|
||||
subscript_dependence_tester (ddr, loop_nest);
|
||||
|
||||
if (flag_check_data_deps)
|
||||
{
|
||||
/* Dump the dependences from the first algorithm. */
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
fprintf (dump_file, "\n\nBanerjee Analyzer\n");
|
||||
dump_data_dependence_relation (dump_file, ddr);
|
||||
}
|
||||
|
||||
if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
|
||||
{
|
||||
bool maybe_dependent;
|
||||
vec<lambda_vector> dir_vects, dist_vects;
|
||||
|
||||
/* Save the result of the first DD analyzer. */
|
||||
dist_vects = DDR_DIST_VECTS (ddr);
|
||||
dir_vects = DDR_DIR_VECTS (ddr);
|
||||
|
||||
/* Reset the information. */
|
||||
DDR_DIST_VECTS (ddr).create (0);
|
||||
DDR_DIR_VECTS (ddr).create (0);
|
||||
|
||||
/* Compute the same information using Omega. */
|
||||
if (!init_omega_for_ddr (ddr, &maybe_dependent))
|
||||
goto csys_dont_know;
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
fprintf (dump_file, "Omega Analyzer\n");
|
||||
dump_data_dependence_relation (dump_file, ddr);
|
||||
}
|
||||
|
||||
/* Check that we get the same information. */
|
||||
if (maybe_dependent)
|
||||
gcc_assert (ddr_consistent_p (stderr, ddr, dist_vects,
|
||||
dir_vects));
|
||||
}
|
||||
}
|
||||
}
|
||||
subscript_dependence_tester (ddr, loop_nest);
|
||||
|
||||
/* As a last case, if the dependence cannot be determined, or if
|
||||
the dependence is considered too difficult to determine, answer
|
||||
"don't know". */
|
||||
else
|
||||
{
|
||||
csys_dont_know:;
|
||||
dependence_stats.num_dependence_undetermined++;
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
|
@ -4731,110 +4164,6 @@ compute_data_dependences_for_loop (struct loop *loop,
|
|||
return res;
|
||||
}
|
||||
|
||||
/* Returns true when the data dependences for the basic block BB have been
|
||||
computed, false otherwise.
|
||||
DATAREFS is initialized to all the array elements contained in this basic
|
||||
block, DEPENDENCE_RELATIONS contains the relations between the data
|
||||
references. Compute read-read and self relations if
|
||||
COMPUTE_SELF_AND_READ_READ_DEPENDENCES is TRUE. */
|
||||
bool
|
||||
compute_data_dependences_for_bb (basic_block bb,
|
||||
bool compute_self_and_read_read_dependences,
|
||||
vec<data_reference_p> *datarefs,
|
||||
vec<ddr_p> *dependence_relations)
|
||||
{
|
||||
if (find_data_references_in_bb (NULL, bb, datarefs) == chrec_dont_know)
|
||||
return false;
|
||||
|
||||
return compute_all_dependences (*datarefs, dependence_relations, vNULL,
|
||||
compute_self_and_read_read_dependences);
|
||||
}
|
||||
|
||||
/* Entry point (for testing only). Analyze all the data references
|
||||
and the dependence relations in LOOP.
|
||||
|
||||
The data references are computed first.
|
||||
|
||||
A relation on these nodes is represented by a complete graph. Some
|
||||
of the relations could be of no interest, thus the relations can be
|
||||
computed on demand.
|
||||
|
||||
In the following function we compute all the relations. This is
|
||||
just a first implementation that is here for:
|
||||
- for showing how to ask for the dependence relations,
|
||||
- for the debugging the whole dependence graph,
|
||||
- for the dejagnu testcases and maintenance.
|
||||
|
||||
It is possible to ask only for a part of the graph, avoiding to
|
||||
compute the whole dependence graph. The computed dependences are
|
||||
stored in a knowledge base (KB) such that later queries don't
|
||||
recompute the same information. The implementation of this KB is
|
||||
transparent to the optimizer, and thus the KB can be changed with a
|
||||
more efficient implementation, or the KB could be disabled. */
|
||||
static void
|
||||
analyze_all_data_dependences (struct loop *loop)
|
||||
{
|
||||
unsigned int i;
|
||||
int nb_data_refs = 10;
|
||||
vec<data_reference_p> datarefs;
|
||||
datarefs.create (nb_data_refs);
|
||||
vec<ddr_p> dependence_relations;
|
||||
dependence_relations.create (nb_data_refs * nb_data_refs);
|
||||
vec<loop_p> loop_nest;
|
||||
loop_nest.create (3);
|
||||
|
||||
/* Compute DDs on the whole function. */
|
||||
compute_data_dependences_for_loop (loop, false, &loop_nest, &datarefs,
|
||||
&dependence_relations);
|
||||
|
||||
if (dump_file)
|
||||
{
|
||||
dump_data_dependence_relations (dump_file, dependence_relations);
|
||||
fprintf (dump_file, "\n\n");
|
||||
|
||||
if (dump_flags & TDF_DETAILS)
|
||||
dump_dist_dir_vectors (dump_file, dependence_relations);
|
||||
|
||||
if (dump_flags & TDF_STATS)
|
||||
{
|
||||
unsigned nb_top_relations = 0;
|
||||
unsigned nb_bot_relations = 0;
|
||||
unsigned nb_chrec_relations = 0;
|
||||
struct data_dependence_relation *ddr;
|
||||
|
||||
FOR_EACH_VEC_ELT (dependence_relations, i, ddr)
|
||||
{
|
||||
if (chrec_contains_undetermined (DDR_ARE_DEPENDENT (ddr)))
|
||||
nb_top_relations++;
|
||||
|
||||
else if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
|
||||
nb_bot_relations++;
|
||||
|
||||
else
|
||||
nb_chrec_relations++;
|
||||
}
|
||||
|
||||
gather_stats_on_scev_database ();
|
||||
}
|
||||
}
|
||||
|
||||
loop_nest.release ();
|
||||
free_dependence_relations (dependence_relations);
|
||||
free_data_refs (datarefs);
|
||||
}
|
||||
|
||||
/* Computes all the data dependences and check that the results of
|
||||
several analyzers are the same. */
|
||||
|
||||
void
|
||||
tree_check_data_deps (void)
|
||||
{
|
||||
struct loop *loop_nest;
|
||||
|
||||
FOR_EACH_LOOP (loop_nest, 0)
|
||||
analyze_all_data_dependences (loop_nest);
|
||||
}
|
||||
|
||||
/* Free the memory used by a data dependence relation DDR. */
|
||||
|
||||
void
|
||||
|
|
|
@ -22,7 +22,6 @@ along with GCC; see the file COPYING3. If not see
|
|||
#define GCC_TREE_DATA_REF_H
|
||||
|
||||
#include "graphds.h"
|
||||
#include "omega.h"
|
||||
#include "tree-chrec.h"
|
||||
|
||||
/*
|
||||
|
@ -301,9 +300,6 @@ extern bool compute_data_dependences_for_loop (struct loop *, bool,
|
|||
vec<loop_p> *,
|
||||
vec<data_reference_p> *,
|
||||
vec<ddr_p> *);
|
||||
extern bool compute_data_dependences_for_bb (basic_block, bool,
|
||||
vec<data_reference_p> *,
|
||||
vec<ddr_p> *);
|
||||
extern void debug_ddrs (vec<ddr_p> );
|
||||
extern void dump_data_reference (FILE *, struct data_reference *);
|
||||
extern void debug (data_reference &ref);
|
||||
|
@ -343,8 +339,6 @@ extern bool dr_may_alias_p (const struct data_reference *,
|
|||
const struct data_reference *, bool);
|
||||
extern bool dr_equal_offsets_p (struct data_reference *,
|
||||
struct data_reference *);
|
||||
extern void tree_check_data_deps (void);
|
||||
|
||||
|
||||
/* Return true when the base objects of data references A and B are
|
||||
the same memory object. */
|
||||
|
|
|
@ -286,54 +286,6 @@ make_pass_vectorize (gcc::context *ctxt)
|
|||
return new pass_vectorize (ctxt);
|
||||
}
|
||||
|
||||
/* Check the correctness of the data dependence analyzers. */
|
||||
|
||||
namespace {
|
||||
|
||||
const pass_data pass_data_check_data_deps =
|
||||
{
|
||||
GIMPLE_PASS, /* type */
|
||||
"ckdd", /* name */
|
||||
OPTGROUP_LOOP, /* optinfo_flags */
|
||||
TV_CHECK_DATA_DEPS, /* tv_id */
|
||||
( PROP_cfg | PROP_ssa ), /* properties_required */
|
||||
0, /* properties_provided */
|
||||
0, /* properties_destroyed */
|
||||
0, /* todo_flags_start */
|
||||
0, /* todo_flags_finish */
|
||||
};
|
||||
|
||||
class pass_check_data_deps : public gimple_opt_pass
|
||||
{
|
||||
public:
|
||||
pass_check_data_deps (gcc::context *ctxt)
|
||||
: gimple_opt_pass (pass_data_check_data_deps, ctxt)
|
||||
{}
|
||||
|
||||
/* opt_pass methods: */
|
||||
virtual bool gate (function *) { return flag_check_data_deps != 0; }
|
||||
virtual unsigned int execute (function *);
|
||||
|
||||
}; // class pass_check_data_deps
|
||||
|
||||
unsigned int
|
||||
pass_check_data_deps::execute (function *fun)
|
||||
{
|
||||
if (number_of_loops (fun) <= 1)
|
||||
return 0;
|
||||
|
||||
tree_check_data_deps ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // anon namespace
|
||||
|
||||
gimple_opt_pass *
|
||||
make_pass_check_data_deps (gcc::context *ctxt)
|
||||
{
|
||||
return new pass_check_data_deps (ctxt);
|
||||
}
|
||||
|
||||
/* Propagation of constants using scev. */
|
||||
|
||||
namespace {
|
||||
|
|
|
@ -57,6 +57,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "optabs.h"
|
||||
#include "tree-scalar-evolution.h"
|
||||
#include "tree-inline.h"
|
||||
#include "params.h"
|
||||
|
||||
static unsigned int tree_ssa_phiopt_worker (bool, bool);
|
||||
static bool conditional_replacement (basic_block, basic_block,
|
||||
|
|
|
@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "insn-codes.h"
|
||||
#include "optabs.h"
|
||||
#include "builtins.h"
|
||||
#include "params.h"
|
||||
|
||||
/* Return true if load- or store-lanes optab OPTAB is implemented for
|
||||
COUNT vectors of type VECTYPE. NAME is the name of OPTAB. */
|
||||
|
|
|
@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "backend.h"
|
||||
#include "tree.h"
|
||||
#include "gimple.h"
|
||||
#include "params.h"
|
||||
#include "rtl.h"
|
||||
#include "ssa.h"
|
||||
#include "alias.h"
|
||||
|
|
Loading…
Reference in New Issue