aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/expr.cc14
-rw-r--r--gcc/testsuite/gcc.dg/pr117712.c13
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;
+}