David tells me that the patch to enable float128 built-in functions to work
with the -mabi=ieeelongdouble option broke AIX because on AIX, the float128
insns are disabled, and they all become CODE_FOR_nothing.  The switch statement
that was added in rs6000.c to map KFmode built-in functions to TFmode breaks
under AIX.

I changed the code to have a separate table, and the first call, I build the
table.  If the insn was not generated, it will just be CODE_FOR_nothing, and
the KF->TF mode conversion will not be done.

I have tested this on a little endian power8 system and there were no
regressions.  Once David verifies that it builds on AIX, can I check this into
the trunk?

2017-11-15  Michael Meissner  <meiss...@linux.vnet.ibm.com>

        * config/rs6000/rs6000.c (rs6000_expand_builtin): Do not use a
        switch to map KFmode built-in functions to TFmode.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meiss...@linux.vnet.ibm.com, phone: +1 (978) 899-4797
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 254782)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -16786,27 +16786,45 @@ rs6000_expand_builtin (tree exp, rtx tar
      double (KFmode) or long double is IEEE 128-bit (TFmode).  It is simpler if
      we only define one variant of the built-in function, and switch the code
      when defining it, rather than defining two built-ins and using the
-     overload table in rs6000-c.c to switch between the two.  */
+     overload table in rs6000-c.c to switch between the two.  On some systems
+     like AIX, the KF/TF mode insns are not generated, and they return
+     CODE_FOR_nothing.  */
   if (FLOAT128_IEEE_P (TFmode))
-    switch (icode)
-      {
-      default:
-       break;
+    {
+      struct map_f128 {
+       enum insn_code from;    /* KFmode insn code that is in the tables.  */
+       enum insn_code to;      /* TFmode insn code to use instead.  */
+      };
+
+      static enum insn_code map_insn_code[NUM_INSN_CODES];
+      static bool first_time = true;
+      const static struct map_f128 map[] = {
+       { CODE_FOR_sqrtkf2_odd,         CODE_FOR_sqrttf2_odd },
+       { CODE_FOR_trunckfdf2_odd,      CODE_FOR_trunctfdf2_odd },
+       { CODE_FOR_addkf3_odd,          CODE_FOR_addtf3_odd },
+       { CODE_FOR_subkf3_odd,          CODE_FOR_subtf3_odd },
+       { CODE_FOR_mulkf3_odd,          CODE_FOR_multf3_odd },
+       { CODE_FOR_divkf3_odd,          CODE_FOR_divtf3_odd },
+       { CODE_FOR_fmakf4_odd,          CODE_FOR_fmatf4_odd },
+       { CODE_FOR_xsxexpqp_kf,         CODE_FOR_xsxexpqp_tf },
+       { CODE_FOR_xsxsigqp_kf,         CODE_FOR_xsxsigqp_tf },
+       { CODE_FOR_xststdcnegqp_kf,     CODE_FOR_xststdcnegqp_tf },
+       { CODE_FOR_xsiexpqp_kf,         CODE_FOR_xsiexpqp_tf },
+       { CODE_FOR_xsiexpqpf_kf,        CODE_FOR_xsiexpqpf_tf },
+       { CODE_FOR_xststdcqp_kf,        CODE_FOR_xststdcqp_tf },
+      };
+
+      if (first_time)
+       {
+         first_time = false;
+         gcc_assert ((int)CODE_FOR_nothing == 0);
+         for (i = 0; i < ARRAY_SIZE (map); i++)
+           map_insn_code[(int)map[i].from] = map[i].to;
+       }
 
-      case CODE_FOR_sqrtkf2_odd:       icode = CODE_FOR_sqrttf2_odd;   break;
-      case CODE_FOR_trunckfdf2_odd:    icode = CODE_FOR_trunctfdf2_odd; break;
-      case CODE_FOR_addkf3_odd:                icode = CODE_FOR_addtf3_odd;    
break;
-      case CODE_FOR_subkf3_odd:                icode = CODE_FOR_subtf3_odd;    
break;
-      case CODE_FOR_mulkf3_odd:                icode = CODE_FOR_multf3_odd;    
break;
-      case CODE_FOR_divkf3_odd:                icode = CODE_FOR_divtf3_odd;    
break;
-      case CODE_FOR_fmakf4_odd:                icode = CODE_FOR_fmatf4_odd;    
break;
-      case CODE_FOR_xsxexpqp_kf:       icode = CODE_FOR_xsxexpqp_tf;   break;
-      case CODE_FOR_xsxsigqp_kf:       icode = CODE_FOR_xsxsigqp_tf;   break;
-      case CODE_FOR_xststdcnegqp_kf:   icode = CODE_FOR_xststdcnegqp_tf; break;
-      case CODE_FOR_xsiexpqp_kf:       icode = CODE_FOR_xsiexpqp_tf;   break;
-      case CODE_FOR_xsiexpqpf_kf:      icode = CODE_FOR_xsiexpqpf_tf;  break;
-      case CODE_FOR_xststdcqp_kf:      icode = CODE_FOR_xststdcqp_tf;  break;
-      }
+      if (map_insn_code[(int)icode] != CODE_FOR_nothing)
+       icode = map_insn_code[(int)icode];
+    }
 
   if (TARGET_DEBUG_BUILTIN)
     {

Reply via email to