This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][C-Family] Disable bogus shortening of DFP vs FP compare
- From: Richard Biener <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: "Joseph S. Myers" <joseph at codesourcery dot com>
- Date: Tue, 4 Nov 2014 16:03:52 +0100 (CET)
- Subject: [PATCH][C-Family] Disable bogus shortening of DFP vs FP compare
- Authentication-results: sourceware.org; auth=none
On the match-and-simplify branch we expose an issue in shorten_compare
which happily transforms (double) float-var != (double) dfp-float-var
to (float) float-var != (float) dfp-float-var which is wrong
and causes
FAIL: c-c++-common/dfp/convert-bfp-12.c -std=c++11 execution test
FAIL: c-c++-common/dfp/convert-bfp-12.c -std=c++1y execution test
FAIL: c-c++-common/dfp/convert-bfp-12.c -std=c++98 execution test
you can expose this latent bug by making get_narrower also
treat CONVERT_EXPRs as conversions - on trunk the DFP value
happens to be converted to double using that.
You then also run into the issue that the C frontend rejects
the compare via its common_type implementation which complains
about a mixed FP - DFP compare.
So the following patch which I am testing right now disables
the (premature) shorten-compare optimization on mixed
FP - DFP operands. It also exposes the issue on trunk by
improving get_narrower.
Ok for trunk either with or without the tree.c hunk? (I'm
going to remove that if it exposes more issues elsewhere
revealed by testing)
Thanks,
Richard.
2014-11-04 Richard Biener <rguenther@suse.de>
* tree.c (get_narrower): Also look through CONVERT_EXPRs.
c-family/
* c-common.c (shorten_compare): Do not shorten mixed
DFP and non-DFP compares.
Index: gcc/tree.c
===================================================================
--- gcc/tree.c (revision 217049)
+++ gcc/tree.c (working copy)
@@ -8494,7 +8494,7 @@ get_narrower (tree op, int *unsignedp_pt
tree win = op;
bool integral_p = INTEGRAL_TYPE_P (TREE_TYPE (op));
- while (TREE_CODE (op) == NOP_EXPR)
+ while (CONVERT_EXPR_P (op))
{
int bitschange
= (TYPE_PRECISION (TREE_TYPE (op))
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c (revision 217049)
+++ gcc/c-family/c-common.c (working copy)
@@ -4314,9 +4314,15 @@ shorten_compare (location_t loc, tree *o
/* If either arg is decimal float and the other is float, find the
proper common type to use for comparison. */
else if (real1 && real2
+ && DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop0)))
+ && DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop1))))
+ type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1));
+
+ /* If either arg is decimal float and the other is float, fail. */
+ else if (real1 && real2
&& (DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop0)))
|| DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop1)))))
- type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1));
+ return 0;
else if (real1 && real2
&& (TYPE_PRECISION (TREE_TYPE (primop0))