diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index b5c287ae90f..243ddbb5da3 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -204,12 +204,8 @@ namespace llvm { /// EmitAlignment - Emit an alignment directive to the specified power of /// two boundary. For example, if you pass in 3 here, you will get an 8 /// byte alignment. If a global value is specified, and if that global has - /// an explicit alignment requested, it will unconditionally override the - /// alignment request. - /// - /// The algorithm is: - /// Align = NumBits; - /// if (GV && GV->hasalignment) Align = GV->getAlignment(); + /// an explicit alignment requested, it will override the alignment request + /// if required for correctness. /// void EmitAlignment(unsigned NumBits, const GlobalValue *GV = 0) const; @@ -218,7 +214,6 @@ namespace llvm { /// it if appropriate. void EmitBasicBlockStart(const MachineBasicBlock *MBB) const; - /// EmitGlobalConstant - Print a general LLVM constant to the .s file. void EmitGlobalConstant(const Constant *CV, unsigned AddrSpace = 0); diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 68e70aae6ab..a694033fa1d 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -61,6 +61,35 @@ static gcp_map_type &getGCMap(void *&P) { } +/// getGVAlignmentLog2 - Return the alignment to use for the specified global +/// value in log2 form. This rounds up to the preferred alignment if possible +/// and legal. +static unsigned getGVAlignmentLog2(const GlobalValue *GV, const TargetData &TD, + unsigned InBits = 0) { + unsigned NumBits = 0; + if (const GlobalVariable *GVar = dyn_cast(GV)) + NumBits = TD.getPreferredAlignmentLog(GVar); + + // If InBits is specified, round it to it. + if (InBits > NumBits) + NumBits = InBits; + + // If the GV has a specified alignment, take it into account. + if (GV->getAlignment() == 0) + return NumBits; + + unsigned GVAlign = Log2_32(GV->getAlignment()); + + // If the GVAlign is larger than NumBits, or if we are required to obey + // NumBits because the GV has an assigned section, obey it. + if (GVAlign > NumBits || GV->hasSection()) + NumBits = GVAlign; + return NumBits; +} + + + + AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer) : MachineFunctionPass(&ID), TM(tm), MAI(tm.getMCAsmInfo()), @@ -227,16 +256,12 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM); const TargetData *TD = TM.getTargetData(); - unsigned Size = TD->getTypeAllocSize(GV->getType()->getElementType()); + uint64_t Size = TD->getTypeAllocSize(GV->getType()->getElementType()); // If the alignment is specified, we *must* obey it. Overaligning a global // with a specified alignment is a prompt way to break globals emitted to // sections and expected to be contiguous (e.g. ObjC metadata). - unsigned AlignLog; - if (unsigned GVAlign = GV->getAlignment()) - AlignLog = Log2_32(GVAlign); - else - AlignLog = TD->getPreferredAlignmentLog(GV); + unsigned AlignLog = getGVAlignmentLog2(GV, *TD); // Handle common and BSS local symbols (.lcomm). if (GVKind.isCommon() || GVKind.isBSSLocal()) { @@ -1010,7 +1035,7 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { unsigned Align = Log2_32(TD->getPointerPrefAlignment()); if (GV->getName() == "llvm.global_ctors") { OutStreamer.SwitchSection(getObjFileLowering().getStaticCtorSection()); - EmitAlignment(Align, 0); + EmitAlignment(Align); EmitXXStructorList(GV->getInitializer()); if (TM.getRelocationModel() == Reloc::Static && @@ -1024,7 +1049,7 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { if (GV->getName() == "llvm.global_dtors") { OutStreamer.SwitchSection(getObjFileLowering().getStaticDtorSection()); - EmitAlignment(Align, 0); + EmitAlignment(Align); EmitXXStructorList(GV->getInitializer()); if (TM.getRelocationModel() == Reloc::Static && @@ -1153,20 +1178,13 @@ void AsmPrinter::EmitLabelOffsetDifference(const MCSymbol *Hi, uint64_t Offset, // EmitAlignment - Emit an alignment directive to the specified power of // two boundary. For example, if you pass in 3 here, you will get an 8 // byte alignment. If a global value is specified, and if that global has -// an explicit alignment requested, it will unconditionally override the -// alignment request. However, if ForcedAlignBits is specified, this value -// has final say: the ultimate alignment will be the max of ForcedAlignBits -// and the alignment computed with NumBits and the global. -// -// The algorithm is: -// Align = NumBits; -// if (GV && GV->hasalignment) Align = GV->getAlignment(); +// an explicit alignment requested, it will override the alignment request +// if required for correctness. // void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV) const { - if (GV && GV->getAlignment()) - NumBits = Log2_32(GV->getAlignment()); + if (GV) NumBits = getGVAlignmentLog2(GV, *TM.getTargetData(), NumBits); - if (NumBits == 0) return; // No need to emit alignment. + if (NumBits == 0) return; // 1-byte aligned: no need to emit alignment. if (getCurrentSection()->getKind().isText()) OutStreamer.EmitCodeAlignment(1 << NumBits); diff --git a/test/CodeGen/X86/alignment.ll b/test/CodeGen/X86/alignment.ll index 06a4f3f8e88..9678e6df740 100644 --- a/test/CodeGen/X86/alignment.ll +++ b/test/CodeGen/X86/alignment.ll @@ -6,7 +6,7 @@ ; CHECK: .bss ; CHECK: .globl GlobalA -; CHECK: .align 8 +; CHECK: .align 16 ; CHECK: GlobalA: ; CHECK: .zero 384 @@ -15,4 +15,29 @@ ; PR6921 @GlobalB = common global { [384 x i8] } zeroinitializer, align 8 -; CHECK: .comm GlobalB,384,8 \ No newline at end of file +; CHECK: .comm GlobalB,384,16 + + +@GlobalC = common global { [384 x i8] } zeroinitializer, align 2 + +; CHECK: .comm GlobalC,384,16 + + + +; This cannot get rounded up to the preferred alignment (16) if they have an +; explicit alignment specified *and* a section specified. +@GlobalAS = global { [384 x i8] } zeroinitializer, align 8, section "foo" + +; CHECK: .globl GlobalAS +; CHECK: .align 8 +; CHECK: GlobalAS: +; CHECK: .zero 384 + +; Common variables should not get rounded up to the preferred alignment (16) if +; they have an explicit alignment specified and a section specified. +; PR6921 +@GlobalBS = common global { [384 x i8] } zeroinitializer, align 8, section "foo" +; CHECK: .comm GlobalBS,384,8 + +@GlobalCS = common global { [384 x i8] } zeroinitializer, align 2, section "foo" +; CHECK: .comm GlobalCS,384,2 \ No newline at end of file diff --git a/test/CodeGen/X86/unaligned-load.ll b/test/CodeGen/X86/unaligned-load.ll index b26097f31b4..a99af0605b1 100644 --- a/test/CodeGen/X86/unaligned-load.ll +++ b/test/CodeGen/X86/unaligned-load.ll @@ -29,8 +29,8 @@ return: declare void @llvm.memcpy.i64(i8* nocapture, i8* nocapture, i64, i32) nounwind ; CORE2: .section -; CORE2: .align 3 +; CORE2: .align 4 ; CORE2-NEXT: _.str1: ; CORE2-NEXT: .asciz "DHRYSTONE PROGRAM, SOME STRING" -; CORE2: .align 3 +; CORE2: .align 4 ; CORE2-NEXT: _.str3: diff --git a/test/FrontendC/cstring-align.c b/test/FrontendC/cstring-align.c index 715d0f31269..b9ec281f567 100644 --- a/test/FrontendC/cstring-align.c +++ b/test/FrontendC/cstring-align.c @@ -1,6 +1,5 @@ // RUN: %llvmgcc %s -c -Os -m32 -emit-llvm -o - | llc -march=x86 -mtriple=i386-apple-darwin10 | FileCheck %s -check-prefix=DARWIN32 // RUN: %llvmgcc %s -c -Os -m64 -emit-llvm -o - | llc -march=x86-64 -mtriple=x86_64-apple-darwin10 | FileCheck %s -check-prefix=DARWIN64 -// XFAIL: * // XTARGET: darwin extern void func(const char *, const char *); @@ -9,10 +8,10 @@ void long_function_name() { func("%s: the function name", __func__); } -// DARWIN64: .align 3 +// DARWIN64: .align 4 // DARWIN64: ___func__. // DARWIN64: .asciz "long_function_name" -// DARWIN32: .align 2 +// DARWIN32: .align 4 // DARWIN32: ___func__. // DARWIN32: .asciz "long_function_name"