[llvm] d2a35e4 - [AIX] Handling the label alignment of a global

via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 3 20:18:28 PDT 2022


Author: esmeyi
Date: 2022-07-03T23:16:16-04:00
New Revision: d2a35e4d39fec0c328f9bb05ad3ea7134751a64e

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

LOG: [AIX] Handling the label alignment of a global
variable with its multiple aliases.

This patch handles the case where a variable has
multiple aliases.
AIX's assembly directive .set is not usable for the
aliasing purpose, and using different labels allows
AIX to emulate symbol aliases. If a value is emitted
between any two labels, meaning they are not aligned,
XCOFF will automatically calculate the offset for them.

This patch implements:
1) Emits the label of the alias just before emitting
the value of the sub-element that the alias referred to.
2) A set of aliases that refers to the same offset
should be aligned.
3) We didn't emit aliasing labels for common and
zero-initialized local symbols in
PPCAIXAsmPrinter::emitGlobalVariableHelper, but
emitted linkage for them in
AsmPrinter::emitGlobalAlias, which caused a FAILURE.
This patch fixes the bug by blocking emitting linkage
for the alias without a label.

Reviewed By: shchenz

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

Added: 
    llvm/test/CodeGen/PowerPC/aix-alias-alignment-2.ll
    llvm/test/CodeGen/PowerPC/aix-alias-alignment.ll

Modified: 
    llvm/include/llvm/CodeGen/AsmPrinter.h
    llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
    llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
    llvm/test/CodeGen/PowerPC/aix-alias.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index fb4627c029b04..5e900e9162d8e 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -41,6 +41,7 @@ class DIEAbbrev;
 class DwarfDebug;
 class GCMetadataPrinter;
 class GCStrategy;
+class GlobalAlias;
 class GlobalObject;
 class GlobalValue;
 class GlobalVariable;
@@ -474,7 +475,11 @@ class AsmPrinter : public MachineFunctionPass {
   virtual const MCExpr *lowerConstant(const Constant *CV);
 
   /// Print a general LLVM constant to the .s file.
-  void emitGlobalConstant(const DataLayout &DL, const Constant *CV);
+  /// On AIX, when an alias refers to a sub-element of a global variable, the
+  /// label of that alias needs to be emitted before the corresponding element.
+  using AliasMapTy = DenseMap<uint64_t, SmallVector<const GlobalAlias *, 1>>;
+  void emitGlobalConstant(const DataLayout &DL, const Constant *CV,
+                          AliasMapTy *AliasList = nullptr);
 
   /// Unnamed constant global variables solely contaning a pointer to
   /// another globals variable act like a global variable "proxy", or GOT

diff  --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 4a31bf85446be..86293c7a4bf37 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1816,6 +1816,11 @@ void AsmPrinter::emitGlobalAlias(Module &M, const GlobalAlias &GA) {
   if (TM.getTargetTriple().isOSBinFormatXCOFF()) {
     assert(MAI->hasVisibilityOnlyWithLinkage() &&
            "Visibility should be handled with emitLinkage() on AIX.");
+
+    // Linkage for alias of global variable has been emitted.
+    if (isa<GlobalVariable>(GA.getAliaseeObject()))
+      return;
+
     emitLinkage(&GA, Name);
     // If it's a function, also emit linkage for aliases of function entry
     // point.
@@ -2860,7 +2865,8 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) {
 static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *C,
                                    AsmPrinter &AP,
                                    const Constant *BaseCV = nullptr,
-                                   uint64_t Offset = 0);
+                                   uint64_t Offset = 0,
+                                   AsmPrinter::AliasMapTy *AliasList = nullptr);
 
 static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP);
 static void emitGlobalConstantFP(APFloat APF, Type *ET, AsmPrinter &AP);
@@ -2914,9 +2920,21 @@ static int isRepeatedByteSequence(const Value *V, const DataLayout &DL) {
   return -1;
 }
 
