Even though llvm emits calls to rt_{s,u}div{,64} when targeting Windows on ARM, it also emits calls to some of these (moddi3, __umoddi3), making the compiler-rt builtins necessary in this configuration.
Diff Detail
Event Timeline
I guess the more proper solution is to change LLVM to call the rt_*div* family of functions instead of moddi3 when targeting Windows/MSVC - but I'm not too sure of how to do that change in order to propose a patch for it. Any hints?
Hi,
So I guess the problem is that we emit the "correct" libcalls for UDIV/SDIV but not for UREM/SREM. I can't seem to find a libcall in Windows for modulo - what is the expected behaviour here?
Modulo can be emitted as a division + multiply-subtract - in fact one of our engineers is working on such a patch right now - it could be extended to work in windows-on-arm mode too perhaps?
I think I really need to know what the expected code should be for modulo.
James
I don't think this fix is correct. We shouldn't be *adding* GNU functions to Windows, but we should be making Clang on Windows emit the right EABI calls.
The way to fix this is to associate those functions in ARMISelLowering, just like we do for EABI.
cheers,
--renato
The existing lib functions, __rt_div etc, return both the quotient and the remainder via some sort of custom return ABI. (For the 32 bit functions, the quotient is in r0 and the remainder in r1, for 64 bit, the quotient is in r0 and r1, and the remainder in r2 and r3.)
Ah, OK, then we need to handle them similar to eabi_divmod. The right place to change is in lib/Target/ARM/ARMISelLowering.cpp - look for divmod and see what changes you need to teach LLVM that rt_div* isn't just DIV but DIVMOD too.
James
Yup. In EABI, both mod and divmod call aeabi_divmod. Mod, in DAG, connects to the second return value directly and LLVM knows how to lower that directly.
I suspect you'll need to do the same for many other EABI calls, not just divmod.
Actually, in my testing with a fairly large codebase, it doesn't emit any EABI calls (those are only hooked up in ARMISelLowering.cpp if the target uses EABI) - the only ones outside of the ones that are present in the msvc "builtins" static lib are moddi3 and umoddi3.
With a bit of crude hacking, I managed to hook up rt_sdiv and rt_sdiv64 to be called in the same fashion as aeabi_idivmod and aeabi_ldivmod. But there's another gotcha - rt_sdiv takes the two operands in the opposite order compared to aeabi_idivmod. How do I change that for these ones?
Probably the last ones missing.
With a bit of crude hacking, I managed to hook up rt_sdiv and rt_sdiv64 to be called in the same fashion as aeabi_idivmod and aeabi_ldivmod. But there's another gotcha - rt_sdiv takes the two operands in the opposite order compared to aeabi_idivmod. How do I change that for these ones?
Why on Earth would anyone do that, if not on purpose, to make user code non-portable?
Right, then you'll need a more complicated lowering.
Basically, divmod is lowered by a SelectionDAG function that behaves like GNU (returns quot, mod stored in the second argument's address). ARM has a special lowering, which uses EABI reg-return (quot in r0 or r0/r1, mod in r1 or r2/r3).
You can try to flip the arguments in one of the functions, probably both, to swap the arguments before processing.
Using "isWindowsABI" won't work, since "rt_div" and friends are used elsewhere. Or you can create a special Dag node just for rt_div and friends, which would be equally ugly.
I seriously hope you can come up with a better idea... :)