<div dir="ltr">Hi Rafael,<div><br></div><div>Sorry for any inconvenience caused! I'm OK if you want to revert this commit, and also thanks for your kindly help to port it to the new GlobalValue alias anyway.</div><div>
<br></div><div>Thanks,</div><div>-Jiangning</div><div><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">2014-05-16 11:43 GMT+08:00 Rafael Espíndola <span dir="ltr"><<a href="mailto:rafael.espindola@gmail.com" target="_blank">rafael.espindola@gmail.com</a>></span>:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Sorry I missed this, but this uses a aliases pointing to GEPs. That is<br>
not supported and is currently fully broken:<br>
<br>
$ cat test.ll<br>
@foo = global [1 x i32] zeroinitializer<br>
<br>
@bar = alias getelementptr ([1 x i32]* @foo, i32 1, i32 1)<br>
<br>
$ llvm-as test.ll -o - | llvm-dis -o -<br>
@foo = global [1 x i32] zeroinitializer<br>
<br>
@bar = alias getelementptr ([1 x i32]* @foo, i64 2, i32 0)<br>
<br>
<br>
The good news is that I found this while rebasing my fix for pr10367<br>
which just got LGTMed and should allow this to be correctly supported<br>
by adding and explicit offset for aliases.<br>
<br>
Since this is off by default anyway, I hope you don't mind If I revert<br>
this tomorrow morning. I volunteer to help you port it to the new<br>
alias :-)<br>
<br>
Cheers,<br>
Rafael<br>
<div class="HOEnZb"><div class="h5"><br>
<br>
<br>
On 15 May 2014 19:45, Jiangning Liu <<a href="mailto:jiangning.liu@arm.com">jiangning.liu@arm.com</a>> wrote:<br>
> Author: jiangning<br>
> Date: Thu May 15 18:45:42 2014<br>
> New Revision: 208934<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=208934&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=208934&view=rev</a><br>
> Log:<br>
> Implement global merge optimization for global variables.<br>
><br>
> This commit implements two command line switches -global-merge-on-external<br>
> and -global-merge-aligned, and both of them are false by default, so this<br>
> optimization is disabled by default for all targets.<br>
><br>
> For ARM64, some back-end behaviors need to be tuned to get this optimization<br>
> further enabled.<br>
><br>
><br>
> Added:<br>
>     llvm/trunk/test/CodeGen/AArch64/global-merge.ll<br>
>     llvm/trunk/test/CodeGen/ARM/global-merge-1.ll<br>
>     llvm/trunk/test/CodeGen/ARM64/global-merge.ll<br>
>     llvm/trunk/test/Transforms/GlobalMerge/AArch64/<br>
>     llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-1.ll<br>
>     llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-2.ll<br>
>     llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-3.ll<br>
>     llvm/trunk/test/Transforms/GlobalMerge/AArch64/lit.local.cfg<br>
> Removed:<br>
>     llvm/trunk/test/CodeGen/AArch64/global_merge_1.ll<br>
> Modified:<br>
>     llvm/trunk/include/llvm/IR/GlobalAlias.h<br>
>     llvm/trunk/include/llvm/Target/TargetLowering.h<br>
>     llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp<br>
>     llvm/trunk/lib/IR/Globals.cpp<br>
>     llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp<br>
>     llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h<br>
>     llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.cpp<br>
>     llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.h<br>
>     llvm/trunk/lib/Transforms/Scalar/GlobalMerge.cpp<br>
>     llvm/trunk/lib/Transforms/Scalar/Scalar.cpp<br>
>     llvm/trunk/test/Transforms/GlobalMerge/ARM/arm.ll<br>
>     llvm/trunk/test/Transforms/GlobalMerge/ARM64/arm64.ll<br>
><br>
> Modified: llvm/trunk/include/llvm/IR/GlobalAlias.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/GlobalAlias.h?rev=208934&r1=208933&r2=208934&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/GlobalAlias.h?rev=208934&r1=208933&r2=208934&view=diff</a><br>

> ==============================================================================<br>
> --- llvm/trunk/include/llvm/IR/GlobalAlias.h (original)<br>
> +++ llvm/trunk/include/llvm/IR/GlobalAlias.h Thu May 15 18:45:42 2014<br>
> @@ -82,6 +82,10 @@ public:<br>
>    static inline bool classof(const Value *V) {<br>
>      return V->getValueID() == Value::GlobalAliasVal;<br>
>    }<br>
> +<br>
> +  // return the constant offset of an expression, with which this global var<br>
> +  // has alias.<br>
> +  uint64_t calculateOffset(const DataLayout &DL) const;<br>
>  };<br>
><br>
>  template <><br>
><br>
> Modified: llvm/trunk/include/llvm/Target/TargetLowering.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=208934&r1=208933&r2=208934&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=208934&r1=208933&r2=208934&view=diff</a><br>

> ==============================================================================<br>
> --- llvm/trunk/include/llvm/Target/TargetLowering.h (original)<br>
> +++ llvm/trunk/include/llvm/Target/TargetLowering.h Thu May 15 18:45:42 2014<br>
> @@ -32,6 +32,7 @@<br>
>  #include "llvm/IR/CallingConv.h"<br>
>  #include "llvm/IR/InlineAsm.h"<br>
>  #include "llvm/IR/IRBuilder.h"<br>
> +#include "llvm/IR/GlobalVariable.h"<br>
>  #include "llvm/MC/MCRegisterInfo.h"<br>
>  #include "llvm/Target/TargetCallingConv.h"<br>
>  #include "llvm/Target/TargetMachine.h"<br>
> @@ -883,6 +884,12 @@ public:<br>
>      return 0;<br>
>    }<br>
><br>
> +  /// Returns the alignment required by global merge on external symbols.<br>
> +  /// By default, returns the natural alignment of merged data structure.<br>
> +  virtual unsigned getGlobalMergeAlignment(StructType *MergedTy) const {<br>
> +    return getDataLayout()->getABITypeAlignment(MergedTy);<br>
> +  }<br>
> +<br>
>    /// Returns true if a cast between SrcAS and DestAS is a noop.<br>
>    virtual bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const {<br>
>      return false;<br>
><br>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=208934&r1=208933&r2=208934&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=208934&r1=208933&r2=208934&view=diff</a><br>

> ==============================================================================<br>
> --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)<br>
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Thu May 15 18:45:42 2014<br>
> @@ -946,8 +946,11 @@ bool AsmPrinter::doFinalization(Module &<br>
>        EmitVisibility(Name, Alias.getVisibility());<br>
><br>
>        // Emit the directives as assignments aka .set:<br>
> -      OutStreamer.EmitAssignment(Name,<br>
> -                                 MCSymbolRefExpr::Create(Target, OutContext));<br>
> +      const MCExpr *Expr = MCSymbolRefExpr::Create(Target, OutContext);<br>
> +      if (uint64_t Offset = Alias.calculateOffset(*TM.getDataLayout()))<br>
> +        Expr = MCBinaryExpr::CreateAdd(Expr,<br>
> +                 MCConstantExpr::Create(Offset, OutContext), OutContext);<br>
> +      OutStreamer.EmitAssignment(Name, Expr);<br>
>      }<br>
>    }<br>
><br>
><br>
> Modified: llvm/trunk/lib/IR/Globals.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Globals.cpp?rev=208934&r1=208933&r2=208934&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Globals.cpp?rev=208934&r1=208933&r2=208934&view=diff</a><br>

