Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

trans: Call fmod manually for 32-bit float rem #27875

Merged
merged 1 commit into from
Aug 19, 2015

Conversation

alexcrichton
Copy link
Member

Currently f32 % f32 will generate a link error on 32-bit MSVC because LLVM
will lower the operation to a call to the nonexistent function fmodf. Work
around in this in the backend by lowering to a call to fmod instead with
necessary extension/truncation between floats/doubles.

Closes #27859

@rust-highfive
Copy link
Collaborator

r? @pcwalton

(rust_highfive has picked a reviewer for you, use r? to override)

@alexcrichton
Copy link
Member Author

r? @nrc

This makes me a little sad, but I was unable to think of a cleaner way to do this :(

@rust-highfive rust-highfive assigned nrc and unassigned pcwalton Aug 18, 2015
@huonw
Copy link
Member

huonw commented Aug 18, 2015

I wonder if we can just remove this branch? Theoretically the trait implementation itself should work fine... right? (At least, it seems it wouldn't be backwards incompatible to rely on the trait, based on #27824 (comment))

@alexcrichton
Copy link
Member Author

Unfortunately we do actually hit this branch, even though there's a trait implementation in scope. For example this code:

pub fn foo(a: f32, b: f32) -> f32 { a % b }

generates this IR at O0

define float @_ZN3foo20hc71bdc578cf276aaeaaE(float, float) unnamed_addr #0 {
entry-block:
  %dropflag_hint_6 = alloca i8
  %dropflag_hint_9 = alloca i8
  %a = alloca float
  %b = alloca float
  store i8 61, i8* %dropflag_hint_6
  store i8 61, i8* %dropflag_hint_9
  store float %0, float* %a, align 4
  store float %1, float* %b, align 4
  %2 = load float, float* %a, align 4
  %3 = load float, float* %b, align 4
  %4 = frem float %2, %3
  ret float %4
}

// these two implementations on day!
let use_trait = tcx.sess.target.target.options.is_like_msvc &&
tcx.sess.target.target.arch == "x86" &&
lhs_t == tcx.types.f32;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't make this conditional on the operand type: you'll run into trouble in optimized builds if someone writes:

#![crate_type="lib"]
pub fn foo(a: f32, b: f32) -> f32 {
    (a as f64 % b as f64) as f32
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe lhs_t is the true type of the operation (e.g. with all types resolved), for example when I run this function through this patch on 32-bit Windows it generates a frem call with 64-bit doubles.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is with optimization turned on? (The problem is that instcombine narrows frem instructions.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right of course, I'll have to poke around and see if I can't get something to work.

@alexcrichton alexcrichton force-pushed the msvc-f32-rem branch 4 times, most recently from 717ddbe to bccd32a Compare August 18, 2015 06:08
@alexcrichton
Copy link
Member Author

Well it looks like @eefriedman's right and LLVM is too smart for it's own good, I'm not sure how to subvert its logic to get it to not generate frem instructions, so closing for now.

@eefriedman
Copy link
Contributor

Well, you could change trans so it never generates frem. LLVM won't convert explicit calls to fmod() into an frem instruction.

Currently `f32 % f32` will generate a link error on 32-bit MSVC because LLVM
will lower the operation to a call to the nonexistent function `fmodf`. Work
around in this in the backend by lowering to a call to `fmod` instead with
necessary extension/truncation between floats/doubles.

Closes rust-lang#27859
@alexcrichton
Copy link
Member Author

That does indeed seem to work! (pushed)

@dylanmckay
Copy link
Contributor

I've just made a patch for LLVM which causes f32 modulus operations to be promoted to f64 modulus operations, but only on 32-bit MSVC. I am currently in the process of testing and upstreaming it. EDIT: It works, and is in the process of being reviewed.

@alexcrichton
Copy link
Member Author

Awesome, thanks @dylanmckay! If that lands I'll see about updating possibly updating LLVM or I'll add a note here saying that this branch should be removed once upstream LLVM has been updated.

@dylanmckay
Copy link
Contributor

No problem @alexcrichton!

With regards to updating LLVM - I am happy to do that. My AVR fork of Rust is easiest to update right after an LLVM upgrade :)

@nrc
Copy link
Member

nrc commented Aug 19, 2015

@bors: r+

@bors
Copy link
Contributor

bors commented Aug 19, 2015

📌 Commit 8a7b0fa has been approved by nrc

@bors
Copy link
Contributor

bors commented Aug 19, 2015

⌛ Testing commit 8a7b0fa with merge c8c14f2...

bors added a commit that referenced this pull request Aug 19, 2015
Currently `f32 % f32` will generate a link error on 32-bit MSVC because LLVM
will lower the operation to a call to the nonexistent function `fmodf`. Work
around in this in the backend by lowering to a call to `fmod` instead with
necessary extension/truncation between floats/doubles.

Closes #27859
@bors bors merged commit 8a7b0fa into rust-lang:master Aug 19, 2015
@alexcrichton alexcrichton deleted the msvc-f32-rem branch August 21, 2015 21:25
ranma42 added a commit to ranma42/rust that referenced this pull request Aug 27, 2015
The old code is temporarily needed in order to keep the MSVC build
working. It should be possible to remove this code after the bootstrap
compiler is updated to contain the MSVC workaround from rust-lang#27875.
@dylanmckay
Copy link
Contributor

This was fixed upstream in r246615.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants