diff --git a/csu/libc-start.c b/csu/libc-start.c
index c2dd159..a2d1391 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -108,6 +108,19 @@ apply_irel (void)
 # define ARCH_INIT_CPU_FEATURES()
 #endif
 
+#if defined ARCH_APPLY_IREL && defined ARCH_SETUP_IREL
+# error "Defining both ARCH_APPLY_IREL and ARCH_SETUP_IREL is prohibited."
+#endif
+
+#ifdef ARCH_APPLY_IREL
+# define ARCH_SETUP_IREL()
+#elif defined ARCH_SETUP_IREL
+# define ARCH_APPLY_IREL()
+#else
+# define ARCH_SETUP_IREL() apply_irel ()
+# define ARCH_APPLY_IREL()
+#endif
+
 STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
 					 MAIN_AUXVEC_DECL),
 			    int argc,
@@ -189,11 +202,16 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
   ARCH_INIT_CPU_FEATURES ();
 
   /* Perform IREL{,A} relocations.  */
-  apply_irel ();
+  ARCH_SETUP_IREL ();
 
   /* The stack guard goes into the TCB, so initialize it early.  */
   __libc_setup_tls ();
 
+  /* In some architectures, IREL{,A} relocations happen after TLS setup in
+     order to let IFUNC resolvers benefit from TCB information, e.g. powerpc's
+     hwcap and platform fields available in the TCB.  */
+  ARCH_APPLY_IREL ();
+
   /* Set up the stack checker's canary.  */
   uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
 # ifdef THREAD_SET_STACK_GUARD
@@ -224,7 +242,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
   __pointer_chk_guard_local = pointer_chk_guard;
 # endif
 
-#endif
+#endif /* !SHARED  */
 
   /* Register the destructor of the dynamic linker if there is any.  */
   if (__glibc_likely (rtld_fini != NULL))
diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile
index e03a202..0d9206b 100644
--- a/sysdeps/powerpc/Makefile
+++ b/sysdeps/powerpc/Makefile
@@ -11,7 +11,15 @@ sysdep-rtld-routines += dl-machine hwcapinfo
 # Don't optimize GD tls sequence to LE.
 LDFLAGS-tst-tlsopt-powerpc += -Wl,--no-tls-optimize
 tests += tst-tlsopt-powerpc
-endif
+
+ifneq (no,$(multi-arch))
+tests-static += tst-tlsifunc-static
+tests-internal += tst-tlsifunc-static
+ifeq (yes,$(build-shared))
+tests-internal += tst-tlsifunc
+endif # build-shared
+endif # multi-arch
+endif # subdir = elf
 
 ifeq ($(subdir),setjmp)
 ifeq (yes,$(build-shared))
diff --git a/sysdeps/powerpc/powerpc64le/Makefile b/sysdeps/powerpc/powerpc64le/Makefile
index bd8a82d..90a41b1 100644
--- a/sysdeps/powerpc/powerpc64le/Makefile
+++ b/sysdeps/powerpc/powerpc64le/Makefile
@@ -1,6 +1,11 @@
 # When building float128 we need to ensure -mfloat128 is
 # passed to all such object files.
 
+# libgcc requires __tcb_parse_hwcap_and_convert_at_platform when built with
+# a binary128 type.  That symbol is provided by the loader on dynamically
+# linked executables, forcing to link the loader after libgcc link.
+f128-loader-link = $(as-needed) $(elf-objpfx)ld.so $(no-as-needed)
+
 ifeq ($(subdir),math)
 # sqrtf128 requires emulation before POWER9.
 CPPFLAGS += -I../soft-fp
@@ -11,6 +16,8 @@ $(foreach suf,$(all-object-suffixes),%f128_r$(suf)): CFLAGS += -mfloat128
 $(objpfx)test-float128%.o $(objpfx)test-float128%.os: CFLAGS += -mfloat128
 $(objpfx)test-ifloat128%.o $(objpfx)test-ifloat128%.os: CFLAGS += -mfloat128
 CFLAGS-libm-test-support-float128.c += -mfloat128
+$(objpfx)test-float128% $(objpfx)test-ifloat128%: \
+  gnulib-tests += $(f128-loader-link)
 endif
 
 # Append flags to string <-> _Float128 routines.
@@ -24,6 +31,9 @@ CFLAGS-tst-strtod6.c += -mfloat128
 CFLAGS-tst-strfrom.c += -mfloat128
 CFLAGS-tst-strfrom-locale.c += -mfloat128
 CFLAGS-strfrom-skeleton.c += -mfloat128
+$(foreach test,bug-strtod bug-strtod2 bug-strtod2 tst-strtod-round \
+tst-wcstod-round tst-strtod6 tst-strrom tst-strfrom-locale \
+strfrom-skeleton,$(objpfx)$(test)): gnulib-tests += $(f128-loader-link)
 
 # When building glibc with support for _Float128, the powers of ten tables in
 # fpioconst.c and in the string conversion functions must be extended.
diff --git a/sysdeps/powerpc/tst-tlsifunc-static.c b/sysdeps/powerpc/tst-tlsifunc-static.c
new file mode 100644
index 0000000..e5313af
--- /dev/null
+++ b/sysdeps/powerpc/tst-tlsifunc-static.c
@@ -0,0 +1,19 @@
+/* Test if an executable can read from the TLS from an STT_GNU_IFUNC resolver.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "tst-tlsifunc.c"
diff --git a/sysdeps/powerpc/tst-tlsifunc.c b/sysdeps/powerpc/tst-tlsifunc.c
new file mode 100644
index 0000000..6d6af8a
--- /dev/null
+++ b/sysdeps/powerpc/tst-tlsifunc.c
@@ -0,0 +1,68 @@
+/* Test if an executable can read from the TLS from an STT_GNU_IFUNC resolver.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <libc-symbols.h>
+#include <tls-macros.h>
+
+__thread int bar;
+static int *bar_ptr = NULL;
+
+int foo (void);
+
+void
+init_foo (void)
+{
+  bar_ptr = TLS_GD (bar);
+}
+
+int
+my_foo (void)
+{
+  printf ("&bar = %p and bar_ptr = %p.\n", &bar, bar_ptr);
+  return bar_ptr != NULL;
+}
+
+__ifunc (foo, foo, my_foo, void, init_foo);
+
+static int
+do_test (void)
+{
+  int ret = 0;
+
+  if (foo ())
+    printf ("PASS: IFUNC resolver called once.\n");
+  else
+    {
+      printf ("FAIL: IFUNC resolver not called once.\n");
+      ret = 1;
+    }
+
+  if (&bar == bar_ptr)
+    printf ("PASS: Address read from IFUNC resolver is correct.\n");
+  else
+    {
+      printf ("FAIL: Address read from IFUNC resolver is incorrect.\n");
+      ret = 1;
+    }
+
+  return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/unix/sysv/linux/powerpc/libc-start.c b/sysdeps/unix/sysv/linux/powerpc/libc-start.c
index ad036c1..dc2df3c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/libc-start.c
+++ b/sysdeps/unix/sysv/linux/powerpc/libc-start.c
@@ -22,6 +22,8 @@
 
 #ifndef SHARED
 #include <hwcapinfo.h>
+static void apply_irel (void);
+# define ARCH_APPLY_IREL() apply_irel ()
 #endif
 
 int __cache_line_size attribute_hidden;