-static void emitGlobalConstantDataSequential(const DataLayout &DL,
-                                             const ConstantDataSequential *CDS,
-                                             AsmPrinter &AP) {
+static void emitGlobalAliasInline(AsmPrinter &AP, uint64_t Offset,
+                                  AsmPrinter::AliasMapTy *AliasList) {
+  if (AliasList) {
+    auto AliasIt = AliasList->find(Offset);
+    if (AliasIt != AliasList->end()) {
+      for (const GlobalAlias *GA : AliasIt->second)
+        AP.OutStreamer->emitLabel(AP.getSymbol(GA));
+      AliasList->erase(Offset);
+    }
+  }
+}
+
+static void emitGlobalConstantDataSequential(
+    const DataLayout &DL, const ConstantDataSequential *CDS, AsmPrinter &AP,
+    AsmPrinter::AliasMapTy *AliasList) {
   // See if we can aggregate this into a .fill, if so, emit it as such.
   int Value = isRepeatedByteSequence(CDS, DL);
   if (Value != -1) {
@@ -2933,17 +2951,20 @@ static void emitGlobalConstantDataSequential(const DataLayout &DL,
   // Otherwise, emit the values in successive locations.
   unsigned ElementByteSize = CDS->getElementByteSize();
   if (isa<IntegerType>(CDS->getElementType())) {
-    for (unsigned i = 0, e = CDS->getNumElements(); i != e; ++i) {
+    for (unsigned I = 0, E = CDS->getNumElements(); I != E; ++I) {
+      emitGlobalAliasInline(AP, ElementByteSize * I, AliasList);
       if (AP.isVerbose())
         AP.OutStreamer->getCommentOS()
-            << format("0x%" PRIx64 "\n", CDS->getElementAsInteger(i));
-      AP.OutStreamer->emitIntValue(CDS->getElementAsInteger(i),
+            << format("0x%" PRIx64 "\n", CDS->getElementAsInteger(I));
+      AP.OutStreamer->emitIntValue(CDS->getElementAsInteger(I),
                                    ElementByteSize);
     }
   } else {
     Type *ET = CDS->getElementType();
-    for (unsigned I = 0, E = CDS->getNumElements(); I != E; ++I)
+    for (unsigned I = 0, E = CDS->getNumElements(); I != E; ++I) {
+      emitGlobalAliasInline(AP, ElementByteSize * I, AliasList);
       emitGlobalConstantFP(CDS->getElementAsAPFloat(I), ET, AP);
+    }
   }
 
   unsigned Size = DL.getTypeAllocSize(CDS->getType());
@@ -2956,7 +2977,8 @@ static void emitGlobalConstantDataSequential(const DataLayout &DL,
 
 static void emitGlobalConstantArray(const DataLayout &DL,
                                     const ConstantArray *CA, AsmPrinter &AP,
-                                    const Constant *BaseCV, uint64_t Offset) {
+                                    const Constant *BaseCV, uint64_t Offset,
+                                    AsmPrinter::AliasMapTy *AliasList) {
   // See if we can aggregate some values.  Make sure it can be
   // represented as a series of bytes of the constant value.
   int Value = isRepeatedByteSequence(CA, DL);
@@ -2964,19 +2986,22 @@ static void emitGlobalConstantArray(const DataLayout &DL,
   if (Value != -1) {
     uint64_t Bytes = DL.getTypeAllocSize(CA->getType());
     AP.OutStreamer->emitFill(Bytes, Value);
-  }
-  else {
-    for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) {
-      emitGlobalConstantImpl(DL, CA->getOperand(i), AP, BaseCV, Offset);
-      Offset += DL.getTypeAllocSize(CA->getOperand(i)->getType());
+  } else {
+    for (unsigned I = 0, E = CA->getNumOperands(); I != E; ++I) {
+      emitGlobalConstantImpl(DL, CA->getOperand(I), AP, BaseCV, Offset,
+                             AliasList);
+      Offset += DL.getTypeAllocSize(CA->getOperand(I)->getType());
     }
   }
 }
 
 static void emitGlobalConstantVector(const DataLayout &DL,
-                                     const ConstantVector *CV, AsmPrinter &AP) {
-  for (unsigned i = 0, e = CV->getType()->getNumElements(); i != e; ++i)
-    emitGlobalConstantImpl(DL, CV->getOperand(i), AP);
+                                     const ConstantVector *CV, AsmPrinter &AP,
+                                     AsmPrinter::AliasMapTy *AliasList) {
+  for (unsigned I = 0, E = CV->getType()->getNumElements(); I != E; ++I) {
+    emitGlobalAliasInline(AP, DL.getTypeAllocSize(CV->getType()) * I, AliasList);
+    emitGlobalConstantImpl(DL, CV->getOperand(I), AP);
+  }
 
   unsigned Size = DL.getTypeAllocSize(CV->getType());
   unsigned EmittedSize = DL.getTypeAllocSize(CV->getType()->getElementType()) *
@@ -2987,21 +3012,24 @@ static void emitGlobalConstantVector(const DataLayout &DL,
 
 static void emitGlobalConstantStruct(const DataLayout &DL,
                                      const ConstantStruct *CS, AsmPrinter &AP,
-                                     const Constant *BaseCV, uint64_t Offset) {
+                                     const Constant *BaseCV, uint64_t Offset,
+                                     AsmPrinter::AliasMapTy *AliasList) {
   // Print the fields in successive locations. Pad to align if needed!
   unsigned Size = DL.getTypeAllocSize(CS->getType());
   const StructLayout *Layout = DL.getStructLayout(CS->getType());
   uint64_t SizeSoFar = 0;
-  for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) {
-    const Constant *Field = CS->getOperand(i);
+  for (unsigned I = 0, E = CS->getNumOperands(); I != E; ++I) {
+    const Constant *Field = CS->getOperand(I);
 
     // Print the actual field value.
-    emitGlobalConstantImpl(DL, Field, AP, BaseCV, Offset + SizeSoFar);
+    emitGlobalConstantImpl(DL, Field, AP, BaseCV, Offset + SizeSoFar,
+                           AliasList);
 
     // Check if padding is needed and insert one or more 0s.
     uint64_t FieldSize = DL.getTypeAllocSize(Field->getType());
-    uint64_t PadSize = ((i == e-1 ? Size : Layout->getElementOffset(i+1))
-                        - Layout->getElementOffset(i)) - FieldSize;
+    uint64_t PadSize = ((I == E - 1 ? Size : Layout->getElementOffset(I + 1)) -
+                        Layout->getElementOffset(I)) -
+                       FieldSize;
     SizeSoFar += FieldSize + PadSize;
 
     // Insert padding - this may include padding to increase the size of the
@@ -3211,7 +3239,9 @@ static void handleIndirectSymViaGOTPCRel(AsmPrinter &AP, const MCExpr **ME,
 
 static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV,
                                    AsmPrinter &AP, const Constant *BaseCV,
-                                   uint64_t Offset) {
+                                   uint64_t Offset,
+                                   AsmPrinter::AliasMapTy *AliasList) {
+  emitGlobalAliasInline(AP, Offset, AliasList);
   uint64_t Size = DL.getTypeAllocSize(CV->getType());
 
   // Globals with sub-elements such as combinations of arrays and structs
@@ -3251,13 +3281,13 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV,
   }
 
   if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(CV))
-    return emitGlobalConstantDataSequential(DL, CDS, AP);
+    return emitGlobalConstantDataSequential(DL, CDS, AP, AliasList);
 
   if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV))
-    return emitGlobalConstantArray(DL, CVA, AP, BaseCV, Offset);
+    return emitGlobalConstantArray(DL, CVA, AP, BaseCV, Offset, AliasList);
 
   if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
-    return emitGlobalConstantStruct(DL, CVS, AP, BaseCV, Offset);
+    return emitGlobalConstantStruct(DL, CVS, AP, BaseCV, Offset, AliasList);
 
   if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
     // Look through bitcasts, which might not be able to be MCExpr'ized (e.g. of
@@ -3276,7 +3306,7 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV,
   }
 
   if (const ConstantVector *V = dyn_cast<ConstantVector>(CV))
-    return emitGlobalConstantVector(DL, V, AP);
+    return emitGlobalConstantVector(DL, V, AP, AliasList);
 
   // Otherwise, it must be a ConstantExpr.  Lower it to an MCExpr, then emit it
   // thread the streamer with EmitValue.
@@ -3292,10 +3322,11 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV,
 }
 
 /// EmitGlobalConstant - Print a general LLVM constant to the .s file.
-void AsmPrinter::emitGlobalConstant(const DataLayout &DL, const Constant *CV) {
+void AsmPrinter::emitGlobalConstant(const DataLayout &DL, const Constant *CV,
+                                    AliasMapTy *AliasList) {
   uint64_t Size = DL.getTypeAllocSize(CV->getType());
   if (Size)
-    emitGlobalConstantImpl(DL, CV, *this);
+    emitGlobalConstantImpl(DL, CV, *this, nullptr, 0, AliasList);
   else if (MAI->hasSubsectionsViaSymbols()) {
     // If the global has zero size, emit a single byte so that two labels don't
     // look like they are at the same location.

diff  --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 22f35c8fa8d3b..b692e6bafea34 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -230,6 +230,9 @@ class PPCAIXAsmPrinter : public PPCAsmPrinter {
 
   void emitGlobalVariableHelper(const GlobalVariable *);
 
+  // Get the offset of an alias based on its AliaseeObject.
+  uint64_t getAliasOffset(const Constant *C);
+
 public:
   PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
       : PPCAsmPrinter(TM, std::move(Streamer)) {
@@ -2352,6 +2355,24 @@ static bool isSpecialLLVMGlobalArrayForStaticInit(const GlobalVariable *GV) {
       .Default(false);
 }
 
+uint64_t PPCAIXAsmPrinter::getAliasOffset(const Constant *C) {
+  if (auto *GA = dyn_cast<GlobalAlias>(C))
+    return getAliasOffset(GA->getAliasee());
+  if (auto *CE = dyn_cast<ConstantExpr>(C)) {
+    const MCExpr *LowC = lowerConstant(CE);
+    const MCBinaryExpr *CBE = dyn_cast<MCBinaryExpr>(LowC);
+    if (!CBE)
+      return 0;
+    if (CBE->getOpcode() != MCBinaryExpr::Add)
+      report_fatal_error("Only adding an offset is supported now.");
+    auto *RHS = dyn_cast<MCConstantExpr>(CBE->getRHS());
+    if (!RHS)
+      report_fatal_error("Unable to get the offset of alias.");
+    return RHS->getValue();
+  }
+  return 0;
+}
+
 void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
   // Special LLVM global arrays have been handled at the initialization.
   if (isSpecialLLVMGlobalArrayToSkip(GV) || isSpecialLLVMGlobalArrayForStaticInit(GV))
@@ -2422,20 +2443,34 @@ void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) {
   }
 
   MCSymbol *EmittedInitSym = GVSym;
+
+  // Emit linkage for the global variable and its aliases.
   emitLinkage(GV, EmittedInitSym);
+  for (const GlobalAlias *GA : GOAliasMap[GV])
+    emitLinkage(GA, getSymbol(GA));
+
   emitAlignment(getGVAlignment(GV, DL), GV);
 
   // When -fdata-sections is enabled, every GlobalVariable will
   // be put into its own csect; therefore, label is not necessary here.
-  if (!TM.getDataSections() || GV->hasSection()) {
+  if (!TM.getDataSections() || GV->hasSection())
     OutStreamer->emitLabel(EmittedInitSym);
+
+  // No alias to emit.
+  if (!GOAliasMap[GV].size()) {
+    emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer());
+    return;
   }
 
-  // Emit aliasing label for global variable.
-  for (const GlobalAlias *Alias : GOAliasMap[GV])
-    OutStreamer->emitLabel(getSymbol(Alias));
+  // Aliases with the same offset should be aligned. Record the list of aliases
+  // associated with the offset.
+  AliasMapTy AliasList;
+  for (const GlobalAlias *GA : GOAliasMap[GV])
+    AliasList[getAliasOffset(GA->getAliasee())].push_back(GA);
 
-  emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer());
+  // Emit alias label and element value for global variable.
+  emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer(),
+                     &AliasList);
 }
 
 void PPCAIXAsmPrinter::emitFunctionDescriptor() {

diff  --git a/llvm/test/CodeGen/PowerPC/aix-alias-alignment-2.ll b/llvm/test/CodeGen/PowerPC/aix-alias-alignment-2.ll
new file mode 100644
index 0000000000000..18061d61a0ada
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-alias-alignment-2.ll
@@ -0,0 +1,79 @@
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \
+; RUN:     -data-sections=false < %s | FileCheck --check-prefix=ASM %s
+
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \
+; RUN:     -data-sections=false -filetype=obj -o %t.o < %s
+; RUN: llvm-objdump --syms %t.o | FileCheck --check-prefix=SYM %s
+
+ at ConstVector = global <2 x i64> <i64 12, i64 34>, align 4
+ at var1 = alias i64, getelementptr inbounds (<2 x i64>, <2 x i64>* @ConstVector, i32 0, i32 1)
+define void @foo1(i64 %a1) {
+  store i64 %a1, i64* getelementptr inbounds (<2 x i64>, <2 x i64>* @ConstVector, i32 0, i32 1), align 4
+  ret void
+}
+
+; ASM:           .globl     ConstVector  # @ConstVector
+; ASM-NEXT:      .globl     var1
+; ASM-NEXT:      .align     4
+; ASM-NEXT: ConstVector:
+; ASM-NEXT:      .vbyte     4, 0         # 0xc
+; ASM-NEXT:      .vbyte     4, 12
+; ASM-NEXT: var1:
+; ASM-NEXT:      .vbyte     4, 0         # 0x22
+; ASM-NEXT:      .vbyte     4, 34
+
+ at ConstDataSeq = global [2 x i64] [i64 12, i64 34], align 4
+ at var2 = alias i64, getelementptr inbounds ([2 x i64], [2 x i64]* @ConstDataSeq, i32 0, i32 1)
+define void @foo2(i64 %a1) {
+  store i64 %a1, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @ConstDataSeq, i32 0, i32 1), align 4
+  ret void
+}
+
+; ASM:           .globl     ConstDataSeq   # @ConstDataSeq
+; ASM-NEXT:      .globl     var2
+; ASM-NEXT:      .align     3
+; ASM-NEXT: ConstDataSeq:
+; ASM-NEXT:      .vbyte     4, 0           # 0xc
+; ASM-NEXT:      .vbyte     4, 12
+; ASM-NEXT: var2:
+; ASM-NEXT:      .vbyte     4, 0           # 0x22
+; ASM-NEXT:      .vbyte     4, 34
+
+%struct.B = type { i64 }
+ at ConstArray = global [2 x %struct.B] [%struct.B {i64 12}, %struct.B {i64 34}], align 4
+ at var3 = alias %struct.B, getelementptr inbounds ([2 x %struct.B], [2 x %struct.B]* @ConstArray, i32 0, i32 0)
+define void @foo3(%struct.B %a1) {
+  store %struct.B %a1, %struct.B* getelementptr inbounds ([2 x %struct.B], [2 x %struct.B]* @ConstArray, i32 0, i32 1), align 4
+  ret void
+}
+
+; ASM:           .globl     ConstArray  # @ConstArray
+; ASM-NEXT:      .globl     var3
+; ASM-NEXT:      .align     3
+; ASM-NEXT: ConstArray:
+; ASM-NEXT: var3:
+; ASM-NEXT:      .vbyte     4, 0        # 0xc
+; ASM-NEXT:      .vbyte     4, 12
+; ASM-NEXT:      .vbyte     4, 0        # 0x22
+; ASM-NEXT:      .vbyte     4, 34
+
+; SYM:      SYMBOL TABLE:
+; SYM-NEXT: 00000000      df *DEBUG*	00000000 <stdin>
+; SYM-NEXT: 00000000 l       .text	0000008a .text
+; SYM-NEXT: 00000000 g     F .text (csect: .text) 	00000000 .foo1
+; SYM-NEXT: 00000030 g     F .text (csect: .text) 	00000000 .foo2
+; SYM-NEXT: 00000060 g     F .text (csect: .text) 	00000000 .foo3
+; SYM-NEXT: 00000090 l       .data	00000030 .data
+; SYM-NEXT: 00000090 g     O .data (csect: .data) 	00000000 ConstVector
+; SYM-NEXT: 00000098 g     O .data (csect: .data) 	00000000 var1
+; SYM-NEXT: 000000a0 g     O .data (csect: .data) 	00000000 ConstDataSeq
+; SYM-NEXT: 000000a8 g     O .data (csect: .data) 	00000000 var2
+; SYM-NEXT: 000000b0 g     O .data (csect: .data) 	00000000 ConstArray
+; SYM-NEXT: 000000b0 g     O .data (csect: .data) 	00000000 var3
+; SYM-NEXT: 000000c0 g     O .data	0000000c foo1
+; SYM-NEXT: 000000cc g     O .data	0000000c foo2
+; SYM-NEXT: 000000d8 g     O .data	0000000c foo3
+; SYM-NEXT: 000000e4 l       .data	00000000 TOC
+; SYM-NEXT: 000000e4 l     O .data	00000004 ConstVector
+; SYM-NEXT: 000000e8 l     O .data	00000004 ConstDataSeq
+; SYM-NEXT: 000000ec l     O .data	00000004 ConstArray

diff  --git a/llvm/test/CodeGen/PowerPC/aix-alias-alignment.ll b/llvm/test/CodeGen/PowerPC/aix-alias-alignment.ll
new file mode 100644
index 0000000000000..aa2db9dc7961b
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-alias-alignment.ll
@@ -0,0 +1,74 @@
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \
+; RUN:     -data-sections=false < %s | FileCheck --check-prefix=ASM %s
+
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \
+; RUN:     -data-sections=true < %s | FileCheck --check-prefix=ASM-DATASECT %s
+
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \
+; RUN:     -data-sections=false -filetype=obj -o %t.o < %s
+; RUN: llvm-objdump -dr %t.o | FileCheck --check-prefix=OBJ %s
+; RUN: llvm-objdump --syms %t.o | FileCheck --check-prefix=SYM %s
+
+ at _MergedGlobals = global <{ i32, i32 }> <{ i32 1, i32 2 }>, align 4
+ at var1 = alias i32, getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 0)
+ at var2 = alias i32, getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1)
+ at var3 = alias i32, i32* @var2
+
+define void @foo(i32 %a1, i32 %a2, i32 %a3) {
+  store i32 %a1, i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 0), align 4
+  store i32 %a2, i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1), align 4
+  ret void
+}
+
+; ASM:              # -- End function
+; ASM-NEXT:         .csect .data[RW],2
+; ASM-NEXT:         .globl  _MergedGlobals # @_MergedGlobals
+; ASM-NEXT:         .globl  var1
+; ASM-NEXT:         .globl  var2
+; ASM-NEXT:         .globl  var3
+; ASM-NEXT:         .align  2
+; ASM-NEXT: _MergedGlobals:
+; ASM-NEXT: var1:
+; ASM-NEXT:         .vbyte  4, 1 # 0x1
+; ASM-NEXT: var2:
+; ASM-NEXT: var3:
+; ASM-NEXT:         .vbyte  4, 2 # 0x2
+; ASM-NEXT:         .toc
+; ASM-NEXT: L..C0:
+; ASM-NEXT:         .tc _MergedGlobals[TC],_MergedGlobals
+
+; ASM-DATASECT:              # -- End function
+; ASM-DATASECT-NEXT:         .csect _MergedGlobals[RW],2
+; ASM-DATASECT-NEXT:         .globl  _MergedGlobals[RW] # @_MergedGlobals
+; ASM-DATASECT-NEXT:         .globl  var1
+; ASM-DATASECT-NEXT:         .globl  var2
+; ASM-DATASECT-NEXT:         .globl  var3
+; ASM-DATASECT-NEXT:         .align  2
+; ASM-DATASECT-NEXT: var1:
+; ASM-DATASECT-NEXT:         .vbyte  4, 1 # 0x1
+; ASM-DATASECT-NEXT: var2:
+; ASM-DATASECT-NEXT: var3:
+; ASM-DATASECT-NEXT:         .vbyte  4, 2 # 0x2
+; ASM-DATASECT-NEXT:         .toc
+; ASM-DATASECT-NEXT: L..C0:
+; ASM-DATASECT-NEXT:         .tc _MergedGlobals[TC],_MergedGlobals[RW]
+
+; OBJ:      00000000 <.foo>:
+; OBJ-NEXT:        0: 80 a2 00 00  	lwz 5, 0(2)
+; OBJ-NEXT: 			00000002:  R_TOC	_MergedGlobals
+; OBJ-NEXT:        4: 90 65 00 00  	stw 3, 0(5)
+; OBJ-NEXT:        8: 90 85 00 04  	stw 4, 4(5)
+; OBJ-NEXT:        c: 4e 80 00 20  	blr
+
+; SYM:      SYMBOL TABLE:
+; SYM-NEXT: 00000000      df *DEBUG*	00000000 <stdin>
+; SYM-NEXT: 00000000 l       .text	00000029 .text
+; SYM-NEXT: 00000000 g     F .text (csect: .text) 	00000000 .foo
+; SYM-NEXT: 0000002c l       .data	00000008 .data
+; SYM-NEXT: 0000002c g     O .data (csect: .data) 	00000000 _MergedGlobals
+; SYM-NEXT: 0000002c g     O .data (csect: .data) 	00000000 var1
+; SYM-NEXT: 00000030 g     O .data (csect: .data) 	00000000 var2
+; SYM-NEXT: 00000030 g     O .data (csect: .data) 	00000000 var3
+; SYM-NEXT: 00000034 g     O .data	0000000c foo
+; SYM-NEXT: 00000040 l       .data	00000000 TOC
+; SYM-NEXT: 00000040 l     O .data	00000004 _MergedGlobals

diff  --git a/llvm/test/CodeGen/PowerPC/aix-alias.ll b/llvm/test/CodeGen/PowerPC/aix-alias.ll
index be35fd526a498..837e84a52fbe1 100644
--- a/llvm/test/CodeGen/PowerPC/aix-alias.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-alias.ll
@@ -75,6 +75,12 @@ entry:
 ; ASM:                                               # -- End function
 ; ASM-NEXT:    .csect .data[RW]
 ; ASM-NEXT:    .globl  var
+; ASM-NEXT:    .globl  var1
+; ASM-NEXT:    .globl  var2
+; ASM-NEXT:    .weak   var_l
+; ASM-NEXT:    .lglobl var_i
+; ASM-NEXT:    .globl  var_h,hidden
+; ASM-NEXT:    .globl  var_p,protected
 ; ASM:       var:
 ; ASM-NEXT:  var1:
 ; ASM-NEXT:  var2:
@@ -83,24 +89,18 @@ entry:
 ; ASM-NEXT:  var_h:
 ; ASM-NEXT:  var_p:
 ; ASM-NEXT:    .vbyte  4, 42
-; ASM-NEXT:   .globl array
+; ASM-NEXT:    .globl array
 ; ASM:       array:
 ; ASM-NEXT:    .vbyte 4, 1 # 0x1
 ; ASM-NEXT:    .vbyte 4, 2 # 0x2
 ; ASM-NEXT:    .globl x
+; ASM-NEXT:    .globl  bitcast_alias
 ; ASM:       x:
 ; ASM-NEXT:  bitcast_alias:
 ; ASM-NEXT:    .vbyte  {{[0-9]+}}, array+4
 ; ASM-NEXT:    .globl  fun_ptr
 ; ASM:       fun_ptr:
 ; ASM-NEXT:    .vbyte  {{[0-9]+}}, fun_weak
-; ASM-NEXT:    .globl  var1
-; ASM-NEXT:    .globl  var2
-; ASM-NEXT:    .weak var_l
-; ASM-NEXT:    .lglobl var_i
-; ASM-NEXT:    .globl  var_h,hidden
-; ASM-NEXT:    .globl  var_p,protected
-; ASM-NEXT:    .globl bitcast_alias
 ; ASM-NEXT:    .weak fun_weak
 ; ASM-NEXT:    .weak .fun_weak
 ; ASM-NEXT:    .globl  fun_hidden,hidden


        


More information about the llvm-commits mailing list