diff --git a/llvm/lib/Target/PowerPC/P10InstrResources.td b/llvm/lib/Target/PowerPC/P10InstrResources.td
--- a/llvm/lib/Target/PowerPC/P10InstrResources.td
+++ b/llvm/lib/Target/PowerPC/P10InstrResources.td
@@ -1296,11 +1296,9 @@
     LD,  LDtoc,  LDtocBA,  LDtocCPT,  LDtocJTI,  LDtocL, SPILLTOVSR_LD,
     LDBRX,
      DFLOADf32, DFLOADf64, LFD,
-    LFDX,  XFLOADf32, XFLOADf64,
     LFIWAX, LIWAX,
     LFIWZX, LIWZX,
     LHA, LHA8,
-    LHAX, LHAX8,
     LHBRX, LHBRX8,
     LHZ, LHZ8,
     LVEBX,
@@ -1309,7 +1307,7 @@
     LVX,
     LVXL,
     LWA, LWA_32,
-    LWAX, LWAX_32,
+    LWAX, LWAXTLS, LWAXTLS_, LWAXTLS_32, LWAX_32,
     LWBRX, LWBRX8,
     LWZ, LWZ8,  LWZtoc, LWZtocL,
     LXSD,
@@ -1340,6 +1338,8 @@
     ICBT,
     LBZX, LBZX8, LBZXTLS, LBZXTLS_, LBZXTLS_32,
     LDX, LDXTLS, LDXTLS_, SPILLTOVSR_LDX,
+    LFDX, LFDXTLS, LFDXTLS_,  XFLOADf32, XFLOADf64,
+    LHAX, LHAX8, LHAXTLS, LHAXTLS_, LHAXTLS_32,
     LHZX, LHZX8, LHZXTLS, LHZXTLS_, LHZXTLS_32,
     LWZX, LWZX8, LWZXTLS, LWZXTLS_, LWZXTLS_32,
     LXVL,
@@ -1442,11 +1442,17 @@
 def : InstRW<[P10W_LD_6C, P10W_DISP_PAIR, P10W_F2_4C],
       (instrs
     LFS,
-    LFSX,
     LXSSP,
     LXSSPX
 )>;
 
+// 2-way crack instructions
+// 6 Cycles Load operations, and 4 Cycles ALU2 operations, 2 input operands
+def : InstRW<[P10W_LD_6C, P10W_DISP_PAIR, P10W_F2_4C],
+      (instrs
+    LFSX, LFSXTLS, LFSXTLS_
+)>;
+
 // 4-way crack instructions
 // 6 Cycles Load operations, 4 Cycles ALU2 operations, 3 Cycles Simple Fixed-point (SFX) operations, and 3 Cycles ALU operations, 1 input operands
 def : InstRW<[P10W_LD_6C, P10W_DISP_PAIR, P10W_F2_4C, P10W_SX_3C, P10W_DISP_ANY, P10W_FX_3C, P10W_DISP_ANY],
@@ -1823,12 +1829,10 @@
      DFSTOREf32, DFSTOREf64, STFD,
     STFDU,
     STFDUX,
-    STFDX,
     STFIWX, STIWX,
     STFS,
     STFSU,
     STFSUX,
-    STFSX,
     STH, STH8,
     STHBRX,
     STHU, STHU8,
@@ -1867,6 +1871,8 @@
     CP_COPY, CP_COPY8,
     STBX, STBX8, STBXTLS, STBXTLS_, STBXTLS_32,
     SPILLTOVSR_STX, STDX, STDXTLS, STDXTLS_,
+    STFDX, STFDXTLS, STFDXTLS_,
+    STFSX, STFSXTLS, STFSXTLS_,
     STHX, STHX8, STHXTLS, STHXTLS_, STHXTLS_32,
     STWX, STWX8, STWXTLS, STWXTLS_, STWXTLS_32,
     STXVL,
diff --git a/llvm/lib/Target/PowerPC/P9InstrResources.td b/llvm/lib/Target/PowerPC/P9InstrResources.td
--- a/llvm/lib/Target/PowerPC/P9InstrResources.td
+++ b/llvm/lib/Target/PowerPC/P9InstrResources.td
@@ -765,6 +765,7 @@
       (instrs
     LFIWZX,
     LFDX,
+    (instregex "LFDXTLS?(_)?$"),
     LFD
 )>;
 
