On 28 July 2016 at 19:05, Prathamesh Kulkarni
<[email protected]> wrote:
> On 8 June 2016 at 19:53, Richard Biener <[email protected]> wrote:
>> On Fri, 3 Jun 2016, Jim Wilson wrote:
>>
>>> On Mon, May 30, 2016 at 12:45 AM, Richard Biener <[email protected]> wrote:
>>> > Joseph - do you know sth about why there's not a full set of divmod
>>> > libfuncs in libgcc?
>>>
>>> Because udivmoddi4 isn't a libfunc, it is a helper function for the
>>> div and mov libfuncs. Since we can compute the signed div and mod
>>> results from udivmoddi4, there was no need to also add a signed
>>> version of it. It was given a libfunc style name so that we had the
>>> option of making it a libfunc in the future, but that never happened.
>>> There was no support for calling any divmod libfunc until it was added
>>> as a special case to call an ARM library (not libgcc) function. This
>>> happened here
>>>
>>> 2004-08-09 Mark Mitchell <[email protected]>
>>>
>>> * config.gcc (arm*-*-eabi*): New target.
>>> * defaults.h (TARGET_LIBGCC_FUNCS): New macro.
>>> (TARGET_LIB_INT_CMP_BIASED): Likewise.
>>> * expmed.c (expand_divmod): Try a two-valued divmod function as a
>>> last resort.
>>> ...
>>> * config/arm/arm.c (arm_init_libfuncs): New function.
>>> (arm_compute_initial_eliminatino_offset): Return HOST_WIDE_INT.
>>> (TARGET_INIT_LIBFUNCS): Define it.
>>> ...
>>>
>>> Later, two ports added their own divmod libfuncs, but I don't see any
>>> evidence that they were ever used, since there is no support for
>>> calling divmod other than the expand_divmod last resort code that only
>>> triggers for ARM.
>>>
>>> It is only now that Prathamesh is adding gimple support for divmod
>>> operations that we need to worry about getting this right, without
>>> breaking the existing ARM library support or the existing udivmoddi4
>>> support.
>>
>> Ok, so as he is primarily targeting the special arm divmod libcall
>> I suppose we can live with special-casing libcall handling to
>> udivmoddi3. It would be nice to not lie about divmod availablilty
>> as libcall though... - it looks like the libcall is also guarded
>> on TARGET_HAS_NO_HW_DIVIDE (unless it was available historically
>> like on x86).
>>
>> So not sure where to go from here.
> Hi,
> I have attached patch, which is rebased on trunk.
> Needed to update divmod-7.c, which now gets transformed to divmod
> thanks to your code-hoisting patch -;)
> We still have the issue of optab_libfunc() returning non-existent
> libcalls. As in previous patch, I am checking
> explicitly for "__udivmoddi4", with a FIXME note.
> I hope that's okay for now ?
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu,
> armv8l-unknown-linux-gnueabihf.
> Bootstrap+test in progress on i686-linux-gnu.
> Cross-tested on arm*-*-*.
Hi Richard,
I have following two approaches to workaround optab_libfunc issue:
a) Not lie about divmod libfunc availability by setting libcall entry to NULL
for sdivmod_optab in optabs.def.
Patch posted for that here:
https://gcc.gnu.org/ml/gcc-patches/2016-08/msg01015.html
Although it doesn't cause any regressions with the gcc testsuite,
I am not sure if this change is correct.
b) Perform the transform only if target-specific divmod is available,
ie, drop targeting
__udivmoddi4. I have attached (untested) patch for that.
When/If we have the optab_libfunc issue resolved, we can later target "generic"
divmod libfunc.
Do either of these approaches look reasonable ?
PS: I am on vacation next week, will get back to working on patch
after returning.
Thanks,
Prathamesh
>
> Thanks,
> Prathamesh
>>
>> Richard.
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index f506a83..618c810 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -2012,28 +2012,14 @@ default_max_noce_ifcvt_seq_cost (edge e)
DImode __udivmoddi4 (DImode op0, DImode op1, DImode *rem). */
void
-default_expand_divmod_libfunc (bool unsignedp, machine_mode mode,
- rtx op0, rtx op1,
- rtx *quot_p, rtx *rem_p)
+default_expand_divmod_libfunc (bool unsignedp ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED,
+ rtx op0 ATTRIBUTE_UNUSED,
+ rtx op1 ATTRIBUTE_UNUSED,
+ rtx *quot_p ATTRIBUTE_UNUSED,
+ rtx *rem_p ATTRIBUTE_UNUSED)
{
- gcc_assert (mode == DImode);
- gcc_assert (unsignedp);
-
- rtx libfunc = optab_libfunc (udivmod_optab, DImode);
- gcc_assert (libfunc);
- gcc_assert (!strcmp (XSTR (libfunc, 0), "__udivmoddi4"));
-
- rtx remainder = assign_stack_temp (DImode, GET_MODE_SIZE (DImode));
- rtx address = XEXP (remainder, 0);
-
- rtx quotient = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
- DImode, 3,
- op0, GET_MODE (op0),
- op1, GET_MODE (op1),
- address, GET_MODE (address));
-
- *quot_p = quotient;
- *rem_p = remainder;
+ gcc_unreachable ();
}
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index ad32744..fda00c7 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -3808,9 +3808,12 @@ target_supports_divmod_p (optab divmod_optab, optab
div_optab, machine_mode mode
if (optab_handler (divmod_optab, mode) != CODE_FOR_nothing)
return true;
- /* Check if libfunc for divmod is available. */
- rtx libfunc = optab_libfunc (divmod_optab, mode);
- if (libfunc != NULL_RTX)
+ /* Check if target-specific divmod libfunc is available.
+ If target overrides expand_divmod_libfunc, then it *has to*
+ set_optab_libfunc (divmod_optab, mode) to target-specific divmod
+ libfunc. */
+
+ if (targetm.expand_divmod_libfunc != default_expand_divmod_libfunc)
{
/* If optab_handler exists for div_optab, perhaps in a wider mode,
we don't want to use the libfunc even if it exists for given mode. */
@@ -3820,12 +3823,7 @@ target_supports_divmod_p (optab divmod_optab, optab
div_optab, machine_mode mode
if (optab_handler (div_optab, div_mode) != CODE_FOR_nothing)
return false;
- /* FIXME: This is a hack to workaround an issue with optab_libfunc().
- optab_libfunc (sdivmod_optab, DImode) returns libfunc "__divmoddi4",
- although __divmoddi4() does not exist in libgcc. For now, enable the
- transform only if libfunc is guaranteed to be __udivmoddi4. */
- return (targetm.expand_divmod_libfunc != default_expand_divmod_libfunc
- || !strcmp (XSTR (libfunc, 0), "__udivmoddi4"));
+ return true;
}
return false;