Skip to content

Commit 96b2288

Browse files
committed
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.
1 parent cae42a4 commit 96b2288

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;
@@ -1591,7 +1590,6 @@ fn trans_scalar_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
15911590
{
15921591
let _icx = push_ctxt("trans_scalar_binop");
15931592

1594-
let tcx = bcx.tcx();
15951593
let lhs_t = lhs.ty;
15961594
assert!(!lhs_t.is_simd());
15971595
let is_float = lhs_t.is_fp();
@@ -1654,42 +1652,7 @@ fn trans_scalar_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
16541652
}
16551653
hir::BiRem => {
16561654
if is_float {
1657-
// LLVM currently always lowers the `frem` instructions appropriate
1658-
// library calls typically found in libm. Notably f64 gets wired up
1659-
// to `fmod` and f32 gets wired up to `fmodf`. Inconveniently for
1660-
// us, 32-bit MSVC does not actually have a `fmodf` symbol, it's
1661-
// instead just an inline function in a header that goes up to a
1662-
// f64, uses `fmod`, and then comes back down to a f32.
1663-
//
1664-
// Although LLVM knows that `fmodf` doesn't exist on MSVC, it will
1665-
// still unconditionally lower frem instructions over 32-bit floats
1666-
// to a call to `fmodf`. To work around this we special case MSVC
1667-
// 32-bit float rem instructions and instead do the call out to
1668-
// `fmod` ourselves.
1669-
//
1670-
// Note that this is currently duplicated with src/libcore/ops.rs
1671-
// which does the same thing, and it would be nice to perhaps unify
1672-
// these two implementations on day! Also note that we call `fmod`
1673-
// for both 32 and 64-bit floats because if we emit any FRem
1674-
// instruction at all then LLVM is capable of optimizing it into a
1675-
// 32-bit FRem (which we're trying to avoid).
1676-
let use_fmod = tcx.sess.target.target.options.is_like_msvc &&
1677-
tcx.sess.target.target.arch == "x86";
1678-
if use_fmod {
1679-
let f64t = Type::f64(bcx.ccx());
1680-
let fty = Type::func(&[f64t, f64t], &f64t);
1681-
let llfn = declare::declare_cfn(bcx.ccx(), "fmod", fty);
1682-
if lhs_t == tcx.types.f32 {
1683-
let lhs = FPExt(bcx, lhs, f64t);
1684-
let rhs = FPExt(bcx, rhs, f64t);
1685-
let res = Call(bcx, llfn, &[lhs, rhs], binop_debug_loc);
1686-
FPTrunc(bcx, res, Type::f32(bcx.ccx()))
1687-
} else {
1688-
Call(bcx, llfn, &[lhs, rhs], binop_debug_loc)
1689-
}
1690-
} else {
1691-
FRem(bcx, lhs, rhs, binop_debug_loc)
1692-
}
1655+
FRem(bcx, lhs, rhs, binop_debug_loc)
16931656
} else {
16941657
// Only zero-check integers; fp %0 is NaN
16951658
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;
@@ -529,43 +527,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
529527
bcx.udiv(lhs, rhs)
530528
},
531529
mir::BinOp::Rem => if is_float {
532-
// LLVM currently always lowers the `frem` instructions appropriate
533-
// library calls typically found in libm. Notably f64 gets wired up
534-
// to `fmod` and f32 gets wired up to `fmodf`. Inconveniently for
535-
// us, 32-bit MSVC does not actually have a `fmodf` symbol, it's
536-
// instead just an inline function in a header that goes up to a
537-
// f64, uses `fmod`, and then comes back down to a f32.
538-
//
539-
// Although LLVM knows that `fmodf` doesn't exist on MSVC, it will
540-
// still unconditionally lower frem instructions over 32-bit floats
541-
// to a call to `fmodf`. To work around this we special case MSVC
542-
// 32-bit float rem instructions and instead do the call out to
543-
// `fmod` ourselves.
544-
//
545-
// Note that this is currently duplicated with src/libcore/ops.rs
546-
// which does the same thing, and it would be nice to perhaps unify
547-
// these two implementations one day! Also note that we call `fmod`
548-
// for both 32 and 64-bit floats because if we emit any FRem
549-
// instruction at all then LLVM is capable of optimizing it into a
550-
// 32-bit FRem (which we're trying to avoid).
551-
let tcx = bcx.tcx();
552-
let use_fmod = tcx.sess.target.target.options.is_like_msvc &&
553-
tcx.sess.target.target.arch == "x86";
554-
if use_fmod {
555-
let f64t = Type::f64(bcx.ccx());
556-
let fty = Type::func(&[f64t, f64t], &f64t);
557-
let llfn = declare::declare_cfn(bcx.ccx(), "fmod", fty);
558-
if input_ty == tcx.types.f32 {
559-
let lllhs = bcx.fpext(lhs, f64t);
560-
let llrhs = bcx.fpext(rhs, f64t);
561-
let llres = bcx.call(llfn, &[lllhs, llrhs], None);
562-
bcx.fptrunc(llres, Type::f32(bcx.ccx()))
563-
} else {
564-
bcx.call(llfn, &[lhs, rhs], None)
565-
}
566-
} else {
567-
bcx.frem(lhs, rhs)
568-
}
530+
bcx.frem(lhs, rhs)
569531
} else if is_signed {
570532
bcx.srem(lhs, rhs)
571533
} else {

0 commit comments

Comments
 (0)