> ==============================================================================<br>
> --- llvm/trunk/lib/IR/Globals.cpp (original)<br>
> +++ llvm/trunk/lib/IR/Globals.cpp Thu May 15 18:45:42 2014<br>
> @@ -15,6 +15,7 @@<br>
>  #include "llvm/IR/GlobalValue.h"<br>
>  #include "llvm/ADT/SmallPtrSet.h"<br>
>  #include "llvm/IR/Constants.h"<br>
> +#include "llvm/IR/DataLayout.h"<br>
>  #include "llvm/IR/DerivedTypes.h"<br>
>  #include "llvm/IR/GlobalAlias.h"<br>
>  #include "llvm/IR/GlobalVariable.h"<br>
> @@ -282,3 +283,27 @@ GlobalObject *GlobalAlias::getAliasedGlo<br>
>        return cast<GlobalObject>(GV);<br>
>    }<br>
>  }<br>
> +<br>
> +uint64_t GlobalAlias::calculateOffset(const DataLayout &DL) const {<br>
> +  uint64_t Offset = 0;<br>
> +  const Constant *C = this;<br>
> +  while (C) {<br>
> +    if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(C)) {<br>
> +      C = GA->getAliasee();<br>
> +    } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {<br>
> +      if (CE->getOpcode() == Instruction::GetElementPtr) {<br>
> +        std::vector<Value*> Args;<br>
> +        for (unsigned I = 1; I < CE->getNumOperands(); ++I)<br>
> +          Args.push_back(CE->getOperand(I));<br>
> +        Offset += DL.getIndexedOffset(CE->getOperand(0)->getType(), Args);<br>
> +      }<br>
> +      C = CE->getOperand(0);<br>
> +    } else if (isa<GlobalValue>(C)) {<br>
> +      return Offset;<br>
> +    } else {<br>
> +      assert(0 && "Unexpected type in alias chain!");<br>
> +      return 0;<br>
> +    }<br>
> +  }<br>
> +  return Offset;<br>
> +}<br>
><br>
> Modified: llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp?rev=208934&r1=208933&r2=208934&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp?rev=208934&r1=208933&r2=208934&view=diff</a><br>

> ==============================================================================<br>
> --- llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp (original)<br>
> +++ llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp Thu May 15 18:45:42 2014<br>
> @@ -5560,3 +5560,17 @@ unsigned AArch64TargetLowering::getMaxim<br>
>    return 4095;<br>
>  }<br>
><br>
> +/// getGlobalMergeAlignment - Set alignment to be the max size of merged<br>
> +/// global variable data structure, and make it aligned up to power of 2.<br>
> +/// This way, we could guarantee the merged global variable data structure<br>
> +/// doesn't cross page boundary, because usually OS always allocates page at<br>
> +/// 4096-byte aligned boundary.<br>
> +unsigned AArch64TargetLowering::getGlobalMergeAlignment(<br>
> +                                  StructType *MergedTy) const {<br>
> +  unsigned Align = getDataLayout()->getTypeAllocSize(MergedTy);<br>
> +  if (Align & (Align - 1))<br>
> +    Align = llvm::NextPowerOf2(Align);<br>
> +<br>
> +  return Align;<br>
> +}<br>
> +<br>
><br>
> Modified: llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h?rev=208934&r1=208933&r2=208934&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h?rev=208934&r1=208933&r2=208934&view=diff</a><br>

> ==============================================================================<br>
> --- llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h (original)<br>
> +++ llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h Thu May 15 18:45:42 2014<br>
> @@ -386,6 +386,10 @@ public:<br>
>    /// be used for loads / stores from the global.<br>
>    unsigned getMaximalGlobalOffset() const override;<br>
><br>
> +  /// getGlobalMergeAlignment - Set alignment to be the max size of merged<br>
> +  /// global variable data structure, and make it aligned up to power of 2.<br>
> +  unsigned getGlobalMergeAlignment(StructType *MergedTy) const override;<br>
> +<br>
>  protected:<br>
>    std::pair<const TargetRegisterClass*, uint8_t><br>
>    findRepresentativeClass(MVT VT) const override;<br>
><br>
> Modified: llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.cpp?rev=208934&r1=208933&r2=208934&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.cpp?rev=208934&r1=208933&r2=208934&view=diff</a><br>

