This is an archive of the discontinued LLVM Phabricator instance.

[compiler-rt] [builtins] Allow building the necessary ARM builtins for MSVC mode with cmake
AbandonedPublic

Authored by mstorsjo on Aug 31 2016, 2:58 AM.

Details

Reviewers
rengolin
compnerd
Summary

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

mstorsjo updated this revision to Diff 69818.Aug 31 2016, 2:58 AM
mstorsjo retitled this revision from to [compiler-rt] [builtins] Allow building the necessary ARM builtins for MSVC mode with cmake.
mstorsjo updated this object.
mstorsjo added reviewers: compnerd, rengolin.
mstorsjo added a subscriber: llvm-commits.

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

rengolin requested changes to this revision.Aug 31 2016, 3:12 AM
rengolin edited edge metadata.

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

This revision now requires changes to proceed.Aug 31 2016, 3:12 AM

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?

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

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.

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.

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.

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?

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.

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... :)

mstorsjo abandoned this revision.Aug 31 2016, 6:34 AM

Abandoning this and continuing the discussion in D24076 instead.