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 <rguent...@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))