diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 45b181943474d953ecaea270d1b1ca4c137afa6f..4cdb2cfadf74ce068533fb280fc8ec52bc53c049 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,44 @@
+2003-10-04  Zack Weinberg  <zack@codesourcery.com>
+
+	* libfuncs.h
+	(LTI_eqhf2, LTI_nehf2, LTI_gthf2, LTI_gehf2, LTI_lthf2)
+	(LTI_lehf2, LTI_unordhf2, LTI_eqsf2, LTI_nesf2, LTI_gtsf2)
+	(LTI_gesf2, LTI_ltsf2, LTI_lesf2, LTI_unordsf2, LTI_eqdf2)
+	(LTI_nedf2, LTI_gtdf2, LTI_gedf2, LTI_ltdf2, LTI_ledf2)
+	(LTI_unorddf2, LTI_eqxf2, LTI_nexf2, LTI_gtxf2, LTI_gexf2)
+	(LTI_ltxf2, LTI_lexf2, LTI_unordxf2, LTI_eqtf2, LTI_netf2)
+	(LTI_gttf2, LTI_getf2, LTI_lttf2, LTI_letf2, LTI_unordtf2)
+	(eqhf2_libfunc, nehf2_libfunc, gthf2_libfunc, gehf2_libfunc)
+	(lthf2_libfunc, lehf2_libfunc, unordhf2_libfunc, eqsf2_libfunc)
+	(nesf2_libfunc, gtsf2_libfunc, gesf2_libfunc, ltsf2_libfunc)
+	(lesf2_libfunc, unordsf2_libfunc eqdf2_libfunc, nedf2_libfunc)
+	(gtdf2_libfunc, gedf2_libfunc, ltdf2_libfunc, ledf2_libfunc)
+	(unorddf2_libfunc eqxf2_libfunc, nexf2_libfunc, gtxf2_libfunc)
+	(gexf2_libfunc, ltxf2_libfunc, lexf2_libfunc, unordxf2_libfunc
+	(eqtf2_libfunc, netf2_libfunc, gttf2_libfunc, getf2_libfunc)
+	(lttf2_libfunc, letf2_libfunc, unordtf2_libfunc):
+	Delete.
+	* optabs.h (OTI_eq, OTI_ne, OTI_gt, OTI_ge, OTI_lt, OTI_le)
+	(OTI_unord, eq_optab, ne_optab, gt_optab, ge_optab, lt_optab)
+	(le_optab, unord_optab): New.
+
+	* optabs.c (prepare_float_lib_cmp): Rewrite.  Get the libfuncs
+	from the code_to_optab table, not a giant switch; use
+	swap_condition; do widening only if a comparison function that
+	we can call exists in a wider mode, not if a cmp_optab insn or
+	libfunc exists in a wider mode; call protect_from_queue
+	exactly once on each operand.
+	(init_optabs): Initialize the new optabs, not the deleted libfuncs.
+
+	* config/gofast.h, config/ia64/ia64.c, config/mips/mips.c
+	* config/pa/pa.c, config/rs6000/rs6000.c, config/sparc/sparc.c:
+	Set floating point comparison libfuncs using set_optab_libfunc
+	on the appropriate optab.
+
+	* config/ia64/ia64.c (ia64_hpux_init_libfuncs): Fix typo.
+	* config/rs6000/rs6000.c (rs6000_init_libfuncs): Correct ABI
+	selector conditionals.
+
 2003-10-04  Stephane Carrez  <stcarrez@nerim.fr>
 
 	* config/m68hc11/t-m68hc11-gas (MULTILIB_MATCHES): m68hcs12 is
@@ -33,9 +74,9 @@
 
 2003-10-03  Robert Bowdidge <bowdidge@apple.com>
 
-        * ggc-page.c (ggc_pch_write_object): Replace fseek() with fwrite() in 
-        PCH generation, avoiding too-frequent flushes when writing to NFS 
-        file system.
+	* ggc-page.c (ggc_pch_write_object): Replace fseek() with fwrite() in
+	PCH generation, avoiding too-frequent flushes when writing to NFS
+	file system.
 
 2003-10-03  Ziemowit Laski  <zlaski@apple.com>
 
@@ -82,7 +123,7 @@
 	* config/mips/mips.md ("type" attr): Add new "prefetchx" value,
 	update comments.
 	(prefetch_indexed_di, prefetch_indexed_si): New insns.
-	
+
 2003-10-03  Jeff Sturm  <jsturm@one-point.com>
 	    Roger Sayle  <roger@eyesopen.com>
 
@@ -123,7 +164,7 @@
 	operand's constraint letter to 'I'.
 	(prefetch_di_address): Likewise.
 	(prefetch_si, prefetch_di): Set third operand to const0_rtx.
-	
+
 2003-10-02  Zack Weinberg  <zack@codesourcery.com>
 
 	* system.h: Poison macros obsoleted by earlier patch.
diff --git a/gcc/config/gofast.h b/gcc/config/gofast.h
index 74a22c779b882d66a6591437bd0729485a6a25c6..3b3efb97b49d902e2fdea6fb6e7ab0bf72e4b3b1 100644
--- a/gcc/config/gofast.h
+++ b/gcc/config/gofast.h
@@ -52,19 +52,19 @@ gofast_maybe_init_libfuncs (void)
      libfuncs, we use our own functions, since GOFAST doesn't supply
      them.  */
 
-  eqsf2_libfunc = init_one_libfunc ("fpcmp");
-  nesf2_libfunc = init_one_libfunc ("fpcmp");
-  gtsf2_libfunc = NULL_RTX;
-  gesf2_libfunc = NULL_RTX;
-  ltsf2_libfunc = init_one_libfunc ("fpcmp");
-  lesf2_libfunc = init_one_libfunc ("fpcmp");
+  set_optab_libfunc (eq_optab, SFmode, "fpcmp");
+  set_optab_libfunc (ne_optab, SFmode, "fpcmp");
+  set_optab_libfunc (gt_optab, SFmode, 0);
+  set_optab_libfunc (ge_optab, SFmode, 0);
+  set_optab_libfunc (lt_optab, SFmode, "fpcmp");
+  set_optab_libfunc (le_optab, SFmode, "fpcmp");
 
-  eqdf2_libfunc = init_one_libfunc ("dpcmp");
-  nedf2_libfunc = init_one_libfunc ("dpcmp");
-  gtdf2_libfunc = NULL_RTX;
-  gedf2_libfunc = NULL_RTX;
-  ltdf2_libfunc = init_one_libfunc ("dpcmp");
-  ledf2_libfunc = init_one_libfunc ("dpcmp");
+  set_optab_libfunc (eq_optab, DFmode, "dpcmp");
+  set_optab_libfunc (ne_optab, DFmode, "dpcmp");
+  set_optab_libfunc (gt_optab, DFmode, 0);
+  set_optab_libfunc (ge_optab, DFmode, 0);
+  set_optab_libfunc (lt_optab, DFmode, "dpcmp");
+  set_optab_libfunc (le_optab, DFmode, "dpcmp");
 
   extendsfdf2_libfunc = init_one_libfunc ("fptodp");
   truncdfsf2_libfunc = init_one_libfunc ("dptofp");
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 1633a585921430c078108c3e909f1e3fea027414..b10b9e9344c04e93afb8d5663ab5a5afefee9923 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -8313,13 +8313,20 @@ ia64_hpux_init_libfuncs (void)
 {
   set_optab_libfunc (add_optab, TFmode, "_U_Qfadd");
   set_optab_libfunc (sub_optab, TFmode, "_U_Qfsub");
-  set_optab_libfunc (smul_optab, TFmode, "_Q_Qfmpy");
+  set_optab_libfunc (smul_optab, TFmode, "_U_Qfmpy");
   set_optab_libfunc (sdiv_optab, TFmode, "_U_Qfdiv");
   set_optab_libfunc (smin_optab, TFmode, "_U_Qfmin");
   set_optab_libfunc (smax_optab, TFmode, "_U_Qfmax");
   set_optab_libfunc (abs_optab, TFmode, "_U_Qfabs");
   set_optab_libfunc (neg_optab, TFmode, "_U_Qfneg");
 
+  set_optab_libfunc (eq_optab, TFmode, "_U_Qfeq");
+  set_optab_libfunc (ne_optab, TFmode, "_U_Qfne");
+  set_optab_libfunc (gt_optab, TFmode, "_U_Qfgt");
+  set_optab_libfunc (ge_optab, TFmode, "_U_Qfge");
+  set_optab_libfunc (lt_optab, TFmode, "_U_Qflt");
+  set_optab_libfunc (le_optab, TFmode, "_U_Qfle");
+
   extendsftf2_libfunc = init_one_libfunc ("_U_Qfcnvff_sgl_to_quad");
   extenddftf2_libfunc = init_one_libfunc ("_U_Qfcnvff_dbl_to_quad");
   trunctfsf2_libfunc = init_one_libfunc ("_U_Qfcnvff_quad_to_sgl");
@@ -8330,12 +8337,6 @@ ia64_hpux_init_libfuncs (void)
   fixtfdi_libfunc = init_one_libfunc ("_U_Qfcnvfxt_quad_to_dbl");
   fixunstfsi_libfunc = init_one_libfunc ("_U_Qfcnvfxut_quad_to_sgl");
   fixunstfdi_libfunc = init_one_libfunc ("_U_Qfcnvfxut_quad_to_dbl");
-  eqtf2_libfunc = init_one_libfunc ("_U_Qfeq");
-  netf2_libfunc = init_one_libfunc ("_U_Qfne");
-  gttf2_libfunc = init_one_libfunc ("_U_Qfgt");
-  getf2_libfunc = init_one_libfunc ("_U_Qfge");
-  lttf2_libfunc = init_one_libfunc ("_U_Qflt");
-  letf2_libfunc = init_one_libfunc ("_U_Qfle");
 }
 
 /* Switch to the section to which we should output X.  The only thing
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index ae27af1cb705794b78924e9e73d88edc223e7fa4..543b112cb7e720d4f69d3db31aaf21980c23a953 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -9015,12 +9015,12 @@ mips_init_libfuncs (void)
       set_optab_libfunc (smul_optab, SFmode, "__mips16_mulsf3");
       set_optab_libfunc (sdiv_optab, SFmode, "__mips16_divsf3");
 
-      eqsf2_libfunc     = init_one_libfunc ("__mips16_eqsf2");
-      nesf2_libfunc     = init_one_libfunc ("__mips16_nesf2");
-      gtsf2_libfunc     = init_one_libfunc ("__mips16_gtsf2");
-      gesf2_libfunc     = init_one_libfunc ("__mips16_gesf2");
-      ltsf2_libfunc     = init_one_libfunc ("__mips16_ltsf2");
-      lesf2_libfunc     = init_one_libfunc ("__mips16_lesf2");
+      set_optab_libfunc (eq_optab, SFmode, "__mips16_eqsf2");
+      set_optab_libfunc (ne_optab, SFmode, "__mips16_nesf2");
+      set_optab_libfunc (gt_optab, SFmode, "__mips16_gtsf2");
+      set_optab_libfunc (ge_optab, SFmode, "__mips16_gesf2");
+      set_optab_libfunc (lt_optab, SFmode, "__mips16_ltsf2");
+      set_optab_libfunc (le_optab, SFmode, "__mips16_lesf2");
 
       floatsisf_libfunc = init_one_libfunc ("__mips16_floatsisf");
       fixsfsi_libfunc   = init_one_libfunc ("__mips16_fixsfsi");
@@ -9032,12 +9032,12 @@ mips_init_libfuncs (void)
 	  set_optab_libfunc (smul_optab, DFmode, "__mips16_muldf3");
 	  set_optab_libfunc (sdiv_optab, DFmode, "__mips16_divdf3");
 
-	  eqdf2_libfunc       = init_one_libfunc ("__mips16_eqdf2");
-	  nedf2_libfunc       = init_one_libfunc ("__mips16_nedf2");
-	  gtdf2_libfunc       = init_one_libfunc ("__mips16_gtdf2");
-	  gedf2_libfunc       = init_one_libfunc ("__mips16_gedf2");
-	  ltdf2_libfunc       = init_one_libfunc ("__mips16_ltdf2");
-	  ledf2_libfunc       = init_one_libfunc ("__mips16_ledf2");
+	  set_optab_libfunc (eq_optab, DFmode, "__mips16_eqdf2");
+	  set_optab_libfunc (ne_optab, DFmode, "__mips16_nedf2");
+	  set_optab_libfunc (gt_optab, DFmode, "__mips16_gtdf2");
+	  set_optab_libfunc (ge_optab, DFmode, "__mips16_gedf2");
+	  set_optab_libfunc (lt_optab, DFmode, "__mips16_ltdf2");
+	  set_optab_libfunc (le_optab, DFmode, "__mips16_ledf2");
 
 	  floatsidf_libfunc   = init_one_libfunc ("__mips16_floatsidf");
 	  fixdfsi_libfunc     = init_one_libfunc ("__mips16_fixdfsi");
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 6134b0b3764b9b2f74afc7898342458516530210..a5b9a4dc22453bfcda976ba6b738d13f98a58185 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -4973,12 +4973,12 @@ pa_hpux_init_libfuncs (void)
   set_optab_libfunc (abs_optab, TFmode, "_U_Qfabs");
   set_optab_libfunc (neg_optab, TFmode, "_U_Qfneg");
 
-  eqtf2_libfunc = init_one_libfunc ("_U_Qfeq");
-  netf2_libfunc = init_one_libfunc ("_U_Qfne");
-  gttf2_libfunc = init_one_libfunc ("_U_Qfgt");
-  getf2_libfunc = init_one_libfunc ("_U_Qfge");
-  lttf2_libfunc = init_one_libfunc ("_U_Qflt");
-  letf2_libfunc = init_one_libfunc ("_U_Qfle");
+  set_optab_libfunc (eq_optab, TFmode, "_U_Qfeq");
+  set_optab_libfunc (ne_optab, TFmode, "_U_Qfne");
+  set_optab_libfunc (gt_optab, TFmode, "_U_Qfgt");
+  set_optab_libfunc (ge_optab, TFmode, "_U_Qfge");
+  set_optab_libfunc (lt_optab, TFmode, "_U_Qflt");
+  set_optab_libfunc (le_optab, TFmode, "_U_Qfle");
 
   extendsftf2_libfunc = init_one_libfunc ("_U_Qfcnvff_sgl_to_quad");
   extenddftf2_libfunc = init_one_libfunc ("_U_Qfcnvff_dbl_to_quad");
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 0a4ebe1f5f6702de20afc472f7777090940508f7..1f037d9f91065f5cc143811ccfa20634623c066a 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -6779,25 +6779,24 @@ rs6000_init_libfuncs (void)
   if (!TARGET_HARD_FLOAT)
     return;
 
-  if (TARGET_AIX)
+  if (DEFAULT_ABI != ABI_V4)
     {
-      /* Optabs entries for the int->float routines and quad FP
-	 operations using the standard AIX names.  */
-      if (! TARGET_POWER2 && ! TARGET_POWERPC)
+      if (TARGET_XCOFF && ! TARGET_POWER2 && ! TARGET_POWERPC)
 	{
+	  /* AIX library routines for float->int conversion.  */
 	  fixdfsi_libfunc = init_one_libfunc ("__itrunc");
 	  fixunsdfsi_libfunc = init_one_libfunc ("__uitrunc");
 	}
 
+      /* Standard AIX/Darwin/64-bit SVR4 quad floating point routines.  */
       set_optab_libfunc (add_optab, TFmode, "_xlqadd");
       set_optab_libfunc (sub_optab, TFmode, "_xlqsub");
       set_optab_libfunc (smul_optab, TFmode, "_xlqmul");
       set_optab_libfunc (sdiv_optab, TFmode, "_xlqdiv");
     }
