From 6b67572ed1a6f2fc43d07eead15e9eda973d339d Mon Sep 17 00:00:00 2001
From: Uros Bizjak <uros@gcc.gnu.org>
Date: Thu, 19 Feb 2009 11:51:04 +0100
Subject: [PATCH] re PR target/39228 (387 optimised __builtin_isinf() gives
 incorrect result)

	PR target/39228
	* config/i386/i386.md (isinfxf2): Split from isinf<mode>2.
	(UNSPEC_FXAM_MEM): New unspec.
	(fxam<mode>2_i387_with_temp): New insn and split pattern.
	(isinf<mode>2): Use MODEF mode iterator.  Force operand[1] through
	memory using fxam<mode>2_i387_with_temp to remove excess precision.

testsuite/ChangeLog:

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

From-SVN: r144293
---
 gcc/ChangeLog                                 | 34 +++++-----
 gcc/config/i386/i386.md                       | 63 ++++++++++++++++++-
 gcc/testsuite/ChangeLog                       |  5 ++
 gcc/testsuite/gcc.c-torture/execute/pr39228.c | 36 +++++++++++
 4 files changed, 122 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr39228.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4d9cf7d554bd..8ca48493c4db 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2009-02-19  Uros Bizjak  <ubizjak@gmail.com>
+
+	PR target/39228
+	* config/i386/i386.md (isinfxf2): Split from isinf<mode>2.
+	(UNSPEC_FXAM_MEM): New unspec.
+	(fxam<mode>2_i387_with_temp): New insn and split pattern.
+	(isinf<mode>2): Use MODEF mode iterator.  Force operand[1] through
+	memory using fxam<mode>2_i387_with_temp to remove excess precision.
+
 2009-02-19  Richard Guenther  <rguenther@suse.de>
 
 	PR tree-optimization/39207
@@ -5,8 +14,7 @@
 	* tree-ssa-structalias.c (storedanything_id, var_storedanything,
 	storedanything_tree): New.
 	(do_ds_constraint): Simplify ANYTHING shortcutting.  Update
-	the STOREDANYTHING solution if the lhs solution contains
-	ANYTHING.
+	the STOREDANYTHING solution if the lhs solution contains ANYTHING.
 	(build_succ_graph): Add edges from STOREDANYTHING to all
 	non-direct nodes.
 	(init_base_vars): Initialize STOREDANYTHING.
@@ -29,8 +37,7 @@
 2009-02-18  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR target/39224
-	* config/i386/i386.c (ix86_return_in_memory): Properly check
-	ABI.
+	* config/i386/i386.c (ix86_return_in_memory): Properly check ABI.
 
 2009-02-18  Jason Merrill  <jason@redhat.com>
 
@@ -197,8 +204,7 @@
 
 	PR target/39149
 	* config/i386/i386.c (override_options): Correct warning
-	messages for -malign-loops,  -malign-jumps and
-	-malign-functions.
+	messages for -malign-loops,  -malign-jumps and -malign-functions.
 
 2009-02-13  H.J. Lu  <hongjiu.lu@intel.com>
 
@@ -210,8 +216,7 @@
 
 	PR target/39162
 	* config/i386/i386.c (type_natural_mode): Add a new argument.
-	Return the original mode and warn ABI change if vector size
-	is 32byte.
+	Return the original mode and warn ABI change if vector size is 32byte.
 	(function_arg_advance): Updated.
 	(function_arg): Likewise.
 	(ix86_function_value): Likewise.
@@ -290,7 +295,7 @@
 	(TARGET_INIT_LIBFUNCS): Likewise.
 
 	* config/ia64/t-glibc (SHLINB_MAPFILES):
-	Add $(srcdir)/config/ia64/libgcc-glibc.ver,
+	Add $(srcdir)/config/ia64/libgcc-glibc.ver.
 
 2009-02-12  H.J. Lu  <hongjiu.lu@intel.com>
 
@@ -736,7 +741,7 @@
 	* c-decl.c (pop_scope): Set DECL_EXTERNAL for functions declared
 	inline but never defined.
 
-2009-01-30  Wolfgang Gellerich  <gellerich@de,ibm.com>
+2009-01-30  Wolfgang Gellerich  <gellerich@de.ibm.com>
 
 	* config/s390/s390.md (*insv<mode>_reg_extimm): Removed.
 	(*insv_h_di_reg_extimm): New insn.
