diff options
-rw-r--r-- | gcc/expr.cc | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr117712.c | 13 |
2 files changed, 26 insertions, 1 deletions
diff --git a/gcc/expr.cc b/gcc/expr.cc index f684e26..9f4382d 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -8747,7 +8747,19 @@ force_operand (rtx value, rtx target) { if (!target) target = gen_reg_rtx (GET_MODE (value)); - op1 = force_operand (XEXP (value, 0), NULL_RTX); + /* FIX or UNSIGNED_FIX with integral mode has unspecified rounding, + while FIX with floating point mode rounds toward zero. So, some + targets use expressions like (fix:SI (fix:DF (reg:DF ...))) + to express rounding toward zero during the conversion to int. + expand_fix isn't able to handle that, it can only handle + FIX/UNSIGNED_FIX from floating point mode to integral one. */ + if ((code == FIX || code == UNSIGNED_FIX) + && GET_CODE (XEXP (value, 0)) == FIX + && (GET_MODE (XEXP (value, 0)) + == GET_MODE (XEXP (XEXP (value, 0), 0)))) + op1 = force_operand (XEXP (XEXP (value, 0), 0), NULL_RTX); + else + op1 = force_operand (XEXP (value, 0), NULL_RTX); switch (code) { case ZERO_EXTEND: diff --git a/gcc/testsuite/gcc.dg/pr117712.c b/gcc/testsuite/gcc.dg/pr117712.c new file mode 100644 index 0000000..7377a61 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr117712.c @@ -0,0 +1,13 @@ +/* PR rtl-optimization/117712 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -ffast-math" } */ + +int b; + +int +foo (int x) +{ + if (b) + x = 0.96 * x; + return x; +} |