rfcs icon indicating copy to clipboard operation
rfcs copied to clipboard

Bring back div_rem

Open alexcrichton opened this issue 10 years ago • 13 comments

Tracking issue for https://github.com/rust-lang/rfcs/pull/850

alexcrichton avatar Feb 27 '15 00:02 alexcrichton

cc @quantheory

alexcrichton avatar Feb 27 '15 00:02 alexcrichton

Any update on this? :)

Boscop avatar Feb 28 '18 14:02 Boscop

Shall it avoid giving negative remainders unlike %?

vi avatar Mar 23 '18 22:03 vi

When you divide -1234 by 10, your remainder is -4.

I think the advantage of div_rem is that the computer is already doing both at once, it's just throwing away part of the work instead of instead of letting us keep both parts.

Lokathor avatar Dec 19 '18 01:12 Lokathor

What exactly would it need to push this forward?

dignifiedquire avatar Dec 24 '18 12:12 dignifiedquire

@dignifiedquire I'd just write a PR against https://github.com/rust-lang/rust/ and then T-libs can decide what to do.

Centril avatar Dec 24 '18 12:12 Centril

Make sure to spec it as const from the start (for integers at least)

Edit: oh crap no const-if yet, nevermind i guess

Lokathor avatar Dec 24 '18 16:12 Lokathor

I want to add a set of uX::wrapping_div_rem(lhs, rhs) -> (uX, uX) functions as a way to guarantee that __udivmodti4 and the like are called, and not have to rely on the compiler backend to combine operations. However, someone encountered an LLVM error where the target sparc-unknown-linux-gnu cannot lower any function that returns a tuple of two u128s. If the function were added, wouldn't that completely break 32-bit SPARC targets unless the LLVM issue is resolved?

AaronKutch avatar Nov 20 '20 20:11 AaronKutch

I'd imagine rustc could add a workaround to do the return lowering in rustc if the LLVM bug is not easy to fix or we want to support old LLVM versions.

programmerjake avatar Nov 20 '20 21:11 programmerjake

Is there someone who wants to tackle the problem? I might try myself, although I have no idea where to begin. I've never messed with code lowering before.

AaronKutch avatar Nov 20 '20 21:11 AaronKutch

It seems to work fine from clang: https://gcc.godbolt.org/z/8xbrWE

programmerjake avatar Nov 20 '20 21:11 programmerjake

I don't know if it's useful, but I have compiled the following code and generated the corresponding LLVM IR:

#[no_mangle]
fn test_128(one: u128, two: u128) -> (u128, u128) {
    let division = one / two;
    (division + 40000000, division - 100000)
}

The LLVM IR is:

; Function Attrs: minsize nounwind optsize
define { i128, i128 } @test_128(i128 %one, i128 %two) unnamed_addr #0 {
start:
  %_6 = icmp eq i128 %two, 0
  br i1 %_6, label %panic, label %bb1, !prof !1, !misexpect !2

bb1:                                              ; preds = %start
  %division = udiv i128 %one, %two
  %_7 = add i128 %division, 40000000
  %_9 = add i128 %division, -100000
  %0 = insertvalue { i128, i128 } undef, i128 %_7, 0
  %1 = insertvalue { i128, i128 } %0, i128 %_9, 1
  ret { i128, i128 } %1

NOTE: I have removed the panic block since I believe it shouldn't be what is causing the error.

The error output generated by rustc is:

LLVM ERROR: unable to allocate function return #6

I have generated the LLVM IR with the flag --emit=llvm-ir. The equivalent function in LLVM IR generated from clang is here.

Thanks a lot!

parraman avatar Nov 20 '20 22:11 parraman

I would like to point out that div_rem methods may have value even without intrinsic functions to implement them.

  • Most importantly, the methods might just help with convenience or readability.
  • The standard library is always compiled with opt-level=3, so the optimization will exist even in debug mode.
  • There is a little bit of room for optimization outside of the intrinsics. Ex: wrapping_div_rem_euclid()

Since the compiler doesn't recognize the hard coded div function, ethnum-rs has a set of div_rem methods analogous to the integer methods in the standard library. I suggest taking a look at the API and documentation as an example of what the div_rem methods could look like. The implementing code itself isn't as applicable because there were different intrinsics to work with.

NCGThompson avatar Dec 21 '23 02:12 NCGThompson