Differential Revision: http://reviews.llvm.org/D19040

llvm-svn: 267229
diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp b/llvm/lib/Target/X86/X86Subtarget.cpp
index c8af972..d02a99f 100644
--- a/llvm/lib/Target/X86/X86Subtarget.cpp
+++ b/llvm/lib/Target/X86/X86Subtarget.cpp
@@ -83,8 +83,12 @@
     } else if (!isTargetWin64()) {
       assert(isTargetELF() && "Unknown rip-relative target");
 
-      // Extra load is needed for all externally visible globals.
-      if (!GV->hasLocalLinkage() && GV->hasDefaultVisibility())
+      // Extra load is needed for all externally visible globals except with
+      // PIE as the definition of the global in an executable is not
+      // overridden.
+
+      if (!GV->hasLocalLinkage() && GV->hasDefaultVisibility() &&
+          !isGlobalDefinedInPIE(GV, TM))
         return X86II::MO_GOTPCREL;
     }
 
@@ -92,8 +96,11 @@
   }
 
   if (isPICStyleGOT()) {   // 32-bit ELF targets.
-    // Extra load is needed for all externally visible.
-    if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
+    // Extra load is needed for all externally visible globals except with
+    // PIE as the definition of the global in an executable is not overridden.
+
+    if (GV->hasLocalLinkage() || GV->hasHiddenVisibility() ||
+        isGlobalDefinedInPIE(GV, TM))
       return X86II::MO_GOTOFF;
     return X86II::MO_GOT;
   }
diff --git a/llvm/lib/Target/X86/X86Subtarget.h b/llvm/lib/Target/X86/X86Subtarget.h
index 7713656..170e5c3 100644
--- a/llvm/lib/Target/X86/X86Subtarget.h
+++ b/llvm/lib/Target/X86/X86Subtarget.h
@@ -548,6 +548,14 @@
     }
   }
 
+  /// Determine if this global is defined in a Position Independent
+  /// Executable (PIE) where its definition cannot be interposed.
+  bool isGlobalDefinedInPIE(const GlobalValue *GV,
+                            const TargetMachine &TM) const {
+    return TM.Options.PositionIndependentExecutable &&
+           !GV->isDeclarationForLinker();
+  }
+
   /// ClassifyGlobalReference - Classify a global variable reference for the
   /// current subtarget according to how we should reference it in a non-pcrel
   /// context.