[clang] 850d53a - LTO: Decide upfront whether to use opaque/non-opaque pointer types

Matthias Braun via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 1 18:07:46 PDT 2022


Author: Matthias Braun
Date: 2022-06-01T18:05:53-07:00
New Revision: 850d53a197f9ffbf5708b7bd795056335e81e9b7

URL: https://github.com/llvm/llvm-project/commit/850d53a197f9ffbf5708b7bd795056335e81e9b7
DIFF: https://github.com/llvm/llvm-project/commit/850d53a197f9ffbf5708b7bd795056335e81e9b7.diff

LOG: LTO: Decide upfront whether to use opaque/non-opaque pointer types

LTO code may end up mixing bitcode files from various sources varying in
their use of opaque pointer types. The current strategy to decide
between opaque / typed pointers upon the first bitcode file loaded does
not work here, since we could be loading a non-opaque bitcode file first
and would then be unable to load any files with opaque pointer types
later.

So for LTO this:
- Adds an `lto::Config::OpaquePointer` option and enforces an upfront
  decision between the two modes.
- Adds `-opaque-pointers`/`-no-opaque-pointers` options to the gold
  plugin; disabled by default.
- `--opaque-pointers`/`--no-opaque-pointers` options with
  `-plugin-opt=-opaque-pointers`/`-plugin-opt=-no-opaque-pointers`
  aliases to lld; disabled by default.
- Adds an `-lto-opaque-pointers` option to the `llvm-lto2` tool.
- Changes the clang driver to pass `-plugin-opt=-opaque-pointers` to
  the linker in LTO modes when clang was configured with opaque
  pointers enabled by default.

This fixes https://github.com/llvm/llvm-project/issues/55377

Differential Revision: https://reviews.llvm.org/D125847

Added: 
    clang/test/Driver/lto-no-opaque-pointers.c
    clang/test/Driver/lto-opaque-pointers.c
    llvm/test/LTO/X86/Inputs/opaque-pointers.ll
    llvm/test/LTO/X86/mix-opaque-typed.ll

Modified: 
    clang/lib/Driver/ToolChains/CommonArgs.cpp
    clang/test/CodeGen/thinlto-inline-asm2.c
    clang/test/Driver/arm-float-abi-lto.c
    clang/test/Driver/memtag_lto.c
    lld/ELF/Config.h
    lld/ELF/Driver.cpp
    lld/ELF/LTO.cpp
    lld/ELF/Options.td
    lld/test/ELF/lto/discard-value-names.ll
    lld/test/ELF/lto/ltopasses-basic.ll
    lld/test/ELF/lto/type-merge.ll
    lld/test/ELF/lto/type-merge2.ll
    lld/test/ELF/lto/wrap-unreferenced-before-codegen.test
    llvm/docs/OpaquePointers.rst
    llvm/include/llvm/LTO/Config.h
    llvm/test/Analysis/StackSafetyAnalysis/ipa-alias.ll
    llvm/test/Analysis/StackSafetyAnalysis/ipa.ll
    llvm/test/LTO/Resolution/X86/alias-alias.ll
    llvm/test/LTO/Resolution/X86/comdat.ll
    llvm/test/LTO/Resolution/X86/ifunc2.ll
    llvm/test/LTO/Resolution/X86/local-def-dllimport.ll
    llvm/test/LTO/X86/cfi_jt_aliases.ll
    llvm/test/LTO/X86/type-mapping-bug4.ll
    llvm/test/ThinLTO/X86/Inputs/import-constant.ll
    llvm/test/ThinLTO/X86/cfi-devirt.ll
    llvm/test/ThinLTO/X86/cfi-unsat.ll
    llvm/test/ThinLTO/X86/devirt-after-icp.ll
    llvm/test/ThinLTO/X86/devirt2.ll
    llvm/test/ThinLTO/X86/devirt_check.ll
    llvm/test/ThinLTO/X86/devirt_promote.ll
    llvm/test/ThinLTO/X86/devirt_single_hybrid.ll
    llvm/test/ThinLTO/X86/funcattrs-prop-unknown.ll
    llvm/test/ThinLTO/X86/globals-import-blockaddr.ll
    llvm/test/ThinLTO/X86/import-constant.ll
    llvm/test/ThinLTO/X86/import-dsolocal.ll
    llvm/test/ThinLTO/X86/index-const-prop-gvref-pie.ll
    llvm/test/ThinLTO/X86/index-const-prop-gvref.ll
    llvm/test/ThinLTO/X86/index-const-prop-linkage.ll
    llvm/test/ThinLTO/X86/reference_non_importable.ll
    llvm/test/ThinLTO/X86/weak_externals.ll
    llvm/tools/gold/gold-plugin.cpp
    llvm/tools/llvm-lto2/llvm-lto2.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 7a22ac4afa7e8..7e9fa055b0bc2 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -559,6 +559,9 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
     CmdArgs.push_back(
         Args.MakeArgString("-plugin-opt=jobs=" + Twine(Parallelism)));
 
