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) {