-  else if (TARGET_ELF)
+  else
     {
-      /* Define library calls for quad FP operations.  These are all
-	 part of the PowerPC 32bit ABI.  */
+      /* 32-bit SVR4 quad floating point routines.  */
 
       set_optab_libfunc (add_optab, TFmode, "_q_add");
       set_optab_libfunc (sub_optab, TFmode, "_q_sub");
@@ -6807,12 +6806,13 @@ rs6000_init_libfuncs (void)
       if (TARGET_PPC_GPOPT || TARGET_POWER2)
 	set_optab_libfunc (sqrt_optab, TFmode, "_q_sqrt");
 
-      eqtf2_libfunc = init_one_libfunc ("_q_feq");
-      netf2_libfunc = init_one_libfunc ("_q_fne");
-      gttf2_libfunc = init_one_libfunc ("_q_fgt");
-      getf2_libfunc = init_one_libfunc ("_q_fge");
-      lttf2_libfunc = init_one_libfunc ("_q_flt");
-      letf2_libfunc = init_one_libfunc ("_q_fle");
+      set_optab_libfunc (eq_optab, TFmode, "_q_feq");
+      set_optab_libfunc (ne_optab, TFmode, "_q_fne");
+      set_optab_libfunc (gt_optab, TFmode, "_q_fgt");
+      set_optab_libfunc (ge_optab, TFmode, "_q_fge");
+      set_optab_libfunc (lt_optab, TFmode, "_q_flt");
+      set_optab_libfunc (le_optab, TFmode, "_q_fle");
+
       trunctfsf2_libfunc = init_one_libfunc ("_q_qtos");
       trunctfdf2_libfunc = init_one_libfunc ("_q_qtod");
       extendsftf2_libfunc = init_one_libfunc ("_q_stoq");
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 28275b724d996fc27f1c5bfe6bc748fac794428b..adea22f4fd021ac243440893043c50ab3d0d096b 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -8424,12 +8424,12 @@ sparc_init_libfuncs (void)
       if (TARGET_FPU)
 	set_optab_libfunc (sqrt_optab, TFmode, "_Q_sqrt");
 
-      eqtf2_libfunc = init_one_libfunc ("_Q_feq");
-      netf2_libfunc = init_one_libfunc ("_Q_fne");
-      gttf2_libfunc = init_one_libfunc ("_Q_fgt");
-      getf2_libfunc = init_one_libfunc ("_Q_fge");
-      lttf2_libfunc = init_one_libfunc ("_Q_flt");
-      letf2_libfunc = init_one_libfunc ("_Q_fle");
+      set_optab_libfunc (eq_optab, TFmode, "_Q_feq");
+      set_optab_libfunc (ne_optab, TFmode, "_Q_fne");
+      set_optab_libfunc (gt_optab, TFmode, "_Q_fgt");
+      set_optab_libfunc (ge_optab, TFmode, "_Q_fge");
+      set_optab_libfunc (lt_optab, TFmode, "_Q_flt");
+      set_optab_libfunc (le_optab, TFmode, "_Q_fle");
 
       trunctfsf2_libfunc = init_one_libfunc ("_Q_qtos");
       trunctfdf2_libfunc = init_one_libfunc ("_Q_qtod");
diff --git a/gcc/libfuncs.h b/gcc/libfuncs.h
index 79b7d4249b2353b31f79bb1b19da1a501183e701..d919ddf8679503a27714b94b3ad03682ad3d712d 100644
--- a/gcc/libfuncs.h
+++ b/gcc/libfuncs.h
@@ -53,46 +53,6 @@ enum libfunc_index
   LTI_unwind_sjlj_register,
   LTI_unwind_sjlj_unregister,
 
-  LTI_eqhf2,
-  LTI_nehf2,
-  LTI_gthf2,
-  LTI_gehf2,
-  LTI_lthf2,
-  LTI_lehf2,
-  LTI_unordhf2,
-
-  LTI_eqsf2,
-  LTI_nesf2,
-  LTI_gtsf2,
-  LTI_gesf2,
-  LTI_ltsf2,
-  LTI_lesf2,
-  LTI_unordsf2,
-
-  LTI_eqdf2,
-  LTI_nedf2,
-  LTI_gtdf2,
-  LTI_gedf2,
-  LTI_ltdf2,
-  LTI_ledf2,
-  LTI_unorddf2,
-
-  LTI_eqxf2,
-  LTI_nexf2,
-  LTI_gtxf2,
-  LTI_gexf2,
-  LTI_ltxf2,
-  LTI_lexf2,
-  LTI_unordxf2,
-
-  LTI_eqtf2,
-  LTI_netf2,
-  LTI_gttf2,
-  LTI_getf2,
-  LTI_lttf2,
-  LTI_letf2,
-  LTI_unordtf2,
-
   LTI_floatsisf,
   LTI_floatdisf,
   LTI_floattisf,
@@ -185,46 +145,6 @@ extern GTY(()) rtx libfunc_table[LTI_MAX];
 #define unwind_sjlj_unregister_libfunc \
   (libfunc_table[LTI_unwind_sjlj_unregister])
 
-#define eqhf2_libfunc	(libfunc_table[LTI_eqhf2])
-#define nehf2_libfunc	(libfunc_table[LTI_nehf2])
-#define gthf2_libfunc	(libfunc_table[LTI_gthf2])
-#define gehf2_libfunc	(libfunc_table[LTI_gehf2])
-#define lthf2_libfunc	(libfunc_table[LTI_lthf2])
-#define lehf2_libfunc	(libfunc_table[LTI_lehf2])
-#define unordhf2_libfunc	(libfunc_table[LTI_unordhf2])
-
-#define eqsf2_libfunc	(libfunc_table[LTI_eqsf2])
-#define nesf2_libfunc	(libfunc_table[LTI_nesf2])
-#define gtsf2_libfunc	(libfunc_table[LTI_gtsf2])
-#define gesf2_libfunc	(libfunc_table[LTI_gesf2])
-#define ltsf2_libfunc	(libfunc_table[LTI_ltsf2])
-#define lesf2_libfunc	(libfunc_table[LTI_lesf2])
-#define unordsf2_libfunc	(libfunc_table[LTI_unordsf2])
-
-#define eqdf2_libfunc	(libfunc_table[LTI_eqdf2])
-#define nedf2_libfunc	(libfunc_table[LTI_nedf2])
-#define gtdf2_libfunc	(libfunc_table[LTI_gtdf2])
-#define gedf2_libfunc	(libfunc_table[LTI_gedf2])
-#define ltdf2_libfunc	(libfunc_table[LTI_ltdf2])
-#define ledf2_libfunc	(libfunc_table[LTI_ledf2])
-#define unorddf2_libfunc	(libfunc_table[LTI_unorddf2])
-
-#define eqxf2_libfunc	(libfunc_table[LTI_eqxf2])
-#define nexf2_libfunc	(libfunc_table[LTI_nexf2])
-#define gtxf2_libfunc	(libfunc_table[LTI_gtxf2])
-#define gexf2_libfunc	(libfunc_table[LTI_gexf2])
-#define ltxf2_libfunc	(libfunc_table[LTI_ltxf2])
-#define lexf2_libfunc	(libfunc_table[LTI_lexf2])
-#define unordxf2_libfunc	(libfunc_table[LTI_unordxf2])
-
-#define eqtf2_libfunc	(libfunc_table[LTI_eqtf2])
-#define netf2_libfunc	(libfunc_table[LTI_netf2])
-#define gttf2_libfunc	(libfunc_table[LTI_gttf2])
-#define getf2_libfunc	(libfunc_table[LTI_getf2])
-#define lttf2_libfunc	(libfunc_table[LTI_lttf2])
-#define letf2_libfunc	(libfunc_table[LTI_letf2])
-#define unordtf2_libfunc	(libfunc_table[LTI_unordtf2])
-
 #define floatsisf_libfunc	(libfunc_table[LTI_floatsisf])
 #define floatdisf_libfunc	(libfunc_table[LTI_floatdisf])
 #define floattisf_libfunc	(libfunc_table[LTI_floattisf])
diff --git a/gcc/optabs.c b/gcc/optabs.c
index bd1b42a68eec9f2f562f73db4c939c472177a5ea..bd9306d4df130f41fe8b29ff29a2a54c80dfd386 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -3872,336 +3872,47 @@ prepare_float_lib_cmp (rtx *px, rtx *py, enum rtx_code *pcomparison,
 		       enum machine_mode *pmode, int *punsignedp)
 {
   enum rtx_code comparison = *pcomparison;
-  rtx tmp;
-  rtx x = *px = protect_from_queue (*px, 0);
-  rtx y = *py = protect_from_queue (*py, 0);
-  enum machine_mode mode = GET_MODE (x);
+  enum rtx_code swapped = swap_condition (comparison);
+  rtx x = protect_from_queue (*px, 0);
+  rtx y = protect_from_queue (*py, 0);
+  enum machine_mode orig_mode = GET_MODE (x);
+  enum machine_mode mode;
   rtx libfunc = 0;
   rtx result;
 
-  if (mode == HFmode)
-    switch (comparison)
-      {
-      case EQ:
-	libfunc = eqhf2_libfunc;
-	break;
-
-      case NE:
-	libfunc = nehf2_libfunc;
-	break;
-
-      case GT:
-	libfunc = gthf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = LT;
-	    libfunc = lthf2_libfunc;
-	  }
-	break;
-
-      case GE:
-	libfunc = gehf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = LE;
-	    libfunc = lehf2_libfunc;
-	  }
-	break;
-
-      case LT:
-	libfunc = lthf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = GT;
-	    libfunc = gthf2_libfunc;
-	  }
-	break;
-
-      case LE:
-	libfunc = lehf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = GE;
-	    libfunc = gehf2_libfunc;
-	  }
-	break;
-
-      case UNORDERED:
-	libfunc = unordhf2_libfunc;
-	break;
-
-      default:
-	break;
-      }
-  else if (mode == SFmode)
-    switch (comparison)
-      {
-      case EQ:
-	libfunc = eqsf2_libfunc;
-	break;
-
-      case NE:
-	libfunc = nesf2_libfunc;
-	break;
-
-      case GT:
-	libfunc = gtsf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = LT;
-	    libfunc = ltsf2_libfunc;
-	  }
-	break;
-
-      case GE:
-	libfunc = gesf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = LE;
-	    libfunc = lesf2_libfunc;
-	  }
-	break;
-
-      case LT:
-	libfunc = ltsf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = GT;
-	    libfunc = gtsf2_libfunc;
-	  }
-	break;
-
-      case LE:
-	libfunc = lesf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = GE;
-	    libfunc = gesf2_libfunc;
-	  }
-	break;
-
-      case UNORDERED:
-	libfunc = unordsf2_libfunc;
-	break;
-
-      default:
-	break;
-      }
-  else if (mode == DFmode)
-    switch (comparison)
-      {
-      case EQ:
-	libfunc = eqdf2_libfunc;
-	break;
-
-      case NE:
-	libfunc = nedf2_libfunc;
-	break;
-
-      case GT:
-	libfunc = gtdf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = LT;
-	    libfunc = ltdf2_libfunc;
-	  }
-	break;
-
-      case GE:
-	libfunc = gedf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = LE;
-	    libfunc = ledf2_libfunc;
-	  }
-	break;
-
-      case LT:
-	libfunc = ltdf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = GT;
-	    libfunc = gtdf2_libfunc;
-	  }
-	break;
-
-      case LE:
-	libfunc = ledf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = GE;
-	    libfunc = gedf2_libfunc;
-	  }
-	break;
-
-      case UNORDERED:
-	libfunc = unorddf2_libfunc;
-	break;
-
-      default:
-	break;
-      }
-  else if (mode == XFmode)
-    switch (comparison)
-      {
-      case EQ:
-	libfunc = eqxf2_libfunc;
-	break;
-
-      case NE:
-	libfunc = nexf2_libfunc;
-	break;
-
-      case GT:
-	libfunc = gtxf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = LT;
-	    libfunc = ltxf2_libfunc;
-	  }
-	break;
-
-      case GE:
-	libfunc = gexf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = LE;
-	    libfunc = lexf2_libfunc;
-	  }
-	break;
-
-      case LT:
-	libfunc = ltxf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = GT;
-	    libfunc = gtxf2_libfunc;
-	  }
-	break;
-
-      case LE:
-	libfunc = lexf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = GE;
-	    libfunc = gexf2_libfunc;
-	  }
-	break;
-
-      case UNORDERED:
-	libfunc = unordxf2_libfunc;
-	break;
-
-      default:
-	break;
-      }
-  else if (mode == TFmode)
-    switch (comparison)
-      {
-      case EQ:
-	libfunc = eqtf2_libfunc;
-	break;
-
-      case NE:
-	libfunc = netf2_libfunc;
-	break;
-
-      case GT:
-	libfunc = gttf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = LT;
-	    libfunc = lttf2_libfunc;
-	  }
-	break;
-
-      case GE:
-	libfunc = getf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = LE;
-	    libfunc = letf2_libfunc;
-	  }
-	break;
-
-      case LT:
-	libfunc = lttf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = GT;
-	    libfunc = gttf2_libfunc;
-	  }
-	break;
-
-      case LE:
-	libfunc = letf2_libfunc;
-	if (libfunc == NULL_RTX)
-	  {
-	    tmp = x; x = y; y = tmp;
-	    *pcomparison = GE;
-	    libfunc = getf2_libfunc;
-	  }
-	break;
-
-      case UNORDERED:
-	libfunc = unordtf2_libfunc;
-	break;
-
-      default:
-	break;
-      }
-  else
+  for (mode = orig_mode; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
     {
-      enum machine_mode wider_mode;
+      if ((libfunc = code_to_optab[comparison]->handlers[mode].libfunc))
+	break;
 
-      for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
-	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+      if ((libfunc = code_to_optab[swapped]->handlers[mode].libfunc))
 	{
-	  if ((cmp_optab->handlers[(int) wider_mode].insn_code
-	       != CODE_FOR_nothing)
-	      || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
-	    {
-	      x = protect_from_queue (x, 0);
-	      y = protect_from_queue (y, 0);
-	      *px = convert_to_mode (wider_mode, x, 0);
-	      *py = convert_to_mode (wider_mode, y, 0);
-	      prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
-	      return;
-	    }
+	  rtx tmp;
+	  tmp = x; x = y; y = tmp;
+	  comparison = swapped;
+	  break;
 	}
-      abort ();
     }
 
-  if (libfunc == 0)
+  if (mode == VOIDmode)
     abort ();
 
+  if (mode != orig_mode)
+    {
+      x = convert_to_mode (mode, x, 0);
+      y = convert_to_mode (mode, y, 0);
+    }
+
+  if (comparison == UNORDERED
+      || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
+    comparison = NE;
+
   result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST_MAKE_BLOCK,
 				    word_mode, 2, x, mode, y, mode);
   *px = result;
   *py = const0_rtx;
   *pmode = word_mode;
-  if (comparison == UNORDERED
-      || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
-    *pcomparison = NE;
+  *pcomparison = comparison;
   *punsignedp = 0;
 }
 
@@ -5430,6 +5141,15 @@ init_optabs (void)
 
   ucmp_optab = init_optab (UNKNOWN);
   tst_optab = init_optab (UNKNOWN);
+
+  eq_optab = init_optab (EQ);
+  ne_optab = init_optab (NE);
+  gt_optab = init_optab (GT);
+  ge_optab = init_optab (GE);
+  lt_optab = init_optab (LT);
+  le_optab = init_optab (LE);
+  unord_optab = init_optab (UNORDERED);
+
   neg_optab = init_optab (NEG);
   negv_optab = init_optabv (NEG);
   abs_optab = init_optab (ABS);
@@ -5530,6 +5250,15 @@ init_optabs (void)
   init_integral_libfuncs (ucmp_optab, "ucmp", '2');
   init_floating_libfuncs (cmp_optab, "cmp", '2');
 
+  /* EQ etc are floating point only.  */
+  init_floating_libfuncs (eq_optab, "eq", '2');
+  init_floating_libfuncs (ne_optab, "ne", '2');
+  init_floating_libfuncs (gt_optab, "gt", '2');
+  init_floating_libfuncs (ge_optab, "ge", '2');
+  init_floating_libfuncs (lt_optab, "lt", '2');
+  init_floating_libfuncs (le_optab, "le", '2');
+  init_floating_libfuncs (unord_optab, "unord", '2');
+
   /* Use cabs for DC complex abs, since systems generally have cabs.
      Don't define any libcall for SCmode, so that cabs will be used.  */
   abs_optab->handlers[(int) DCmode].libfunc
@@ -5575,46 +5304,6 @@ init_optabs (void)
   unwind_sjlj_unregister_libfunc
     = init_one_libfunc ("_Unwind_SjLj_Unregister");
 
-  eqhf2_libfunc = init_one_libfunc ("__eqhf2");
-  nehf2_libfunc = init_one_libfunc ("__nehf2");
-  gthf2_libfunc = init_one_libfunc ("__gthf2");
-  gehf2_libfunc = init_one_libfunc ("__gehf2");
-  lthf2_libfunc = init_one_libfunc ("__lthf2");
-  lehf2_libfunc = init_one_libfunc ("__lehf2");
-  unordhf2_libfunc = init_one_libfunc ("__unordhf2");
-
-  eqsf2_libfunc = init_one_libfunc ("__eqsf2");
-  nesf2_libfunc = init_one_libfunc ("__nesf2");
-  gtsf2_libfunc = init_one_libfunc ("__gtsf2");
-  gesf2_libfunc = init_one_libfunc ("__gesf2");
-  ltsf2_libfunc = init_one_libfunc ("__ltsf2");
-  lesf2_libfunc = init_one_libfunc ("__lesf2");
-  unordsf2_libfunc = init_one_libfunc ("__unordsf2");
-
-  eqdf2_libfunc = init_one_libfunc ("__eqdf2");
-  nedf2_libfunc = init_one_libfunc ("__nedf2");
-  gtdf2_libfunc = init_one_libfunc ("__gtdf2");
-  gedf2_libfunc = init_one_libfunc ("__gedf2");
-  ltdf2_libfunc = init_one_libfunc ("__ltdf2");
-  ledf2_libfunc = init_one_libfunc ("__ledf2");
-  unorddf2_libfunc = init_one_libfunc ("__unorddf2");
-
-  eqxf2_libfunc = init_one_libfunc ("__eqxf2");
-  nexf2_libfunc = init_one_libfunc ("__nexf2");
-  gtxf2_libfunc = init_one_libfunc ("__gtxf2");
-  gexf2_libfunc = init_one_libfunc ("__gexf2");
-  ltxf2_libfunc = init_one_libfunc ("__ltxf2");
-  lexf2_libfunc = init_one_libfunc ("__lexf2");
-  unordxf2_libfunc = init_one_libfunc ("__unordxf2");
-
-  eqtf2_libfunc = init_one_libfunc ("__eqtf2");
-  netf2_libfunc = init_one_libfunc ("__netf2");
-  gttf2_libfunc = init_one_libfunc ("__gttf2");
-  getf2_libfunc = init_one_libfunc ("__getf2");
-  lttf2_libfunc = init_one_libfunc ("__lttf2");
-  letf2_libfunc = init_one_libfunc ("__letf2");
-  unordtf2_libfunc = init_one_libfunc ("__unordtf2");
-
   floatsisf_libfunc = init_one_libfunc ("__floatsisf");
   floatdisf_libfunc = init_one_libfunc ("__floatdisf");
   floattisf_libfunc = init_one_libfunc ("__floattisf");
diff --git a/gcc/optabs.h b/gcc/optabs.h
index dc515b345298e24c71c869e20840122fa94feecb..02c0af5d33ab0c6963061a657c524ebaec9b1b2c 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -161,6 +161,15 @@ enum optab_index
   /* tst insn; compare one operand against 0 */
   OTI_tst,
 
+  /* Floating point comparison optabs - used primarily for libfuncs */
+  OTI_eq,
+  OTI_ne,
+  OTI_gt,
+  OTI_ge,
+  OTI_lt,
+  OTI_le,
+  OTI_unord,
+
   /* String length */
   OTI_strlen,
 
@@ -243,6 +252,14 @@ extern GTY(()) optab optab_table[OTI_MAX];
 #define ucmp_optab (optab_table[OTI_ucmp])
 #define tst_optab (optab_table[OTI_tst])
 
+#define eq_optab (optab_table[OTI_eq])
+#define ne_optab (optab_table[OTI_ne])
+#define gt_optab (optab_table[OTI_gt])
+#define ge_optab (optab_table[OTI_ge])
+#define lt_optab (optab_table[OTI_lt])
+#define le_optab (optab_table[OTI_le])
+#define unord_optab (optab_table[OTI_unord])
+
 #define strlen_optab (optab_table[OTI_strlen])
 
 #define cbranch_optab (optab_table[OTI_cbranch])