+  if (!CLANG_ENABLE_OPAQUE_POINTERS_INTERNAL)
+    CmdArgs.push_back(Args.MakeArgString("-plugin-opt=no-opaque-pointers"));
+
   // If an explicit debugger tuning argument appeared, pass it along.
   if (Arg *A = Args.getLastArg(options::OPT_gTune_Group,
                                options::OPT_ggdbN_Group)) {

diff  --git a/clang/test/CodeGen/thinlto-inline-asm2.c b/clang/test/CodeGen/thinlto-inline-asm2.c
index 5d7bbc097de7c..7606b27deac87 100644
--- a/clang/test/CodeGen/thinlto-inline-asm2.c
+++ b/clang/test/CodeGen/thinlto-inline-asm2.c
@@ -5,7 +5,7 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -flto=thin -emit-llvm-bc %t/b.c -o %t/b.bc
 // RUN: llvm-nm %t/a.bc | FileCheck %s --check-prefix=NM
 
-// RUN: llvm-lto2 run %t/a.bc %t/b.bc -o %t/out -save-temps -r=%t/a.bc,ref,plx -r=%t/b.bc,ff_h264_cabac_tables,pl
+// RUN: llvm-lto2 run -lto-opaque-pointers %t/a.bc %t/b.bc -o %t/out -save-temps -r=%t/a.bc,ref,plx -r=%t/b.bc,ff_h264_cabac_tables,pl
 // RUN: llvm-dis < %t/out.2.2.internalize.bc | FileCheck %s
 
 //--- a.c

diff  --git a/clang/test/Driver/arm-float-abi-lto.c b/clang/test/Driver/arm-float-abi-lto.c
index 83c2435d97a4d..8b6d8ff6b5d7a 100644
--- a/clang/test/Driver/arm-float-abi-lto.c
+++ b/clang/test/Driver/arm-float-abi-lto.c
@@ -2,9 +2,9 @@
 
 // RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -S -o - -emit-llvm -DCALL_LIB -DDEFINE_LIB | FileCheck %s
 
-// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=full -c -o %t.call_full.bc -DCALL_LIB
-// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=full -c -o %t.define_full.bc -DDEFINE_LIB
-// RUN: llvm-lto2 run -o %t.lto_full -save-temps %t.call_full.bc %t.define_full.bc \
+// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -Xclang -opaque-pointers -flto=full -c -o %t.call_full.bc -DCALL_LIB
+// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -Xclang -opaque-pointers -flto=full -c -o %t.define_full.bc -DDEFINE_LIB
+// RUN: llvm-lto2 run -lto-opaque-pointers -o %t.lto_full -save-temps %t.call_full.bc %t.define_full.bc \
 // RUN:  -r %t.call_full.bc,fn,px \
 // RUN:  -r %t.call_full.bc,fwrite,l \
 // RUN:  -r %t.call_full.bc,putchar,l \
@@ -14,9 +14,9 @@
 // RUN:  -r %t.define_full.bc,otherfn,px
 // RUN: llvm-dis %t.lto_full.0.4.opt.bc -o - | FileCheck %s
 
-// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=thin -c -o %t.call_thin.bc -DCALL_LIB
-// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=thin -c -o %t.define_thin.bc -DDEFINE_LIB
-// RUN: llvm-lto2 run -o %t.lto_thin -save-temps %t.call_thin.bc %t.define_thin.bc \
+// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -Xclang -opaque-pointers -flto=thin -c -o %t.call_thin.bc -DCALL_LIB
+// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -Xclang -opaque-pointers -flto=thin -c -o %t.define_thin.bc -DDEFINE_LIB
+// RUN: llvm-lto2 run -lto-opaque-pointers -o %t.lto_thin -save-temps %t.call_thin.bc %t.define_thin.bc \
 // RUN:  -r %t.call_thin.bc,fn,px \
 // RUN:  -r %t.call_thin.bc,fwrite,l \
 // RUN:  -r %t.call_thin.bc,putchar,l \

diff  --git a/clang/test/Driver/lto-no-opaque-pointers.c b/clang/test/Driver/lto-no-opaque-pointers.c
new file mode 100644
index 0000000000000..9146ae5da5824
--- /dev/null
+++ b/clang/test/Driver/lto-no-opaque-pointers.c
@@ -0,0 +1,5 @@
+// UNSUPPORTED: enable-opaque-pointers
+// RUN: %clang --target=x86_64-unknown-linux -### %s -flto 2> %t
+// RUN: FileCheck %s < %t
+
+// CHECK: -plugin-opt=no-opaque-pointers

diff  --git a/clang/test/Driver/lto-opaque-pointers.c b/clang/test/Driver/lto-opaque-pointers.c
new file mode 100644
index 0000000000000..acdf13c21fd41
--- /dev/null
+++ b/clang/test/Driver/lto-opaque-pointers.c
@@ -0,0 +1,5 @@
+// REQUIRES: enable-opaque-pointers
+// RUN: %clang --target=x86_64-unknown-linux -### %s -flto 2> %t
+// RUN: FileCheck %s < %t
+
+// CHECK-NOT: -plugin-opt=no-opaque-pointers

diff  --git a/clang/test/Driver/memtag_lto.c b/clang/test/Driver/memtag_lto.c
index d73670f99cb60..2ad22141608c7 100644
--- a/clang/test/Driver/memtag_lto.c
+++ b/clang/test/Driver/memtag_lto.c
@@ -8,9 +8,9 @@
 // RUN: %clang -O1 -target aarch64-unknown-linux -mllvm -stack-safety-print %s -S -o - 2>&1 | FileCheck %s
 
 // Full LTO
-// RUN: %clang -O1 -target aarch64-unknown-linux -c %s -flto=full -o %t.ltonewpm1.bc
-// RUN: %clang -O1 -target aarch64-unknown-linux -c -DBUILD2 %s -flto=full -o %t.ltonewpm2.bc
-// RUN: llvm-lto2 run -o %t.ltonewpm %t.ltonewpm1.bc %t.ltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \
+// RUN: %clang -O1 -target aarch64-unknown-linux -c %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm1.bc
+// RUN: %clang -O1 -target aarch64-unknown-linux -c -DBUILD2 %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm2.bc
+// RUN: llvm-lto2 run -lto-opaque-pointers -o %t.ltonewpm %t.ltonewpm1.bc %t.ltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \
 // RUN:  -r %t.ltonewpm1.bc,fn,plx \
 // RUN:  -r %t.ltonewpm1.bc,use,lx \
 // RUN:  -r %t.ltonewpm1.bc,use_local,plx \
@@ -19,9 +19,9 @@
 // RUN:  -r %t.ltonewpm2.bc,z, 2>&1 | FileCheck %s --allow-empty
 
 // Thin LTO, new PM
-// RUN: %clang -O1 -target aarch64-unknown-linux -c %s -flto=thin -o %t.thinltonewpm1.bc
-// RUN: %clang -O1 -target aarch64-unknown-linux -c -DBUILD2 %s -flto=thin -o %t.thinltonewpm2.bc
-// RUN: llvm-lto2 run -o %t.thinltonewpm %t.thinltonewpm1.bc %t.thinltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \
+// RUN: %clang -O1 -target aarch64-unknown-linux -c %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm1.bc
+// RUN: %clang -O1 -target aarch64-unknown-linux -c -DBUILD2 %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm2.bc
+// RUN: llvm-lto2 run -lto-opaque-pointers -o %t.thinltonewpm %t.thinltonewpm1.bc %t.thinltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \
 // RUN:  -r %t.thinltonewpm1.bc,fn,plx \
 // RUN:  -r %t.thinltonewpm1.bc,use,lx \
 // RUN:  -r %t.thinltonewpm1.bc,use_local,plx \
@@ -39,9 +39,9 @@
 // RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -mllvm -stack-safety-print %s -S -o /dev/null 2>&1 | FileCheck %s -check-prefixes=SSI,XUNSAFE,YSAFE
 
 // Full LTO: both are safe.
-// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -flto=full -o %t.ltonewpm1.bc
-// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c -DBUILD2 %s -flto=full -o %t.ltonewpm2.bc
-// RUN: llvm-lto2 run -o %t.ltonewpm %t.ltonewpm1.bc %t.ltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \
+// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm1.bc
+// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c -DBUILD2 %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm2.bc
+// RUN: llvm-lto2 run -lto-opaque-pointers -o %t.ltonewpm %t.ltonewpm1.bc %t.ltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \
 // RUN:  -r %t.ltonewpm1.bc,fn,plx \
 // RUN:  -r %t.ltonewpm1.bc,use,lx \
 // RUN:  -r %t.ltonewpm1.bc,use_local,plx \
@@ -50,9 +50,9 @@
 // RUN:  -r %t.ltonewpm2.bc,z, 2>&1 | FileCheck %s -check-prefixes=SSI,XSAFE,YSAFE
 
 // Thin LTO: both are safe.
-// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -flto=thin -o %t.thinltonewpm1.bc
-// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c -DBUILD2 %s -flto=thin -o %t.thinltonewpm2.bc
-// RUN: llvm-lto2 run -o %t.thinltonewpm %t.thinltonewpm1.bc %t.thinltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \
+// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm1.bc
+// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c -DBUILD2 %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm2.bc
+// RUN: llvm-lto2 run -lto-opaque-pointers -o %t.thinltonewpm %t.thinltonewpm1.bc %t.thinltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \
 // RUN:  -r %t.thinltonewpm1.bc,fn,plx \
 // RUN:  -r %t.thinltonewpm1.bc,use,lx \
 // RUN:  -r %t.thinltonewpm1.bc,use_local,plx \

diff  --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 32eb832776ff9..8a469c106a68a 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -198,6 +198,7 @@ struct Configuration {
   bool nostdlib;
   bool oFormatBinary;
   bool omagic;
+  bool opaquePointers;
   bool optEB = false;
   bool optEL = false;
   bool optimizeBBJumps;

diff  --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 1e0a46040eb95..7b5a588fa3e5c 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1126,6 +1126,8 @@ static void readConfigs(opt::InputArgList &args) {
   config->nostdlib = args.hasArg(OPT_nostdlib);
   config->oFormatBinary = isOutputFormatBinary(args);
   config->omagic = args.hasFlag(OPT_omagic, OPT_no_omagic, false);
+  config->opaquePointers = args.hasFlag(
+      OPT_plugin_opt_opaque_pointers, OPT_plugin_opt_no_opaque_pointers, true);
   config->optRemarksFilename = args.getLastArgValue(OPT_opt_remarks_filename);
   config->optStatsFilename = args.getLastArgValue(OPT_plugin_opt_stats_file);
 

diff  --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index ae5447f57f919..488ac40e82d3c 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -164,6 +164,8 @@ static lto::Config createConfig() {
   c.RunCSIRInstr = config->ltoCSProfileGenerate;
   c.PGOWarnMismatch = config->ltoPGOWarnMismatch;
 
+  c.OpaquePointers = config->opaquePointers;
+
   if (config->emitLLVM) {
     c.PostInternalizeModuleHook = [](size_t task, const Module &m) {
       if (std::unique_ptr<raw_fd_ostream> os =

diff  --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 73e7b2dded675..249f538f02672 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -626,6 +626,10 @@ def: J<"plugin-opt=cs-profile-path=">,
 def: J<"plugin-opt=obj-path=">,
   Alias<lto_obj_path_eq>,
   HelpText<"Alias for --lto-obj-path=">;
+def plugin_opt_opaque_pointers: F<"plugin-opt=opaque-pointers">,
+  HelpText<"Use opaque pointers in IR during LTO (default)">;
+def plugin_opt_no_opaque_pointers: F<"plugin-opt=no-opaque-pointers">,
+  HelpText<"Use typed pointers in IR during LTO">;
 def: J<"plugin-opt=opt-remarks-filename=">,
   Alias<opt_remarks_filename>,
   HelpText<"Alias for --opt-remarks-filename">;

diff  --git a/lld/test/ELF/lto/discard-value-names.ll b/lld/test/ELF/lto/discard-value-names.ll
index d3f10ddaa352b..545c7bda1a9a9 100644
--- a/lld/test/ELF/lto/discard-value-names.ll
+++ b/lld/test/ELF/lto/discard-value-names.ll
@@ -7,7 +7,7 @@
 ; CHECK: @GlobalValueName
 ; CHECK: @foo(i32 %in)
 ; CHECK: somelabel:
-; CHECK:  %GV = load i32, i32* @GlobalValueName
+; CHECK:  %GV = load i32, ptr @GlobalValueName
 ; CHECK:  %add = add i32 %in, %GV
 ; CHECK:  ret i32 %add
 

diff  --git a/lld/test/ELF/lto/ltopasses-basic.ll b/lld/test/ELF/lto/ltopasses-basic.ll
index 8489e70e18dc6..bc8328c644b60 100644
--- a/lld/test/ELF/lto/ltopasses-basic.ll
+++ b/lld/test/ELF/lto/ltopasses-basic.ll
@@ -12,6 +12,6 @@ define void @ctor() {
 }
 
 ; `@ctor` doesn't do anything and so the optimizer should kill it, leaving no ctors
-; CHECK: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer
+; CHECK: @llvm.global_ctors = appending global [0 x { i32, ptr, ptr }] zeroinitializer
 
 ; MLLVM: Pass Arguments:

diff  --git a/lld/test/ELF/lto/type-merge.ll b/lld/test/ELF/lto/type-merge.ll
index c020703373546..97eb6b771e884 100644
--- a/lld/test/ELF/lto/type-merge.ll
+++ b/lld/test/ELF/lto/type-merge.ll
@@ -14,13 +14,13 @@ define void @foo()  {
 declare void @bar(i8*)
 
 ; CHECK:      define void @foo() {
-; CHECK-NEXT:   call void @bar(i8* null)
+; CHECK-NEXT:   call void @bar(ptr null)
 ; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }
 
-; CHECK: declare void @bar(i8*)
+; CHECK: declare void @bar(ptr)
 
 ; CHECK:      define void @zed() {
-; CHECK-NEXT:   call void bitcast (void (i8*)* @bar to void ()*)()
+; CHECK-NEXT:   call void @bar()
 ; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }

diff  --git a/lld/test/ELF/lto/type-merge2.ll b/lld/test/ELF/lto/type-merge2.ll
index 95fed45db9a51..61dc7ff882eee 100644
--- a/lld/test/ELF/lto/type-merge2.ll
+++ b/lld/test/ELF/lto/type-merge2.ll
@@ -14,15 +14,12 @@ define void @foo()  {
 }
 declare void @bar(%zed*)
 
-; CHECK:      %zed = type { i8 }
-; CHECK-NEXT: %zed.0 = type { i16 }
-
 ; CHECK:      define void @foo() {
-; CHECK-NEXT:   call void bitcast (void (%zed.0*)* @bar to void (%zed*)*)(%zed* null)
+; CHECK-NEXT:   call void @bar(ptr null)
 ; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }
 
-; CHECK:      define void @bar(%zed.0* %this) {
-; CHECK-NEXT:   store %zed.0* %this, %zed.0** null
+; CHECK:      define void @bar(ptr %this) {
+; CHECK-NEXT:   store ptr %this, ptr null
 ; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }

diff  --git a/lld/test/ELF/lto/wrap-unreferenced-before-codegen.test b/lld/test/ELF/lto/wrap-unreferenced-before-codegen.test
index 49c1fc5a82a27..9618948a2059d 100644
--- a/lld/test/ELF/lto/wrap-unreferenced-before-codegen.test
+++ b/lld/test/ELF/lto/wrap-unreferenced-before-codegen.test
@@ -28,8 +28,9 @@
 # RUN: llvm-mc -triple x86_64-elf -filetype=obj -o %t/malloc.o %t/malloc.s
 # RUN: ld.lld -shared -o %t/libmalloc.so -soname libmalloc.so %t/malloc.o
 # RUN: llvm-mc -triple x86_64-elf -filetype=obj -o %t/emutls.o %t/emutls.s
-# RUN: llvm-as -o %t/usetls.bc %t/usetls.ll
-# RUN: ld.lld -shared -o %t/libusetls.so %t/usetls.bc %t/libmalloc.so \
+# RUN: llvm-as -opaque-pointers=1 -o %t/usetls.bc %t/usetls.ll
+# RUN: ld.lld --plugin-opt=opaque-pointers -shared -o %t/libusetls.so \
+# RUN:   %t/usetls.bc %t/libmalloc.so \
 # RUN:   --start-lib %t/emutls.o -mllvm -emulated-tls --wrap malloc
 # RUN: llvm-objdump --dynamic-reloc --disassemble %t/libusetls.so | \
 # RUN:   FileCheck --check-prefix=USETLS-DISASM %s

diff  --git a/llvm/docs/OpaquePointers.rst b/llvm/docs/OpaquePointers.rst
index de553874a859f..8ae2595ae66e7 100644
--- a/llvm/docs/OpaquePointers.rst
+++ b/llvm/docs/OpaquePointers.rst
@@ -205,6 +205,9 @@ For users of the clang cc1 interface, ``-no-opaque-pointers`` can be passed.
 Note that the ``CLANG_ENABLE_OPAQUE_POINTERS`` cmake option has no effect on
 the cc1 interface.
 
+Usage for LTO can be disabled by passing ``-Wl,-plugin-opt=no-opaque-pointers``
+to the clang driver.
+
 The next steps for the opaque pointer migration are:
 
 * Migrate Clang/LLVM tests to use opaque pointers.

diff  --git a/llvm/include/llvm/LTO/Config.h b/llvm/include/llvm/LTO/Config.h
index dd4f8daac104c..54bb82d84d96e 100644
--- a/llvm/include/llvm/LTO/Config.h
+++ b/llvm/include/llvm/LTO/Config.h
@@ -177,6 +177,10 @@ struct Config {
   /// Add FSAFDO discriminators.
   bool AddFSDiscriminator = false;
 
+  /// Use opaque pointer types. Used to call LLVMContext::setOpaquePointers
+  /// unless already set by the `-opaque-pointers` commandline option.
+  bool OpaquePointers = true;
+
   /// If this field is set, LTO will write input file paths and symbol
   /// resolutions here in llvm-lto2 command line flag format. This can be
   /// used for testing and for running the LTO pipeline outside of the linker
@@ -288,6 +292,8 @@ struct LTOLLVMContext : LLVMContext {
     enableDebugTypeODRUniquing();
     setDiagnosticHandler(
         std::make_unique<LTOLLVMDiagnosticHandler>(&DiagHandler), true);
+    if (!hasSetOpaquePointersValue())
+      setOpaquePointers(C.OpaquePointers);
   }
   DiagnosticHandlerFunction DiagHandler;
 };

diff  --git a/llvm/test/Analysis/StackSafetyAnalysis/ipa-alias.ll b/llvm/test/Analysis/StackSafetyAnalysis/ipa-alias.ll
index 8602bc7f706e8..8a371054c2262 100644
--- a/llvm/test/Analysis/StackSafetyAnalysis/ipa-alias.ll
+++ b/llvm/test/Analysis/StackSafetyAnalysis/ipa-alias.ll
@@ -33,7 +33,7 @@
 ; RUN:  -r %t.summ1.bc,PreemptableAliasWrite1,px \
 ; RUN:  -r %t.summ1.bc,Write1,px
 
-; RUN: llvm-lto2 run %t.summ0.bc %t.summ1.bc -o %t.lto -stack-safety-print -stack-safety-run -save-temps -thinlto-threads 1 -O0 \
+; RUN: llvm-lto2 run -opaque-pointers=0 %t.summ0.bc %t.summ1.bc -o %t.lto -stack-safety-print -stack-safety-run -save-temps -thinlto-threads 1 -O0 \
 ; RUN:  $(cat %t.res.txt) \
 ; RUN:    2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,LTO
 

diff  --git a/llvm/test/Analysis/StackSafetyAnalysis/ipa.ll b/llvm/test/Analysis/StackSafetyAnalysis/ipa.ll
index 1f1b379a2e8a3..6324b6b8c1964 100644
--- a/llvm/test/Analysis/StackSafetyAnalysis/ipa.ll
+++ b/llvm/test/Analysis/StackSafetyAnalysis/ipa.ll
@@ -83,7 +83,7 @@
 ; RUN:  -r %t.summ1.bc,Write8,px \
 ; RUN:  -r %t.summ1.bc,WriteAndReturn8,px
 
-; RUN: llvm-lto2 run %t.summ0.bc %t.summ1.bc -o %t.lto -stack-safety-print -stack-safety-run -save-temps -thinlto-threads 1 -O0 \
+; RUN: llvm-lto2 run -opaque-pointers=0 %t.summ0.bc %t.summ1.bc -o %t.lto -stack-safety-print -stack-safety-run -save-temps -thinlto-threads 1 -O0 \
 ; RUN:  $(cat %t.res.txt) \
 ; RUN:    2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,LTO
 

diff  --git a/llvm/test/LTO/Resolution/X86/alias-alias.ll b/llvm/test/LTO/Resolution/X86/alias-alias.ll
index a8489112ae99e..093b5973d24ca 100644
--- a/llvm/test/LTO/Resolution/X86/alias-alias.ll
+++ b/llvm/test/LTO/Resolution/X86/alias-alias.ll
@@ -6,10 +6,10 @@
 
 ; CHECK-NOT: alias
 ; CHECK: @c = global i32 1
-; CHECK-NEXT: @d = global i32* @a
+; CHECK-NEXT: @d = global ptr @a
 ; CHECK-EMPTY:
-; CHECK-NEXT: @a = weak alias i32, i32* @b
-; CHECK-NEXT: @b = internal alias i32, i32* @c
+; CHECK-NEXT: @a = weak alias i32, ptr @b
+; CHECK-NEXT: @b = internal alias i32, ptr @c
 
 ; RES: 1.o{{$}}
 ; RES-NEXT: {{^}}-r={{.*}}1.o,c,p{{$}}

diff  --git a/llvm/test/LTO/Resolution/X86/comdat.ll b/llvm/test/LTO/Resolution/X86/comdat.ll
index 06b61b7edf8bc..52b8f7f78805e 100644
--- a/llvm/test/LTO/Resolution/X86/comdat.ll
+++ b/llvm/test/LTO/Resolution/X86/comdat.ll
@@ -50,36 +50,36 @@ bb11:
 
 ; CHECK-DAG: @v1 = weak_odr global i32 42, comdat($c1)
 
-; CHECK-DAG: @r11 = global i32* @v1{{$}}
-; CHECK-DAG: @r12 = global i32 (i8*)* @f1{{$}}
+; CHECK-DAG: @r11 = global ptr @v1{{$}}
+; CHECK-DAG: @r12 = global ptr @f1{{$}}
 
-; CHECK-DAG: @r21 = global i32* @v1{{$}}
-; CHECK-DAG: @r22 = global i32 (i8*)* @f1{{$}}
+; CHECK-DAG: @r21 = global ptr @v1{{$}}
+; CHECK-DAG: @r22 = global ptr @f1{{$}}
 
 ; CHECK-DAG: @v1.1 = internal global i32 41, comdat($c2)
 
-; CHECK-DAG: @a11 = alias i32, i32* @v1{{$}}
-; CHECK-DAG: @a12 = alias i16, bitcast (i32* @v1 to i16*)
+; CHECK-DAG: @a11 = alias i32, ptr @v1{{$}}
+; CHECK-DAG: @a12 = alias i16, ptr @v1{{$}}
 
-; CHECK-DAG: @a13 = alias i32 (i8*), i32 (i8*)* @f1{{$}}
-; CHECK-DAG: @a14 = alias i16, bitcast (i32 (i8*)* @f1 to i16*)
+; CHECK-DAG: @a13 = alias i32 (ptr), ptr @f1{{$}}
+; CHECK-DAG: @a14 = alias i16, ptr @f1{{$}}
 
-; CHECK-DAG: @a21 = alias i32, i32* @v1.1{{$}}
-; CHECK-DAG: @a22 = alias i16, bitcast (i32* @v1.1 to i16*)
+; CHECK-DAG: @a21 = alias i32, ptr @v1.1{{$}}
+; CHECK-DAG: @a22 = alias i16, ptr @v1.1{{$}}
 
-; CHECK-DAG: @a23 = alias i32 (i8*), i32 (i8*)* @f1.2{{$}}
-; CHECK-DAG: @a24 = alias i16, bitcast (i32 (i8*)* @f1.2 to i16*)
+; CHECK-DAG: @a23 = alias i32 (ptr), ptr @f1.2{{$}}
+; CHECK-DAG: @a24 = alias i16, ptr @f1.2{{$}}
 
-; CHECK:      define weak_odr dso_local i32 @f1(i8* %0) comdat($c1) {
+; CHECK:      define weak_odr dso_local i32 @f1(ptr %0) comdat($c1) {
 ; CHECK-NEXT: bb10:
 ; CHECK-NEXT:   br label %bb11{{$}}
 ; CHECK:      bb11:
 ; CHECK-NEXT:   ret i32 42
 ; CHECK-NEXT: }
 
-; CHECK:      define internal i32 @f1.2(i8* %this) comdat($c2) {
+; CHECK:      define internal i32 @f1.2(ptr %this) comdat($c2) {
 ; CHECK-NEXT: bb20:
-; CHECK-NEXT:   store i8* %this, i8** null
+; CHECK-NEXT:   store ptr %this, ptr null
 ; CHECK-NEXT:   br label %bb21
 ; CHECK:      bb21:
 ; CHECK-NEXT:   ret i32 41

diff  --git a/llvm/test/LTO/Resolution/X86/ifunc2.ll b/llvm/test/LTO/Resolution/X86/ifunc2.ll
index 0d824f6f3b27c..5dcfdbd44e70c 100644
--- a/llvm/test/LTO/Resolution/X86/ifunc2.ll
+++ b/llvm/test/LTO/Resolution/X86/ifunc2.ll
@@ -6,14 +6,14 @@
 target datalayout = "e-p:64:64"
 target triple = "x86_64-unknown-linux-gnu"
 
-; CHECK: @foo = ifunc i32 (), i32 ()* ()* @foo_resolver.2
+; CHECK: @foo = ifunc i32 (), ptr @foo_resolver.2
 @foo = ifunc i32 (), i32 ()* ()* @foo_resolver
 
-; CHECK: define internal i32 ()* @foo_resolver.2() {
-; CHECK-NEXT: ret i32 ()* inttoptr (i32 1 to i32 ()*)
+; CHECK: define internal ptr @foo_resolver.2() {
+; CHECK-NEXT: ret ptr inttoptr (i32 1 to ptr)
 define weak i32 ()* @foo_resolver() {
   ret i32 ()* inttoptr (i32 1 to i32 ()*)
 }
 
-; CHECK: define i32 ()* @foo_resolver() {
-; CHECK-NEXT: ret i32 ()* inttoptr (i32 2 to i32 ()*)
+; CHECK: define ptr @foo_resolver() {
+; CHECK-NEXT: ret ptr inttoptr (i32 2 to ptr)

diff  --git a/llvm/test/LTO/Resolution/X86/local-def-dllimport.ll b/llvm/test/LTO/Resolution/X86/local-def-dllimport.ll
index 25b69b737362d..2dcd7ee64fa29 100644
--- a/llvm/test/LTO/Resolution/X86/local-def-dllimport.ll
+++ b/llvm/test/LTO/Resolution/X86/local-def-dllimport.ll
@@ -13,7 +13,7 @@ target triple = "x86_64-unknown-linux-gnu"
 $g = comdat any
 @g = global i8 42, comdat, !type !0
 
-; CHECK: define available_externally dllimport i8* @f()
+; CHECK: define available_externally dllimport ptr @f()
 define available_externally dllimport i8* @f() {
   ret i8* @g
 }

diff  --git a/llvm/test/LTO/X86/Inputs/opaque-pointers.ll b/llvm/test/LTO/X86/Inputs/opaque-pointers.ll
new file mode 100644
index 0000000000000..3c644346532ee
--- /dev/null
+++ b/llvm/test/LTO/X86/Inputs/opaque-pointers.ll
@@ -0,0 +1,7 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i64 @foo(ptr %p) {
+  %t = load i64, ptr %p
+  ret i64 %t
+}

diff  --git a/llvm/test/LTO/X86/cfi_jt_aliases.ll b/llvm/test/LTO/X86/cfi_jt_aliases.ll
index d5d85d0dcbd35..06737f628a417 100644
--- a/llvm/test/LTO/X86/cfi_jt_aliases.ll
+++ b/llvm/test/LTO/X86/cfi_jt_aliases.ll
@@ -46,7 +46,7 @@
 ; CHECK-THIN-OD:      jmp {{.*}} <a.cfi_jt
 ; CHECK-THIN-OD-NEXT: R_X86_64_PLT32 a
 
-; CHECK-USED: @llvm.used = appending global [3 x i8*] [i8* bitcast (void ()* @a.cfi_jt to i8*), i8* bitcast (void ()* @b.cfi_jt to i8*), i8* bitcast (void ()* @c.cfi_jt to i8*)], section "llvm.metadata"
+; CHECK-USED: @llvm.used = appending global [3 x ptr] [ptr @a.cfi_jt, ptr @b.cfi_jt, ptr @c.cfi_jt], section "llvm.metadata"
 
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"

diff  --git a/llvm/test/LTO/X86/mix-opaque-typed.ll b/llvm/test/LTO/X86/mix-opaque-typed.ll
new file mode 100644
index 0000000000000..fc95cd53b953d
--- /dev/null
+++ b/llvm/test/LTO/X86/mix-opaque-typed.ll
@@ -0,0 +1,19 @@
+; RUN: llvm-as -opaque-pointers=0 %s -o %t-typed.bc
+; RUN: llvm-as -opaque-pointers=1 %S/Inputs/opaque-pointers.ll -o %t-opaque.bc
+; RUN: llvm-lto2 run -o %t-lto.bc %t-typed.bc %t-opaque.bc -save-temps \
+; RUN:     -lto-opaque-pointers \
+; RUN:     -r %t-typed.bc,call_foo,px -r %t-typed.bc,foo,l \
+; RUN:     -r %t-opaque.bc,foo,px
+; RUN: opt -S -o - %t-lto.bc.0.4.opt.bc | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare i64 @foo(i64* %p);
+
+define i64 @call_foo(i64* %p) {
+  ; CHECK-LABEL: define i64 @call_foo(ptr nocapture readonly %p) local_unnamed_addr #0 {
+  ; CHECK-NEXT: %t.i = load i64, ptr %p, align 8
+  %t = call i64 @foo(i64* %p)
+  ret i64 %t
+}

diff  --git a/llvm/test/LTO/X86/type-mapping-bug4.ll b/llvm/test/LTO/X86/type-mapping-bug4.ll
index bdd687cfbefdc..da8275e8d327c 100644
--- a/llvm/test/LTO/X86/type-mapping-bug4.ll
+++ b/llvm/test/LTO/X86/type-mapping-bug4.ll
@@ -13,26 +13,25 @@
 ; Stage1 and stage2 are described in type-mapping-bug4_1.ll.
 ; Stage3 is described in this file.
 
-; CHECK: %class.CCSM = type opaque
-; CHECK: %class.CB = type { %"class.std::unique_ptr_base.1" }
-; CHECK: %"class.std::unique_ptr_base.1" = type { %class.CCSM* }
+; CHECK: %class.CB.1 = type { %"class.std::unique_ptr_base.2" }
+; CHECK: %"class.std::unique_ptr_base.2" = type { ptr }
 
 ; CHECK: define void @j() {
-; CHECK:   call void @h(%class.CCSM* undef)
+; CHECK:   call void @h(ptr undef)
 ; CHECK:   ret void
 ; CHECK: }
 
-; CHECK: declare void @h(%class.CCSM*)
+; CHECK: declare void @h(ptr)
 
 ; CHECK: define void @a() {
-; CHECK:   call void @llvm.dbg.value(metadata %class.CB* undef, metadata !10, metadata !DIExpression())
+; CHECK:   call void @llvm.dbg.value(metadata ptr undef, metadata !10, metadata !DIExpression())
 ; CHECK:   ret void
 ; CHECK: }
 
 ; CHECK: declare void @llvm.dbg.value(metadata, metadata, metadata) #0
 
-; CHECK: define void @d(%class.CB* %0) {
-; CHECK:   %2 = getelementptr inbounds %class.CB, %class.CB* undef, i64 0, i32 0, i32 0
+; CHECK: define void @d(ptr %0) {
+; CHECK:   %2 = getelementptr inbounds %class.CB.1, ptr undef, i64 0, i32 0, i32 0
 ; CHECK:   ret void
 ; CHECK: }
 

diff  --git a/llvm/test/ThinLTO/X86/Inputs/import-constant.ll b/llvm/test/ThinLTO/X86/Inputs/import-constant.ll
index 94bba2d02c885..dce788ace1c97 100644
--- a/llvm/test/ThinLTO/X86/Inputs/import-constant.ll
+++ b/llvm/test/ThinLTO/X86/Inputs/import-constant.ll
@@ -10,6 +10,6 @@ target triple = "x86_64-unknown-linux-gnu"
 
 define dso_local nonnull %struct.S* @_Z6getObjv() local_unnamed_addr {
 entry:
-  store %struct.S* null, %struct.S** getelementptr inbounds (%struct.Q, %struct.Q* @outer, i64 0, i32 0), align 8
+  store %struct.S* null, %struct.S** getelementptr inbounds (%struct.Q, %struct.Q* @outer, i64 1, i32 0), align 8
   ret %struct.S* @_ZL3Obj
 }

diff  --git a/llvm/test/ThinLTO/X86/cfi-devirt.ll b/llvm/test/ThinLTO/X86/cfi-devirt.ll
index 4ad6090075a2f..78fad2f15ad0e 100644
--- a/llvm/test/ThinLTO/X86/cfi-devirt.ll
+++ b/llvm/test/ThinLTO/X86/cfi-devirt.ll
@@ -94,7 +94,7 @@ cont2:
   ; CHECK-IR: br i1 {{.*}}, label %trap, label %cont2
 
   ; We still have to call it as virtual.
-  ; CHECK-IR: %call3 = tail call i32 %7
+  ; CHECK-IR: %call3 = tail call i32 %5
   %call3 = tail call i32 %8(%struct.A* nonnull %obj, i32 %call)
   ret i32 %call3
 }

diff  --git a/llvm/test/ThinLTO/X86/cfi-unsat.ll b/llvm/test/ThinLTO/X86/cfi-unsat.ll
index fffe077a21d5a..e60ebdc9e4313 100644
--- a/llvm/test/ThinLTO/X86/cfi-unsat.ll
+++ b/llvm/test/ThinLTO/X86/cfi-unsat.ll
@@ -59,14 +59,12 @@ cont:
 
 ; CHECK-IR0: define weak_odr i32 @test
 ; CHECK-IR0-NEXT: entry:
-; CHECK-IR0-NEXT: %0 = bitcast
 ; CHECK-IR0-NEXT: %vtable5 =
 ; CHECK-IR0-NEXT: tail call void @llvm.trap()
 ; CHECK-IR0-NEXT: unreachable
 ; CHECK-IR0-NEXT: }
 ; CHECK-IR0: define weak_odr i32 @testb
 ; CHECK-IR0-NEXT: entry:
-; CHECK-IR0-NEXT: %0 = bitcast
 ; CHECK-IR0-NEXT: %vtable5 =
 ; CHECK-IR0-NEXT: tail call void @llvm.trap()
 ; CHECK-IR0-NEXT: unreachable

diff  --git a/llvm/test/ThinLTO/X86/devirt-after-icp.ll b/llvm/test/ThinLTO/X86/devirt-after-icp.ll
index 7c1cec4c1ccfe..0b306f90feaeb 100644
--- a/llvm/test/ThinLTO/X86/devirt-after-icp.ll
+++ b/llvm/test/ThinLTO/X86/devirt-after-icp.ll
@@ -100,7 +100,7 @@ if.true.direct_targ:                              ; preds = %entry
   %8 = load i32 (%class.B*)*, i32 (%class.B*)** %vfn.i, align 8
 ; Call to bar() can be devirtualized to call to B::bar(), since it was
 ; inlined from B::foo() after ICP introduced the guarded promotion.
-; CHECK-IR: %call.i = tail call i32 @_ZN1B3barEv(%class.B* %3)
+; CHECK-IR: %call.i = tail call i32 @_ZN1B3barEv(ptr nonnull %a)
   %call.i = tail call i32 %8(%class.B* %5)
   br label %if.end.icp
 

diff  --git a/llvm/test/ThinLTO/X86/devirt2.ll b/llvm/test/ThinLTO/X86/devirt2.ll
index 0a10a40e26fd8..43f76a81ba524 100644
--- a/llvm/test/ThinLTO/X86/devirt2.ll
+++ b/llvm/test/ThinLTO/X86/devirt2.ll
@@ -180,7 +180,7 @@ entry:
   ; Check that the call was devirtualized. Ignore extra character before
   ; symbol name which would happen if it was promoted during module
   ; splitting for hybrid WPD.
-  ; CHECK-IR1: %call = tail call i32 bitcast (void ()* @{{.*}}_ZN1A1nEi
+  ; CHECK-IR1: %call = tail call i32 @_ZN1A1nEi
   %call = tail call i32 %fptr1(%struct.A* nonnull %obj, i32 %a)
 
   %3 = bitcast i8** %vtable to i32 (%struct.A*, i32)**

diff  --git a/llvm/test/ThinLTO/X86/devirt_check.ll b/llvm/test/ThinLTO/X86/devirt_check.ll
index 63a64cb2e1b19..bf03afa0d8c61 100644
--- a/llvm/test/ThinLTO/X86/devirt_check.ll
+++ b/llvm/test/ThinLTO/X86/devirt_check.ll
@@ -54,20 +54,20 @@ entry:
 
   ; Check that the call was devirtualized, but preceeded by a check guarding
   ; a trap if the function pointer doesn't match.
-  ; TRAP:   %.not = icmp eq i32 (%struct.A*, i32)* %fptr1, @_ZN1A1nEi
+  ; TRAP:   %.not = icmp eq ptr %fptr1, @_ZN1A1nEi
   ; Ensure !prof and !callees metadata for indirect call promotion removed.
   ; TRAP-NOT: prof
   ; TRAP-NOT: callees
-  ; TRAP:   br i1 %.not, label %3, label %2
-  ; TRAP: 2:
+  ; TRAP:   br i1 %.not, label %1, label %0
+  ; TRAP: 0:
   ; TRAP:   tail call void @llvm.debugtrap()
-  ; TRAP:   br label %3
-  ; TRAP: 3:
+  ; TRAP:   br label %1
+  ; TRAP: 1:
   ; TRAP:   tail call i32 @_ZN1A1nEi
   ; Check that the call was devirtualized, but preceeded by a check guarding
   ; a fallback if the function pointer doesn't match.
-  ; FALLBACK:   %2 = icmp eq i32 (%struct.A*, i32)* %fptr1, @_ZN1A1nEi
-  ; FALLBACK:   br i1 %2, label %if.true.direct_targ, label %if.false.orig_indirect
+  ; FALLBACK:   %0 = icmp eq ptr %fptr1, @_ZN1A1nEi
+  ; FALLBACK:   br i1 %0, label %if.true.direct_targ, label %if.false.orig_indirect
   ; FALLBACK: if.true.direct_targ:
   ; FALLBACK:   tail call i32 @_ZN1A1nEi
   ; Ensure !prof and !callees metadata for indirect call promotion removed.

diff  --git a/llvm/test/ThinLTO/X86/devirt_promote.ll b/llvm/test/ThinLTO/X86/devirt_promote.ll
index e978d543d900f..39f0229de9ca6 100644
--- a/llvm/test/ThinLTO/X86/devirt_promote.ll
+++ b/llvm/test/ThinLTO/X86/devirt_promote.ll
@@ -58,7 +58,7 @@ entry:
   %fptr1 = load i32 (%struct.A*, i32)*, i32 (%struct.A*, i32)** %2, align 8
 
   ; Check that the call was devirtualized.
-  ; CHECK-IR1: %call = tail call i32 bitcast (void ()* @_ZN1A1nEi
+  ; CHECK-IR1: %call = tail call i32 @_ZN1A1nEi
   %call = tail call i32 %fptr1(%struct.A* nonnull %obj, i32 %a)
 
   ret i32 %call

diff  --git a/llvm/test/ThinLTO/X86/devirt_single_hybrid.ll b/llvm/test/ThinLTO/X86/devirt_single_hybrid.ll
index 5966794152c16..f5a37551085ab 100644
--- a/llvm/test/ThinLTO/X86/devirt_single_hybrid.ll
+++ b/llvm/test/ThinLTO/X86/devirt_single_hybrid.ll
@@ -24,7 +24,7 @@
 
 ; REMARK-COUNT-3: single-impl: devirtualized a call to _ZNK1A1fEv
 
-; IMPORT:       define available_externally hidden i32 @_ZNK1A1fEv(%struct.A* %this)
+; IMPORT:       define available_externally hidden i32 @_ZNK1A1fEv(ptr %this)
 ; IMPORT-NEXT:  entry:
 ; IMPORT-NEXT:      ret i32 3
 

diff  --git a/llvm/test/ThinLTO/X86/funcattrs-prop-unknown.ll b/llvm/test/ThinLTO/X86/funcattrs-prop-unknown.ll
index c53120f1416da..c509b669ccbe8 100644
--- a/llvm/test/ThinLTO/X86/funcattrs-prop-unknown.ll
+++ b/llvm/test/ThinLTO/X86/funcattrs-prop-unknown.ll
@@ -8,14 +8,14 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 
 ; CHECK-NOT: ; Function Attrs:
-; CHECK: define i32 @indirect(i32 ()* nocapture %0) {
+; CHECK: define i32 @indirect(ptr nocapture %0) {
 define i32 @indirect(i32 ()* nocapture) {
   %2 = tail call i32 %0()
   ret i32 %2
 }
 
 ; CHECK-NOT: ; Function Attrs:
-; CHECK: define i8* @inlineasm() {
+; CHECK: define ptr @inlineasm() {
 define i8* @inlineasm() {
 entry:
   %0 = tail call i8* asm sideeffect "lea ff_h264_cabac_tables(%rip), $0", "=&r,~{dirflag},~{fpsr},~{flags}"()
@@ -32,4 +32,4 @@ define void @selectcallee() {
 
 declare void @f()
 declare void @g()
- at global = extern_weak global i32
\ No newline at end of file
+ at global = extern_weak global i32

diff  --git a/llvm/test/ThinLTO/X86/globals-import-blockaddr.ll b/llvm/test/ThinLTO/X86/globals-import-blockaddr.ll
index 96d7b851abbf3..e7a3ffbffb7c1 100644
--- a/llvm/test/ThinLTO/X86/globals-import-blockaddr.ll
+++ b/llvm/test/ThinLTO/X86/globals-import-blockaddr.ll
@@ -6,9 +6,9 @@
 ; Verify that we haven't imported GV containing blockaddress
 ; CHECK: @label_addr.llvm.0 = external hidden constant
 ; Verify that bar is not imported since it has address-taken block that is target of indirect branch
-; CHECK: declare [1 x i8*]* @bar()
+; CHECK: declare ptr @bar()
 ; Verify that foo is imported
-; CHECK: available_externally [1 x i8*]* @foo
+; CHECK: available_externally ptr @foo
 
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"

diff  --git a/llvm/test/ThinLTO/X86/import-constant.ll b/llvm/test/ThinLTO/X86/import-constant.ll
index e5254948f591e..dd45c51e85d09 100644
--- a/llvm/test/ThinLTO/X86/import-constant.ll
+++ b/llvm/test/ThinLTO/X86/import-constant.ll
@@ -25,18 +25,18 @@
 ; RUN: llvm-dis %t-out-norefs.1.3.import.bc -o - | FileCheck %s --check-prefix=NOREFS
 
 ; Check that variable has been promoted in the source module
-; PROMOTE: @_ZL3Obj.llvm.{{.*}} = hidden constant %struct.S { i32 4, i32 8, i32* @val }
+; PROMOTE: @_ZL3Obj.llvm.{{.*}} = hidden constant %struct.S { i32 4, i32 8, ptr @val }
 
 ; @outer is a write-only variable, so it's been converted to zeroinitializer.
 ; IMPORT:      @val = available_externally global i32 42
-; IMPORT-NEXT: @_ZL3Obj.llvm.{{.*}} = available_externally hidden constant %struct.S { i32 4, i32 8, i32* @val }
+; IMPORT-NEXT: @_ZL3Obj.llvm.{{.*}} = available_externally hidden constant %struct.S { i32 4, i32 8, ptr @val }
 ; IMPORT-NEXT: @outer = internal local_unnamed_addr global %struct.Q zeroinitializer
 
 ; OPT: @outer = internal unnamed_addr global %struct.Q zeroinitializer
 
 ; OPT:      define dso_local i32 @main()
 ; OPT-NEXT: entry:
-; OPT-NEXT:   store %struct.S* null, %struct.S** getelementptr inbounds (%struct.Q, %struct.Q* @outer, i64 0, i32 0)
+; OPT-NEXT:   store ptr null, ptr getelementptr inbounds (%struct.Q, ptr @outer, i64 1, i32 0)
 ; OPT-NEXT:   ret i32 12
 
 ; NOREFS:      @_ZL3Obj.llvm.{{.*}} = external hidden constant %struct.S

diff  --git a/llvm/test/ThinLTO/X86/import-dsolocal.ll b/llvm/test/ThinLTO/X86/import-dsolocal.ll
index 11d41e70e19b6..aea53cfcd0743 100644
--- a/llvm/test/ThinLTO/X86/import-dsolocal.ll
+++ b/llvm/test/ThinLTO/X86/import-dsolocal.ll
@@ -21,21 +21,21 @@
 ; RUN: llvm-dis %t2.1.3.import.bc -o - | FileCheck %s --check-prefixes=DEST,DEST2
 
 ; DEST:      @a = available_externally global i32 42, align 4
-; DEST-NEXT: @b = external global i32*, align 8
+; DEST-NEXT: @b = external global ptr, align 8
 ; DEST:      declare void @linkonce()
 ; DEST:      declare void @weak()
 ; DEST:      define dso_local i32 @main()
 ; DEST:      define available_externally void @extern()
 
-; DEST1:     declare i32 @extern_aux(i32*, i32**)
-; DEST1:     declare i32 @linkonceodr_aux(i32*, i32**)
-; DEST2:     define available_externally i32 @extern_aux(i32* %a, i32** %b)
-; DEST2:     define available_externally i32 @linkonceodr_aux(i32* %a, i32** %b)
+; DEST1:     declare i32 @extern_aux(ptr, ptr)
+; DEST1:     declare i32 @linkonceodr_aux(ptr, ptr)
+; DEST2:     define available_externally i32 @extern_aux(ptr %a, ptr %b)
+; DEST2:     define available_externally i32 @linkonceodr_aux(ptr %a, ptr %b)
 
 ; DEST:      define available_externally void @weakodr()
 
-; DEST1:     declare i32 @weakodr_aux(i32*, i32**)
-; DEST2:     define available_externally i32 @weakodr_aux(i32* %a, i32** %b)
+; DEST1:     declare i32 @weakodr_aux(ptr, ptr)
+; DEST2:     define available_externally i32 @weakodr_aux(ptr %a, ptr %b)
 
 ;--- a.ll
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"

diff  --git a/llvm/test/ThinLTO/X86/index-const-prop-gvref-pie.ll b/llvm/test/ThinLTO/X86/index-const-prop-gvref-pie.ll
index 62c4164594c32..85eacf4d8baed 100644
--- a/llvm/test/ThinLTO/X86/index-const-prop-gvref-pie.ll
+++ b/llvm/test/ThinLTO/X86/index-const-prop-gvref-pie.ll
@@ -6,7 +6,7 @@
 ; RUN: llvm-dis %t3.2.3.import.bc -o - | FileCheck %s --check-prefix=DEST
 
 ;; For PIE, keep dso_local for declarations to enable direct access.
-; DEST:      @b = external dso_local global i32*
+; DEST:      @b = external dso_local global ptr
 ; DEST-NEXT: @a = available_externally dso_local global i32 42, align 4
 
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"

diff  --git a/llvm/test/ThinLTO/X86/index-const-prop-gvref.ll b/llvm/test/ThinLTO/X86/index-const-prop-gvref.ll
index 293eb1dc33a66..069285f8eb377 100644
--- a/llvm/test/ThinLTO/X86/index-const-prop-gvref.ll
+++ b/llvm/test/ThinLTO/X86/index-const-prop-gvref.ll
@@ -12,13 +12,13 @@
 ; RUN: llvm-dis %t4.2.3.import.bc -o - | FileCheck %s --check-prefix=DEST_DSO
 
 ; No variable in the source module should have been internalized
-; SRC:      @b = dso_local global i32* @a
+; SRC:      @b = dso_local global ptr @a
 ; SRC-NEXT: @a = dso_local global i32 42
 
 ; We can't internalize globals referenced by other live globals
-; DEST:          @b = external dso_local global i32*
+; DEST:          @b = external dso_local global ptr
 ; DEST-NEXT:     @a = available_externally dso_local global i32 42, align 4
-; DEST_DSO:      @b = external global i32*
+; DEST_DSO:      @b = external global ptr
 ; DEST_DSO-NEXT: @a = available_externally global i32 42, align 4
 
 ;; Test old API.

diff  --git a/llvm/test/ThinLTO/X86/index-const-prop-linkage.ll b/llvm/test/ThinLTO/X86/index-const-prop-linkage.ll
index 80f3f11e2c543..c94224cda7c47 100644
--- a/llvm/test/ThinLTO/X86/index-const-prop-linkage.ll
+++ b/llvm/test/ThinLTO/X86/index-const-prop-linkage.ll
@@ -9,7 +9,7 @@
 ; - common linkage
 ; - available_externally linkage
 ; - reference from @llvm.used
-; CHECK:      @llvm.used = appending global [1 x i32*] [i32* @g2]
+; CHECK:      @llvm.used = appending global [1 x ptr] [ptr @g2]
 ; CHECK-NEXT: @g1 = external global i32, align 4
 ; CHECK-NEXT: @g2 = available_externally global i32 42, align 4
 ; CHECK-NEXT: @g3 = available_externally global i32 42, align 4

diff  --git a/llvm/test/ThinLTO/X86/reference_non_importable.ll b/llvm/test/ThinLTO/X86/reference_non_importable.ll
index a488b2432f7bd..e36bf370d813a 100644
--- a/llvm/test/ThinLTO/X86/reference_non_importable.ll
+++ b/llvm/test/ThinLTO/X86/reference_non_importable.ll
@@ -22,7 +22,7 @@ target triple = "x86_64-apple-macosx10.11.0"
 
 ; We want foo to be imported in the main module!
 ; RUN: llvm-dis < %t.o.2.3.import.bc  | FileCheck  %s --check-prefix=IMPORT
-; IMPORT: define available_externally dso_local i8** @foo()
+; IMPORT: define available_externally dso_local ptr @foo()
 define i8 **@foo() {
 	ret i8 **@b
 }

diff  --git a/llvm/test/ThinLTO/X86/weak_externals.ll b/llvm/test/ThinLTO/X86/weak_externals.ll
index 83e0e0ecd6110..c731cd5d533e7 100644
--- a/llvm/test/ThinLTO/X86/weak_externals.ll
+++ b/llvm/test/ThinLTO/X86/weak_externals.ll
@@ -10,9 +10,9 @@
 ; RUN: llvm-dis %t.out.1.2.internalize.bc -o - | FileCheck %s --check-prefix=INTERNALIZE
 
 ; CHECK: @_ZZN9SingletonI1SE11getInstanceEvE8instance = available_externally dso_local global %struct.S zeroinitializer
-; CHECK: @_ZZN9SingletonI1SE11getInstanceEvE13instance_weak = available_externally dso_local global %struct.S* null, align 8
-; CHECK: define linkonce_odr dso_local dereferenceable(16) %struct.S* @_ZN9SingletonI1SE11getInstanceEv() comdat
-; INTERNALIZE: define internal dereferenceable(16) %struct.S* @_ZN9SingletonI1SE11getInstanceEv()
+; CHECK: @_ZZN9SingletonI1SE11getInstanceEvE13instance_weak = available_externally dso_local global ptr null, align 8
+; CHECK: define linkonce_odr dso_local dereferenceable(16) ptr @_ZN9SingletonI1SE11getInstanceEv() comdat
+; INTERNALIZE: define internal dereferenceable(16) ptr @_ZN9SingletonI1SE11getInstanceEv()
 
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"

diff  --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp
index 019bfe07e026f..a9814c650f055 100644
--- a/llvm/tools/gold/gold-plugin.cpp
+++ b/llvm/tools/gold/gold-plugin.cpp
@@ -208,6 +208,8 @@ namespace options {
   static std::string stats_file;
   // Asserts that LTO link has whole program visibility
   static bool whole_program_visibility = false;
+  // Use opaque pointer types.
+  static bool opaque_pointers = true;
 
   // Optimization remarks filename, accepted passes and hotness options
   static std::string RemarksFilename;
@@ -308,6 +310,10 @@ namespace options {
       RemarksFormat = std::string(opt);
     } else if (opt.consume_front("stats-file=")) {
       stats_file = std::string(opt);
+    } else if (opt == "opaque-pointers") {
+      opaque_pointers = true;
+    } else if (opt == "no-opaque-pointers") {
+      opaque_pointers = false;
     } else {
       // Save this option to pass to the code generator.
       // ParseCommandLineOptions() expects argv[0] to be program name. Lazily
@@ -957,6 +963,8 @@ static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite,
 
   Conf.HasWholeProgramVisibility = options::whole_program_visibility;
 
+  Conf.OpaquePointers = options.opaque_pointers;
+
   Conf.StatsFile = options::stats_file;
   return std::make_unique<LTO>(std::move(Conf), Backend,
                                 options::ParallelCodeGenParallelismLevel);

diff  --git a/llvm/tools/llvm-lto2/llvm-lto2.cpp b/llvm/tools/llvm-lto2/llvm-lto2.cpp
index a4ba5457b067a..ca563f2885698 100644
--- a/llvm/tools/llvm-lto2/llvm-lto2.cpp
+++ b/llvm/tools/llvm-lto2/llvm-lto2.cpp
@@ -143,6 +143,10 @@ static cl::opt<bool>
                  cl::desc("Run PGO context sensitive IR instrumentation"),
                  cl::init(false), cl::Hidden);
 
+static cl::opt<bool> LtoOpaquePointers("lto-opaque-pointers",
+                                       cl::desc("Enable opaque pointer types"),
+                                       cl::init(true), cl::Hidden);
+
 static cl::opt<bool>
     DebugPassManager("debug-pass-manager", cl::init(false), cl::Hidden,
                      cl::desc("Print pass management debugging information"));
@@ -291,6 +295,7 @@ static int run(int argc, char **argv) {
   Conf.StatsFile = StatsFile;
   Conf.PTO.LoopVectorization = Conf.OptLevel > 1;
   Conf.PTO.SLPVectorization = Conf.OptLevel > 1;
+  Conf.OpaquePointers = LtoOpaquePointers;
 
   ThinBackend Backend;
   if (ThinLTODistributedIndexes)


        


More information about the cfe-commits mailing list