@@ -815,9 +816,9 @@
 def : InstRW<[P9_LoadAndALUOp_6C, IP_EXEC_1C, IP_AGEN_1C,
               DISP_1C, DISP_1C],
       (instrs
-    (instregex "LHA(X)?(8)?$"),
+    (instregex "LHA(X)?(TLS)?(8)?(_32)?(_)?$"),
     (instregex "CP_PASTE(8)?_rec$"),
-    (instregex "LWA(X)?(_32)?$"),
+    (instregex "LWA(X)?(TLS)?(_32)?(_)?$"),
     TCHECK
 )>;
 
@@ -850,6 +851,7 @@
               DISP_3SLOTS_1C, DISP_3SLOTS_1C],
       (instrs
     LFSX,
+    (instregex "LFSXTLS?(_)?$"),
     LFS
 )>;
 
@@ -891,7 +893,7 @@
 // all three dispatches for the superslice.
 def : InstRW<[P9_LS_1C, IP_EXEC_1C, IP_AGEN_1C, DISP_3SLOTS_1C],
       (instrs
-    (instregex "STF(S|D|IWX|SX|DX)$"),
+    (instregex "STF(S|D|IWX|SX|DX|SXTLS|DXTLS|SXTLS_|DXTLS_)$"),
     (instregex "STXS(D|DX|SPX|IWX|IBX|IHX|SP)(v)?$"),
     (instregex "STW(8)?$"),
     (instregex "(D|X)FSTORE(f32|f64)$"),
diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
--- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -738,6 +738,14 @@
       Opcode = PPC::STDXTLS;
       break;
     }
+    case MVT::f32: {
+      Opcode = PPC::STFSXTLS;
+      break;
+    }
+    case MVT::f64: {
+      Opcode = PPC::STFDXTLS;
+      break;
+    }
   }
   SDValue Chain = ST->getChain();
   SDVTList VTs = ST->getVTList();
@@ -762,6 +770,7 @@
   SDLoc dl(LD);
   EVT MemVT = LD->getMemoryVT();
   EVT RegVT = LD->getValueType(0);
+  bool isSExt = LD->getExtensionType() == ISD::SEXTLOAD;
   unsigned Opcode;
   switch (MemVT.getSimpleVT().SimpleTy) {
     default:
@@ -771,17 +780,29 @@
       break;
     }
     case MVT::i16: {
-      Opcode = (RegVT == MVT::i32) ? PPC::LHZXTLS_32 : PPC::LHZXTLS;
+      Opcode = (RegVT == MVT::i32) ? isSExt ? PPC::LHAXTLS_32 : PPC::LHZXTLS_32
+               : isSExt            ? PPC::LHAXTLS
+                                   : PPC::LHZXTLS;
       break;
     }
     case MVT::i32: {
-      Opcode = (RegVT == MVT::i32) ? PPC::LWZXTLS_32 : PPC::LWZXTLS;
+      Opcode = (RegVT == MVT::i32) ? isSExt ? PPC::LWAXTLS_32 : PPC::LWZXTLS_32
+               : isSExt            ? PPC::LWAXTLS
+                                   : PPC::LWZXTLS;
       break;
     }
     case MVT::i64: {
       Opcode = PPC::LDXTLS;
       break;
     }
+    case MVT::f32: {
+      Opcode = PPC::LFSXTLS;
+      break;
+    }
+    case MVT::f64: {
+      Opcode = PPC::LFDXTLS;
+      break;
+    }
   }
   SDValue Chain = LD->getChain();
   SDVTList VTs = LD->getVTList();
diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -724,18 +724,32 @@
                       "lbzx $RST, $RA, $RB", IIC_LdStLoad, []>;
 def LHZXTLS : XForm_1<31, 279, (outs g8rc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
                       "lhzx $RST, $RA, $RB", IIC_LdStLoad, []>;
+def LHAXTLS : XForm_1<31, 343, (outs g8rc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
+                      "lhax $RST, $RA, $RB", IIC_LdStLoad, []>;
 def LWZXTLS : XForm_1<31,  23, (outs g8rc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
                       "lwzx $RST, $RA, $RB", IIC_LdStLoad, []>;
+def LWAXTLS : XForm_1<31, 341, (outs g8rc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
+                      "lwax $RST, $RA, $RB", IIC_LdStLoad, []>;
 def LDXTLS  : XForm_1<31,  21, (outs g8rc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
                       "ldx $RST, $RA, $RB", IIC_LdStLD, []>, isPPC64;
 def LBZXTLS_32 : XForm_1<31,  87, (outs gprc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
                          "lbzx $RST, $RA, $RB", IIC_LdStLoad, []>;
 def LHZXTLS_32 : XForm_1<31, 279, (outs gprc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
                          "lhzx $RST, $RA, $RB", IIC_LdStLoad, []>;
+def LHAXTLS_32 : XForm_1<31, 343, (outs gprc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
+                         "lhax $RST, $RA, $RB", IIC_LdStLoad, []>;
 def LWZXTLS_32 : XForm_1<31,  23, (outs gprc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
                          "lwzx $RST, $RA, $RB", IIC_LdStLoad, []>;
+def LWAXTLS_32 : XForm_1<31, 341, (outs gprc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
+                         "lwax $RST, $RA, $RB", IIC_LdStLoad, []>;
 
 }
+let mayLoad = 1, Predicates = [HasFPU] in {
+def LFSXTLS : XForm_25<31, 535, (outs f4rc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
+                       "lfsx $RST, $RA, $RB", IIC_LdStLFD, []>;
+def LFDXTLS : XForm_25<31, 599, (outs f8rc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
+                       "lfdx $RST, $RA, $RB", IIC_LdStLFD, []>;
+}
 
 let mayStore = 1 in {
 def STBXTLS : XForm_8<31, 215, (outs), (ins g8rc:$RST, ptr_rc_nor0:$RA, tlsreg:$RB),
@@ -761,6 +775,14 @@
                          PPC970_DGroup_Cracked;
 
 }
+let mayStore = 1, Predicates = [HasFPU] in {
+def STFSXTLS : XForm_8<31, 663, (outs), (ins f4rc:$RST, ptr_rc_nor0:$RA, tlsreg:$RB),
+                       "stfsx $RST, $RA, $RB", IIC_LdStSTFD, []>,
+                       PPC970_DGroup_Cracked;
+def STFDXTLS : XForm_8<31, 727, (outs), (ins f8rc:$RST, ptr_rc_nor0:$RA, tlsreg:$RB),
+                       "stfdx $RST, $RA, $RB", IIC_LdStSTFD, []>,
+                       PPC970_DGroup_Cracked;
+}
 
 let isCommutable = 1 in
 defm ADDC8 : XOForm_1rc<31, 10, 0, (outs g8rc:$RT), (ins g8rc:$RA, g8rc:$RB),
@@ -834,12 +856,23 @@
                       "lbzx $RST, $RA, $RB", IIC_LdStLoad, []>;
 def LHZXTLS_ : XForm_1<31, 279, (outs g8rc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
                       "lhzx $RST, $RA, $RB", IIC_LdStLoad, []>;
+def LHAXTLS_ : XForm_1<31, 343, (outs g8rc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
+                       "lhax $RST, $RA, $RB", IIC_LdStLoad, []>;
 def LWZXTLS_ : XForm_1<31,  23, (outs g8rc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
                       "lwzx $RST, $RA, $RB", IIC_LdStLoad, []>;
+def LWAXTLS_ : XForm_1<31, 341, (outs g8rc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
+                       "lwax $RST, $RA, $RB", IIC_LdStLoad, []>;
 def LDXTLS_  : XForm_1<31,  21, (outs g8rc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
                       "ldx $RST, $RA, $RB", IIC_LdStLD, []>, isPPC64;
 }
 
+let mayLoad = 1, Predicates = [HasFPU] in {
+def LFSXTLS_ : XForm_25<31, 535, (outs f4rc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
+                        "lfsx $RST, $RA, $RB", IIC_LdStLFD, []>;
+def LFDXTLS_ : XForm_25<31, 599, (outs f8rc:$RST), (ins ptr_rc_nor0:$RA, tlsreg:$RB),
+                        "lfdx $RST, $RA, $RB", IIC_LdStLFD, []>;
+}
+
 let mayStore = 1 in {
 def STBXTLS_ : XForm_8<31, 215, (outs), (ins g8rc:$RST, ptr_rc_nor0:$RA, tlsreg:$RB),
                       "stbx $RST, $RA, $RB", IIC_LdStStore, []>,
@@ -854,6 +887,15 @@
                        "stdx $RST, $RA, $RB", IIC_LdStSTD, []>, isPPC64,
                        PPC970_DGroup_Cracked;
 }
+
+let mayStore = 1, Predicates = [HasFPU] in {
+def STFSXTLS_ : XForm_8<31, 663, (outs), (ins f4rc:$RST, ptr_rc_nor0:$RA, tlsreg:$RB),
+                        "stfsx $RST, $RA, $RB", IIC_LdStSTFD, []>,
+                        PPC970_DGroup_Cracked;
+def STFDXTLS_ : XForm_8<31, 727, (outs), (ins f8rc:$RST, ptr_rc_nor0:$RA, tlsreg:$RB),
+                        "stfdx $RST, $RA, $RB", IIC_LdStSTFD, []>,
+                        PPC970_DGroup_Cracked;
+}
 }
 
 let isCommutable = 1 in {
diff --git a/llvm/test/CodeGen/PowerPC/aix-vec_insert_elt.ll b/llvm/test/CodeGen/PowerPC/aix-vec_insert_elt.ll
--- a/llvm/test/CodeGen/PowerPC/aix-vec_insert_elt.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-vec_insert_elt.ll
@@ -592,8 +592,8 @@
 ;
 ; CHECK-32-P10-LABEL: testDouble1:
 ; CHECK-32-P10:       # %bb.0: # %entry
-; CHECK-32-P10-NEXT:    rlwinm 3, 5, 3, 28, 28
 ; CHECK-32-P10-NEXT:    addi 4, 1, -16
+; CHECK-32-P10-NEXT:    rlwinm 3, 5, 3, 28, 28
 ; CHECK-32-P10-NEXT:    stxv 34, -16(1)
 ; CHECK-32-P10-NEXT:    stfdx 1, 4, 3
 ; CHECK-32-P10-NEXT:    lxv 34, -16(1)
@@ -650,8 +650,8 @@
 ; CHECK-32-P10-LABEL: testDouble2:
 ; CHECK-32-P10:       # %bb.0: # %entry
 ; CHECK-32-P10-NEXT:    lfd 0, 0(3)
-; CHECK-32-P10-NEXT:    rlwinm 4, 4, 3, 28, 28
 ; CHECK-32-P10-NEXT:    addi 6, 1, -32
+; CHECK-32-P10-NEXT:    rlwinm 4, 4, 3, 28, 28
 ; CHECK-32-P10-NEXT:    stxv 34, -32(1)
 ; CHECK-32-P10-NEXT:    rlwinm 5, 5, 3, 28, 28
 ; CHECK-32-P10-NEXT:    stfdx 0, 6, 4
@@ -723,8 +723,8 @@
 ; CHECK-32-P10-LABEL: testDouble3:
 ; CHECK-32-P10:       # %bb.0: # %entry
 ; CHECK-32-P10-NEXT:    plfd 0, 65536(3), 0
-; CHECK-32-P10-NEXT:    rlwinm 4, 4, 3, 28, 28
 ; CHECK-32-P10-NEXT:    addi 6, 1, -32
+; CHECK-32-P10-NEXT:    rlwinm 4, 4, 3, 28, 28
 ; CHECK-32-P10-NEXT:    stxv 34, -32(1)
 ; CHECK-32-P10-NEXT:    rlwinm 5, 5, 3, 28, 28
 ; CHECK-32-P10-NEXT:    stfdx 0, 6, 4
diff --git a/llvm/test/CodeGen/PowerPC/tls-pie-xform.ll b/llvm/test/CodeGen/PowerPC/tls-pie-xform.ll
--- a/llvm/test/CodeGen/PowerPC/tls-pie-xform.ll
+++ b/llvm/test/CodeGen/PowerPC/tls-pie-xform.ll
@@ -5,6 +5,8 @@
 @var_short = external thread_local local_unnamed_addr global i16, align 2
 @var_int = external thread_local local_unnamed_addr global i32, align 4
 @var_long_long = external thread_local local_unnamed_addr global i64, align 8
+@var_float = external thread_local local_unnamed_addr global float, align 4
+@var_double = external thread_local local_unnamed_addr global double, align 8
 
 define dso_local zeroext i8 @test_char_one() {
 ; CHECK-LABEL: test_char_one:
@@ -53,6 +55,18 @@
 ; CHECK:       # %bb.0: # %entry
 ; CHECK-NEXT:    addis 3, 2, var_short@got@tprel@ha
 ; CHECK-NEXT:    ld 3, var_short@got@tprel@l(3)
+; CHECK-NEXT:    lhax 3, 3, var_short@tls
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i16, ptr @var_short, align 2, !tbaa !7
+  ret i16 %0
+}
+
+define dso_local zeroext i16 @test_short_one_zeroext() {
+; CHECK-LABEL: test_short_one_zeroext:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addis 3, 2, var_short@got@tprel@ha
+; CHECK-NEXT:    ld 3, var_short@got@tprel@l(3)
 ; CHECK-NEXT:    lhzx 3, 3, var_short@tls
 ; CHECK-NEXT:    blr
 entry:
@@ -95,6 +109,18 @@
 ; CHECK:       # %bb.0: # %entry
 ; CHECK-NEXT:    addis 3, 2, var_int@got@tprel@ha
 ; CHECK-NEXT:    ld 3, var_int@got@tprel@l(3)
+; CHECK-NEXT:    lwax 3, 3, var_int@tls
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i32, ptr @var_int, align 4, !tbaa !9
+  ret i32 %0
+}
+
+define dso_local zeroext i32 @test_int_one_zeroext() {
+; CHECK-LABEL: test_int_one_zeroext:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addis 3, 2, var_int@got@tprel@ha
+; CHECK-NEXT:    ld 3, var_int@got@tprel@l(3)
 ; CHECK-NEXT:    lwzx 3, 3, var_int@tls
 ; CHECK-NEXT:    blr
 entry:
@@ -172,6 +198,54 @@
   ret i64 %add
 }
 
+define float @test_float_one() {
+; CHECK-LABEL: test_float_one:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addis 3, 2, var_float@got@tprel@ha
+; CHECK-NEXT:    ld 3, var_float@got@tprel@l(3)
+; CHECK-NEXT:    lfsx 1, 3, var_float@tls
+; CHECK-NEXT:    blr
+entry:
+  %0 = load float, ptr @var_float, align 4
+  ret float %0
+}
+
+define void @test_float_two(float %a) {
+; CHECK-LABEL: test_float_two:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addis 3, 2, var_float@got@tprel@ha
+; CHECK-NEXT:    ld 3, var_float@got@tprel@l(3)
+; CHECK-NEXT:    stfsx 1, 3, var_float@tls
+; CHECK-NEXT:    blr
+entry:
+  store float %a, ptr @var_float, align 4
+  ret void
+}
+
+define double @test_double_one() {
+; CHECK-LABEL: test_double_one:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addis 3, 2, var_double@got@tprel@ha
+; CHECK-NEXT:    ld 3, var_double@got@tprel@l(3)
+; CHECK-NEXT:    lfdx 1, 3, var_double@tls
+; CHECK-NEXT:    blr
+entry:
+  %0 = load double, ptr @var_double, align 8
+  ret double %0
+}
+
+define void @test_double_two(double %a) {
+; CHECK-LABEL: test_double_two:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addis 3, 2, var_double@got@tprel@ha
+; CHECK-NEXT:    ld 3, var_double@got@tprel@l(3)
+; CHECK-NEXT:    stfdx 1, 3, var_double@tls
+; CHECK-NEXT:    blr
+entry:
+  store double %a, ptr @var_double, align 8
+  ret void
+}
+
 !llvm.module.flags = !{!0, !1, !2}
 
 !0 = !{i32 1, !"wchar_size", i32 4}
diff --git a/llvm/test/MC/PowerPC/ppc64-tls-relocs-01.s b/llvm/test/MC/PowerPC/ppc64-tls-relocs-01.s
--- a/llvm/test/MC/PowerPC/ppc64-tls-relocs-01.s
+++ b/llvm/test/MC/PowerPC/ppc64-tls-relocs-01.s
@@ -7,7 +7,9 @@
         addis 3, 2, t@got@tprel@ha
         ld 3, t@got@tprel@l(3)
         lwzx 4, 3, t@tls
+        lwax 4, 3, t@tls
         lhzx 4, 3, t@tls
+        lhax 4, 3, t@tls
         lbzx 4, 3, t@tls
         ldx 4, 3, t@tls
         stbx 4, 3, t@tls
@@ -38,4 +40,6 @@
 # CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_TLS t 0x0
 # CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_TLS t 0x0
 # CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_TLS t 0x0
+# CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_TLS t 0x0
+# CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_TLS t 0x0
 # CHECK-NEXT:   }
diff --git a/llvm/test/MC/PowerPC/ppc64-tls-relocs-double-01.s b/llvm/test/MC/PowerPC/ppc64-tls-relocs-double-01.s
new file mode 100644
--- /dev/null
+++ b/llvm/test/MC/PowerPC/ppc64-tls-relocs-double-01.s
@@ -0,0 +1,30 @@
+# RUN: llvm-mc -triple=powerpc64-unknown-linux-gnu -filetype=obj %s | \
+# RUN: llvm-readobj -r - | FileCheck %s
+
+        .text
+        addis 3, 13, myDouble@tprel@ha
+        addi 3, 3, myDouble@tprel@l
+        addis 3, 2, myDouble@got@tprel@ha
+        ld 3, myDouble@got@tprel@l(3)
+        lfdx 4, 3, myDouble@tls
+        stfdx 4, 3, myDouble@tls
+        .type myDouble,@object
+        .section .tbss,"awT",@nobits
+        .globl myDouble
+        .align 2
+
+myDouble:
+	.quad	0
+	.size	myDouble, 8
+
+# Check for a pair of R_PPC64_TPREL16_HA / R_PPC64_TPREL16_LO relocs
+# against the thread-local symbol 'myDouble'.
+# CHECK:      Relocations [
+# CHECK:        Section ({{[0-9]+}}) .rela.text {
+# CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_TPREL16_HA myDouble
+# CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_TPREL16_LO myDouble
+# CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_GOT_TPREL16_HA myDouble 0x0
+# CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_GOT_TPREL16_LO_DS myDouble 0x0
+# CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_TLS myDouble 0x0
+# CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_TLS myDouble 0x0
+# CHECK-NEXT:   }
diff --git a/llvm/test/MC/PowerPC/ppc64-tls-relocs-float-01.s b/llvm/test/MC/PowerPC/ppc64-tls-relocs-float-01.s
new file mode 100644
--- /dev/null
+++ b/llvm/test/MC/PowerPC/ppc64-tls-relocs-float-01.s
@@ -0,0 +1,30 @@
+# RUN: llvm-mc -triple=powerpc64-unknown-linux-gnu -filetype=obj %s | \
+# RUN: llvm-readobj -r - | FileCheck %s
+
+        .text
+        addis 3, 13, myFloat@tprel@ha
+        addi 3, 3, myFloat@tprel@l
+        addis 3, 2, myFloat@got@tprel@ha
+        ld 3, myFloat@got@tprel@l(3)
+        lfsx 4, 3, myFloat@tls
+        stfsx 4, 3, myFloat@tls
+        .type myFloat,@object
+        .section .tbss,"awT",@nobits
+        .globl myFloat
+        .align 2
+
+myFloat:
+	.long	0
+	.size	myFloat, 4
+
+# Check for a pair of R_PPC64_TPREL16_HA / R_PPC64_TPREL16_LO relocs
+# against the thread-local symbol 'myFloat'.
+# CHECK:      Relocations [
+# CHECK:        Section ({{[0-9]+}}) .rela.text {
+# CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_TPREL16_HA myFloat
+# CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_TPREL16_LO myFloat
+# CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_GOT_TPREL16_HA myFloat 0x0
+# CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_GOT_TPREL16_LO_DS myFloat 0x0
+# CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_TLS myFloat 0x0
+# CHECK-NEXT:     0x{{[0-9,A-F]+}} R_PPC64_TLS myFloat 0x0
+# CHECK-NEXT:   }