This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Document a bunch of expression tree codes
NOT_EXPR (UNORDERED_EXPR (x, y)) => ORDERED_EXPR (x, y)
NOT_EXPR (ORDERED_EXPR (x, y)) => UNORDERED_EXPR (x, y)
UNORDERED (x, x) => isnan (x)
ORDERED (x, x) => NOT_EXPR (isnan (x))
isnan (x) || isnan (y) => UNORDERED (x, y)
!isnan (x) && !isnan (y) => ORDERED (x, y)
I think so. I'm sure about the last two; from there, the rest are
simple algebraic manipulations.
And if -fno-trapping-math,
NOT_EXPR (UNLT_EXPR (x, y)) => GE_EXPR (x, y)
>
And if -fno-trapping-math and HONOR_NANS (mode),
NOT_EXPR (GE_EXPR (x, y)) => UNLT_EXPR (x, y)
I also think so. Both of these actually require HONOR_NANS, otherwise
UNLT_EXPR would not be produced, would it?
Would something like the attached patch be acceptable if the regtests
pass? Would additional regtests be necessary?
Paolo
2004-05-26 Paolo Bonzini <bonzini@gnu.org>
Roger Sayle <roger@eyesopen.com>
* c-common.c (c_common_truthvalue_conversion):
Handle LTGT_EXPR.
* c-typeck.c (build_binary_op): Likewise.
* dojump.c (do_jump): Likewise.
* expr.c (expand_expr_real_1, do_store_flag): Likewise.
* predict.c (tree_predict_by_opcode): Likewise.
* real.c (real_compare): Likewise.
* tree-cfg.c (verify_expr): Likewise.
* tree-inline.c (estimate_num_insns_1): Likewise.
* tree-pretty-print.c (dump_generic_node): Likewise.
(op_symbol): Print unordered comparison differently.
* tree.def (LTGT_EXPR): New '<' tree code.
* fold-const.c (invert_tree_comparison): Add HONOR_NANS
parameter.
(invert_truthvalue): Let invert_tree_comparison decide
whether it is valid to fold the comparison.
(fold_relational_const): Integer modes do not honor NaNs.
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.501
diff -p -u -r1.501 c-common.c
--- c-common.c 22 May 2004 18:16:38 -0000 1.501
+++ c-common.c 26 May 2004 07:58:38 -0000
@@ -2582,7 +2582,7 @@ c_common_truthvalue_conversion (tree exp
switch (TREE_CODE (expr))
{
- case EQ_EXPR: case NE_EXPR: case UNEQ_EXPR:
+ case EQ_EXPR: case NE_EXPR: case UNEQ_EXPR: case LTGT_EXPR:
case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
case UNLE_EXPR: case UNGE_EXPR: case UNLT_EXPR: case UNGT_EXPR:
case ORDERED_EXPR: case UNORDERED_EXPR:
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.304
diff -p -u -r1.304 c-typeck.c
--- c-typeck.c 14 May 2004 02:32:55 -0000 1.304
+++ c-typeck.c 26 May 2004 07:58:39 -0000
@@ -6798,6 +6798,7 @@ build_binary_op (enum tree_code code, tr
case UNGT_EXPR:
case UNGE_EXPR:
case UNEQ_EXPR:
+ case LTGT_EXPR:
build_type = integer_type_node;
if (code0 != REAL_TYPE || code1 != REAL_TYPE)
{
Index: dojump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dojump.c,v
retrieving revision 1.16
diff -p -u -r1.16 dojump.c
--- dojump.c 29 Apr 2004 07:50:55 -0000 1.16
+++ dojump.c 26 May 2004 07:58:39 -0000
@@ -525,7 +525,7 @@ do_jump (tree exp, rtx if_false_label, r
{
enum rtx_code rcode1;
- enum tree_code tcode2;
+ enum tree_code tcode1 = UNORDERED_EXPR, tcode2;
case UNLT_EXPR:
rcode1 = UNLT;
@@ -547,6 +547,11 @@ do_jump (tree exp, rtx if_false_label, r
rcode1 = UNEQ;
tcode2 = EQ_EXPR;
goto unordered_bcc;
+ case LTGT_EXPR:
+ rcode1 = LTGT;
+ tcode1 = LT_EXPR;
+ tcode2 = GT_EXPR;
+ goto unordered_bcc;
unordered_bcc:
mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
@@ -560,8 +565,8 @@ do_jump (tree exp, rtx if_false_label, r
tree cmp0, cmp1;
/* If the target doesn't support combined unordered
- compares, decompose into UNORDERED + comparison. */
- cmp0 = fold (build (UNORDERED_EXPR, TREE_TYPE (exp), op0, op1));
+ compares, decompose into two comparisons. */
+ cmp0 = fold (build (tcode1, TREE_TYPE (exp), op0, op1));
cmp1 = fold (build (tcode2, TREE_TYPE (exp), op0, op1));
exp = build (TRUTH_ORIF_EXPR, TREE_TYPE (exp), cmp0, cmp1);
do_jump (exp, if_false_label, if_true_label);
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.647
diff -p -u -r1.647 expr.c
--- expr.c 19 May 2004 06:26:21 -0000 1.647
+++ expr.c 26 May 2004 07:58:41 -0000
@@ -8304,6 +8304,7 @@ expand_expr_real_1 (tree exp, rtx target
case UNGT_EXPR:
case UNGE_EXPR:
case UNEQ_EXPR:
+ case LTGT_EXPR:
temp = do_store_flag (exp,
modifier != EXPAND_STACK_PARM ? target : NULL_RTX,
tmode != VOIDmode ? tmode : mode, 0);
@@ -9814,6 +9815,9 @@ do_store_flag (tree exp, rtx target, enu
case UNEQ_EXPR:
code = UNEQ;
break;
+ case LTGT_EXPR:
+ code = LTGT;
+ break;
default:
abort ();
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.382
diff -p -u -r1.382 fold-const.c
--- fold-const.c 24 May 2004 03:02:44 -0000 1.382
+++ fold-const.c 26 May 2004 07:58:43 -0000
@@ -69,7 +69,7 @@ static tree const_binop (enum tree_code,
static hashval_t size_htab_hash (const void *);
static int size_htab_eq (const void *, const void *);
static tree fold_convert_const (enum tree_code, tree, tree);
-static enum tree_code invert_tree_comparison (enum tree_code);
+static enum tree_code invert_tree_comparison (enum tree_code, bool);
static enum tree_code swap_tree_comparison (enum tree_code);
static int comparison_to_compcode (enum tree_code);
static enum tree_code compcode_to_comparison (int);
@@ -2057,11 +2057,15 @@ pedantic_non_lvalue (tree x)
/* Given a tree comparison code, return the code that is the logical inverse
of the given code. It is not safe to do this for floating-point
- comparisons, except for NE_EXPR and EQ_EXPR. */
+ comparisons, except for NE_EXPR and EQ_EXPR, so we receive a machine mode
+ as well: if reversing the comparison is unsafe, return ERROR_MARK. */
static enum tree_code
-invert_tree_comparison (enum tree_code code)
+invert_tree_comparison (enum tree_code code, bool honor_nans)
{
+ if (honor_nans && flag_trapping_math)
+ return ERROR_MARK;
+
switch (code)
{
case EQ_EXPR:
@@ -2069,13 +2073,29 @@ invert_tree_comparison (enum tree_code c
case NE_EXPR:
return EQ_EXPR;
case GT_EXPR:
- return LE_EXPR;
+ return honor_nans ? UNLE_EXPR : LE_EXPR;
case GE_EXPR:
- return LT_EXPR;
+ return honor_nans ? UNLT_EXPR : LT_EXPR;
case LT_EXPR:
- return GE_EXPR;
+ return honor_nans ? UNGE_EXPR : GE_EXPR;
case LE_EXPR:
+ return honor_nans ? UNGT_EXPR : GT_EXPR;
+ case LTGT_EXPR:
+ return UNEQ_EXPR;
+ case UNEQ_EXPR:
+ return LTGT_EXPR;
+ case UNGT_EXPR:
+ return LE_EXPR;
+ case UNGE_EXPR:
+ return LT_EXPR;
+ case UNLT_EXPR:
+ return GE_EXPR;
+ case UNLE_EXPR:
return GT_EXPR;
+ case ORDERED_EXPR:
+ return UNORDERED_EXPR;
+ case UNORDERED_EXPR:
+ return ORDERED_EXPR;
default:
abort ();
}
@@ -2702,17 +2722,15 @@ invert_truthvalue (tree arg)
&& code != NE_EXPR
&& code != EQ_EXPR)
return build1 (TRUTH_NOT_EXPR, type, arg);
- else if (code == UNORDERED_EXPR
- || code == ORDERED_EXPR
- || code == UNEQ_EXPR
- || code == UNLT_EXPR
- || code == UNLE_EXPR
- || code == UNGT_EXPR
- || code == UNGE_EXPR)
- return build1 (TRUTH_NOT_EXPR, type, arg);
else
- return build2 (invert_tree_comparison (code), type,
- TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1));
+ {
+ code = invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (type)));
+ if (code == ERROR_MARK)
+ return build1 (TRUTH_NOT_EXPR, type, arg);
+ else
+ return build2 (code, type,
+ TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1));
+ }
}
switch (code)
@@ -9856,7 +9874,7 @@ fold_relational_const (enum tree_code co
if (code == NE_EXPR || code == GE_EXPR)
{
invert = 1;
- code = invert_tree_comparison (code);
+ code = invert_tree_comparison (code, false);
}
/* Compute a result for LT or EQ if args permit;
Index: predict.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/predict.c,v
retrieving revision 1.104
diff -p -u -r1.104 predict.c
--- predict.c 13 May 2004 06:39:44 -0000 1.104
+++ predict.c 26 May 2004 07:58:44 -0000
@@ -865,6 +865,7 @@ tree_predict_by_opcode (basic_block bb)
break;
case NE_EXPR:
+ case LTGT_EXPR:
/* Floating point comparisons appears to behave in a very
unpredictable way because of special role of = tests in
FP code. */
Index: real.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.c,v
retrieving revision 1.141
diff -p -u -r1.141 real.c
--- real.c 22 Mar 2004 00:40:44 -0000 1.141
+++ real.c 26 May 2004 07:58:44 -0000
@@ -1080,6 +1080,8 @@ real_compare (int icode, const REAL_VALU
return do_compare (op0, op1, 1) >= 0;
case UNEQ_EXPR:
return do_compare (op0, op1, 0) == 0;
+ case LTGT_EXPR:
+ return do_compare (op0, op1, 0) != 0;
default:
abort ();
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-cfg.c,v
retrieving revision 2.3
diff -p -u -r2.3 tree-cfg.c
--- tree-cfg.c 19 May 2004 19:30:27 -0000 2.3
+++ tree-cfg.c 26 May 2004 07:58:45 -0000
@@ -3097,6 +3097,7 @@ verify_expr (tree *tp, int *walk_subtree
case UNGT_EXPR:
case UNGE_EXPR:
case UNEQ_EXPR:
+ case LTGT_EXPR:
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
Index: tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.102
diff -p -u -r1.102 tree-inline.c
--- tree-inline.c 15 May 2004 23:07:51 -0000 1.102
+++ tree-inline.c 26 May 2004 07:58:45 -0000
@@ -1324,6 +1324,7 @@ estimate_num_insns_1 (tree *tp, int *wal
case UNGT_EXPR:
case UNGE_EXPR:
case UNEQ_EXPR:
+ case LTGT_EXPR:
case CONVERT_EXPR:
Index: tree-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-pretty-print.c,v
retrieving revision 2.2
diff -p -u -r2.2 tree-pretty-print.c
--- tree-pretty-print.c 15 May 2004 23:07:52 -0000 2.2
+++ tree-pretty-print.c 26 May 2004 07:58:45 -0000
@@ -905,6 +905,7 @@ dump_generic_node (pretty_printer *buffe
case UNGT_EXPR:
case UNGE_EXPR:
case UNEQ_EXPR:
+ case LTGT_EXPR:
{
const char *op = op_symbol (node);
op0 = TREE_OPERAND (node, 0);
@@ -1787,27 +1788,35 @@ op_symbol (tree op)
return "&";
case EQ_EXPR:
- case UNEQ_EXPR:
return "==";
+ case UNEQ_EXPR:
+ return "u==";
case NE_EXPR:
return "!=";
case LT_EXPR:
- case UNLT_EXPR:
return "<";
+ case UNLT_EXPR:
+ return "u<";
case LE_EXPR:
- case UNLE_EXPR:
return "<=";
+ case UNLE_EXPR:
+ return "u<=";
case GT_EXPR:
- case UNGT_EXPR:
return ">";
+ case UNGT_EXPR:
+ return "u>";
case GE_EXPR:
- case UNGE_EXPR:
return ">=";
+ case UNGE_EXPR:
+ return "u>=";
+
+ case LTGT_EXPR:
+ return "<>";
case LSHIFT_EXPR:
return "<<";
Index: tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.def,v
retrieving revision 1.76
diff -p -u -r1.76 tree.def
--- tree.def 14 May 2004 02:32:58 -0000 1.76
+++ tree.def 26 May 2004 07:58:46 -0000
@@ -681,6 +681,9 @@ DEFTREECODE (UNGT_EXPR, "ungt_expr", '<'
DEFTREECODE (UNGE_EXPR, "unge_expr", '<', 2)
DEFTREECODE (UNEQ_EXPR, "uneq_expr", '<', 2)
+/* This is the reverse of uneq_expr. */
+DEFTREECODE (LTGT_EXPR, "ltgt_expr", '<', 2)
+
/* Operations for Pascal sets. Not used now. */
DEFTREECODE (IN_EXPR, "in_expr", '2', 2)
DEFTREECODE (SET_LE_EXPR, "set_le_expr", '<', 2)