Attached patch builds on previous libgcc patch and implements TARGET_EXPAND_DIVMOD_LIBFUNC target hook.
The same approach can also be used on other targets without hardware divmod insn. Patch also fixes several gcc.dg/divmod-?.c testsuite failures for x86_64 multilibs. 2016-10-31 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.c (ix86_init_libfuncs): New. Call darwin_rename_builtins here. (ix86_expand_divmod_libfunc): New. (TARGET_INIT_LIBFUNCS): Unconditionally define to ix86_init_libfuncs. (TARGET_EXPAND_DIVMOD_LIBFUNC): Define. testsuite/Changelog: 2016-10-31 Uros Bizjak <ubiz...@gmail.com> * lib/target-supports.exp (check_effective_target_divmod): Add i?86-*-*. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Uros.
Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 241697) +++ config/i386/i386.c (working copy) @@ -50571,9 +50571,44 @@ ix86_addr_space_zero_address_valid (addr_space_t a { return as != ADDR_SPACE_GENERIC; } -#undef TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID -#define TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID ix86_addr_space_zero_address_valid +static void +ix86_init_libfuncs (void) +{ + if (TARGET_64BIT) + { + set_optab_libfunc (sdivmod_optab, TImode, "__divmodti4"); + set_optab_libfunc (udivmod_optab, TImode, "__udivmodti4"); + } + else + { + set_optab_libfunc (sdivmod_optab, DImode, "__divmoddi4"); + set_optab_libfunc (udivmod_optab, DImode, "__udivmoddi4"); + } + +#if TARGET_MACHO + darwin_rename_builtins (); +#endif +} + +/* Generate call to __divmoddi4. */ + +static void +ix86_expand_divmod_libfunc (rtx libfunc, machine_mode mode, + rtx op0, rtx op1, + rtx *quot_p, rtx *rem_p) +{ + rtx rem = assign_386_stack_local (mode, SLOT_TEMP); + + rtx quot = emit_library_call_value (libfunc, NULL_RTX, LCT_NORMAL, + mode, 3, + op0, GET_MODE (op0), + op1, GET_MODE (op1), + XEXP (rem, 0), Pmode); + *quot_p = quot; + *rem_p = rem; +} + /* Initialize the GCC target structure. */ #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY ix86_return_in_memory @@ -50957,11 +50992,6 @@ ix86_addr_space_zero_address_valid (addr_space_t a #undef TARGET_CONDITIONAL_REGISTER_USAGE #define TARGET_CONDITIONAL_REGISTER_USAGE ix86_conditional_register_usage -#if TARGET_MACHO -#undef TARGET_INIT_LIBFUNCS -#define TARGET_INIT_LIBFUNCS darwin_rename_builtins -#endif - #undef TARGET_LOOP_UNROLL_ADJUST #define TARGET_LOOP_UNROLL_ADJUST ix86_loop_unroll_adjust @@ -51052,6 +51082,15 @@ ix86_addr_space_zero_address_valid (addr_space_t a #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 1 +#undef TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID +#define TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID ix86_addr_space_zero_address_valid + +#undef TARGET_INIT_LIBFUNCS +#define TARGET_INIT_LIBFUNCS ix86_init_libfuncs + +#undef TARGET_EXPAND_DIVMOD_LIBFUNC +#define TARGET_EXPAND_DIVMOD_LIBFUNC ix86_expand_divmod_libfunc + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-i386.h" Index: testsuite/lib/target-supports.exp =================================================================== --- testsuite/lib/target-supports.exp (revision 241697) +++ testsuite/lib/target-supports.exp (working copy) @@ -8110,7 +8110,7 @@ proc check_effective_target_divmod { } { #TODO: Add checks for all targets that have either hardware divmod insn # or define libfunc for divmod. if { [istarget arm*-*-*] - || [istarget x86_64-*-*] } { + || [istarget x86_64-*-*] || [istarget i?86-*-*] } { return 1 } return 0