> ==============================================================================<br>
> --- llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.cpp (original)<br>
> +++ llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.cpp Thu May 15 18:45:42 2014<br>
> @@ -630,6 +630,20 @@ unsigned ARM64TargetLowering::getMaximal<br>
>    return 4095;<br>
>  }<br>
><br>
> +/// getGlobalMergeAlignment - Set alignment to be the max size of merged<br>
> +/// global variable data structure, and make it aligned up to power of 2.<br>
> +/// This way, we could guarantee the merged global variable data structure<br>
> +/// doesn't cross page boundary, because usually OS always allocates page at<br>
> +/// 4096-byte aligned boundary.<br>
> +unsigned ARM64TargetLowering::getGlobalMergeAlignment(<br>
> +                                StructType *MergedTy) const {<br>
> +  unsigned Align = getDataLayout()->getTypeAllocSize(MergedTy);<br>
> +  if (Align & (Align - 1))<br>
> +    Align = llvm::NextPowerOf2(Align);<br>
> +<br>
> +  return Align;<br>
> +}<br>
> +<br>
>  FastISel *<br>
>  ARM64TargetLowering::createFastISel(FunctionLoweringInfo &funcInfo,<br>
>                                      const TargetLibraryInfo *libInfo) const {<br>
><br>
> Modified: llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.h?rev=208934&r1=208933&r2=208934&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.h?rev=208934&r1=208933&r2=208934&view=diff</a><br>

> ==============================================================================<br>
> --- llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.h (original)<br>
> +++ llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.h Thu May 15 18:45:42 2014<br>
> @@ -236,6 +236,10 @@ public:<br>
>    /// be used for loads / stores from the global.<br>
>    unsigned getMaximalGlobalOffset() const override;<br>
><br>
> +  /// getGlobalMergeAlignment - Set alignment to be the max size of merged<br>
> +  /// global variable data structure, and make it aligned up to power of 2.<br>
> +  unsigned getGlobalMergeAlignment(StructType *MergedTy) const override;<br>
> +<br>
>    /// Returns true if a cast between SrcAS and DestAS is a noop.<br>
>    bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override {<br>
>      // Addrspacecasts are always noops.<br>
><br>
> Modified: llvm/trunk/lib/Transforms/Scalar/GlobalMerge.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GlobalMerge.cpp?rev=208934&r1=208933&r2=208934&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GlobalMerge.cpp?rev=208934&r1=208933&r2=208934&view=diff</a><br>

> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/Scalar/GlobalMerge.cpp (original)<br>
> +++ llvm/trunk/lib/Transforms/Scalar/GlobalMerge.cpp Thu May 15 18:45:42 2014<br>
> @@ -72,7 +72,7 @@ using namespace llvm;<br>
>  #define DEBUG_TYPE "global-merge"<br>
><br>
>  static cl::opt<bool><br>
> -EnableGlobalMerge("global-merge", cl::Hidden,<br>
> +EnableGlobalMerge("enable-global-merge", cl::NotHidden,<br>
>                    cl::desc("Enable global merge pass"),<br>
>                    cl::init(true));<br>
><br>
> @@ -81,6 +81,16 @@ EnableGlobalMergeOnConst("global-merge-o<br>
>                           cl::desc("Enable global merge pass on constants"),<br>
>                           cl::init(false));<br>
><br>
> +static cl::opt<bool><br>
> +EnableGlobalMergeOnExternal("global-merge-on-external", cl::Hidden,<br>
> +                   cl::desc("Enable global merge pass on external linkage"),<br>
> +                   cl::init(false));<br>
> +<br>
> +static cl::opt<bool><br>
> +EnableGlobalMergeAligned("global-merge-aligned", cl::Hidden,<br>
> +                   cl::desc("Set target specific alignment for global merge pass"),<br>
> +                   cl::init(false));<br>
> +<br>
>  STATISTIC(NumMerged      , "Number of globals merged");<br>
>  namespace {<br>
>    class GlobalMerge : public FunctionPass {<br>
> @@ -129,9 +139,21 @@ namespace {<br>
>  } // end anonymous namespace<br>
><br>
>  char GlobalMerge::ID = 0;<br>
> -INITIALIZE_PASS(GlobalMerge, "global-merge",<br>
> -                "Global Merge", false, false)<br>
><br>
> +static void *initializeGlobalMergePassOnce(PassRegistry &Registry) {<br>
> +  PassInfo *PI = new PassInfo(<br>
> +      "Merge global variables",<br>
> +      "global-merge", &GlobalMerge::ID,<br>
> +      PassInfo::NormalCtor_t(callDefaultCtor<GlobalMerge>), false,<br>
> +      false, PassInfo::TargetMachineCtor_t(<br>
> +                 callTargetMachineCtor<GlobalMerge>));<br>
> +  Registry.registerPass(*PI, true);<br>
> +  return PI;<br>
> +}<br>
> +<br>
> +void llvm::initializeGlobalMergePass(PassRegistry &Registry) {<br>
> +  CALL_ONCE_INITIALIZATION(initializeGlobalMergePassOnce)<br>
> +}<br>
><br>
>  bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals,<br>
>                            Module &M, bool isConst, unsigned AddrSpace) const {<br>
> @@ -154,11 +176,16 @@ bool GlobalMerge::doMerge(SmallVectorImp<br>
><br>
>    Type *Int32Ty = Type::getInt32Ty(M.getContext());<br>
><br>
> +  assert (Globals.size() > 1);<br>
> +<br>
>    for (size_t i = 0, e = Globals.size(); i != e; ) {<br>
>      size_t j = 0;<br>
>      uint64_t MergedSize = 0;<br>
>      std::vector<Type*> Tys;<br>
>      std::vector<Constant*> Inits;<br>
> +<br>
> +    bool HasExternal = false;<br>
> +    GlobalVariable *TheFirstExternal = 0;<br>
>      for (j = i; j != e; ++j) {<br>
>        Type *Ty = Globals[j]->getType()->getElementType();<br>
>        MergedSize += DL->getTypeAllocSize(Ty);<br>
> @@ -167,17 +194,45 @@ bool GlobalMerge::doMerge(SmallVectorImp<br>
>        }<br>
>        Tys.push_back(Ty);<br>
>        Inits.push_back(Globals[j]->getInitializer());<br>
> +<br>
> +      if (Globals[j]->hasExternalLinkage() && !HasExternal) {<br>
> +        HasExternal = true;<br>
> +        TheFirstExternal = Globals[j];<br>
> +      }<br>
>      }<br>
><br>
> +    // If merged variables doesn't have external linkage, we needn't to expose<br>
> +    // the symbol after merging.<br>
> +    GlobalValue::LinkageTypes Linkage = HasExternal ?<br>
> +                                          GlobalValue::ExternalLinkage :<br>
> +                                          GlobalValue::InternalLinkage ;<br>
> +<br>
> +    // If merged variables have external linkage, we use symbol name of the<br>
> +    // first variable merged as the suffix of global symbol name. This would<br>
> +    // be able to avoid the link-time naming conflict for globalm symbols.<br>
> +    Twine MergedGVName = HasExternal ?<br>
> +                           "_MergedGlobals_" + TheFirstExternal->getName() :<br>
> +                           "_MergedGlobals" ;<br>
> +<br>
>      StructType *MergedTy = StructType::get(M.getContext(), Tys);<br>
>      Constant *MergedInit = ConstantStruct::get(MergedTy, Inits);<br>
> +<br>
>      GlobalVariable *MergedGV = new GlobalVariable(M, MergedTy, isConst,<br>
> -                                                  GlobalValue::InternalLinkage,<br>
> -                                                  MergedInit, "_MergedGlobals",<br>
> -                                                  nullptr,<br>
> -                                                  GlobalVariable::NotThreadLocal,<br>
> -                                                  AddrSpace);<br>
> +                                     Linkage, MergedInit, MergedGVName,<br>
> +                                     nullptr, GlobalVariable::NotThreadLocal,<br>
> +                                     AddrSpace);<br>
> +<br>
> +    if (EnableGlobalMergeAligned) {<br>
> +      unsigned Align = TLI->getGlobalMergeAlignment(MergedTy);<br>
> +      assert(((Align % DL->getABITypeAlignment(MergedTy)) == 0) &&<br>
> +        "Specified alignment doesn't meet natural alignment requirement.");<br>
> +      MergedGV->setAlignment(Align);<br>
> +    }<br>
> +<br>
>      for (size_t k = i; k < j; ++k) {<br>
> +      GlobalValue::LinkageTypes Linkage = Globals[k]->getLinkage();<br>
> +      std::string Name = Globals[k]->getName();<br>
> +<br>
>        Constant *Idx[2] = {<br>
>          ConstantInt::get(Int32Ty, 0),<br>
>          ConstantInt::get(Int32Ty, k-i)<br>
> @@ -185,6 +240,12 @@ bool GlobalMerge::doMerge(SmallVectorImp<br>
>        Constant *GEP = ConstantExpr::getInBoundsGetElementPtr(MergedGV, Idx);<br>
>        Globals[k]->replaceAllUsesWith(GEP);<br>
>        Globals[k]->eraseFromParent();<br>
> +<br>
> +      if (Linkage != GlobalValue::InternalLinkage) {<br>
> +        // Generate a new alias...<br>
> +        new GlobalAlias(GEP->getType(), Linkage, Name, GEP, &M);<br>
> +      }<br>
> +<br>
>        NumMerged++;<br>
>      }<br>
>      i = j;<br>
> @@ -245,8 +306,12 @@ bool GlobalMerge::doInitialization(Modul<br>
>    // Grab all non-const globals.<br>
>    for (Module::global_iterator I = M.global_begin(),<br>
>           E = M.global_end(); I != E; ++I) {<br>
> -    // Merge is safe for "normal" internal globals only<br>
> -    if (!I->hasLocalLinkage() || I->isThreadLocal() || I->hasSection())<br>
> +    // Merge is safe for "normal" internal or external globals only<br>
> +    if (I->isDeclaration() || I->isThreadLocal() || I->hasSection())<br>
> +      continue;<br>
> +<br>
> +    if (!(EnableGlobalMergeOnExternal && I->hasExternalLinkage())<br>
> +          && !I->hasInternalLinkage())<br>
>        continue;<br>
><br>
>      PointerType *PT = dyn_cast<PointerType>(I->getType());<br>
><br>
> Modified: llvm/trunk/lib/Transforms/Scalar/Scalar.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Scalar.cpp?rev=208934&r1=208933&r2=208934&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Scalar.cpp?rev=208934&r1=208933&r2=208934&view=diff</a><br>

> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/Scalar/Scalar.cpp (original)<br>
> +++ llvm/trunk/lib/Transforms/Scalar/Scalar.cpp Thu May 15 18:45:42 2014<br>
> @@ -38,6 +38,7 @@ void llvm::initializeScalarOpts(PassRegi<br>
>    initializeDSEPass(Registry);<br>
>    initializeGVNPass(Registry);<br>
>    initializeEarlyCSEPass(Registry);<br>
> +  initializeGlobalMergePass(Registry);<br>
>    initializeIndVarSimplifyPass(Registry);<br>
>    initializeJumpThreadingPass(Registry);<br>
>    initializeLICMPass(Registry);<br>
><br>
> Added: llvm/trunk/test/CodeGen/AArch64/global-merge.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/global-merge.ll?rev=208934&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/global-merge.ll?rev=208934&view=auto</a><br>

> ==============================================================================<br>
> --- llvm/trunk/test/CodeGen/AArch64/global-merge.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AArch64/global-merge.ll Thu May 15 18:45:42 2014<br>
> @@ -0,0 +1,34 @@<br>
> +; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -O0 | FileCheck --check-prefix=NO-MERGE %s<br>
> +; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -O0 -global-merge-on-external=true -global-merge-aligned=true | FileCheck --check-prefix=NO-MERGE %s<br>
> +<br>
> +; RUN: llc < %s -mtriple=arm64-apple-ios -O0 | FileCheck %s --check-prefix=CHECK-APPLE-IOS-NO-MERGE<br>
> +; RUN: llc < %s -mtriple=arm64-apple-ios -O0 -global-merge-on-external=true -global-merge-aligned=false | FileCheck %s --check-prefix=CHECK-APPLE-IOS-NO-MERGE<br>
> +<br>
> +; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -O1 | FileCheck %s<br>
> +; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -O1 -global-merge-on-external=true -global-merge-aligned=true | FileCheck %s<br>
> +<br>
> +; RUN: llc < %s -mtriple=arm64-apple-ios -O1 | FileCheck %s --check-prefix=CHECK-APPLE-IOS<br>
> +; RUN: llc < %s -mtriple=arm64-apple-ios -O1 -global-merge-on-external=true -global-merge-aligned=false | FileCheck %s --check-prefix=CHECK-APPLE-IOS<br>
> +<br>
> +@m = internal global i32 0, align 4<br>
> +@n = internal global i32 0, align 4<br>
> +<br>
> +define void @f1(i32 %a1, i32 %a2) {<br>
> +; CHECK-LABEL: f1:<br>
> +; CHECK: adrp x{{[0-9]+}}, _MergedGlobals<br>
> +; CHECK-NOT: adrp<br>
> +<br>
> +; CHECK-APPLE-IOS-LABEL: f1:<br>
> +; CHECK-APPLE-IOS: adrp x{{[0-9]+}}, __MergedGlobals<br>
> +; CHECK-APPLE-IOS-NOT: adrp<br>
> +  store i32 %a1, i32* @m, align 4<br>
> +  store i32 %a2, i32* @n, align 4<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; CHECK:        .local _MergedGlobals<br>
> +; CHECK:        .comm  _MergedGlobals,8,8<br>
> +; NO-MERGE-NOT: .local _MergedGlobals<br>
> +<br>
> +; CHECK-APPLE-IOS: .zerofill __DATA,__bss,__MergedGlobals,8,3<br>
> +; CHECK-APPLE-IOS-NO-MERGE-NOT: .zerofill __DATA,__bss,__MergedGlobals,8,3<br>
><br>
> Removed: llvm/trunk/test/CodeGen/AArch64/global_merge_1.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/global_merge_1.ll?rev=208933&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/global_merge_1.ll?rev=208933&view=auto</a><br>

> ==============================================================================<br>
> --- llvm/trunk/test/CodeGen/AArch64/global_merge_1.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/AArch64/global_merge_1.ll (removed)<br>
> @@ -1,17 +0,0 @@<br>
> -; RUN: llc < %s -mtriple=aarch64-none-linux-gnu | FileCheck %s<br>
> -<br>
> -@m = internal global i32 0, align 4<br>
> -@n = internal global i32 0, align 4<br>
> -<br>
> -define void @f1(i32 %a1, i32 %a2) {<br>
> -; CHECK-LABEL: f1:<br>
> -; CHECK: adrp x{{[0-9]+}}, _MergedGlobals<br>
> -; CHECK-NOT: adrp<br>
> -  store i32 %a1, i32* @m, align 4<br>
> -  store i32 %a2, i32* @n, align 4<br>
> -  ret void<br>
> -}<br>
> -<br>
> -; CHECK:        .local _MergedGlobals<br>
> -; CHECK:        .comm  _MergedGlobals,8,8<br>
> -<br>
><br>
> Added: llvm/trunk/test/CodeGen/ARM/global-merge-1.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/global-merge-1.ll?rev=208934&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/global-merge-1.ll?rev=208934&view=auto</a><br>

> ==============================================================================<br>
> --- llvm/trunk/test/CodeGen/ARM/global-merge-1.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/ARM/global-merge-1.ll Thu May 15 18:45:42 2014<br>
> @@ -0,0 +1,85 @@<br>
> +; RUN: llc %s -O0 -o - | FileCheck -check-prefix=NO-MERGE %s<br>
> +; RUN: llc %s -O0 -o - -enable-global-merge=false | FileCheck -check-prefix=NO-MERGE %s<br>
> +; RUN: llc %s -O0 -o - -enable-global-merge=true | FileCheck -check-prefix=NO-MERGE %s<br>
> +; RUN: llc %s -O1 -o - | FileCheck -check-prefix=MERGE %s<br>
> +; RUN: llc %s -O1 -o - -enable-global-merge=false | FileCheck -check-prefix=NO-MERGE %s<br>
> +; RUN: llc %s -O1 -o - -enable-global-merge=true | FileCheck -check-prefix=MERGE %s<br>
> +<br>
> +; MERGE-NOT: .zerofill __DATA,__bss,_bar,20,2<br>
> +; MERGE-NOT: .zerofill __DATA,__bss,_baz,20,2<br>
> +; MERGE-NOT: .zerofill __DATA,__bss,_foo,20,2<br>
> +; MERGE: .zerofill __DATA,__bss,__MergedGlobals,60,4<br>
> +; MERGE-NOT: .zerofill __DATA,__bss,_bar,20,2<br>
> +; MERGE-NOT: .zerofill __DATA,__bss,_baz,20,2<br>
> +; MERGE-NOT: .zerofill __DATA,__bss,_foo,20,2<br>
> +<br>
> +; NO-MERGE-NOT: .zerofill __DATA,__bss,__MergedGlobals,60,4<br>
> +; NO-MERGE: .zerofill __DATA,__bss,_bar,20,2<br>
> +; NO-MERGE: .zerofill __DATA,__bss,_baz,20,2<br>
> +; NO-MERGE: .zerofill __DATA,__bss,_foo,20,2<br>
> +; NO-MERGE-NOT: .zerofill __DATA,__bss,__MergedGlobals,60,4<br>
> +<br>
> +target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32"<br>
> +target triple = "thumbv7-apple-ios3.0.0"<br>
> +<br>
> +@bar = internal global [5 x i32] zeroinitializer, align 4<br>
> +@baz = internal global [5 x i32] zeroinitializer, align 4<br>
> +@foo = internal global [5 x i32] zeroinitializer, align 4<br>
> +<br>
> +; Function Attrs: nounwind ssp<br>
> +define internal void @initialize() #0 {<br>
> +  %1 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #3<br>
> +  store i32 %1, i32* getelementptr inbounds ([5 x i32]* @bar, i32 0, i32 0), align 4, !tbaa !1<br>
> +  %2 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #3<br>
> +  store i32 %2, i32* getelementptr inbounds ([5 x i32]* @baz, i32 0, i32 0), align 4, !tbaa !1<br>
> +  %3 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #3<br>
> +  store i32 %3, i32* getelementptr inbounds ([5 x i32]* @bar, i32 0, i32 1), align 4, !tbaa !1<br>
> +  %4 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #3<br>
> +  store i32 %4, i32* getelementptr inbounds ([5 x i32]* @baz, i32 0, i32 1), align 4, !tbaa !1<br>
> +  %5 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #3<br>
> +  store i32 %5, i32* getelementptr inbounds ([5 x i32]* @bar, i32 0, i32 2), align 4, !tbaa !1<br>
> +  %6 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #3<br>
> +  store i32 %6, i32* getelementptr inbounds ([5 x i32]* @baz, i32 0, i32 2), align 4, !tbaa !1<br>
> +  %7 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #3<br>
> +  store i32 %7, i32* getelementptr inbounds ([5 x i32]* @bar, i32 0, i32 3), align 4, !tbaa !1<br>
> +  %8 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #3<br>
> +  store i32 %8, i32* getelementptr inbounds ([5 x i32]* @baz, i32 0, i32 3), align 4, !tbaa !1<br>
> +  %9 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #3<br>
> +  store i32 %9, i32* getelementptr inbounds ([5 x i32]* @bar, i32 0, i32 4), align 4, !tbaa !1<br>
> +  %10 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #3<br>
> +  store i32 %10, i32* getelementptr inbounds ([5 x i32]* @baz, i32 0, i32 4), align 4, !tbaa !1<br>
> +  ret void<br>
> +}<br>
> +<br>
> +declare i32 @calc(...) #1<br>
> +<br>
> +; Function Attrs: nounwind ssp<br>
> +define internal void @calculate() #0 {<br>
> +  %1 = load <4 x i32>* bitcast ([5 x i32]* @bar to <4 x i32>*), align 4<br>
> +  %2 = load <4 x i32>* bitcast ([5 x i32]* @baz to <4 x i32>*), align 4<br>
> +  %3 = mul <4 x i32> %2, %1<br>
> +  store <4 x i32> %3, <4 x i32>* bitcast ([5 x i32]* @foo to <4 x i32>*), align 4<br>
> +  %4 = load i32* getelementptr inbounds ([5 x i32]* @bar, i32 0, i32 4), align 4, !tbaa !1<br>
> +  %5 = load i32* getelementptr inbounds ([5 x i32]* @baz, i32 0, i32 4), align 4, !tbaa !1<br>
> +  %6 = mul nsw i32 %5, %4<br>
> +  store i32 %6, i32* getelementptr inbounds ([5 x i32]* @foo, i32 0, i32 4), align 4, !tbaa !1<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; Function Attrs: nounwind readnone ssp<br>
> +define internal i32* @returnFoo() #2 {<br>
> +  ret i32* getelementptr inbounds ([5 x i32]* @foo, i32 0, i32 0)<br>
> +}<br>
> +<br>
> +attributes #0 = { nounwind ssp "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }<br>

> +attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }<br>

> +attributes #2 = { nounwind readnone ssp "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }<br>

> +attributes #3 = { nounwind }<br>
> +<br>
> +!llvm.ident = !{!0}<br>
> +<br>
> +!0 = metadata !{metadata !"LLVM version 3.4 "}<br>
> +!1 = metadata !{metadata !2, metadata !2, i64 0}<br>
> +!2 = metadata !{metadata !"int", metadata !3, i64 0}<br>
> +!3 = metadata !{metadata !"omnipotent char", metadata !4, i64 0}<br>
> +!4 = metadata !{metadata !"Simple C/C++ TBAA"}<br>
><br>
> Added: llvm/trunk/test/CodeGen/ARM64/global-merge.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM64/global-merge.ll?rev=208934&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM64/global-merge.ll?rev=208934&view=auto</a><br>

> ==============================================================================<br>
> --- llvm/trunk/test/CodeGen/ARM64/global-merge.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/ARM64/global-merge.ll Thu May 15 18:45:42 2014<br>
> @@ -0,0 +1,88 @@<br>
> +; RUN: llc %s -O0 -o - | FileCheck -check-prefix=NO-MERGE %s<br>
> +; RUN: llc %s -O0 -o - -enable-global-merge=false | FileCheck -check-prefix=NO-MERGE %s<br>
> +; RUN: llc %s -O0 -o - -enable-global-merge=true | FileCheck -check-prefix=NO-MERGE %s<br>
> +; RUN: llc %s -O1 -o - | FileCheck -check-prefix=MERGE %s<br>
> +; RUN: llc %s -O1 -o - -enable-global-merge=false | FileCheck -check-prefix=NO-MERGE %s<br>
> +; RUN: llc %s -O1 -o - -enable-global-merge=true | FileCheck -check-prefix=MERGE %s<br>
> +<br>
> +; MERGE-NOT: .zerofill __DATA,__bss,_bar,20,2<br>
> +; MERGE-NOT: .zerofill __DATA,__bss,_baz,20,2<br>
> +; MERGE-NOT: .zerofill __DATA,__bss,_foo,20,2<br>
> +; MERGE: .zerofill __DATA,__bss,__MergedGlobals,60,4<br>
> +; MERGE-NOT: .zerofill __DATA,__bss,_bar,20,2<br>
> +; MERGE-NOT: .zerofill __DATA,__bss,_baz,20,2<br>
> +; MERGE-NOT: .zerofill __DATA,__bss,_foo,20,2<br>
> +<br>
> +; NO-MERGE-NOT: .zerofill __DATA,__bss,__MergedGlobals,60,4<br>
> +; NO-MERGE: .zerofill __DATA,__bss,_bar,20,2<br>
> +; NO-MERGE: .zerofill __DATA,__bss,_baz,20,2<br>
> +; NO-MERGE: .zerofill __DATA,__bss,_foo,20,2<br>
> +; NO-MERGE-NOT: .zerofill __DATA,__bss,__MergedGlobals,60,4<br>
> +<br>
> +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n32:64-S128"<br>
> +target triple = "arm64-apple-ios7.0.0"<br>
> +<br>
> +@bar = internal global [5 x i32] zeroinitializer, align 4<br>
> +@baz = internal global [5 x i32] zeroinitializer, align 4<br>
> +@foo = internal global [5 x i32] zeroinitializer, align 4<br>
> +<br>
> +; Function Attrs: nounwind ssp<br>
> +define internal void @initialize() #0 {<br>
> +  %1 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #2<br>
> +  store i32 %1, i32* getelementptr inbounds ([5 x i32]* @bar, i64 0, i64 0), align 4<br>
> +  %2 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #2<br>
> +  store i32 %2, i32* getelementptr inbounds ([5 x i32]* @baz, i64 0, i64 0), align 4<br>
> +  %3 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #2<br>
> +  store i32 %3, i32* getelementptr inbounds ([5 x i32]* @bar, i64 0, i64 1), align 4<br>
> +  %4 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #2<br>
> +  store i32 %4, i32* getelementptr inbounds ([5 x i32]* @baz, i64 0, i64 1), align 4<br>
> +  %5 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #2<br>
> +  store i32 %5, i32* getelementptr inbounds ([5 x i32]* @bar, i64 0, i64 2), align 4<br>
> +  %6 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #2<br>
> +  store i32 %6, i32* getelementptr inbounds ([5 x i32]* @baz, i64 0, i64 2), align 4<br>
> +  %7 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #2<br>
> +  store i32 %7, i32* getelementptr inbounds ([5 x i32]* @bar, i64 0, i64 3), align 4<br>
> +  %8 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #2<br>
> +  store i32 %8, i32* getelementptr inbounds ([5 x i32]* @baz, i64 0, i64 3), align 4<br>
> +  %9 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #2<br>
> +  store i32 %9, i32* getelementptr inbounds ([5 x i32]* @bar, i64 0, i64 4), align 4<br>
> +  %10 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #2<br>
> +  store i32 %10, i32* getelementptr inbounds ([5 x i32]* @baz, i64 0, i64 4), align 4<br>
> +  ret void<br>
> +}<br>
> +<br>
> +declare i32 @calc(...)<br>
> +<br>
> +; Function Attrs: nounwind ssp<br>
> +define internal void @calculate() #0 {<br>
> +  %1 = load i32* getelementptr inbounds ([5 x i32]* @bar, i64 0, i64 0), align 4<br>
> +  %2 = load i32* getelementptr inbounds ([5 x i32]* @baz, i64 0, i64 0), align 4<br>
> +  %3 = mul nsw i32 %2, %1<br>
> +  store i32 %3, i32* getelementptr inbounds ([5 x i32]* @foo, i64 0, i64 0), align 4<br>
> +  %4 = load i32* getelementptr inbounds ([5 x i32]* @bar, i64 0, i64 1), align 4<br>
> +  %5 = load i32* getelementptr inbounds ([5 x i32]* @baz, i64 0, i64 1), align 4<br>
> +  %6 = mul nsw i32 %5, %4<br>
> +  store i32 %6, i32* getelementptr inbounds ([5 x i32]* @foo, i64 0, i64 1), align 4<br>
> +  %7 = load i32* getelementptr inbounds ([5 x i32]* @bar, i64 0, i64 2), align 4<br>
> +  %8 = load i32* getelementptr inbounds ([5 x i32]* @baz, i64 0, i64 2), align 4<br>
> +  %9 = mul nsw i32 %8, %7<br>
> +  store i32 %9, i32* getelementptr inbounds ([5 x i32]* @foo, i64 0, i64 2), align 4<br>
> +  %10 = load i32* getelementptr inbounds ([5 x i32]* @bar, i64 0, i64 3), align 4<br>
> +  %11 = load i32* getelementptr inbounds ([5 x i32]* @baz, i64 0, i64 3), align 4<br>
> +  %12 = mul nsw i32 %11, %10<br>
> +  store i32 %12, i32* getelementptr inbounds ([5 x i32]* @foo, i64 0, i64 3), align 4<br>
> +  %13 = load i32* getelementptr inbounds ([5 x i32]* @bar, i64 0, i64 4), align 4<br>
> +  %14 = load i32* getelementptr inbounds ([5 x i32]* @baz, i64 0, i64 4), align 4<br>
> +  %15 = mul nsw i32 %14, %13<br>
> +  store i32 %15, i32* getelementptr inbounds ([5 x i32]* @foo, i64 0, i64 4), align 4<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; Function Attrs: nounwind readnone ssp<br>
> +define internal i32* @returnFoo() #1 {<br>
> +  ret i32* getelementptr inbounds ([5 x i32]* @foo, i64 0, i64 0)<br>
> +}<br>
> +<br>
> +attributes #0 = { nounwind ssp }<br>
> +attributes #1 = { nounwind readnone ssp }<br>
> +attributes #2 = { nounwind }<br>
><br>
> Added: llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-1.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-1.ll?rev=208934&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-1.ll?rev=208934&view=auto</a><br>

> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-1.ll (added)<br>
> +++ llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-1.ll Thu May 15 18:45:42 2014<br>
> @@ -0,0 +1,22 @@<br>
> +; RUN: opt %s -mtriple=aarch64-none-linux-gnu -global-merge -S -o - | FileCheck %s<br>
> +; RUN: opt %s -mtriple=aarch64-none-linux-gnu -global-merge -global-merge-on-external -global-merge-aligned -S -o - | FileCheck %s<br>
> +<br>
> +; RUN: opt %s -mtriple=arm64-linux-gnuabi -global-merge -S -o - | FileCheck %s<br>
> +; RUN: opt %s -mtriple=arm64-linux-gnuabi -global-merge -global-merge-on-external -global-merge-aligned -S -o - | FileCheck %s<br>
> +<br>
> +; RUN: opt %s -mtriple=arm64-apple-ios -global-merge -S -o - | FileCheck %s<br>
> +; RUN: opt %s -mtriple=arm64-apple-ios -global-merge -global-merge-on-external -global-merge-aligned -S -o - | FileCheck %s<br>
> +<br>
> +@m = internal global i32 0, align 4<br>
> +@n = internal global i32 0, align 4<br>
> +<br>
> +; CHECK: @_MergedGlobals = internal global { i32, i32 } zeroinitializer<br>
> +<br>
> +define void @f1(i32 %a1, i32 %a2) {<br>
> +; CHECK-LABEL: @f1<br>
> +; CHECK: getelementptr inbounds ({ i32, i32 }* @_MergedGlobals, i32 0, i32 0)<br>
> +; CHECK: getelementptr inbounds ({ i32, i32 }* @_MergedGlobals, i32 0, i32 1)<br>
> +  store i32 %a1, i32* @m, align 4<br>
> +  store i32 %a2, i32* @n, align 4<br>
> +  ret void<br>
> +}<br>
><br>
> Added: llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-2.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-2.ll?rev=208934&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-2.ll?rev=208934&view=auto</a><br>

> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-2.ll (added)<br>
> +++ llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-2.ll Thu May 15 18:45:42 2014<br>
> @@ -0,0 +1,30 @@<br>
> +; RUN: opt %s -mtriple=aarch64-none-linux-gnu -global-merge -global-merge-on-external -global-merge-aligned -S -o - | FileCheck %s<br>
> +; RUN: opt %s -mtriple=arm64-linux-gnuabi -global-merge -global-merge-on-external -global-merge-aligned -S -o - | FileCheck %s<br>
> +; RUN: opt %s -mtriple=arm64-apple-ios -global-merge -global-merge-on-external -global-merge-aligned -S -o - | FileCheck %s<br>
> +<br>
> +@x = global i32 0, align 4<br>
> +@y = global i32 0, align 4<br>
> +@z = global i32 0, align 4<br>
> +<br>
> +; CHECK: @_MergedGlobals_x = global { i32, i32, i32 } zeroinitializer, align 16<br>
> +; CHECK: @x = alias getelementptr inbounds ({ i32, i32, i32 }* @_MergedGlobals_x, i32 0, i32 0)<br>
> +; CHECK: @y = alias getelementptr inbounds ({ i32, i32, i32 }* @_MergedGlobals_x, i32 0, i32 1)<br>
> +; CHECK: @z = alias getelementptr inbounds ({ i32, i32, i32 }* @_MergedGlobals_x, i32 0, i32 2)<br>
> +<br>
> +define void @f1(i32 %a1, i32 %a2) {<br>
> +; CHECK-LABEL: @f1<br>
> +; CHECK: getelementptr inbounds ({ i32, i32, i32 }* @_MergedGlobals_x, i32 0, i32 0)<br>
> +; CHECK: getelementptr inbounds ({ i32, i32, i32 }* @_MergedGlobals_x, i32 0, i32 1)<br>
> +  store i32 %a1, i32* @x, align 4<br>
> +  store i32 %a2, i32* @y, align 4<br>
> +  ret void<br>
> +}<br>
> +<br>
> +define void @g1(i32 %a1, i32 %a2) {<br>
> +; CHECK-LABEL: @g1<br>
> +; CHECK: getelementptr inbounds ({ i32, i32, i32 }* @_MergedGlobals_x, i32 0, i32 1)<br>
> +; CHECK: getelementptr inbounds ({ i32, i32, i32 }* @_MergedGlobals_x, i32 0, i32 2)<br>
> +  store i32 %a1, i32* @y, align 4<br>
> +  store i32 %a2, i32* @z, align 4<br>
> +  ret void<br>
> +}<br>
><br>
> Added: llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-3.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-3.ll?rev=208934&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-3.ll?rev=208934&view=auto</a><br>

> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-3.ll (added)<br>
> +++ llvm/trunk/test/Transforms/GlobalMerge/AArch64/global-merge-3.ll Thu May 15 18:45:42 2014<br>
> @@ -0,0 +1,27 @@<br>
> +; RUN: opt %s -mtriple=aarch64-none-linux-gnu -global-merge -global-merge-on-external -global-merge-aligned -S -o - | FileCheck %s<br>
> +; RUN: opt %s -mtriple=arm64-linux-gnuabi -global-merge -global-merge-on-external -global-merge-aligned -S -o - | FileCheck %s<br>
> +; RUN: opt %s -mtriple=arm64-apple-ios -global-merge -global-merge-on-external -global-merge-aligned -S -o - | FileCheck %s<br>
> +<br>
> +@x = global [1000 x i32] zeroinitializer, align 1<br>
> +@y = global [1000 x i32] zeroinitializer, align 1<br>
> +@z = internal global i32 1, align 4<br>
> +<br>
> +; CHECK: @_MergedGlobals_x = global { i32, [1000 x i32] } { i32 1, [1000 x i32] zeroinitializer }, align 4096<br>
> +; CHECK: @_MergedGlobals_y = global { [1000 x i32] } zeroinitializer, align 4096<br>
> +<br>
> +; CHECK: @x = alias getelementptr inbounds ({ i32, [1000 x i32] }* @_MergedGlobals_x, i32 0, i32 1)<br>
> +; CHECK: @y = alias getelementptr inbounds ({ [1000 x i32] }* @_MergedGlobals_y, i32 0, i32 0)<br>
> +<br>
> +define void @f1(i32 %a1, i32 %a2, i32 %a3) {<br>
> +; CHECK-LABEL: @f1<br>
> +; CHECK: %x3 = getelementptr inbounds [1000 x i32]* getelementptr inbounds ({ i32, [1000 x i32] }* @_MergedGlobals_x, i32 0, i32 1), i32 0, i64 3<br>
> +; CHECK: %y3 = getelementptr inbounds [1000 x i32]* getelementptr inbounds ({ [1000 x i32] }* @_MergedGlobals_y, i32 0, i32 0), i32 0, i64 3<br>
> +; CHECK: store i32 %a3, i32* getelementptr inbounds ({ i32, [1000 x i32] }* @_MergedGlobals_x, i32 0, i32 0), align 4<br>
> +<br>
> +  %x3 = getelementptr inbounds [1000 x i32]* @x, i32 0, i64 3<br>
> +  %y3 = getelementptr inbounds [1000 x i32]* @y, i32 0, i64 3<br>
> +  store i32 %a1, i32* %x3, align 4<br>
> +  store i32 %a2, i32* %y3, align 4<br>
> +  store i32 %a3, i32* @z, align 4<br>
> +  ret void<br>
> +}<br>
><br>
> Added: llvm/trunk/test/Transforms/GlobalMerge/AArch64/lit.local.cfg<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/AArch64/lit.local.cfg?rev=208934&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/AArch64/lit.local.cfg?rev=208934&view=auto</a><br>

> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/GlobalMerge/AArch64/lit.local.cfg (added)<br>
> +++ llvm/trunk/test/Transforms/GlobalMerge/AArch64/lit.local.cfg Thu May 15 18:45:42 2014<br>
> @@ -0,0 +1,4 @@<br>
> +targets = set(config.root.targets_to_build.split())<br>
> +if not 'AArch64' in targets:<br>
> +    config.unsupported = True<br>
> +<br>
><br>
> Modified: llvm/trunk/test/Transforms/GlobalMerge/ARM/arm.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/ARM/arm.ll?rev=208934&r1=208933&r2=208934&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/ARM/arm.ll?rev=208934&r1=208933&r2=208934&view=diff</a><br>

> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/GlobalMerge/ARM/arm.ll (original)<br>
> +++ llvm/trunk/test/Transforms/GlobalMerge/ARM/arm.ll Thu May 15 18:45:42 2014<br>
> @@ -1,23 +1,4 @@<br>
> -; RUN: llc %s -O0 -o - | FileCheck -check-prefix=NO-MERGE %s<br>
> -; RUN: llc %s -O0 -o - -global-merge=false | FileCheck -check-prefix=NO-MERGE %s<br>
> -; RUN: llc %s -O0 -o - -global-merge=true | FileCheck -check-prefix=NO-MERGE %s<br>
> -; RUN: llc %s -O1 -o - | FileCheck -check-prefix=MERGE %s<br>
> -; RUN: llc %s -O1 -o - -global-merge=false | FileCheck -check-prefix=NO-MERGE %s<br>
> -; RUN: llc %s -O1 -o - -global-merge=true | FileCheck -check-prefix=MERGE %s<br>
> -<br>
> -; MERGE-NOT: .zerofill __DATA,__bss,_bar,20,2<br>
> -; MERGE-NOT: .zerofill __DATA,__bss,_baz,20,2<br>
> -; MERGE-NOT: .zerofill __DATA,__bss,_foo,20,2<br>
> -; MERGE: .zerofill __DATA,__bss,__MergedGlobals,60,4<br>
> -; MERGE-NOT: .zerofill __DATA,__bss,_bar,20,2<br>
> -; MERGE-NOT: .zerofill __DATA,__bss,_baz,20,2<br>
> -; MERGE-NOT: .zerofill __DATA,__bss,_foo,20,2<br>
> -<br>
> -; NO-MERGE-NOT: .zerofill __DATA,__bss,__MergedGlobals,60,4<br>
> -; NO-MERGE: .zerofill __DATA,__bss,_bar,20,2<br>
> -; NO-MERGE: .zerofill __DATA,__bss,_baz,20,2<br>
> -; NO-MERGE: .zerofill __DATA,__bss,_foo,20,2<br>
> -; NO-MERGE-NOT: .zerofill __DATA,__bss,__MergedGlobals,60,4<br>
> +; RUN: opt %s -mtriple=arm-linux-gnuabi -global-merge -S -o - | FileCheck %s<br>
><br>
>  target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32"<br>
>  target triple = "thumbv7-apple-ios3.0.0"<br>
> @@ -26,6 +7,8 @@ target triple = "thumbv7-apple-ios3.0.0"<br>
>  @baz = internal global [5 x i32] zeroinitializer, align 4<br>
>  @foo = internal global [5 x i32] zeroinitializer, align 4<br>
><br>
> +; CHECK: @_MergedGlobals = internal global { [5 x i32], [5 x i32], [5 x i32] } zeroinitializer<br>
> +<br>
>  ; Function Attrs: nounwind ssp<br>
>  define internal void @initialize() #0 {<br>
>    %1 = tail call i32 bitcast (i32 (...)* @calc to i32 ()*)() #3<br>
><br>
> Modified: llvm/trunk/test/Transforms/GlobalMerge/ARM64/arm64.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/ARM64/arm64.ll?rev=208934&r1=208933&r2=208934&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/ARM64/arm64.ll?rev=208934&r1=208933&r2=208934&view=diff</a><br>

> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/GlobalMerge/ARM64/arm64.ll (original)<br>
> +++ llvm/trunk/test/Transforms/GlobalMerge/ARM64/arm64.ll Thu May 15 18:45:42 2014<br>
> @@ -1,23 +1,6 @@<br>
> -; RUN: llc %s -O0 -o - | FileCheck -check-prefix=NO-MERGE %s<br>
> -; RUN: llc %s -O0 -o - -global-merge=false | FileCheck -check-prefix=NO-MERGE %s<br>
> -; RUN: llc %s -O0 -o - -global-merge=true | FileCheck -check-prefix=NO-MERGE %s<br>
> -; RUN: llc %s -O1 -o - | FileCheck -check-prefix=MERGE %s<br>
> -; RUN: llc %s -O1 -o - -global-merge=false | FileCheck -check-prefix=NO-MERGE %s<br>
> -; RUN: llc %s -O1 -o - -global-merge=true | FileCheck -check-prefix=MERGE %s<br>
> +; RUN: opt %s -mtriple=arm64-linux-gnuabi -global-merge -S -o - | FileCheck %s<br>
><br>
> -; MERGE-NOT: .zerofill __DATA,__bss,_bar,20,2<br>
> -; MERGE-NOT: .zerofill __DATA,__bss,_baz,20,2<br>
> -; MERGE-NOT: .zerofill __DATA,__bss,_foo,20,2<br>
> -; MERGE: .zerofill __DATA,__bss,__MergedGlobals,60,4<br>
> -; MERGE-NOT: .zerofill __DATA,__bss,_bar,20,2<br>
> -; MERGE-NOT: .zerofill __DATA,__bss,_baz,20,2<br>
> -; MERGE-NOT: .zerofill __DATA,__bss,_foo,20,2<br>
> -<br>
> -; NO-MERGE-NOT: .zerofill __DATA,__bss,__MergedGlobals,60,4<br>
> -; NO-MERGE: .zerofill __DATA,__bss,_bar,20,2<br>
> -; NO-MERGE: .zerofill __DATA,__bss,_baz,20,2<br>
> -; NO-MERGE: .zerofill __DATA,__bss,_foo,20,2<br>
> -; NO-MERGE-NOT: .zerofill __DATA,__bss,__MergedGlobals,60,4<br>
> +; CHECK: @_MergedGlobals = internal global { [5 x i32], [5 x i32], [5 x i32] } zeroinitializer<br>
><br>
>  target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n32:64-S128"<br>
>  target triple = "arm64-apple-ios7.0.0"<br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</div></div></blockquote></div><br></div>