270 lines
7.6 KiB
Diff
270 lines
7.6 KiB
Diff
Index: fold-const.c
|
||
===================================================================
|
||
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
|
||
retrieving revision 1.226.2.9
|
||
diff -u -p -r1.226.2.9 fold-const.c
|
||
--- gcc/fold-const.c 21 Jul 2003 19:07:12 -0000 1.226.2.9
|
||
+++ gcc/fold-const.c 30 Jul 2003 21:29:05 -0000
|
||
@@ -1011,6 +1011,233 @@ associate_trees (t1, t2, code, type)
|
||
|
||
return fold (build (code, type, convert (type, t1), convert (type, t2)));
|
||
}
|
||
+
|
||
+static tree tree_get_index PARAMS ((tree));
|
||
+static int indirect_ref_zero_ofs_p PARAMS ((tree));
|
||
+static int indirect_ref_nonzero_ofs_p PARAMS ((tree));
|
||
+static tree associate_trees_refs PARAMS ((tree, tree, enum tree_code, tree));
|
||
+static void split_tree_indirect_refs PARAMS ((tree, enum tree_code, tree));
|
||
+static void split_tree_for_reorder PARAMS ((tree, enum tree_code, tree));
|
||
+static int compare_trees PARAMS ((const PTR, const PTR));
|
||
+static tree reorder_memrefs PARAMS ((tree, tree, enum tree_code, tree));
|
||
+static tree reorder_summands PARAMS ((tree, tree, enum tree_code, tree));
|
||
+
|
||
+static tree
|
||
+tree_get_index (t)
|
||
+ tree t;
|
||
+{
|
||
+ if (TREE_CODE (t) == ARRAY_REF)
|
||
+ return TREE_OPERAND (t, 1);
|
||
+ else
|
||
+ {
|
||
+ t = TREE_OPERAND (t, 0);
|
||
+ if (TREE_CODE (t) != PLUS_EXPR)
|
||
+ return NULL_TREE;
|
||
+ return TREE_OPERAND (t, 1);
|
||
+ }
|
||
+}
|
||
+
|
||
+static int
|
||
+indirect_ref_nonzero_ofs_p (t)
|
||
+ tree t;
|
||
+{
|
||
+ tree i = tree_get_index (t);
|
||
+ if (i && TREE_CODE (i) == INTEGER_CST && !integer_zerop (i))
|
||
+ return 1;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int
|
||
+indirect_ref_zero_ofs_p (t)
|
||
+ tree t;
|
||
+{
|
||
+ tree i = tree_get_index (t);
|
||
+ if (!i)
|
||
+ return 1;
|
||
+ if (TREE_CODE (i) == INTEGER_CST && integer_zerop (i))
|
||
+ return 1;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static tree
|
||
+associate_trees_refs (t1, t2, code, type)
|
||
+ tree t1, t2;
|
||
+ enum tree_code code;
|
||
+ tree type;
|
||
+{
|
||
+ if (t1 == 0)
|
||
+ return t2;
|
||
+ else if (t2 == 0)
|
||
+ return t1;
|
||
+ return build (code, type, convert (type, t1), convert (type, t2));
|
||
+}
|
||
+
|
||
+#define MAX_SUMMANDS 100
|
||
+static tree merged_z, merged_nz, merged_rest;
|
||
+static tree summands[MAX_SUMMANDS];
|
||
+static int num_summands;
|
||
+static void
|
||
+split_tree_indirect_refs (in, code, type)
|
||
+ tree in;
|
||
+ enum tree_code code;
|
||
+ tree type;
|
||
+{
|
||
+ /* Strip any conversions that don't change the machine mode or signedness. */
|
||
+ STRIP_SIGN_NOPS (in);
|
||
+
|
||
+ if (TREE_CODE (in) == INDIRECT_REF || TREE_CODE (in) == ARRAY_REF)
|
||
+ {
|
||
+ if (indirect_ref_zero_ofs_p (in))
|
||
+ merged_z = associate_trees_refs (merged_z, in, code, type);
|
||
+ else if (indirect_ref_nonzero_ofs_p (in))
|
||
+ merged_nz = associate_trees_refs (merged_nz, in, code, type);
|
||
+ else
|
||
+ merged_rest = associate_trees_refs (merged_rest, in, code, type);
|
||
+ }
|
||
+ else if (TREE_CODE (in) == code)
|
||
+ {
|
||
+ tree op0 = TREE_OPERAND (in, 0);
|
||
+ tree op1 = TREE_OPERAND (in, 1);
|
||
+ split_tree_indirect_refs (op0, code, type);
|
||
+ split_tree_indirect_refs (op1, code, type);
|
||
+ }
|
||
+ else
|
||
+ merged_rest = associate_trees_refs (merged_rest, in, code, type);
|
||
+}
|
||
+
|
||
+static void
|
||
+split_tree_for_reorder (in, code, type)
|
||
+ tree in;
|
||
+ enum tree_code code;
|
||
+ tree type;
|
||
+{
|
||
+ /* Strip any conversions that don't change the machine mode or signedness. */
|
||
+ STRIP_SIGN_NOPS (in);
|
||
+
|
||
+ if ((TREE_CODE (in) == INDIRECT_REF
|
||
+ || TREE_CODE (in) == ARRAY_REF
|
||
+ || TREE_CODE (in) == VAR_DECL)
|
||
+ && num_summands < MAX_SUMMANDS)
|
||
+ summands[num_summands++] = in;
|
||
+ else if (TREE_CODE (in) == code)
|
||
+ {
|
||
+ tree op0 = TREE_OPERAND (in, 0);
|
||
+ tree op1 = TREE_OPERAND (in, 1);
|
||
+ split_tree_for_reorder (op0, code, type);
|
||
+ split_tree_for_reorder (op1, code, type);
|
||
+ }
|
||
+ else
|
||
+ merged_rest = associate_trees_refs (merged_rest, in, code, type);
|
||
+}
|
||
+
|
||
+static int
|
||
+compare_trees (v1, v2)
|
||
+ const PTR v1;
|
||
+ const PTR v2;
|
||
+{
|
||
+ tree t1 = *((const tree *) v1);
|
||
+ tree t2 = *((const tree *) v2);
|
||
+
|
||
+ if (t1 == t2)
|
||
+ return 0;
|
||
+ /* Everything besides var_decls and indirect_refs last. */
|
||
+ if (TREE_CODE (t1) != INDIRECT_REF
|
||
+ && TREE_CODE (t1) != ARRAY_REF
|
||
+ && TREE_CODE (t1) != VAR_DECL)
|
||
+ return 1;
|
||
+ if (TREE_CODE (t2) != INDIRECT_REF
|
||
+ && TREE_CODE (t2) != ARRAY_REF
|
||
+ && TREE_CODE (t2) != VAR_DECL)
|
||
+ return -1;
|
||
+ /* All indirect_refs with nonzero index before var_decls.
|
||
+ All indirect_refs with zero index after var_decls. */
|
||
+ if (TREE_CODE (t1) != TREE_CODE (t2))
|
||
+ {
|
||
+ if (TREE_CODE (t1) == INDIRECT_REF || TREE_CODE (t1) == ARRAY_REF)
|
||
+ {
|
||
+ if (indirect_ref_nonzero_ofs_p (t1))
|
||
+ return -1;
|
||
+ else
|
||
+ return 1;
|
||
+ }
|
||
+ /* t2 is a INDIRECT_REF or ARRAY_REF, so we can call that without
|
||
+ checking. */
|
||
+ else if (indirect_ref_nonzero_ofs_p (t2))
|
||
+ return 1;
|
||
+ else
|
||
+ return -1;
|
||
+ }
|
||
+ if (TREE_CODE (t1) == VAR_DECL)
|
||
+ {
|
||
+ if (IDENTIFIER_HASH_VALUE (DECL_NAME (t1))
|
||
+ < IDENTIFIER_HASH_VALUE (DECL_NAME (t2)))
|
||
+ return -1;
|
||
+ else
|
||
+ return 1;
|
||
+ }
|
||
+ /* We have two indirect_refs here. */
|
||
+ if (indirect_ref_nonzero_ofs_p (t1) && indirect_ref_nonzero_ofs_p (t2))
|
||
+ /* As both had non-zero index, we know that tree_get_index() really
|
||
+ returns INTEGER_CST. */
|
||
+ return tree_int_cst_compare (tree_get_index (t1), tree_get_index (t2));
|
||
+ else if (indirect_ref_zero_ofs_p (t1))
|
||
+ return 1;
|
||
+ else
|
||
+ return -1;
|
||
+}
|
||
+
|
||
+static tree
|
||
+reorder_memrefs (in0, in1, code, type)
|
||
+ tree in0, in1;
|
||
+ enum tree_code code;
|
||
+ tree type;
|
||
+{
|
||
+ tree ret = 0;
|
||
+ merged_z = 0;
|
||
+ merged_nz = 0;
|
||
+ merged_rest = 0;
|
||
+ /* XXX We can't yet handle MINUS_EXPR. */
|
||
+ if (code == MINUS_EXPR)
|
||
+ return 0;
|
||
+ if (in0)
|
||
+ split_tree_indirect_refs (in0, code, type);
|
||
+ if (in1)
|
||
+ split_tree_indirect_refs (in1, code, type);
|
||
+ if (merged_nz || merged_z)
|
||
+ {
|
||
+ ret = associate_trees_refs (merged_nz, merged_z, code, type);
|
||
+ ret = associate_trees_refs (ret, merged_rest, code, type);
|
||
+ }
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+static tree
|
||
+reorder_summands (in0, in1, code, type)
|
||
+ tree in0, in1;
|
||
+ enum tree_code code;
|
||
+ tree type;
|
||
+{
|
||
+ tree ret = 0;
|
||
+ merged_rest = 0;
|
||
+ num_summands = 0;
|
||
+ /* XXX We can't yet handle MINUS_EXPR. */
|
||
+ if (code == MINUS_EXPR)
|
||
+ return 0;
|
||
+ if (in0)
|
||
+ split_tree_for_reorder (in0, code, type);
|
||
+ if (in1)
|
||
+ split_tree_for_reorder (in1, code, type);
|
||
+ if (num_summands > 2)
|
||
+ {
|
||
+ int i;
|
||
+ qsort (summands, num_summands, sizeof (tree), compare_trees);
|
||
+ ret = summands[0];
|
||
+ for (i = 1; i < num_summands; i++)
|
||
+ ret = associate_trees_refs (ret, summands[i], code, type);
|
||
+ ret = associate_trees_refs (ret, merged_rest, code, type);
|
||
+ }
|
||
+ return ret;
|
||
+}
|
||
|
||
/* Combine two integer constants ARG1 and ARG2 under operation CODE
|
||
to produce a new constant.
|
||
@@ -5378,11 +5605,16 @@ fold (expr)
|
||
+ (lit0 != 0) + (lit1 != 0)
|
||
+ (minus_lit0 != 0) + (minus_lit1 != 0)))
|
||
{
|
||
+ tree tmp;
|
||
+ tmp = reorder_summands (var0, var1, code, type);
|
||
/* Recombine MINUS_EXPR operands by using PLUS_EXPR. */
|
||
if (code == MINUS_EXPR)
|
||
code = PLUS_EXPR;
|
||
|
||
- var0 = associate_trees (var0, var1, code, type);
|
||
+ if (tmp)
|
||
+ var0 = tmp;
|
||
+ else
|
||
+ var0 = associate_trees (var0, var1, code, type);
|
||
con0 = associate_trees (con0, con1, code, type);
|
||
lit0 = associate_trees (lit0, lit1, code, type);
|
||
minus_lit0 = associate_trees (minus_lit0, minus_lit1, code, type);
|
||
@@ -5424,6 +5656,9 @@ fold (expr)
|
||
con0 = associate_trees (con0, lit0, code, type);
|
||
return convert (type, associate_trees (var0, con0, code, type));
|
||
}
|
||
+ var0 = reorder_summands (arg0, arg1, code, type);
|
||
+ if (var0)
|
||
+ return convert (type, var0);
|
||
}
|
||
|
||
binary:
|