diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index 9f34aee1947cd..4365c436fe494 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -1,7 +1,7 @@
 use crate::char;
 use crate::convert::TryFrom;
 use crate::mem;
-use crate::ops::{self, Add, Sub, Try};
+use crate::ops::{self, Try};
 
 use super::{FusedIterator, TrustedLen};
 
@@ -201,24 +201,12 @@ macro_rules! step_identical_methods {
 
         #[inline]
         fn forward(start: Self, n: usize) -> Self {
-            // In debug builds, trigger a panic on overflow.
-            // This should optimize completely out in release builds.
-            if Self::forward_checked(start, n).is_none() {
-                let _ = Add::add(Self::MAX, 1);
-            }
-            // Do wrapping math to allow e.g. `Step::forward(-128i8, 255)`.
-            start.wrapping_add(n as Self)
+            start + (n as Self)
         }
 
         #[inline]
         fn backward(start: Self, n: usize) -> Self {
-            // In debug builds, trigger a panic on overflow.
-            // This should optimize completely out in release builds.
-            if Self::backward_checked(start, n).is_none() {
-                let _ = Sub::sub(Self::MIN, 1);
-            }
-            // Do wrapping math to allow e.g. `Step::backward(127i8, 255)`.
-            start.wrapping_sub(n as Self)
+            start - (n as Self)
         }
     };
 }
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index 8aea9a9f58850..43657be481396 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -1139,6 +1139,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
+    fn get_is_trivial_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> bool {
+        self.root
+            .tables
+            .is_trivial_mir
+            .get(self, id)
+            .filter(|_| !self.is_proc_macro(id))
+            .map_or(false, |v| v.decode((self, tcx)))
+    }
+
     fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
         self.root
             .tables
diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
index 10b89cdd15a52..20ae2dcbde336 100644
--- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
+++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
@@ -111,6 +111,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
             bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);
         })
     }
+    is_trivial_mir => { *tcx.arena.alloc(cdata.get_is_trivial_mir(tcx, def_id.index)) }
     optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) }
     promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) }
     unused_generic_params => { cdata.get_unused_generic_params(def_id.index) }
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index 6723e236a1fe9..62cbea8d74d1f 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -1125,6 +1125,7 @@ impl EncodeContext<'a, 'tcx> {
     fn encode_optimized_mir(&mut self, def_id: LocalDefId) {
         debug!("EntryBuilder::encode_mir({:?})", def_id);
         if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
+            record!(self.tables.is_trivial_mir[def_id.to_def_id()] <- self.tcx.is_trivial_mir(def_id));
             record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id));
 
             let unused = self.tcx.unused_generic_params(def_id);
diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs
index 1c287be9f6bbc..935d24e50eaa1 100644
--- a/src/librustc_metadata/rmeta/mod.rs
+++ b/src/librustc_metadata/rmeta/mod.rs
@@ -283,6 +283,7 @@ define_tables! {
     // Also, as an optimization, a missing entry indicates an empty `&[]`.
     inferred_outlives: Table<DefIndex, Lazy!(&'tcx [(ty::Predicate<'tcx>, Span)])>,
     super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
+    is_trivial_mir: Table<DefIndex, Lazy<bool>>,
     mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
     promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
     unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs
index a8f6723a35605..ae61093199fc5 100644
--- a/src/librustc_middle/query/mod.rs
+++ b/src/librustc_middle/query/mod.rs
@@ -260,6 +260,10 @@ rustc_queries! {
             }
         }
 
+        query is_trivial_mir(key: DefId) -> bool {
+            desc { |tcx| "checking if MIR for `{}` is trivial", tcx.def_path_str(key) }
+        }
+
         /// MIR after our optimization passes have run. This is MIR that is ready
         /// for codegen. This is also the only query that can fetch non-local MIR, at present.
         query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> {
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 92ea162e419db..881eec0c2d69a 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -38,7 +38,7 @@ struct CallSite<'tcx> {
 
 impl<'tcx> MirPass<'tcx> for Inline {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
-        if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
+        if tcx.sess.opts.debugging_opts.mir_opt_level >= 1 {
             if tcx.sess.opts.debugging_opts.instrument_coverage {
                 // The current implementation of source code coverage injects code region counters
                 // into the MIR, and assumes a 1-to-1 correspondence between MIR and source-code-
@@ -100,7 +100,12 @@ impl Inliner<'tcx> {
                     continue;
                 }
 
-                let callee_body = if let Some(callee_def_id) = callsite.callee.as_local() {
+                let callee_body = if self.tcx.is_trivial_mir(callsite.callee) {
+                    self.tcx.optimized_mir(callsite.callee)
+                } else if self.tcx.sess.opts.debugging_opts.mir_opt_level < 2 {
+                    // Only inline trivial functions by default.
+                    continue;
+                } else if let Some(callee_def_id) = callsite.callee.as_local() {
                     let callee_hir_id = self.tcx.hir().as_local_hir_id(callee_def_id);
                     let self_hir_id =
                         self.tcx.hir().as_local_hir_id(self.source.def_id().expect_local());
@@ -802,3 +807,44 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
         *scope = self.scope_map[*scope];
     }
 }
+
+struct FunctionCallFinder {
+    found: bool,
+}
+
+impl FunctionCallFinder {
+    fn new() -> Self {
+        FunctionCallFinder { found: false }
+    }
+}
+
+impl<'tcx> Visitor<'tcx> for FunctionCallFinder {
+    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, _location: Location) {
+        if let TerminatorKind::Call { .. } = terminator.kind {
+            self.found = true;
+        }
+    }
+}
+
+pub fn is_trivial_mir(tcx: TyCtxt<'tcx>, did: DefId) -> bool {
+    debug!("is_trivial_mir({:?})", did);
+    if tcx.is_constructor(did) {
+        debug!("is_trivial_mir = true (constructor)");
+        return true;
+    }
+
+    if let Some(did) = did.as_local() {
+        let body = tcx
+            .mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did))
+            .borrow();
+        let mut finder = FunctionCallFinder::new();
+        finder.visit_body(&body);
+        debug!("is_trivial_mir = {}", !finder.found);
+        !finder.found
+    } else {
+        // This branch is only taken if no `optimized_mir` is available for
+        // an extern crate, as `is_trivial_mir` has otherwise been encoded.
+        debug!("is_trivial_mir = false (no MIR available)");
+        false
+    }
+}
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 3803ee78fd4d9..aec1b9e952321 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -61,6 +61,7 @@ pub(crate) fn provide(providers: &mut Providers) {
         },
         mir_validated,
         mir_drops_elaborated_and_const_checked,
+        is_trivial_mir: inline::is_trivial_mir,
         optimized_mir,
         optimized_mir_of_const_arg,
         is_mir_available,
@@ -510,6 +511,8 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>)
         return shim::build_adt_ctor(tcx, def.did.to_def_id());
     }
 
+    // `is_trivial_mir` uses `mir_drops_elaborated_and_const_checked` so run that first.
+    tcx.ensure().is_trivial_mir(def.did.to_def_id());
     let mut body = tcx.mir_drops_elaborated_and_const_checked(def).steal();
     run_optimization_passes(tcx, &mut body, def.did, None);