This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] for PR 17591
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 25 Sep 2004 16:44:08 +0200
- Subject: [patch] for PR 17591
Hello,
this patch fixes handling of varying component offsets in ivopts and
invariant motion, thus fixing the bootstrap problem and several of the
testsuite failures in this PR.
Also handling of ALIGN_INDIRECT_REF and MISALIGNED_INDIRECT_REF in
ivopts is wrong. Until I can come up with a better solution, this
patch avoids (miss)optimizing them completely.
Older patch for ada bootstrap problem
(http://gcc.gnu.org/ml/gcc-patches/2004-09/msg01863.html) is included
in order to make testing possible.
Bootstrapped & regtested on i686.
Zdenek
PR bootstrap/17591
* tree-ssa-loop-im.c (for_each_index): Call callback for component_refs
with varying offset.
* tree-ssa-loop-ivopts.c (abnormal_ssa_name_p): New function.
(idx_contains_abnormal_ssa_name_p): Scan step and lower bound for
ARRAY_REFS.
(expr_invariant_in_loop_p): New function.
(idx_find_step): Handle step and lower bound for ARRAY_REFs. Handle
component_ref_field_offset for COMPONENT_REFs. Do not allow
ALIGN_INDIRECT_REFs and MISALIGNED_INDIRECT_REFs.
(add_address_candidates): Do not handle ALIGN_INDIRECT_REFs and
MISALIGNED_INDIRECT_REFs.
(idx_remove_ssa_names): Handle step and lower bound for ARRAY_REFs.
(rewrite_address_base): Do not handle ALIGN_INDIRECT_REFs and
MISALIGNED_INDIRECT_REFs.
Index: tree-ssa-loop-im.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-im.c,v
retrieving revision 2.14
diff -c -3 -p -r2.14 tree-ssa-loop-im.c
*** tree-ssa-loop-im.c 23 Sep 2004 14:34:19 -0000 2.14
--- tree-ssa-loop-im.c 24 Sep 2004 13:47:13 -0000
*************** get_stmt_uid (tree stmt)
*** 128,134 ****
bool
for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
{
! tree *nxt;
for (; ; addr_p = nxt)
{
--- 128,134 ----
bool
for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
{
! tree *nxt, *idx;
for (; ; addr_p = nxt)
{
*************** for_each_index (tree *addr_p, bool (*cbc
*** 144,150 ****
return cbck (*addr_p, nxt, data);
case BIT_FIELD_REF:
- case COMPONENT_REF:
case VIEW_CONVERT_EXPR:
case ARRAY_RANGE_REF:
case REALPART_EXPR:
--- 144,149 ----
*************** for_each_index (tree *addr_p, bool (*cbc
*** 152,157 ****
--- 151,167 ----
nxt = &TREE_OPERAND (*addr_p, 0);
break;
+ case COMPONENT_REF:
+ /* If the component has varying offset, it behaves like index
+ as well. */
+ idx = &TREE_OPERAND (*addr_p, 2);
+ if (*idx
+ && !cbck (*addr_p, idx, data))
+ return false;
+
+ nxt = &TREE_OPERAND (*addr_p, 0);
+ break;
+
case ARRAY_REF:
nxt = &TREE_OPERAND (*addr_p, 0);
if (!cbck (*addr_p, &TREE_OPERAND (*addr_p, 1), data))
Index: tree-ssa-loop-ivopts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-ivopts.c,v
retrieving revision 2.12
diff -c -3 -p -r2.12 tree-ssa-loop-ivopts.c
*** tree-ssa-loop-ivopts.c 23 Sep 2004 14:34:19 -0000 2.12
--- tree-ssa-loop-ivopts.c 24 Sep 2004 13:47:14 -0000
*************** determine_biv_step (tree phi)
*** 701,717 ****
return step;
}
! /* Returns false if INDEX is a ssa name that occurs in an
abnormal phi node. Callback for for_each_index. */
static bool
! idx_contains_abnormal_ssa_name_p (tree base ATTRIBUTE_UNUSED, tree *index,
void *data ATTRIBUTE_UNUSED)
{
! if (TREE_CODE (*index) != SSA_NAME)
! return true;
! return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (*index) == 0;
}
/* Returns true if EXPR contains a ssa name that occurs in an
--- 701,736 ----
return step;
}
! /* Returns true if EXP is a ssa name that occurs in an abnormal phi node. */
!
! static bool
! abnormal_ssa_name_p (tree exp)
! {
! if (!exp)
! return false;
!
! if (TREE_CODE (exp) != SSA_NAME)
! return false;
!
! return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) != 0;
! }
!
! /* Returns false if BASE or INDEX contains a ssa name that occurs in an
abnormal phi node. Callback for for_each_index. */
static bool
! idx_contains_abnormal_ssa_name_p (tree base, tree *index,
void *data ATTRIBUTE_UNUSED)
{
! if (TREE_CODE (base) == ARRAY_REF)
! {
! if (abnormal_ssa_name_p (TREE_OPERAND (base, 2)))
! return false;
! if (abnormal_ssa_name_p (TREE_OPERAND (base, 3)))
! return false;
! }
! return !abnormal_ssa_name_p (*index);
}
/* Returns true if EXPR contains a ssa name that occurs in an
*************** find_interesting_uses_cond (struct ivopt
*** 1146,1151 ****
--- 1165,1203 ----
record_use (data, cond_p, civ, stmt, USE_COMPARE);
}
+ /* Returns true if expression EXPR is obviously invariant in LOOP,
+ i.e. if all its operands are defined outside of the LOOP. */
+
+ static bool
+ expr_invariant_in_loop_p (struct loop *loop, tree expr)
+ {
+ basic_block def_bb;
+ unsigned i, len;
+
+ if (is_gimple_min_invariant (expr))
+ return true;
+
+ if (TREE_CODE (expr) == SSA_NAME)
+ {
+ def_bb = bb_for_stmt (SSA_NAME_DEF_STMT (expr));
+ if (def_bb
+ && flow_bb_inside_loop_p (loop, def_bb))
+ return false;
+
+ return true;
+ }
+
+ if (!EXPR_P (expr))
+ return false;
+
+ len = first_rtl_op (TREE_CODE (expr));
+ for (i = 0; i < len; i++)
+ if (!expr_invariant_in_loop_p (loop, TREE_OPERAND (expr, i)))
+ return false;
+
+ return true;
+ }
+
/* Cumulates the steps of indices into DATA and replaces their values with the
initial ones. Returns false when the value of the index cannot be determined.
Callback for for_each_index. */
*************** idx_find_step (tree base, tree *idx, voi
*** 1162,1171 ****
{
struct ifs_ivopts_data *dta = data;
struct iv *iv;
! tree step, type, iv_type, iv_step, lbound;
! basic_block def_bb;
struct loop *loop = dta->ivopts_data->current_loop;
!
if (TREE_CODE (*idx) != SSA_NAME)
return true;
--- 1214,1248 ----
{
struct ifs_ivopts_data *dta = data;
struct iv *iv;
! tree step, type, iv_type, iv_step, lbound, off;
struct loop *loop = dta->ivopts_data->current_loop;
!
! if (TREE_CODE (base) == MISALIGNED_INDIRECT_REF
! || TREE_CODE (base) == ALIGN_INDIRECT_REF)
! return false;
!
! /* If base is a component ref, require that the offset of the reference
! is invariant. */
! if (TREE_CODE (base) == COMPONENT_REF)
! {
! off = component_ref_field_offset (base);
! return expr_invariant_in_loop_p (loop, off);
! }
!
! /* If base is array, first check whether we will be able to move the
! reference out of the loop (in order to take its address in strength
! reduction). In order for this to work we need both lower bound
! and step to be loop invariants. */
! if (TREE_CODE (base) == ARRAY_REF)
! {
! step = array_ref_element_size (base);
! lbound = array_ref_low_bound (base);
!
! if (!expr_invariant_in_loop_p (loop, step)
! || !expr_invariant_in_loop_p (loop, lbound))
! return false;
! }
!
if (TREE_CODE (*idx) != SSA_NAME)
return true;
*************** idx_find_step (tree base, tree *idx, voi
*** 1183,1209 ****
if (TREE_CODE (base) == ARRAY_REF)
{
step = array_ref_element_size (base);
- lbound = array_ref_low_bound (base);
/* We only handle addresses whose step is an integer constant. */
if (TREE_CODE (step) != INTEGER_CST)
return false;
-
- /* We need the lower bound to be invariant in loop, since otherwise
- we are unable to initialize a new induction variable created
- in strength reduction -- we need to take the address of the
- reference in front of the loop. */
- if (is_gimple_min_invariant (lbound))
- ; /* Nothing to do. */
- else if (TREE_CODE (lbound) != SSA_NAME)
- return false;
- else
- {
- def_bb = bb_for_stmt (SSA_NAME_DEF_STMT (lbound));
- if (def_bb
- && flow_bb_inside_loop_p (loop, def_bb))
- return false;
- }
}
else
/* The step for pointer arithmetics already is 1 byte. */
--- 1260,1269 ----
*************** find_interesting_uses_address (struct iv
*** 1269,1277 ****
|| zero_p (step))
goto fail;
! if (TREE_CODE (base) == INDIRECT_REF
! || TREE_CODE (base) == ALIGN_INDIRECT_REF
! || TREE_CODE (base) == MISALIGNED_INDIRECT_REF)
base = TREE_OPERAND (base, 0);
else
base = build_addr (base);
--- 1329,1338 ----
|| zero_p (step))
goto fail;
! gcc_assert (TREE_CODE (base) != ALIGN_INDIRECT_REF);
! gcc_assert (TREE_CODE (base) != MISALIGNED_INDIRECT_REF);
!
! if (TREE_CODE (base) == INDIRECT_REF)
base = TREE_OPERAND (base, 0);
else
base = build_addr (base);
*************** add_address_candidates (struct ivopts_da
*** 1701,1709 ****
if (base != TREE_OPERAND (iv->base, 0))
{
! if (TREE_CODE (base) == INDIRECT_REF
! || TREE_CODE (base) == ALIGN_INDIRECT_REF
! || TREE_CODE (base) == MISALIGNED_INDIRECT_REF)
base = TREE_OPERAND (base, 0);
else
base = build_addr (base);
--- 1762,1771 ----
if (base != TREE_OPERAND (iv->base, 0))
{
! gcc_assert (TREE_CODE (base) != ALIGN_INDIRECT_REF);
! gcc_assert (TREE_CODE (base) != MISALIGNED_INDIRECT_REF);
!
! if (TREE_CODE (base) == INDIRECT_REF)
base = TREE_OPERAND (base, 0);
else
base = build_addr (base);
*************** rewrite_use_nonlinear_expr (struct ivopt
*** 3805,3815 ****
for_each_index. */
static bool
! idx_remove_ssa_names (tree base ATTRIBUTE_UNUSED, tree *idx,
void *data ATTRIBUTE_UNUSED)
{
if (TREE_CODE (*idx) == SSA_NAME)
*idx = SSA_NAME_VAR (*idx);
return true;
}
--- 3867,3892 ----
for_each_index. */
static bool
! idx_remove_ssa_names (tree base, tree *idx,
void *data ATTRIBUTE_UNUSED)
{
+ tree *op;
+
if (TREE_CODE (*idx) == SSA_NAME)
*idx = SSA_NAME_VAR (*idx);
+
+ if (TREE_CODE (base) == ARRAY_REF)
+ {
+ op = &TREE_OPERAND (base, 2);
+ if (*op
+ && TREE_CODE (*op) == SSA_NAME)
+ *op = SSA_NAME_VAR (*op);
+ op = &TREE_OPERAND (base, 3);
+ if (*op
+ && TREE_CODE (*op) == SSA_NAME)
+ *op = SSA_NAME_VAR (*op);
+ }
+
return true;
}
*************** rewrite_address_base (block_stmt_iterato
*** 3837,3845 ****
if (!var || TREE_CODE (with) != SSA_NAME)
goto do_rewrite;
! if (TREE_CODE (var) == INDIRECT_REF
! || TREE_CODE (var) == ALIGN_INDIRECT_REF
! || TREE_CODE (var) == MISALIGNED_INDIRECT_REF)
var = TREE_OPERAND (var, 0);
if (TREE_CODE (var) == SSA_NAME)
{
--- 3914,3923 ----
if (!var || TREE_CODE (with) != SSA_NAME)
goto do_rewrite;
!
! gcc_assert (TREE_CODE (var) != ALIGN_INDIRECT_REF);
! gcc_assert (TREE_CODE (var) != MISALIGNED_INDIRECT_REF);
! if (TREE_CODE (var) == INDIRECT_REF)
var = TREE_OPERAND (var, 0);
if (TREE_CODE (var) == SSA_NAME)
{
*************** rewrite_address_base (block_stmt_iterato
*** 3876,3894 ****
do_rewrite:
orig = NULL_TREE;
! if (TREE_CODE (*op) == INDIRECT_REF
! || TREE_CODE (*op) == ALIGN_INDIRECT_REF
! || TREE_CODE (*op) == MISALIGNED_INDIRECT_REF)
orig = REF_ORIGINAL (*op);
if (!orig)
orig = unshare_and_remove_ssa_names (*op);
! if (TREE_CODE (bvar) == ALIGN_INDIRECT_REF)
! *op = build1 (ALIGN_INDIRECT_REF, TREE_TYPE (*op), with);
! else if (TREE_CODE (bvar) == MISALIGNED_INDIRECT_REF)
! *op = build2 (MISALIGNED_INDIRECT_REF, TREE_TYPE (*op), with, TREE_OPERAND (*op, 1));
! else
! *op = build1 (INDIRECT_REF, TREE_TYPE (*op), with);
/* Record the original reference, for purposes of alias analysis. */
REF_ORIGINAL (*op) = orig;
--- 3954,3968 ----
do_rewrite:
orig = NULL_TREE;
! gcc_assert (TREE_CODE (*op) != ALIGN_INDIRECT_REF);
! gcc_assert (TREE_CODE (*op) != MISALIGNED_INDIRECT_REF);
!
! if (TREE_CODE (*op) == INDIRECT_REF)
orig = REF_ORIGINAL (*op);
if (!orig)
orig = unshare_and_remove_ssa_names (*op);
! *op = build1 (INDIRECT_REF, TREE_TYPE (*op), with);
/* Record the original reference, for purposes of alias analysis. */
REF_ORIGINAL (*op) = orig;