[PATCH, i386]: Fix PR target/39228, 387 optimised __builtin_isinf() gives incorrect result

Uros Bizjak ubizjak@gmail.com
Wed Feb 18 13:48:00 GMT 2009


Hello!

Attached patch fixes PR target/39228 by forcing operands[1] through
volatile memory. This will strip excess precision from input operand.

Patch was bootstrapped on i686-pc-linux-gnu. Patch also includes
generic testcase that will check for possible problems with isinf()
functions.

2009-02-18  Uros Bizjak  <ubizjak@gmail.com>

	PR target/39228
	* config/i386/i386.md (isinfxf2): Split from isinf<mode>2.
	(isinf<mode>2): Use MODEF mode iterator.  Force operand[1]
	through volatile memory to remove excess precision.

testsuite/ChangeLog:

2009-02-18  Uros Bizjak  <ubizjak@gmail.com>

	PR target/39228
	* gcc.c-torture/execute/pr39228.c: New test.

I will wait for possible comments for a day or two before comitting
this patch to 4.4 mainline and 4.3 branch.

Uros.
-------------- next part --------------
Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md	(revision 144259)
+++ config/i386/i386.md	(working copy)
@@ -18811,9 +18811,35 @@
    (set_attr "unit" "i387")
    (set_attr "mode" "<MODE>")])
 
+(define_expand "isinfxf2"
+  [(use (match_operand:SI 0 "register_operand" ""))
+   (use (match_operand:XF 1 "register_operand" ""))]
+  "TARGET_USE_FANCY_MATH_387
+   && TARGET_C99_FUNCTIONS"
+{
+  rtx mask = GEN_INT (0x45);
+  rtx val = GEN_INT (0x05);
+
+  rtx cond;
+
+  rtx scratch = gen_reg_rtx (HImode);
+  rtx res = gen_reg_rtx (QImode);
+
+  emit_insn (gen_fxamxf2_i387 (scratch, operands[1]));
+
+  emit_insn (gen_andqi_ext_0 (scratch, scratch, mask));
+  emit_insn (gen_cmpqi_ext_3 (scratch, val));
+  cond = gen_rtx_fmt_ee (EQ, QImode,
+			 gen_rtx_REG (CCmode, FLAGS_REG),
+			 const0_rtx);
+  emit_insn (gen_rtx_SET (VOIDmode, res, cond));
+  emit_insn (gen_zero_extendqisi2 (operands[0], res));
+  DONE;
+})
+
 (define_expand "isinf<mode>2"
   [(use (match_operand:SI 0 "register_operand" ""))
-   (use (match_operand:X87MODEF 1 "register_operand" ""))]
+   (use (match_operand:MODEF 1 "nonimmediate_operand" ""))]
   "TARGET_USE_FANCY_MATH_387
    && TARGET_C99_FUNCTIONS
    && !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
@@ -18826,7 +18852,22 @@
   rtx scratch = gen_reg_rtx (HImode);
   rtx res = gen_reg_rtx (QImode);
 
+  /* Remove excess precision by forcing value through memory. */
+  if (REG_P (operands[1]))
+    {
+      int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL;
+      rtx temp = assign_386_stack_local (<MODE>mode, slot);
+
+      MEM_VOLATILE_P (temp) = 1;
+
+      emit_move_insn (temp, operands[1]);
+      emit_move_insn (operands[1], temp);
+    }
+  else
+    operands[1] = force_reg (<MODE>mode, operands[1]);
+
   emit_insn (gen_fxam<mode>2_i387 (scratch, operands[1]));
+
   emit_insn (gen_andqi_ext_0 (scratch, scratch, mask));
   emit_insn (gen_cmpqi_ext_3 (scratch, val));
   cond = gen_rtx_fmt_ee (EQ, QImode,
Index: testsuite/gcc.c-torture/execute/pr39228.c
===================================================================
--- testsuite/gcc.c-torture/execute/pr39228.c	(revision 0)
+++ testsuite/gcc.c-torture/execute/pr39228.c	(revision 0)
@@ -0,0 +1,36 @@
+extern void abort (void);
+
+static int __attribute__((always_inline)) testf (float b)
+{
+  float c = 1.01f * b;
+
+  return __builtin_isinff (c);
+}
+
+static int __attribute__((always_inline)) test (double b)
+{
+  double c = 1.01 * b;
+
+  return __builtin_isinf (c);
+}
+
+static int __attribute__((always_inline)) testl (long double b)
+{
+  long double c = 1.01L * b;
+
+  return __builtin_isinfl (c);
+}
+
+int main()
+{
+  int x;
+
+  x = testf (__FLT_MAX__);
+  x &= test (__DBL_MAX__);
+  x &= testl (__LDBL_MAX__);
+
+  if (x == 0)
+    abort ();
+
+  return 0;
+}


More information about the Gcc-patches mailing list