From ae94e594164b193236002516970aeec4c4574768 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 5 Dec 2008 01:06:39 +0000 Subject: [PATCH] Re-did 60519. It turns out Darwin's handling of hidden visibility symbols are a bit more complicate than I expected. Both declarations and weak definitions still need a stub indirection. However, the stubs are in data section and they contain the addresses of the actual symbols. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60571 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelLowering.cpp | 9 ++- lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp | 55 +++++++++----- lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp | 95 ++++++++++++++++++------- lib/Target/PowerPC/PPCSubtarget.cpp | 9 ++- lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp | 27 ++++++- lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h | 3 +- lib/Target/X86/X86Subtarget.cpp | 12 ++-- test/CodeGen/PowerPC/hidden-vis-2.ll | 12 ++++ test/CodeGen/PowerPC/hidden-vis.ll | 9 +++ test/CodeGen/X86/hidden-vis-2.ll | 1 - test/CodeGen/X86/hidden-vis-3.ll | 15 ++++ test/CodeGen/X86/hidden-vis-4.ll | 11 +++ 12 files changed, 203 insertions(+), 55 deletions(-) create mode 100644 test/CodeGen/PowerPC/hidden-vis-2.ll create mode 100644 test/CodeGen/PowerPC/hidden-vis.ll create mode 100644 test/CodeGen/X86/hidden-vis-3.ll create mode 100644 test/CodeGen/X86/hidden-vis-4.ll diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 69452c13601..02a0ed624dc 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -830,9 +830,12 @@ SDValue ARMTargetLowering::LowerGlobalAddressELF(SDValue Op, /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol /// even in non-static mode. static bool GVIsIndirectSymbol(GlobalValue *GV, Reloc::Model RelocM) { - return RelocM != Reloc::Static && - (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() || - (GV->isDeclaration() && !GV->hasNotBeenReadFromBitcode())); + // If symbol visibility is hidden, the extra load is not needed if + // the symbol is definitely defined in the current translation unit. + bool isDecl = GV->isDeclaration() && !GV->hasNotBeenReadFromBitcode(); + if (GV->hasHiddenVisibility() && (!isDecl && !GV->hasCommonLinkage())) + return false; + return RelocM != Reloc::Static && (isDecl || GV->mayBeOverridden()); } SDValue ARMTargetLowering::LowerGlobalAddressDarwin(SDValue Op, diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index ae6c3544bb9..9d81acdb117 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -32,6 +32,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Mangler.h" #include "llvm/Support/MathExtras.h" @@ -73,11 +74,15 @@ namespace { /// GVNonLazyPtrs - Keeps the set of GlobalValues that require /// non-lazy-pointers for indirect access. - std::set GVNonLazyPtrs; + StringSet<> GVNonLazyPtrs; + + /// HiddenGVNonLazyPtrs - Keeps the set of GlobalValues with hidden + /// visibility that require non-lazy-pointers for indirect access. + StringSet<> HiddenGVNonLazyPtrs; /// FnStubs - Keeps the set of external function GlobalAddresses that the /// asm printer should generate stubs for. - std::set FnStubs; + StringSet<> FnStubs; /// PCRelGVs - Keeps the set of GlobalValues used in pc relative /// constantpool. @@ -141,7 +146,10 @@ namespace { if (!GV) Name += ACPV->getSymbol(); if (ACPV->isNonLazyPointer()) { - GVNonLazyPtrs.insert(Name); + if (GV->hasHiddenVisibility()) + HiddenGVNonLazyPtrs.insert(Name); + else + GVNonLazyPtrs.insert(Name); printSuffixedName(Name, "$non_lazy_ptr"); } else if (ACPV->isStub()) { FnStubs.insert(Name); @@ -927,9 +935,8 @@ bool ARMAsmPrinter::doFinalization(Module &M) { SwitchToDataSection(""); // Output stubs for dynamically-linked functions - unsigned j = 1; - for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end(); - i != e; ++i, ++j) { + for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end(); + i != e; ++i) { if (TM.getRelocationModel() == Reloc::PIC_) SwitchToTextSection(".section __TEXT,__picsymbolstub4,symbol_stubs," "none,16", 0); @@ -940,10 +947,10 @@ bool ARMAsmPrinter::doFinalization(Module &M) { EmitAlignment(2); O << "\t.code\t32\n"; - std::string p = *i; + const char *p = i->getKeyData(); printSuffixedName(p, "$stub"); O << ":\n"; - O << "\t.indirect_symbol " << *i << "\n"; + O << "\t.indirect_symbol " << p << "\n"; O << "\tldr ip, "; printSuffixedName(p, "$slp"); O << "\n"; @@ -966,23 +973,37 @@ bool ARMAsmPrinter::doFinalization(Module &M) { SwitchToDataSection(".lazy_symbol_pointer", 0); printSuffixedName(p, "$lazy_ptr"); O << ":\n"; - O << "\t.indirect_symbol " << *i << "\n"; + O << "\t.indirect_symbol " << p << "\n"; O << "\t.long\tdyld_stub_binding_helper\n"; } O << "\n"; // Output non-lazy-pointers for external and common global variables. - if (!GVNonLazyPtrs.empty()) + if (!GVNonLazyPtrs.empty()) { SwitchToDataSection(".non_lazy_symbol_pointer", 0); - for (std::set::iterator i = GVNonLazyPtrs.begin(), - e = GVNonLazyPtrs.end(); i != e; ++i) { - std::string p = *i; - printSuffixedName(p, "$non_lazy_ptr"); - O << ":\n"; - O << "\t.indirect_symbol " << *i << "\n"; - O << "\t.long\t0\n"; + for (StringSet<>::iterator i = GVNonLazyPtrs.begin(), + e = GVNonLazyPtrs.end(); i != e; ++i) { + const char *p = i->getKeyData(); + printSuffixedName(p, "$non_lazy_ptr"); + O << ":\n"; + O << "\t.indirect_symbol " << p << "\n"; + O << "\t.long\t0\n"; + } } + if (!HiddenGVNonLazyPtrs.empty()) { + SwitchToSection(TAI->getDataSection()); + for (StringSet<>::iterator i = HiddenGVNonLazyPtrs.begin(), + e = HiddenGVNonLazyPtrs.end(); i != e; ++i) { + const char *p = i->getKeyData(); + EmitAlignment(2); + printSuffixedName(p, "$non_lazy_ptr"); + O << ":\n"; + O << "\t.long " << p << "\n"; + } + } + + // Emit initial debug information. // FIXME: Dwarf support. //DW.EndModule(); diff --git a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp index 3ed72658401..8b37167f4ad 100644 --- a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp @@ -43,14 +43,14 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" -#include +#include "llvm/ADT/StringSet.h" using namespace llvm; STATISTIC(EmittedInsts, "Number of machine instrs printed"); namespace { struct VISIBILITY_HIDDEN PPCAsmPrinter : public AsmPrinter { - std::set FnStubs, GVStubs; + StringSet<> FnStubs, GVStubs, HiddenGVStubs; const PPCSubtarget &Subtarget; PPCAsmPrinter(raw_ostream &O, TargetMachine &TM, const TargetAsmInfo *T) @@ -387,10 +387,18 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) { // External or weakly linked global variables need non-lazily-resolved stubs if (TM.getRelocationModel() != Reloc::Static) { - if (((GV->isDeclaration() || GV->hasWeakLinkage() || - GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) { - GVStubs.insert(Name); - printSuffixedName(Name, "$non_lazy_ptr"); + if (GV->isDeclaration() || GV->mayBeOverridden()) { + if (GV->hasHiddenVisibility()) { + if (!GV->isDeclaration() && !GV->hasCommonLinkage()) + O << Name; + else { + HiddenGVStubs.insert(Name); + printSuffixedName(Name, "$non_lazy_ptr"); + } + } else { + GVStubs.insert(Name); + printSuffixedName(Name, "$non_lazy_ptr"); + } if (GV->hasExternalWeakLinkage()) ExtWeakSymbols.insert(GV); return; @@ -416,7 +424,10 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) { void PPCAsmPrinter::EmitExternalGlobal(const GlobalVariable *GV) { std::string Name = getGlobalLinkName(GV); if (TM.getRelocationModel() != Reloc::Static) { - GVStubs.insert(Name); + if (GV->hasHiddenVisibility()) + HiddenGVStubs.insert(Name); + else + GVStubs.insert(Name); printSuffixedName(Name, "$non_lazy_ptr"); return; } @@ -979,51 +990,70 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) { // Output stubs for dynamically-linked functions if (TM.getRelocationModel() == Reloc::PIC_) { - for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end(); + for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end(); i != e; ++i) { SwitchToTextSection("\t.section __TEXT,__picsymbolstub1,symbol_stubs," "pure_instructions,32"); EmitAlignment(4); - std::string p = *i; - std::string L0p = (p[0]=='\"') ? "\"L0$" + p.substr(1) : "L0$" + p ; + const char *p = i->getKeyData(); + bool hasQuote = p[0]=='\"'; printSuffixedName(p, "$stub"); O << ":\n"; - O << "\t.indirect_symbol " << *i << '\n'; + O << "\t.indirect_symbol " << p << '\n'; O << "\tmflr r0\n"; - O << "\tbcl 20,31," << L0p << '\n'; - O << L0p << ":\n"; + O << "\tbcl 20,31,"; + if (hasQuote) + O << "\"L0$" << &p[1]; + else + O << "L0$" << p; + O << '\n'; + if (hasQuote) + O << "\"L0$" << &p[1]; + else + O << "L0$" << p; + O << ":\n"; O << "\tmflr r11\n"; O << "\taddis r11,r11,ha16("; printSuffixedName(p, "$lazy_ptr"); - O << "-" << L0p << ")\n"; + O << "-"; + if (hasQuote) + O << "\"L0$" << &p[1]; + else + O << "L0$" << p; + O << ")\n"; O << "\tmtlr r0\n"; if (isPPC64) O << "\tldu r12,lo16("; else O << "\tlwzu r12,lo16("; printSuffixedName(p, "$lazy_ptr"); - O << "-" << L0p << ")(r11)\n"; + O << "-"; + if (hasQuote) + O << "\"L0$" << &p[1]; + else + O << "L0$" << p; + O << ")(r11)\n"; O << "\tmtctr r12\n"; O << "\tbctr\n"; SwitchToDataSection(".lazy_symbol_pointer"); printSuffixedName(p, "$lazy_ptr"); O << ":\n"; - O << "\t.indirect_symbol " << *i << '\n'; + O << "\t.indirect_symbol " << p << '\n'; if (isPPC64) O << "\t.quad dyld_stub_binding_helper\n"; else O << "\t.long dyld_stub_binding_helper\n"; } } else { - for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end(); + for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end(); i != e; ++i) { SwitchToTextSection("\t.section __TEXT,__symbol_stub1,symbol_stubs," "pure_instructions,16"); EmitAlignment(4); - std::string p = *i; + const char *p = i->getKeyData(); printSuffixedName(p, "$stub"); O << ":\n"; - O << "\t.indirect_symbol " << *i << '\n'; + O << "\t.indirect_symbol " << p << '\n'; O << "\tlis r11,ha16("; printSuffixedName(p, "$lazy_ptr"); O << ")\n"; @@ -1038,7 +1068,7 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) { SwitchToDataSection(".lazy_symbol_pointer"); printSuffixedName(p, "$lazy_ptr"); O << ":\n"; - O << "\t.indirect_symbol " << *i << '\n'; + O << "\t.indirect_symbol " << p << '\n'; if (isPPC64) O << "\t.quad dyld_stub_binding_helper\n"; else @@ -1061,12 +1091,12 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) { // Output stubs for external and common global variables. if (!GVStubs.empty()) { SwitchToDataSection(".non_lazy_symbol_pointer"); - for (std::set::iterator I = GVStubs.begin(), - E = GVStubs.end(); I != E; ++I) { - std::string p = *I; + for (StringSet<>::iterator i = GVStubs.begin(), e = GVStubs.end(); + i != e; ++i) { + std::string p = i->getKeyData(); printSuffixedName(p, "$non_lazy_ptr"); O << ":\n"; - O << "\t.indirect_symbol " << *I << '\n'; + O << "\t.indirect_symbol " << p << '\n'; if (isPPC64) O << "\t.quad\t0\n"; else @@ -1074,6 +1104,23 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) { } } + if (!HiddenGVStubs.empty()) { + SwitchToSection(TAI->getDataSection()); + for (StringSet<>::iterator i = HiddenGVStubs.begin(), e = HiddenGVStubs.end(); + i != e; ++i) { + std::string p = i->getKeyData(); + EmitAlignment(isPPC64 ? 3 : 2); + printSuffixedName(p, "$non_lazy_ptr"); + O << ":\n"; + if (isPPC64) + O << "\t.quad\t"; + else + O << "\t.long\t"; + O << p << '\n'; + } + } + + // Emit initial debug information. DW.EndModule(); diff --git a/lib/Target/PowerPC/PPCSubtarget.cpp b/lib/Target/PowerPC/PPCSubtarget.cpp index 14983fcf1de..e63368bd659 100644 --- a/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/lib/Target/PowerPC/PPCSubtarget.cpp @@ -141,8 +141,11 @@ bool PPCSubtarget::hasLazyResolverStub(const GlobalValue *GV) const { // We never hae stubs if HasLazyResolverStubs=false or if in static mode. if (!HasLazyResolverStubs || TM.getRelocationModel() == Reloc::Static) return false; - + // If symbol visibility is hidden, the extra load is not needed if + // the symbol is definitely defined in the current translation unit. + bool isDecl = GV->isDeclaration() && !GV->hasNotBeenReadFromBitcode(); + if (GV->hasHiddenVisibility() && !isDecl && !GV->hasCommonLinkage()) + return false; return GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() || - GV->hasCommonLinkage() || - (GV->isDeclaration() && !GV->hasNotBeenReadFromBitcode()); + GV->hasCommonLinkage() || isDecl; } diff --git a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp index 66319c39816..76b1ddc2457 100644 --- a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp @@ -391,6 +391,14 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, FnStubs.insert(Name); printSuffixedName(Name, "$stub"); } + } else if (GV->hasHiddenVisibility()) { + if (!GV->isDeclaration() && !GV->hasCommonLinkage()) + // Definition is not definitely in the current translation unit. + O << Name; + else { + HiddenGVStubs.insert(Name); + printSuffixedName(Name, "$non_lazy_ptr"); + } } else { GVStubs.insert(Name); printSuffixedName(Name, "$non_lazy_ptr"); @@ -875,6 +883,15 @@ void X86ATTAsmPrinter::printGVStub(const char *GV, const char *Prefix) { O << GV << "\n\t.long\t0\n"; } +/// printHiddenGVStub - Print stub for a hidden global value. +/// +void X86ATTAsmPrinter::printHiddenGVStub(const char *GV, const char *Prefix) { + EmitAlignment(2); + printSuffixedName(GV, "$non_lazy_ptr", Prefix); + if (Prefix) O << Prefix; + O << ":\n" << TAI->getData32bitsDirective() << GV << '\n'; +} + bool X86ATTAsmPrinter::doFinalization(Module &M) { // Print out module-level global variables here. @@ -908,9 +925,8 @@ bool X86ATTAsmPrinter::doFinalization(Module &M) { SwitchToDataSection(""); // Output stubs for dynamically-linked functions - unsigned j = 1; for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end(); - i != e; ++i, ++j) { + i != e; ++i) { SwitchToDataSection("\t.section __IMPORT,__jump_table,symbol_stubs," "self_modifying_code+pure_instructions,5", 0); const char *p = i->getKeyData(); @@ -949,6 +965,13 @@ bool X86ATTAsmPrinter::doFinalization(Module &M) { i != e; ++i) printGVStub(i->getKeyData()); + if (!HiddenGVStubs.empty()) { + SwitchToSection(TAI->getDataSection()); + for (StringSet<>::iterator i = HiddenGVStubs.begin(), e = HiddenGVStubs.end(); + i != e; ++i) + printHiddenGVStub(i->getKeyData()); + } + // Emit final debug information. DW.EndModule(); diff --git a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h index 312c11d570c..40a5b4fb1d7 100644 --- a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h +++ b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h @@ -121,13 +121,14 @@ struct VISIBILITY_HIDDEN X86ATTAsmPrinter : public AsmPrinter { void printModuleLevelGV(const GlobalVariable* GVar); void printGVStub(const char *GV, const char *Prefix = NULL); + void printHiddenGVStub(const char *GV, const char *Prefix = NULL); bool runOnMachineFunction(MachineFunction &F); void emitFunctionHeader(const MachineFunction &MF); // Necessary for Darwin to print out the apprioriate types of linker stubs - StringSet<> FnStubs, GVStubs, LinkOnceStubs; + StringSet<> FnStubs, GVStubs, HiddenGVStubs; // Necessary for dllexport support StringSet<> DLLExportedFns, DLLExportedGVs; diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index c17f2dc6825..b836471afc1 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -40,10 +40,14 @@ bool X86Subtarget::GVRequiresExtraLoad(const GlobalValue* GV, if (TM.getRelocationModel() != Reloc::Static && TM.getCodeModel() != CodeModel::Large) { if (isTargetDarwin()) { - return (!isDirectCall && - (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() || - GV->hasCommonLinkage() || - (GV->isDeclaration() && !GV->hasNotBeenReadFromBitcode()))); + bool isDecl = GV->isDeclaration() && !GV->hasNotBeenReadFromBitcode(); + if (GV->hasHiddenVisibility() && + (Is64Bit || (!isDecl && !GV->hasCommonLinkage()))) + // If symbol visibility is hidden, the extra load is not needed if + // target is x86-64 or the symbol is definitely defined in the current + // translation unit. + return false; + return !isDirectCall && (isDecl || GV->mayBeOverridden()); } else if (isTargetELF()) { // Extra load is needed for all externally visible. if (isDirectCall) diff --git a/test/CodeGen/PowerPC/hidden-vis-2.ll b/test/CodeGen/PowerPC/hidden-vis-2.ll new file mode 100644 index 00000000000..4c9ae552f7c --- /dev/null +++ b/test/CodeGen/PowerPC/hidden-vis-2.ll @@ -0,0 +1,12 @@ +; RUN: llvm-as < %s | llc -mtriple=powerpc-apple-darwin9 | grep non_lazy_ptr | count 6 + +@x = external hidden global i32 ; [#uses=1] +@y = extern_weak hidden global i32 ; [#uses=1] + +define i32 @t() nounwind readonly { +entry: + %0 = load i32* @x, align 4 ; [#uses=1] + %1 = load i32* @y, align 4 ; [#uses=1] + %2 = add i32 %1, %0 ; [#uses=1] + ret i32 %2 +} diff --git a/test/CodeGen/PowerPC/hidden-vis.ll b/test/CodeGen/PowerPC/hidden-vis.ll new file mode 100644 index 00000000000..e04c89aebcc --- /dev/null +++ b/test/CodeGen/PowerPC/hidden-vis.ll @@ -0,0 +1,9 @@ +; RUN: llvm-as < %s | llc -mtriple=powerpc-apple-darwin9 | not grep non_lazy_ptr + +@x = weak hidden global i32 0 ; [#uses=1] + +define i32 @t() nounwind readonly { +entry: + %0 = load i32* @x, align 4 ; [#uses=1] + ret i32 %0 +} diff --git a/test/CodeGen/X86/hidden-vis-2.ll b/test/CodeGen/X86/hidden-vis-2.ll index 4df1c1c5b21..e000547f44f 100644 --- a/test/CodeGen/X86/hidden-vis-2.ll +++ b/test/CodeGen/X86/hidden-vis-2.ll @@ -1,6 +1,5 @@ ; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | grep mov | count 1 ; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin9 | not grep GOT -; XFAIL: * @x = weak hidden global i32 0 ; [#uses=1] diff --git a/test/CodeGen/X86/hidden-vis-3.ll b/test/CodeGen/X86/hidden-vis-3.ll new file mode 100644 index 00000000000..81dc76e1488 --- /dev/null +++ b/test/CodeGen/X86/hidden-vis-3.ll @@ -0,0 +1,15 @@ +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | grep mov | count 3 +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | grep non_lazy_ptr +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | grep long | count 2 +; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin9 | not grep GOT + +@x = external hidden global i32 ; [#uses=1] +@y = extern_weak hidden global i32 ; [#uses=1] + +define i32 @t() nounwind readonly { +entry: + %0 = load i32* @x, align 4 ; [#uses=1] + %1 = load i32* @y, align 4 ; [#uses=1] + %2 = add i32 %1, %0 ; [#uses=1] + ret i32 %2 +} diff --git a/test/CodeGen/X86/hidden-vis-4.ll b/test/CodeGen/X86/hidden-vis-4.ll new file mode 100644 index 00000000000..e6936de1036 --- /dev/null +++ b/test/CodeGen/X86/hidden-vis-4.ll @@ -0,0 +1,11 @@ +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | grep non_lazy_ptr +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | grep long +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | grep comm + +@x = common hidden global i32 0 ; [#uses=1] + +define i32 @t() nounwind readonly { +entry: + %0 = load i32* @x, align 4 ; [#uses=1] + ret i32 %0 +} -- 2.11.0