Skip to content

Commit 6859599

Browse files
committed
Rollup merge of rust-lang#33508 - alexcrichton:always-lower-frem, r=nikomatsakis
trans: Always lower to `frem` Long ago LLVM unfortunately didn't handle the 32-bit MSVC case of `frem` where it can't be lowered to `fmodf` because that symbol doesn't exist. That was since fixed in http://reviews.llvm.org/D12099 (landed as r246615) and was released in what appears to be LLVM 3.8. Now that we're using that branch of LLVM let's remove our own hacks and help LLVM optimize a little better by giving it knowledge about what we're doing.
2 parents be92e9b + 96b2288 commit 6859599

File tree

2 files changed

+2
-77
lines changed

2 files changed

+2
-77
lines changed

src/librustc_trans/expr.rs

+1-38
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ use cleanup::{self, CleanupMethods, DropHintMethods};
6363
use common::*;
6464
use datum::*;
6565
use debuginfo::{self, DebugLoc, ToDebugLoc};
66-
use declare;
6766
use glue;
6867
use machine;
6968
use tvec;
@@ -1593,7 +1592,6 @@ fn trans_scalar_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
15931592
{
15941593
let _icx = push_ctxt("trans_scalar_binop");
15951594

1596-
let tcx = bcx.tcx();
15971595
let lhs_t = lhs.ty;
15981596
assert!(!lhs_t.is_simd());
15991597
let is_float = lhs_t.is_fp();
@@ -1656,42 +1654,7 @@ fn trans_scalar_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
16561654
}
16571655
hir::BiRem => {
16581656
if is_float {
1659-
// LLVM currently always lowers the `frem` instructions appropriate
1660-
// library calls typically found in libm. Notably f64 gets wired up
1661-
// to `fmod` and f32 gets wired up to `fmodf`. Inconveniently for
1662-
// us, 32-bit MSVC does not actually have a `fmodf` symbol, it's
1663-
// instead just an inline function in a header that goes up to a
1664-
// f64, uses `fmod`, and then comes back down to a f32.
1665-
//
1666-
// Although LLVM knows that `fmodf` doesn't exist on MSVC, it will
1667-
// still unconditionally lower frem instructions over 32-bit floats
1668-
// to a call to `fmodf`. To work around this we special case MSVC
1669-
// 32-bit float rem instructions and instead do the call out to
1670-
// `fmod` ourselves.
1671-
//
1672-
// Note that this is currently duplicated with src/libcore/ops.rs
1673-
// which does the same thing, and it would be nice to perhaps unify
1674-
// these two implementations on day! Also note that we call `fmod`
1675-
// for both 32 and 64-bit floats because if we emit any FRem
1676-
// instruction at all then LLVM is capable of optimizing it into a
1677-
// 32-bit FRem (which we're trying to avoid).
1678-
let use_fmod = tcx.sess.target.target.options.is_like_msvc &&
1679-
tcx.sess.target.target.arch == "x86";
1680-
if use_fmod {
1681-
let f64t = Type::f64(bcx.ccx());
1682-
let fty = Type::func(&[f64t, f64t], &f64t);
1683-
let llfn = declare::declare_cfn(bcx.ccx(), "fmod", fty);
1684-
if lhs_t == tcx.types.f32 {
1685-
let lhs = FPExt(bcx, lhs, f64t);
1686-
let rhs = FPExt(bcx, rhs, f64t);
1687-
let res = Call(bcx, llfn, &[lhs, rhs], binop_debug_loc);
1688-
FPTrunc(bcx, res, Type::f32(bcx.ccx()))
1689-
} else {
1690-
Call(bcx, llfn, &[lhs, rhs], binop_debug_loc)
1691-
}
1692-
} else {
1693-
FRem(bcx, lhs, rhs, binop_debug_loc)
1694-
}
1657+
FRem(bcx, lhs, rhs, binop_debug_loc)
16951658
} else {
16961659
// Only zero-check integers; fp %0 is NaN
16971660
bcx = base::fail_if_zero_or_overflows(bcx,

src/librustc_trans/mir/rvalue.rs

+1-39
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,8 @@ use callee::Callee;
1919
use common::{self, C_uint, BlockAndBuilder, Result};
2020
use datum::{Datum, Lvalue};
2121
use debuginfo::DebugLoc;
22-
use declare;
2322
use adt;
2423
use machine;
25-
use type_::Type;
2624
use type_of;
2725
use tvec;
2826
use value::Value;
@@ -531,43 +529,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
531529
bcx.udiv(lhs, rhs)
532530
},
533531
mir::BinOp::Rem => if is_float {
534-
// LLVM currently always lowers the `frem` instructions appropriate
535-
// library calls typically found in libm. Notably f64 gets wired up
536-
// to `fmod` and f32 gets wired up to `fmodf`. Inconveniently for
537-
// us, 32-bit MSVC does not actually have a `fmodf` symbol, it's
538-
// instead just an inline function in a header that goes up to a
539-
// f64, uses `fmod`, and then comes back down to a f32.
540-
//
541-
// Although LLVM knows that `fmodf` doesn't exist on MSVC, it will
542-
// still unconditionally lower frem instructions over 32-bit floats
543-
// to a call to `fmodf`. To work around this we special case MSVC
544-
// 32-bit float rem instructions and instead do the call out to
545-
// `fmod` ourselves.
546-
//
547-
// Note that this is currently duplicated with src/libcore/ops.rs
548-
// which does the same thing, and it would be nice to perhaps unify
549-
// these two implementations one day! Also note that we call `fmod`
550-
// for both 32 and 64-bit floats because if we emit any FRem
551-
// instruction at all then LLVM is capable of optimizing it into a
552-
// 32-bit FRem (which we're trying to avoid).
553-
let tcx = bcx.tcx();
554-
let use_fmod = tcx.sess.target.target.options.is_like_msvc &&
555-
tcx.sess.target.target.arch == "x86";
556-
if use_fmod {
557-
let f64t = Type::f64(bcx.ccx());
558-
let fty = Type::func(&[f64t, f64t], &f64t);
559-
let llfn = declare::declare_cfn(bcx.ccx(), "fmod", fty);
560-
if input_ty == tcx.types.f32 {
561-
let lllhs = bcx.fpext(lhs, f64t);
562-
let llrhs = bcx.fpext(rhs, f64t);
563-
let llres = bcx.call(llfn, &[lllhs, llrhs], None);
564-
bcx.fptrunc(llres, Type::f32(bcx.ccx()))
565-
} else {
566-
bcx.call(llfn, &[lhs, rhs], None)
567-
}
568-
} else {
569-
bcx.frem(lhs, rhs)
570-
}
532+
bcx.frem(lhs, rhs)
571533
} else if is_signed {
572534
bcx.srem(lhs, rhs)
573535
} else {

0 commit comments

Comments
 (0)