Index: clang/include/clang/Basic/CodeGenOptions.def =================================================================== --- clang/include/clang/Basic/CodeGenOptions.def +++ clang/include/clang/Basic/CodeGenOptions.def @@ -469,6 +469,9 @@ ENUM_CODEGENOPT(ZeroCallUsedRegs, llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind, 5, llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip) +/// Whether to normalize result to opaque pointers. +CODEGENOPT(NormalizeOpaquePointers, 1, 0) + #undef CODEGENOPT #undef ENUM_CODEGENOPT #undef VALUE_CODEGENOPT Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -5506,6 +5506,9 @@ def discard_value_names : Flag<["-"], "discard-value-names">, HelpText<"Discard value names in LLVM IR">, MarshallingInfoFlag>; +def normalize_opaque_pointers : Flag<["-"], "normalize-opaque-pointers">, + HelpText<"Normalize final output to opaque pointers">, + MarshallingInfoFlag>; def plugin_arg : JoinedAndSeparate<["-"], "plugin-arg-">, MetaVarName<" ">, HelpText<"Pass to plugin ">; Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -99,6 +99,63 @@ extern cl::opt DebugInfoCorrelate; } +static std::unique_ptr +cloneModuleIntoContext(LLVMContext &NewCtx, const Module &M, + bool ShouldPreserveUseListOrder) { + SmallVector Buffer; + raw_svector_ostream OS(Buffer); + WriteBitcodeToFile(M, OS, ShouldPreserveUseListOrder); + MemoryBufferRef MBuf(OS.str(), "temporary bitcode"); + Expected> Module = parseBitcodeFile(MBuf, NewCtx); + if (!Module) + handleAllErrors(Module.takeError()); + return std::move(*Module); +} + +static void normalizeModuleForOpaquePointers(Module &M) { + for (Function &F : M.functions()) { + for (BasicBlock &BB : F) { + for (Instruction &I : make_early_inc_range(BB)) { + // Drop no-op bitcasts from ptr to ptr, which will not be present + // with opaque pointers. + if (auto *BC = dyn_cast(&I)) { + if (BC->getType() == BC->getOperand(0)->getType() && + BC->getType()->isPointerTy()) { + BC->replaceAllUsesWith(BC->getOperand(0)); + BC->eraseFromParent(); + } + } + } + } + } +} + +class NormalizeOpaquePointersPrintModulePass + : public PassInfoMixin { + raw_ostream &OS; + bool ShouldPreserveUseListOrder; + +public: + NormalizeOpaquePointersPrintModulePass(raw_ostream &OS, + bool ShouldPreserveUseListOrder) + : OS(OS), ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {} + + PreservedAnalyses run(Module &M, AnalysisManager &) { + if (M.getContext().supportsTypedPointers()) { + LLVMContext OpaqueCtx; + OpaqueCtx.enableOpaquePointers(); + std::unique_ptr OpaqueM = + cloneModuleIntoContext(OpaqueCtx, M, ShouldPreserveUseListOrder); + normalizeModuleForOpaquePointers(*OpaqueM); + OpaqueM->print(OS, nullptr, ShouldPreserveUseListOrder); + } else { + M.print(OS, nullptr, ShouldPreserveUseListOrder); + } + return PreservedAnalyses::all(); + } + static bool isRequired() { return true; } +}; + namespace { // Default filename used for profile generation. @@ -1488,7 +1545,11 @@ break; case Backend_EmitLL: - MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists)); + if (CodeGenOpts.NormalizeOpaquePointers) + MPM.addPass(NormalizeOpaquePointersPrintModulePass( + *OS, CodeGenOpts.EmitLLVMUseLists)); + else + MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists)); break; default: Index: clang/test/CodeGenCXX/2009-12-23-MissingSext.cpp =================================================================== --- clang/test/CodeGenCXX/2009-12-23-MissingSext.cpp +++ clang/test/CodeGenCXX/2009-12-23-MissingSext.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple x86_64-unknown-unknown -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -normalize-opaque-pointers %s -triple x86_64-unknown-unknown -emit-llvm -o - | FileCheck %s // The store of p.y into the temporary was not // getting extended to 32 bits, so uninitialized // bits of the temporary were used. 7366161. @@ -8,11 +8,11 @@ }; int bar(struct foo p, int x) { // CHECK: bar -// CHECK: %[[val:.*]] = load i32, i32* {{.*}} +// CHECK: %[[val:.*]] = load i32, ptr {{.*}} // CHECK-NEXT: ashr i32 %[[val]] -// CHECK: = load i32, i32* {{.*}} -// CHECK: = load i32, i32* {{.*}} -// CHECK: %[[val:.*]] = load i32, i32* {{.*}} +// CHECK: = load i32, ptr {{.*}} +// CHECK: = load i32, ptr {{.*}} +// CHECK: %[[val:.*]] = load i32, ptr {{.*}} // CHECK-NEXT: ashr i32 %[[val]] x = (p.y > x ? x : p.y); return x;