diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 6c18e753d790b..c8038e5e0fccb 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -921,12 +921,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         span_bug!(span, "invalid type for asm sym (fn)");
                     }
                 }
-                mir::InlineAsmOperand::SymStatic { ref value } => {
-                    if let Some(def_id) = value.check_static_ptr(bx.tcx()) {
-                        InlineAsmOperandRef::SymStatic { def_id }
-                    } else {
-                        span_bug!(span, "invalid type for asm sym (static)");
-                    }
+                mir::InlineAsmOperand::SymStatic { def_id } => {
+                    InlineAsmOperandRef::SymStatic { def_id }
                 }
             })
             .collect();
diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs
index 904424462bfe7..9df42679ade04 100644
--- a/src/librustc_middle/mir/mod.rs
+++ b/src/librustc_middle/mir/mod.rs
@@ -1240,7 +1240,7 @@ pub enum InlineAsmOperand<'tcx> {
         value: Box<Constant<'tcx>>,
     },
     SymStatic {
-        value: Box<Constant<'tcx>>,
+        def_id: DefId,
     },
 }
 
@@ -1636,9 +1636,11 @@ impl<'tcx> TerminatorKind<'tcx> {
                         InlineAsmOperand::Const { value } => {
                             write!(fmt, "const {:?}", value)?;
                         }
-                        InlineAsmOperand::SymFn { value }
-                        | InlineAsmOperand::SymStatic { value } => {
-                            write!(fmt, "sym {:?}", value)?;
+                        InlineAsmOperand::SymFn { value } => {
+                            write!(fmt, "sym_fn {:?}", value)?;
+                        }
+                        InlineAsmOperand::SymStatic { def_id } => {
+                            write!(fmt, "sym_static {:?}", def_id)?;
                         }
                     }
                 }
diff --git a/src/librustc_middle/mir/visit.rs b/src/librustc_middle/mir/visit.rs
index 351dc33dbe355..220dfa80f06ad 100644
--- a/src/librustc_middle/mir/visit.rs
+++ b/src/librustc_middle/mir/visit.rs
@@ -563,10 +563,10 @@ macro_rules! make_mir_visitor {
                                         );
                                     }
                                 }
-                                InlineAsmOperand::SymFn { value }
-                                | InlineAsmOperand::SymStatic { value } => {
+                                InlineAsmOperand::SymFn { value } => {
                                     self.visit_constant(value, source_location);
                                 }
+                                InlineAsmOperand::SymStatic { def_id: _ } => {}
                             }
                         }
                     }
diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs
index 9c23ee74413cb..a0935517aaaea 100644
--- a/src/librustc_mir/borrow_check/invalidation.rs
+++ b/src/librustc_mir/borrow_check/invalidation.rs
@@ -208,7 +208,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                             }
                         }
                         InlineAsmOperand::SymFn { value: _ }
-                        | InlineAsmOperand::SymStatic { value: _ } => {}
+                        | InlineAsmOperand::SymStatic { def_id: _ } => {}
                     }
                 }
             }
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index d17c111d0c42c..8f2977039280b 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -759,7 +759,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
                             }
                         }
                         InlineAsmOperand::SymFn { value: _ }
-                        | InlineAsmOperand::SymStatic { value: _ } => {}
+                        | InlineAsmOperand::SymStatic { def_id: _ } => {}
                     }
                 }
             }
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index da02211d002a8..4e8b796d500d9 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -439,7 +439,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                             }
                         }
                         InlineAsmOperand::SymFn { value: _ }
-                        | InlineAsmOperand::SymStatic { value: _ } => {}
+                        | InlineAsmOperand::SymStatic { def_id: _ } => {}
                     }
                 }
             }
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 297b899ef0bd6..c4dadf0938b58 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -634,9 +634,19 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
             }
             mir::TerminatorKind::InlineAsm { ref operands, .. } => {
                 for op in operands {
-                    if let mir::InlineAsmOperand::SymFn { value } = op {
-                        let fn_ty = self.monomorphize(value.literal.ty);
-                        visit_fn_use(self.tcx, fn_ty, false, &mut self.output);
+                    match *op {
+                        mir::InlineAsmOperand::SymFn { ref value } => {
+                            let fn_ty = self.monomorphize(value.literal.ty);
+                            visit_fn_use(self.tcx, fn_ty, false, &mut self.output);
+                        }
+                        mir::InlineAsmOperand::SymStatic { def_id } => {
+                            let instance = Instance::mono(self.tcx, def_id);
+                            if should_monomorphize_locally(self.tcx, &instance) {
+                                trace!("collecting asm sym static {:?}", def_id);
+                                self.output.push(MonoItem::Static(def_id));
+                            }
+                        }
+                        _ => {}
                     }
                 }
             }
diff --git a/src/librustc_mir_build/build/expr/into.rs b/src/librustc_mir_build/build/expr/into.rs
index d5d1ddc5b7d7b..6b8d13de96a33 100644
--- a/src/librustc_mir_build/build/expr/into.rs
+++ b/src/librustc_mir_build/build/expr/into.rs
@@ -353,8 +353,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         hair::InlineAsmOperand::SymFn { expr } => {
                             mir::InlineAsmOperand::SymFn { value: box this.as_constant(expr) }
                         }
-                        hair::InlineAsmOperand::SymStatic { expr } => {
-                            mir::InlineAsmOperand::SymStatic { value: box this.as_constant(expr) }
+                        hair::InlineAsmOperand::SymStatic { def_id } => {
+                            mir::InlineAsmOperand::SymStatic { def_id }
                         }
                     })
                     .collect();
diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs
index d0b35f3212251..ef038a132d9ac 100644
--- a/src/librustc_mir_build/hair/cx/expr.rs
+++ b/src/librustc_mir_build/hair/cx/expr.rs
@@ -465,25 +465,8 @@ fn make_mirror_unadjusted<'a, 'tcx>(
                                     }
                                 }
 
-                                Res::Def(DefKind::Static, id) => {
-                                    ty = cx.tcx.static_ptr_ty(id);
-                                    let ptr = cx.tcx.create_static_alloc(id);
-                                    InlineAsmOperand::SymStatic {
-                                        expr: Expr {
-                                            ty,
-                                            temp_lifetime,
-                                            span: expr.span,
-                                            kind: ExprKind::StaticRef {
-                                                literal: ty::Const::from_scalar(
-                                                    cx.tcx,
-                                                    Scalar::Ptr(ptr.into()),
-                                                    ty,
-                                                ),
-                                                def_id: id,
-                                            },
-                                        }
-                                        .to_ref(),
-                                    }
+                                Res::Def(DefKind::Static, def_id) => {
+                                    InlineAsmOperand::SymStatic { def_id }
                                 }
 
                                 _ => {
diff --git a/src/librustc_mir_build/hair/mod.rs b/src/librustc_mir_build/hair/mod.rs
index c869699bb20e4..5f280e8568cd4 100644
--- a/src/librustc_mir_build/hair/mod.rs
+++ b/src/librustc_mir_build/hair/mod.rs
@@ -374,7 +374,7 @@ crate enum InlineAsmOperand<'tcx> {
         expr: ExprRef<'tcx>,
     },
     SymStatic {
-        expr: ExprRef<'tcx>,
+        def_id: DefId,
     },
 }
 
diff --git a/src/test/ui/asm/sym.rs b/src/test/ui/asm/sym.rs
index 83a3672af49ce..8cff16aa75f69 100644
--- a/src/test/ui/asm/sym.rs
+++ b/src/test/ui/asm/sym.rs
@@ -1,8 +1,9 @@
 // no-system-llvm
 // only-x86_64
+// only-linux
 // run-pass
 
-#![feature(asm, track_caller)]
+#![feature(asm, track_caller, thread_local)]
 
 extern "C" fn f1() -> i32 {
     111
@@ -15,9 +16,9 @@ fn f2() -> i32 {
 }
 
 macro_rules! call {
-    ($func:path) => {{
-        let result: i32;
+    ($func:path) => {
         unsafe {
+            let result: i32;
             asm!("call {}", sym $func,
                 out("rax") result,
                 out("rcx") _, out("rdx") _, out("rdi") _, out("rsi") _,
@@ -27,12 +28,53 @@ macro_rules! call {
                 out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _,
                 out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _,
             );
+            result
         }
-        result
-    }}
+    }
 }
 
+macro_rules! static_addr {
+    ($s:expr) => {
+        unsafe {
+            let result: *const u32;
+            // LEA performs a RIP-relative address calculation and returns the address
+            asm!("lea {}, [rip + {}]", out(reg) result, sym $s);
+            result
+        }
+    }
+}
+macro_rules! static_tls_addr {
+    ($s:expr) => {
+        unsafe {
+            let result: *const u32;
+            asm!(
+                "
+                    # Load TLS base address
+                    mov {out}, qword ptr fs:[0]
+                    # Calculate the address of sym in the TLS block. The @tpoff
+                    # relocation gives the offset of the symbol from the start
+                    # of the TLS block.
+                    lea {out}, [{out} + {sym}@tpoff]
+                ",
+                out = out(reg) result,
+                sym = sym $s
+            );
+            result
+        }
+    }
+}
+
+static S1: u32 = 111;
+#[thread_local]
+static S2: u32 = 222;
+
 fn main() {
     assert_eq!(call!(f1), 111);
     assert_eq!(call!(f2), 222);
+    assert_eq!(static_addr!(S1), &S1 as *const u32);
+    assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
+    std::thread::spawn(|| {
+        assert_eq!(static_addr!(S1), &S1 as *const u32);
+        assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
+    });
 }