@@ -875,7 +880,7 @@
 	* reload1.c (compute_use_by_pseudos, reload, count_pseudo,
 	count_spilled_pseudo, find_reg, alter_reg, delete_output_reload):
 	Remove flag_ira.
-	(finish_spills): Ditto.  Remove code for !flga_ira.
+	(finish_spills): Ditto.  Remove code for !flag_ira.
 	
 2009-01-29  Kenneth Zadeck  <zadeck@naturalbridge.com>
 
@@ -978,7 +983,8 @@
 2009-01-28  Jakub Jelinek  <jakub@redhat.com>
 
 	PR rtl-optimization/38740
-	* reorg.c (gate_handle_delay_slots): Avoid dbr scheduling if !optimize.
+	* reorg.c (gate_handle_delay_slots): Avoid dbr scheduling
+	if !optimize.
 	* config/mips/mips.c (mips_reorg): Likewise.
 
 2009-01-28  Richard Guenther  <rguenther@suse.de>
@@ -1242,8 +1248,8 @@
 2009-01-20  Joseph Myers  <joseph@codesourcery.com>
 
 	PR other/38758
-	* longlong.h: Update copyright years.  Use soft-fp license
-	notice.  Sync __clz_tab declaration with glibc.
+	* longlong.h: Update copyright years.  Use soft-fp license notice.
+	Sync __clz_tab declaration with glibc.
 
 2009-01-20  Steve Ellcey  <sje@cup.hp.com>
 
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index de669ba865e7..2fbf654a208d 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -146,6 +146,7 @@
    (UNSPEC_FPREM1_U		91)
 
    (UNSPEC_C2_FLAG		95)
+   (UNSPEC_FXAM_MEM		96)
 
    ; SSP patterns
    (UNSPEC_SP_SET		100)
@@ -18811,9 +18812,56 @@
    (set_attr "unit" "i387")
    (set_attr "mode" "<MODE>")])
 
+(define_insn_and_split "fxam<mode>2_i387_with_temp"
+  [(set (match_operand:HI 0 "register_operand" "")
+	(unspec:HI
+	  [(match_operand:MODEF 1 "memory_operand" "")]
+	  UNSPEC_FXAM_MEM))]
+  "TARGET_USE_FANCY_MATH_387
+   && !(reload_completed || reload_in_progress)"
+  "#"
+  "&& 1"
+  [(set (match_dup 2)(match_dup 1))
+   (set (match_dup 0)
+	(unspec:HI [(match_dup 2)] UNSPEC_FXAM))]
+{
+  operands[2] = gen_reg_rtx (<MODE>mode);
+
+  MEM_VOLATILE_P (operands[1]) = 1;
+}
+  [(set_attr "type" "multi")
+   (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 +18874,18 @@
   rtx scratch = gen_reg_rtx (HImode);
   rtx res = gen_reg_rtx (QImode);
 
-  emit_insn (gen_fxam<mode>2_i387 (scratch, operands[1]));
+  /* Remove excess precision by forcing value through memory. */
+  if (memory_operand (operands[1], VOIDmode))
+    emit_insn (gen_fxam<mode>2_i387_with_temp (scratch, operands[1]));
+  else
+    {
+      int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL;
+      rtx temp = assign_386_stack_local (<MODE>mode, slot);
+
+      emit_move_insn (temp, operands[1]);
+      emit_insn (gen_fxam<mode>2_i387_with_temp (scratch, temp));
+    }
+
   emit_insn (gen_andqi_ext_0 (scratch, scratch, mask));
   emit_insn (gen_cmpqi_ext_3 (scratch, val));
   cond = gen_rtx_fmt_ee (EQ, QImode,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 036d40215f90..a01fa1fd0189 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-02-19  Uros Bizjak  <ubizjak@gmail.com>
+
+	PR target/39228
+	* gcc.c-torture/execute/pr39228.c: New test.
+
 2009-02-19  Richard Guenther  <rguenther@suse.de>
 
 	PR tree-optimization/39074
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr39228.c b/gcc/testsuite/gcc.c-torture/execute/pr39228.c
new file mode 100644
index 000000000000..06d8efd1a5bb
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr39228.c
@@ -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()
+{
+  if (testf (__FLT_MAX__) < 1)
+    abort ();
+
+  if (test (__DBL_MAX__) < 1)
+    abort ();
+
+  if (testl (__LDBL_MAX__) < 1)
+    abort ();
+
+  return 0;
+}
-- 
GitLab