llvm.org GIT mirror llvm / 38d8be1
CodeGen: Stick constant pool entries in COMDAT sections for WinCOFF COFF lacks a feature that other object file formats support: mergeable sections. To work around this, MSVC sticks constant pool entries in special COMDAT sections so that each constant is in it's own section. This permits unused constants to be dropped and it also allows duplicate constants in different translation units to get merged together. This fixes PR20262. Differential Revision: http://reviews.llvm.org/D4482 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213006 91177308-0d34-0410-b5e6-96231b3b80d8 David Majnemer 6 years ago
16 changed file(s) with 192 addition(s) and 28 deletion(s). Raw diff Collapse all Expand all
4242
4343 /// Given a constant with the SectionKind, return a section that it should be
4444 /// placed in.
45 const MCSection *getSectionForConstant(SectionKind Kind) const override;
45 const MCSection *getSectionForConstant(SectionKind Kind,
46 const Constant *C) const override;
4647
4748 const MCSection *getExplicitSectionGlobal(const GlobalValue *GV,
4849 SectionKind Kind, Mangler &Mang,
99100 SectionKind Kind, Mangler &Mang,
100101 const TargetMachine &TM) const override;
101102
102 const MCSection *getSectionForConstant(SectionKind Kind) const override;
103 const MCSection *getSectionForConstant(SectionKind Kind,
104 const Constant *C) const override;
103105
104106 /// The mach-o version of this method defaults to returning a stub reference.
105107 const MCExpr *
3535 /// The COMDAT symbol of this section. Only valid if this is a COMDAT
3636 /// section. Two COMDAT sections are merged if they have the same
3737 /// COMDAT symbol.
38 const MCSymbol *COMDATSymbol;
38 MCSymbol *COMDATSymbol;
3939
4040 /// Selection - This is the Selection field for the section symbol, if
4141 /// it is a COMDAT section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0
4444 private:
4545 friend class MCContext;
4646 MCSectionCOFF(StringRef Section, unsigned Characteristics,
47 const MCSymbol *COMDATSymbol, int Selection, SectionKind K)
47 MCSymbol *COMDATSymbol, int Selection, SectionKind K)
4848 : MCSection(SV_COFF, K), SectionName(Section),
4949 Characteristics(Characteristics), COMDATSymbol(COMDATSymbol),
5050 Selection(Selection) {
6666 return SectionName.str() + "_end";
6767 }
6868 unsigned getCharacteristics() const { return Characteristics; }
69 const MCSymbol *getCOMDATSymbol() const { return COMDATSymbol; }
69 MCSymbol *getCOMDATSymbol() const { return COMDATSymbol; }
7070 int getSelection() const { return Selection; }
7171
7272 void setSelection(int Selection) const;
6969
7070 /// Given a constant with the SectionKind, return a section that it should be
7171 /// placed in.
72 virtual const MCSection *getSectionForConstant(SectionKind Kind) const;
72 virtual const MCSection *getSectionForConstant(SectionKind Kind,
73 const Constant *C) const;
7374
7475 /// Classify the specified global variable into a set of target independent
7576 /// categories embodied in SectionKind.
10631063
10641064 SectionKind Kind = CPE.getSectionKind(TM.getDataLayout());
10651065
1066 const MCSection *S = getObjFileLowering().getSectionForConstant(Kind);
1066 const Constant *C = nullptr;
1067 if (!CPE.isMachineConstantPoolEntry())
1068 C = CPE.Val.ConstVal;
1069
1070 const MCSection *S = getObjFileLowering().getSectionForConstant(Kind, C);
10671071
10681072 // The number of sections are small, just do a linear search from the
10691073 // last section to the first.
10861090 }
10871091
10881092 // Now print stuff into the calculated sections.
1093 const MCSection *CurSection = nullptr;
1094 unsigned Offset = 0;
10891095 for (unsigned i = 0, e = CPSections.size(); i != e; ++i) {
1090 OutStreamer.SwitchSection(CPSections[i].S);
1091 EmitAlignment(Log2_32(CPSections[i].Alignment));
1092
1093 unsigned Offset = 0;
10941096 for (unsigned j = 0, ee = CPSections[i].CPEs.size(); j != ee; ++j) {
10951097 unsigned CPI = CPSections[i].CPEs[j];
1098 MCSymbol *Sym = GetCPISymbol(CPI);
1099 if (!Sym->isUndefined())
1100 continue;
1101
1102 if (CurSection != CPSections[i].S) {
1103 OutStreamer.SwitchSection(CPSections[i].S);
1104 EmitAlignment(Log2_32(CPSections[i].Alignment));
1105 CurSection = CPSections[i].S;
1106 Offset = 0;
1107 }
1108
10961109 MachineConstantPoolEntry CPE = CP[CPI];
10971110
10981111 // Emit inter-object padding for alignment.
11021115
11031116 Type *Ty = CPE.getType();
11041117 Offset = NewOffset + TM.getDataLayout()->getTypeAllocSize(Ty);
1105 OutStreamer.EmitLabel(GetCPISymbol(CPI));
1106
1118
1119 OutStreamer.EmitLabel(Sym);
11071120 if (CPE.isMachineConstantPoolEntry())
11081121 EmitMachineConstantPoolValue(CPE.Val.MachineCPVal);
11091122 else
11411154 } else {
11421155 // Otherwise, drop it in the readonly section.
11431156 const MCSection *ReadOnlySection =
1144 getObjFileLowering().getSectionForConstant(SectionKind::getReadOnly());
1157 getObjFileLowering().getSectionForConstant(SectionKind::getReadOnly(),
1158 /*C=*/nullptr);
11451159 OutStreamer.SwitchSection(ReadOnlySection);
11461160 JTInDiffSection = true;
11471161 }
337337 /// getSectionForConstant - Given a mergeable constant with the
338338 /// specified size and relocation information, return a section that it
339339 /// should be placed in.
340 const MCSection *TargetLoweringObjectFileELF::
341 getSectionForConstant(SectionKind Kind) const {
340 const MCSection *
341 TargetLoweringObjectFileELF::getSectionForConstant(SectionKind Kind,
342 const Constant *C) const {
342343 if (Kind.isMergeableConst4() && MergeableConst4Section)
343344 return MergeableConst4Section;
344345 if (Kind.isMergeableConst8() && MergeableConst8Section)
653654 }
654655
655656 const MCSection *
656 TargetLoweringObjectFileMachO::getSectionForConstant(SectionKind Kind) const {
657 TargetLoweringObjectFileMachO::getSectionForConstant(SectionKind Kind,
658 const Constant *C) const {
657659 // If this constant requires a relocation, we have to put it in the data
658660 // segment, not in the text segment.
659661 if (Kind.isDataRel() || Kind.isReadOnlyWithRel())
290290 if (!IterBool.second)
291291 return Iter->second;
292292
293 const MCSymbol *COMDATSymbol = nullptr;
293 MCSymbol *COMDATSymbol = nullptr;
294294 if (!COMDATSymName.empty())
295295 COMDATSymbol = GetOrCreateSymbol(COMDATSymName);
296296
8686 new NVPTXSection(MCSection::SV_ELF, SectionKind::getMetadata());
8787 }
8888
89 const MCSection *getSectionForConstant(SectionKind Kind) const override {
89 const MCSection *getSectionForConstant(SectionKind Kind,
90 const Constant *C) const override {
9091 return ReadOnlySection;
9192 }
9293
296296 /// specified size and relocation information, return a section that it
297297 /// should be placed in.
298298 const MCSection *
299 TargetLoweringObjectFile::getSectionForConstant(SectionKind Kind) const {
299 TargetLoweringObjectFile::getSectionForConstant(SectionKind Kind,
300 const Constant *C) const {
300301 if (Kind.isReadOnly() && ReadOnlySection != nullptr)
301302 return ReadOnlySection;
302303
1717 #include "X86InstrInfo.h"
1818 #include "X86MachineFunctionInfo.h"
1919 #include "llvm/ADT/SmallString.h"
20 #include "llvm/CodeGen/MachineConstantPool.h"
2021 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
2122 #include "llvm/CodeGen/MachineValueType.h"
2223 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
2829 #include "llvm/MC/MCAsmInfo.h"
2930 #include "llvm/MC/MCContext.h"
3031 #include "llvm/MC/MCExpr.h"
32 #include "llvm/MC/MCSectionCOFF.h"
3133 #include "llvm/MC/MCSectionMachO.h"
3234 #include "llvm/MC/MCStreamer.h"
3335 #include "llvm/MC/MCSymbol.h"
548550 4 /*size*/);
549551 }
550552
553 MCSymbol *X86AsmPrinter::GetCPISymbol(unsigned CPID) const {
554 if (Subtarget->isTargetKnownWindowsMSVC()) {
555 const MachineConstantPoolEntry &CPE =
556 MF->getConstantPool()->getConstants()[CPID];
557 if (!CPE.isMachineConstantPoolEntry()) {
558 SectionKind Kind = CPE.getSectionKind(TM.getDataLayout());
559 const Constant *C = CPE.Val.ConstVal;
560 const MCSectionCOFF *S = cast(
561 getObjFileLowering().getSectionForConstant(Kind, C));
562 if (MCSymbol *Sym = S->getCOMDATSymbol()) {
563 if (Sym->isUndefined())
564 OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global);
565 return Sym;
566 }
567 }
568 }
569
570 return AsmPrinter::GetCPISymbol(CPID);
571 }
572
551573 void X86AsmPrinter::GenerateExportDirective(const MCSymbol *Sym, bool IsData) {
552574 SmallString<128> Directive;
553575 raw_svector_ostream OS(Directive);
4949 unsigned AsmVariant, const char *ExtraCode,
5050 raw_ostream &OS) override;
5151
52 /// \brief Return the symbol for the specified constant pool entry.
53 MCSymbol *GetCPISymbol(unsigned CPID) const override;
54
5255 bool runOnMachineFunction(MachineFunction &F) override;
5356 };
5457
77 //===----------------------------------------------------------------------===//
88
99 #include "X86TargetObjectFile.h"
10 #include "llvm/ADT/StringExtras.h"
1011 #include "llvm/IR/Mangler.h"
1112 #include "llvm/IR/Operator.h"
1213 #include "llvm/MC/MCContext.h"
1314 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCSectionCOFF.h"
1416 #include "llvm/MC/MCSectionELF.h"
1517 #include "llvm/Support/Dwarf.h"
1618 #include "llvm/Target/TargetLowering.h"
105107 MCSymbolRefExpr::VK_COFF_IMGREL32,
106108 getContext());
107109 }
110
111 static std::string APIntToHexString(const APInt &AI, unsigned Width) {
112 std::string HexString = utohexstr(AI.getLimitedValue(), /*LowerCase=*/true);
113 unsigned Size = HexString.size();
114 assert(Width >= Size && "hex string is too large!");
115 HexString.insert(HexString.begin(), Width - Size, '0');
116
117 return HexString;
118 }
119
120
121 static std::string scalarConstantToHexString(const Constant *C) {
122 Type *Ty = C->getType();
123 if (Ty->isFloatTy()) {
124 const auto *CFP = cast(C);
125 return APIntToHexString(CFP->getValueAPF().bitcastToAPInt(), /*Width=*/8);
126 } else if (Ty->isDoubleTy()) {
127 const auto *CFP = cast(C);
128 return APIntToHexString(CFP->getValueAPF().bitcastToAPInt(), /*Width=*/16);
129 } else if (const auto *ITy = dyn_cast(Ty)) {
130 const auto *CI = cast(C);
131 return APIntToHexString(CI->getValue(), (ITy->getBitWidth() / 8) * 2);
132 }
133 llvm_unreachable("unexpected constant pool element type!");
134 }
135
136 const MCSection *
137 X86WindowsTargetObjectFile::getSectionForConstant(SectionKind Kind,
138 const Constant *C) const {
139 if (Kind.isReadOnly()) {
140 if (C) {
141 Type *Ty = C->getType();
142 SmallString<32> COMDATSymName;
143 if (Ty->isFloatTy() || Ty->isDoubleTy()) {
144 COMDATSymName = "__real@";
145 COMDATSymName += scalarConstantToHexString(C);
146 } else if (const auto *VTy = dyn_cast(Ty)) {
147 uint64_t NumBits = VTy->getBitWidth();
148 if (NumBits == 128 || NumBits == 256) {
149 const auto *CDV = cast(C);
150 COMDATSymName = NumBits == 128 ? "__xmm@" : "__ymm@";
151 for (int I = CDV->getNumElements() - 1, E = -1; I != E; --I)
152 COMDATSymName +=
153 scalarConstantToHexString(CDV->getElementAsConstant(I));
154 }
155 }
156 if (!COMDATSymName.empty()) {
157 unsigned Characteristics = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
158 COFF::IMAGE_SCN_MEM_READ |
159 COFF::IMAGE_SCN_LNK_COMDAT;
160 return getContext().getCOFFSection(".rdata", Characteristics, Kind,
161 COMDATSymName,
162 COFF::IMAGE_COMDAT_SELECT_ANY);
163 }
164 }
165 }
166
167 return TargetLoweringObjectFile::getSectionForConstant(Kind, C);
168 }
4545 const MCExpr *
4646 getExecutableRelativeSymbol(const ConstantExpr *CE, Mangler &Mang,
4747 const TargetMachine &TM) const override;
48
49 /// \brief Given a mergeable constant with the specified size and relocation
50 /// information, return a section that it should be placed in.
51 const MCSection *getSectionForConstant(SectionKind Kind,
52 const Constant *C) const override;
4853 };
4954
5055 } // end namespace llvm
164164 report_fatal_error("Target does not support TLS or Common sections");
165165 }
166166
167 const MCSection *XCoreTargetObjectFile::
168 getSectionForConstant(SectionKind Kind) const {
167 const MCSection *
168 XCoreTargetObjectFile::getSectionForConstant(SectionKind Kind,
169 const Constant *C) const {
169170 if (Kind.isMergeableConst4()) return MergeableConst4Section;
170171 if (Kind.isMergeableConst8()) return MergeableConst8Section;
171172 if (Kind.isMergeableConst16()) return MergeableConst16Section;
3333 Mangler &Mang,
3434 const TargetMachine &TM) const override;
3535
36 const MCSection *getSectionForConstant(SectionKind Kind) const override;
36 const MCSection *getSectionForConstant(SectionKind Kind,
37 const Constant *C) const override;
3738 };
3839 } // end namespace llvm
3940
None ; RUN: llc < %s -mtriple=x86_64-linux -mcpu=corei7 | FileCheck %s
1 ; RUN: llc < %s -mtriple=x86_64-win32 -mcpu=corei7 | FileCheck %s
0 ; RUN: llc < %s -mtriple=x86_64-linux -mcpu=corei7 | FileCheck %s --check-prefix=COMMON --check-prefix=LINUX
1 ; RUN: llc < %s -mtriple=x86_64-win32 -mcpu=corei7 | FileCheck %s --check-prefix=COMMON --check-prefix=MSVC
22
33 ; llc should share constant pool entries between this integer vector
44 ; and this floating-point vector since they have the same encoding.
55
6 ; CHECK: LCPI0_0(%rip), %xmm0
7 ; CHECK: movaps %xmm0, ({{%rdi|%rcx}})
8 ; CHECK: movaps %xmm0, ({{%rsi|%rdx}})
6 ; LINUX: LCPI0_0(%rip), %xmm0
7 ; MSVC: __xmm@40000000400000004000000040000000(%rip), %xmm0
8 ; COMMON: movaps %xmm0, ({{%rdi|%rcx}})
9 ; COMMON: movaps %xmm0, ({{%rsi|%rdx}})
910
1011 define void @foo(<4 x i32>* %p, <4 x float>* %q, i1 %t) nounwind {
1112 entry:
0 ; RUN: llc < %s -mtriple=x86_64-win32 -mcpu=corei7 | FileCheck %s
1 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
2 target triple = "x86_64-pc-windows-msvc"
3
4 define double @double() {
5 ret double 0x0000000000800000
6 }
7 ; CHECK: .globl __real@0000000000800000
8 ; CHECK-NEXT: .section .rdata,"rd",discard,__real@0000000000800000
9 ; CHECK-NEXT: .align 8
10 ; CHECK-NEXT: __real@0000000000800000:
11 ; CHECK-NEXT: .quad 8388608
12 ; CHECK: double:
13 ; CHECK: movsd __real@0000000000800000(%rip), %xmm0
14 ; CHECK-NEXT: ret
15
16 define <4 x i32> @vec1() {
17 ret <4 x i32>
18 }
19 ; CHECK: .globl __xmm@00000000000000010000000200000003
20 ; CHECK-NEXT: .section .rdata,"rd",discard,__xmm@00000000000000010000000200000003
21 ; CHECK-NEXT: .align 16
22 ; CHECK-NEXT: __xmm@00000000000000010000000200000003:
23 ; CHECK-NEXT: .long 3
24 ; CHECK-NEXT: .long 2
25 ; CHECK-NEXT: .long 1
26 ; CHECK-NEXT: .long 0
27 ; CHECK: vec1:
28 ; CHECK: movaps __xmm@00000000000000010000000200000003(%rip), %xmm0
29 ; CHECK-NEXT: ret
30
31 define <8 x i16> @vec2() {
32 ret <8 x i16>
33 }
34 ; CHECK: .globl __xmm@00000001000200030004000500060007
35 ; CHECK-NEXT: .section .rdata,"rd",discard,__xmm@00000001000200030004000500060007
36 ; CHECK-NEXT: .align 16
37 ; CHECK-NEXT: __xmm@00000001000200030004000500060007:
38 ; CHECK-NEXT: .short 7
39 ; CHECK-NEXT: .short 6
40 ; CHECK-NEXT: .short 5
41 ; CHECK-NEXT: .short 4
42 ; CHECK-NEXT: .short 3
43 ; CHECK-NEXT: .short 2
44 ; CHECK-NEXT: .short 1
45 ; CHECK-NEXT: .short 0
46 ; CHECK: vec2:
47 ; CHECK: movaps __xmm@00000001000200030004000500060007(%rip), %xmm0
48 ; CHECK-NEXT: ret