This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa/mainline PATCH] fold "test"==0 into constant
- From: Jan Hubicka <jh at suse dot cz>
- To: gcc-patches at gcc dot gnu dot org, rth at redhat dot com
- Date: Thu, 6 Nov 2003 11:11:57 +0100
- Subject: [tree-ssa/mainline PATCH] fold "test"==0 into constant
Hi,
another problem I noticed debugging RTL expansion is that do_jump is able to
simplify if ("test"==0) into 0, while fold_const is not able to do so. This
match several thousdant times during GCC boostrap to my surprise.
The patch bellow is based on merging tree_expr_nonnegative_p and RTL
nonzero_address implementation so it catch these and slightly more
sophisficated cases.
Bootstrapped/regtested tree-SSA branch, mainline testing in progress (i386-unknown-linux).
OK for mainline/tree-SSA?
Honza
2003-11-06 Jan Hubicka <jh@suse.cz>
* fold-const.c (tree_expr_nonzero_p): New function.
(fold_relational_const): Use it.
index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.213.2.55
diff -c -3 -p -r1.213.2.55 fold-const.c
*** fold-const.c 30 Oct 2003 02:27:40 -0000 1.213.2.55
--- fold-const.c 6 Nov 2003 10:05:36 -0000
*************** tree_expr_nonnegative_p (tree t)
*** 8605,8610 ****
--- 8605,8719 ----
return 0;
}
+ /* Return true when T is an address and is known to be nonzero.
+ For floating point we further ensure that T is not denormal.
+ Similar logic is present in nonzero_address in rtlanal.h */
+ static bool
+ tree_expr_nonzero_p (tree t)
+ {
+ switch (TREE_CODE (t))
+ {
+ case ABS_EXPR:
+ return ((FLOAT_TYPE_P (t) || !TREE_OVERFLOW (t))
+ && tree_expr_nonzero_p (t));
+
+ case INTEGER_CST:
+ return !integer_zerop (t);
+
+ case REAL_CST:
+ /* ??? We should check !real_zerop (t) && not-denormal. */
+ return false;
+
+ case PLUS_EXPR:
+ if (!TREE_OVERFLOW (t) && !FLOAT_TYPE_P (t))
+ {
+ if (tree_expr_nonzero_p (TREE_OPERAND (t, 0)))
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+ if (tree_expr_nonzero_p (TREE_OPERAND (t, 1)))
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+ return false;
+ }
+ break;
+
+ case MULT_EXPR:
+ if (!TREE_OVERFLOW (t) && !FLOAT_TYPE_P (t))
+ {
+ return (tree_expr_nonzero_p (TREE_OPERAND (t, 0))
+ && tree_expr_nonzero_p (TREE_OPERAND (t, 1)));
+ }
+ break;
+
+ case NOP_EXPR:
+ {
+ tree inner_type = TREE_TYPE (TREE_OPERAND (t, 0));
+ tree outer_type = TREE_TYPE (t);
+
+ return (TYPE_PRECISION (inner_type) >= TYPE_PRECISION (outer_type)
+ && tree_expr_nonzero_p (TREE_OPERAND (t, 0)));
+ if (TREE_CODE (outer_type) == REAL_TYPE)
+ {
+ if (TREE_CODE (inner_type) == REAL_TYPE)
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+ if (TREE_CODE (inner_type) == INTEGER_TYPE)
+ {
+ if (TREE_UNSIGNED (inner_type))
+ return 1;
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+ }
+ }
+ else if (TREE_CODE (outer_type) == INTEGER_TYPE)
+ {
+ if (TREE_CODE (inner_type) == REAL_TYPE)
+ return tree_expr_nonnegative_p (TREE_OPERAND (t,0));
+ if (TREE_CODE (inner_type) == INTEGER_TYPE)
+ return TYPE_PRECISION (inner_type) < TYPE_PRECISION (outer_type)
+ && TREE_UNSIGNED (inner_type);
+ }
+ }
+ break;
+ case ADDR_EXPR:
+ /* Weak declarations may link to NULL. */
+ if (DECL_P (TREE_OPERAND (t, 0)))
+ return !DECL_WEAK (TREE_OPERAND (t, 0));
+ /* Constants and all other cases are never weak. */
+ return true;
+
+ case COND_EXPR:
+ return (tree_expr_nonzero_p (TREE_OPERAND (t, 1))
+ && tree_expr_nonzero_p (TREE_OPERAND (t, 2)));
+ case MIN_EXPR:
+ return (tree_expr_nonzero_p (TREE_OPERAND (t, 0))
+ && tree_expr_nonzero_p (TREE_OPERAND (t, 1)));
+ case COMPOUND_EXPR:
+ case MODIFY_EXPR:
+ case BIND_EXPR:
+ return tree_expr_nonzero_p (TREE_OPERAND (t, 1));
+ case MAX_EXPR:
+ if (tree_expr_nonzero_p (TREE_OPERAND (t, 0)))
+ {
+ if (tree_expr_nonzero_p (TREE_OPERAND (t, 1)))
+ return true;
+ return (tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+ && tree_expr_nonnegative_p (TREE_OPERAND (t, 1)));
+ }
+ else if (tree_expr_nonzero_p (TREE_OPERAND (t, 1)))
+ {
+ if (tree_expr_nonzero_p (TREE_OPERAND (t, 0)))
+ return true;
+ return (tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+ && tree_expr_nonnegative_p (TREE_OPERAND (t, 1)));
+ }
+ break;
+ case SAVE_EXPR:
+ case NON_LVALUE_EXPR:
+ return tree_expr_nonzero_p (TREE_OPERAND (t, 0));
+ case RTL_EXPR:
+ return nonzero_address_p (RTL_EXPR_RTL (t));
+
+ default:
+ break;
+ }
+ return false;
+ }
+
/* Return true if `r' is known to be non-negative.
Only handles constants at the moment. */
*************** fold_relational_const (enum tree_code co
*** 8787,8792 ****
--- 8896,8908 ----
0);
}
+ else if (code == EQ_EXPR
+ && integer_zerop (op1) && tree_expr_nonzero_p (op0))
+ tem = build_int_2 (0, 0);
+ else if (code == NE_EXPR
+ && integer_zerop (op1) && tree_expr_nonzero_p (op0))
+ tem = build_int_2 (1, 0);
+
/* Two real constants can be compared explicitly. */
else if (TREE_CODE (op0) == REAL_CST && TREE_CODE (op1) == REAL_CST)
{