[PATCH] D120327: compiler-rt: Add udivmodei5 to builtins and add bitint library

Matthias Gehre via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon May 9 07:20:26 PDT 2022


mgehre-amd added a comment.

There is some push back on the gcc mailing list both on requiring an extra word to enable Knuth [0]
and generally defining the libgcc function before _BitInt is implemented in gcc [1].
There are also concerns about whether this would be consistent with the ABI,
which is isn't finalized on all targets yet.

I see a few options going forward:

1. Continue discussion with the gcc folks.

I'm not sure that I can move the discussion anywhere.

2. I prototyped replacing the division with an inlined and fully unrolled version of

  set_zero(quo, words);
  set_zero(rem, words);
  
  unsigned bits = words * WORD_SIZE_IN_BITS;
  for (int i = bits - 1; i >= 0; --i) {
    left_shift_1(rem, words);                    // rem <<= 1;
    set_bit_0(rem, words, get_bit(a, words, i)); // rem(bit 0) = a(bit i);
    if (ucompare(rem, b, words) >= 0) {          // if (rem >= b)
      subtract(rem, b, words);                   // rem -= b;
      set_bit(quo, words, i);                    // quo(bit i) = 1;
    }
  }

during SelectionDAG legalization. This seems to generally work, requires no compiler-rt
extension, but leads to ~5600 instructions on AArch64 for a single udiv i256.
I just created a SelectionDAG node for every line above, and let SelectionDAG legalize
those further to native types.

3. Do the expansion of large udivs on LLVM IR (in TargetPassConfig::addIRPasses ?).

This has the advantage that we are allowed to create loops and functions, so we can
keep the loop rolled to save on the instruction count. We can also keep the function
outlined. We would still specialize based on the integer type, so
the implementation for i256 would look like

  define i256 __llvm__udivrem256(i256 a, i256 b) {
    ...
  loop_body:
    ..
    ; rem <<= 1;
    %rem_sh = shl i256 %rem, 1
    ; rem(bit 0) = a(bit i);
    %a_n1 = lshr i256 %a, %i
    %a_n = and i256 %a_n1, 1
    %rem_sb = or i256 %rem_sh, %a_n
     ...

which makes the pass simple to write. The backend later expands those big integer types
into native ones.

4. Continue with the current approach, but rename the functions to `__llvm_divmodei5` to be independent

of what gcc will decide to do.
We still need build libbitint and link to it whenever the user selects libgcc as their runtime library.
`WEAK_IF_BITINT_LIBRARY` can be removed; the functions always have strong linkage.

What do you think?

[0] https://gcc.gnu.org/pipermail/gcc/2022-May/238659.html
[1] https://gcc.gnu.org/pipermail/gcc/2022-May/238666.html


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D120327/new/

https://reviews.llvm.org/D120327



More information about the llvm-commits mailing list