Index: include/llvm/ADT/StringExtras.h =================================================================== --- include/llvm/ADT/StringExtras.h +++ include/llvm/ADT/StringExtras.h @@ -53,7 +53,7 @@ /// This should only be used with unsigned types. /// template -static inline char *utohex_buffer(IntTy X, char *BufferEnd) { +static inline char *utohex_buffer(IntTy X, char *BufferEnd, bool LowerCase = false) { char *BufPtr = BufferEnd; *--BufPtr = 0; // Null terminate buffer. if (X == 0) { @@ -63,15 +63,15 @@ while (X) { unsigned char Mod = static_cast(X) & 15; - *--BufPtr = hexdigit(Mod); + *--BufPtr = hexdigit(Mod, LowerCase); X >>= 4; } return BufPtr; } -static inline std::string utohexstr(uint64_t X) { +static inline std::string utohexstr(uint64_t X, bool LowerCase = false) { char Buffer[17]; - return utohex_buffer(X, Buffer+17); + return utohex_buffer(X, Buffer+17, LowerCase); } static inline std::string utostr_32(uint32_t X, bool isNeg = false) { Index: include/llvm/CodeGen/AsmPrinter.h =================================================================== --- include/llvm/CodeGen/AsmPrinter.h +++ include/llvm/CodeGen/AsmPrinter.h @@ -19,6 +19,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/IR/InlineAsm.h" +#include "llvm/MC/SectionKind.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" Index: include/llvm/CodeGen/MachineConstantPool.h =================================================================== --- include/llvm/CodeGen/MachineConstantPool.h +++ include/llvm/CodeGen/MachineConstantPool.h @@ -17,6 +17,7 @@ #define LLVM_CODEGEN_MACHINECONSTANTPOOL_H #include "llvm/ADT/DenseSet.h" +#include "llvm/MC/SectionKind.h" #include #include #include @@ -119,6 +120,8 @@ /// them. /// 2: This entry may have arbitrary relocations. unsigned getRelocationInfo() const; + + SectionKind getSectionKind(const TargetMachine &TM) const; }; /// The MachineConstantPool class keeps track of constants referenced by a Index: include/llvm/CodeGen/TargetLoweringObjectFileImpl.h =================================================================== --- include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -43,8 +43,8 @@ /// Given a constant with the SectionKind, return a section that it should be /// placed in. - const MCSection *getSectionForConstant(SectionKind Kind, - const Constant *C) const override; + const MCSection *getSectionForConstant(SectionKind Kind, const Constant *C, + MCStreamer &Streamer) const override; const MCSection *getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, @@ -101,8 +101,8 @@ SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const override; - const MCSection *getSectionForConstant(SectionKind Kind, - const Constant *C) const override; + const MCSection *getSectionForConstant(SectionKind Kind, const Constant *C, + MCStreamer &Streamer) const override; /// The mach-o version of this method defaults to returning a stub reference. const MCExpr * Index: include/llvm/MC/MCSectionCOFF.h =================================================================== --- include/llvm/MC/MCSectionCOFF.h +++ include/llvm/MC/MCSectionCOFF.h @@ -36,7 +36,7 @@ /// The COMDAT symbol of this section. Only valid if this is a COMDAT /// section. Two COMDAT sections are merged if they have the same /// COMDAT symbol. - const MCSymbol *COMDATSymbol; + MCSymbol *COMDATSymbol; /// Selection - This is the Selection field for the section symbol, if /// it is a COMDAT section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 @@ -45,7 +45,7 @@ private: friend class MCContext; MCSectionCOFF(StringRef Section, unsigned Characteristics, - const MCSymbol *COMDATSymbol, int Selection, SectionKind K) + MCSymbol *COMDATSymbol, int Selection, SectionKind K) : MCSection(SV_COFF, K), SectionName(Section), Characteristics(Characteristics), COMDATSymbol(COMDATSymbol), Selection(Selection) { @@ -67,7 +67,7 @@ return SectionName.str() + "_end"; } unsigned getCharacteristics() const { return Characteristics; } - const MCSymbol *getCOMDATSymbol() const { return COMDATSymbol; } + MCSymbol *getCOMDATSymbol() const { return COMDATSymbol; } int getSelection() const { return Selection; } void setSelection(int Selection) const; Index: include/llvm/Target/TargetLoweringObjectFile.h =================================================================== --- include/llvm/Target/TargetLoweringObjectFile.h +++ include/llvm/Target/TargetLoweringObjectFile.h @@ -71,7 +71,8 @@ /// Given a constant with the SectionKind, return a section that it should be /// placed in. virtual const MCSection *getSectionForConstant(SectionKind Kind, - const Constant *C) const; + const Constant *C, + MCStreamer &Streamer) const; /// Classify the specified global variable into a set of target independent /// categories embodied in SectionKind. Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1062,27 +1062,14 @@ const MachineConstantPoolEntry &CPE = CP[i]; unsigned Align = CPE.getAlignment(); - SectionKind Kind; - switch (CPE.getRelocationInfo()) { - default: llvm_unreachable("Unknown section kind"); - case 2: Kind = SectionKind::getReadOnlyWithRel(); break; - case 1: - Kind = SectionKind::getReadOnlyWithRelLocal(); - break; - case 0: - switch (TM.getDataLayout()->getTypeAllocSize(CPE.getType())) { - case 4: Kind = SectionKind::getMergeableConst4(); break; - case 8: Kind = SectionKind::getMergeableConst8(); break; - case 16: Kind = SectionKind::getMergeableConst16();break; - default: Kind = SectionKind::getMergeableConst(); break; - } - } + SectionKind Kind = CPE.getSectionKind(TM); const Constant *C = nullptr; if (!CPE.isMachineConstantPoolEntry()) C = CPE.Val.ConstVal; - const MCSection *S = getObjFileLowering().getSectionForConstant(Kind, C); + const MCSection *S = + getObjFileLowering().getSectionForConstant(Kind, C, OutStreamer); // The number of sections are small, just do a linear search from the // last section to the first. @@ -1105,13 +1092,21 @@ } // Now print stuff into the calculated sections. + const MCSection *CurSection = nullptr; for (unsigned i = 0, e = CPSections.size(); i != e; ++i) { - OutStreamer.SwitchSection(CPSections[i].S); - EmitAlignment(Log2_32(CPSections[i].Alignment)); - unsigned Offset = 0; for (unsigned j = 0, ee = CPSections[i].CPEs.size(); j != ee; ++j) { unsigned CPI = CPSections[i].CPEs[j]; + MCSymbol *Sym = GetCPISymbol(CPI); + if (!Sym->isUndefined()) + continue; + + if (CurSection != CPSections[i].S) { + OutStreamer.SwitchSection(CPSections[i].S); + EmitAlignment(Log2_32(CPSections[i].Alignment)); + CurSection = CPSections[i].S; + } + MachineConstantPoolEntry CPE = CP[CPI]; // Emit inter-object padding for alignment. @@ -1121,8 +1116,8 @@ Type *Ty = CPE.getType(); Offset = NewOffset + TM.getDataLayout()->getTypeAllocSize(Ty); - OutStreamer.EmitLabel(GetCPISymbol(CPI)); + OutStreamer.EmitLabel(Sym); if (CPE.isMachineConstantPoolEntry()) EmitMachineConstantPoolValue(CPE.Val.MachineCPVal); else @@ -1161,7 +1156,7 @@ // Otherwise, drop it in the readonly section. const MCSection *ReadOnlySection = getObjFileLowering().getSectionForConstant(SectionKind::getReadOnly(), - /*C=*/nullptr); + /*C=*/nullptr, OutStreamer); OutStreamer.SwitchSection(ReadOnlySection); JTInDiffSection = true; } Index: lib/CodeGen/MachineFunction.cpp =================================================================== --- lib/CodeGen/MachineFunction.cpp +++ lib/CodeGen/MachineFunction.cpp @@ -836,6 +836,37 @@ return Val.ConstVal->getRelocationInfo(); } +SectionKind +MachineConstantPoolEntry::getSectionKind(const TargetMachine &TM) const { + SectionKind Kind; + switch (getRelocationInfo()) { + default: + llvm_unreachable("Unknown section kind"); + case 2: + Kind = SectionKind::getReadOnlyWithRel(); + break; + case 1: + Kind = SectionKind::getReadOnlyWithRelLocal(); + break; + case 0: + switch (TM.getDataLayout()->getTypeAllocSize(getType())) { + case 4: + Kind = SectionKind::getMergeableConst4(); + break; + case 8: + Kind = SectionKind::getMergeableConst8(); + break; + case 16: + Kind = SectionKind::getMergeableConst16(); + break; + default: + Kind = SectionKind::getMergeableConst(); + break; + } + } + return Kind; +} + MachineConstantPool::~MachineConstantPool() { for (unsigned i = 0, e = Constants.size(); i != e; ++i) if (Constants[i].isMachineConstantPoolEntry()) Index: lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -340,7 +340,8 @@ /// should be placed in. const MCSection * TargetLoweringObjectFileELF::getSectionForConstant(SectionKind Kind, - const Constant *C) const { + const Constant *C, + MCStreamer &Streamer) const { if (Kind.isMergeableConst4() && MergeableConst4Section) return MergeableConst4Section; if (Kind.isMergeableConst8() && MergeableConst8Section) @@ -654,9 +655,8 @@ return DataSection; } -const MCSection * -TargetLoweringObjectFileMachO::getSectionForConstant(SectionKind Kind, - const Constant *C) const { +const MCSection *TargetLoweringObjectFileMachO::getSectionForConstant( + SectionKind Kind, const Constant *C, MCStreamer &Streamer) const { // If this constant requires a relocation, we have to put it in the data // segment, not in the text segment. if (Kind.isDataRel() || Kind.isReadOnlyWithRel()) Index: lib/MC/MCContext.cpp =================================================================== --- lib/MC/MCContext.cpp +++ lib/MC/MCContext.cpp @@ -291,7 +291,7 @@ if (!IterBool.second) return Iter->second; - const MCSymbol *COMDATSymbol = nullptr; + MCSymbol *COMDATSymbol = nullptr; if (!COMDATSymName.empty()) COMDATSymbol = GetOrCreateSymbol(COMDATSymName); Index: lib/Target/NVPTX/NVPTXTargetObjectFile.h =================================================================== --- lib/Target/NVPTX/NVPTXTargetObjectFile.h +++ lib/Target/NVPTX/NVPTXTargetObjectFile.h @@ -87,8 +87,8 @@ new NVPTXSection(MCSection::SV_ELF, SectionKind::getMetadata()); } - const MCSection *getSectionForConstant(SectionKind Kind, - const Constant *C) const override { + const MCSection *getSectionForConstant(SectionKind Kind, const Constant *C, + MCStreamer &Streamer) const override { return ReadOnlySection; } Index: lib/Target/TargetLoweringObjectFile.cpp =================================================================== --- lib/Target/TargetLoweringObjectFile.cpp +++ lib/Target/TargetLoweringObjectFile.cpp @@ -296,9 +296,8 @@ /// getSectionForConstant - Given a mergable constant with the /// specified size and relocation information, return a section that it /// should be placed in. -const MCSection * -TargetLoweringObjectFile::getSectionForConstant(SectionKind Kind, - const Constant *C) const { +const MCSection *TargetLoweringObjectFile::getSectionForConstant( + SectionKind Kind, const Constant *C, MCStreamer &Streamer) const { if (Kind.isReadOnly() && ReadOnlySection != nullptr) return ReadOnlySection; Index: lib/Target/X86/X86AsmPrinter.h =================================================================== --- lib/Target/X86/X86AsmPrinter.h +++ lib/Target/X86/X86AsmPrinter.h @@ -11,6 +11,7 @@ #define X86ASMPRINTER_H #include "X86Subtarget.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/StackMaps.h" #include "llvm/Target/TargetMachine.h" @@ -22,6 +23,7 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter { const X86Subtarget *Subtarget; StackMaps SM; + DenseSet EmittedConstantPoolValues; void GenerateExportDirective(const MCSymbol *Sym, bool IsData); @@ -50,6 +52,9 @@ unsigned AsmVariant, const char *ExtraCode, raw_ostream &OS) override; + /// \brief Return the symbol for the specified constant pool entry. + MCSymbol *GetCPISymbol(unsigned CPID) const override; + bool runOnMachineFunction(MachineFunction &F) override; }; Index: lib/Target/X86/X86AsmPrinter.cpp =================================================================== --- lib/Target/X86/X86AsmPrinter.cpp +++ lib/Target/X86/X86AsmPrinter.cpp @@ -18,6 +18,7 @@ #include "X86InstrInfo.h" #include "X86MachineFunctionInfo.h" #include "llvm/ADT/SmallString.h" +#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" @@ -29,6 +30,7 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" @@ -549,6 +551,23 @@ 4 /*size*/); } +MCSymbol *X86AsmPrinter::GetCPISymbol(unsigned CPID) const { + if (Subtarget->isTargetKnownWindowsMSVC()) { + const MachineConstantPoolEntry &CPE = + MF->getConstantPool()->getConstants()[CPID]; + if (!CPE.isMachineConstantPoolEntry()) { + SectionKind Kind = CPE.getSectionKind(TM); + const Constant *C = CPE.Val.ConstVal; + const MCSectionCOFF *S = cast( + getObjFileLowering().getSectionForConstant(Kind, C, OutStreamer)); + if (MCSymbol *Sym = S->getCOMDATSymbol()) + return Sym; + } + } + + return AsmPrinter::GetCPISymbol(CPID); +} + void X86AsmPrinter::GenerateExportDirective(const MCSymbol *Sym, bool IsData) { SmallString<128> Directive; raw_svector_ostream OS(Directive); Index: lib/Target/X86/X86TargetObjectFile.h =================================================================== --- lib/Target/X86/X86TargetObjectFile.h +++ lib/Target/X86/X86TargetObjectFile.h @@ -10,6 +10,8 @@ #ifndef LLVM_TARGET_X86_TARGETOBJECTFILE_H #define LLVM_TARGET_X86_TARGETOBJECTFILE_H +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/Target/TargetLoweringObjectFile.h" @@ -46,6 +48,11 @@ const MCExpr * getExecutableRelativeSymbol(const ConstantExpr *CE, Mangler &Mang, const TargetMachine &TM) const override; + + /// \brief Given a mergeable constant with the specified size and relocation + /// information, return a section that it should be placed in. + const MCSection *getSectionForConstant(SectionKind Kind, const Constant *C, + MCStreamer &Streamer) const override; }; } // end namespace llvm Index: lib/Target/X86/X86TargetObjectFile.cpp =================================================================== --- lib/Target/X86/X86TargetObjectFile.cpp +++ lib/Target/X86/X86TargetObjectFile.cpp @@ -8,10 +8,12 @@ //===----------------------------------------------------------------------===// #include "X86TargetObjectFile.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Operator.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/Support/Dwarf.h" #include "llvm/Target/TargetLowering.h" @@ -106,3 +108,69 @@ MCSymbolRefExpr::VK_COFF_IMGREL32, getContext()); } + +static std::string APIntToHexString(const APInt &AI, unsigned Width) { + std::string HexString = utohexstr(AI.getLimitedValue(), /*LowerCase=*/true); + unsigned Size = HexString.size(); + assert(Width >= Size && "hex string is too large!"); + HexString.insert(HexString.begin(), Width - Size, '0'); + + return HexString; +} + + +static std::string scalarConstantToHexString(const Constant *C) { + Type *Ty = C->getType(); + if (Ty->isFloatTy()) { + const auto *CFP = cast(C); + return APIntToHexString(CFP->getValueAPF().bitcastToAPInt(), /*Width=*/8); + } else if (Ty->isDoubleTy()) { + const auto *CFP = cast(C); + return APIntToHexString(CFP->getValueAPF().bitcastToAPInt(), /*Width=*/16); + } else if (const auto *ITy = dyn_cast(Ty)) { + const auto *CI = cast(C); + return APIntToHexString(CI->getValue(), (ITy->getBitWidth() / 8) * 2); + } + llvm_unreachable("unexpected constant pool element type!"); +} + +const MCSection *X86WindowsTargetObjectFile::getSectionForConstant( + SectionKind Kind, const Constant *C, MCStreamer &Streamer) const { + if (Kind.isReadOnly()) { + if (C) { + Type *Ty = C->getType(); + SmallString<32> COMDATSymName; + if (Ty->isFloatTy() || Ty->isDoubleTy()) { + COMDATSymName = "__real@"; + COMDATSymName += scalarConstantToHexString(C); + } else if (const auto *VTy = dyn_cast(Ty)) { + uint64_t NumBits = VTy->getBitWidth(); + if (NumBits == 128 || NumBits == 256) { + const auto *CDV = cast(C); + COMDATSymName = NumBits == 128 ? "__xmm@" : "__ymm@"; + for (int I = CDV->getNumElements() - 1, E = -1; I != E; --I) + COMDATSymName += + scalarConstantToHexString(CDV->getElementAsConstant(I)); + } + } + if (!COMDATSymName.empty()) { + unsigned Characteristics = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_LNK_COMDAT; + const MCSectionCOFF *S = + cast(getContext().getCOFFSection( + ".rdata", Characteristics, Kind, COMDATSymName, + COFF::IMAGE_COMDAT_SELECT_ANY)); + MCSymbol *Sym = S->getCOMDATSymbol(); + if (Sym->isUndefined()) + Streamer.EmitSymbolAttribute(Sym, MCSA_Global); + return S; + } + } + + if (ReadOnlySection) + return ReadOnlySection; + } + + return DataSection; +} Index: lib/Target/XCore/XCoreTargetObjectFile.h =================================================================== --- lib/Target/XCore/XCoreTargetObjectFile.h +++ lib/Target/XCore/XCoreTargetObjectFile.h @@ -34,8 +34,8 @@ Mangler &Mang, const TargetMachine &TM) const override; - const MCSection *getSectionForConstant(SectionKind Kind, - const Constant *C) const override; + const MCSection *getSectionForConstant(SectionKind Kind, const Constant *C, + MCStreamer &Streamer) const override; }; } // end namespace llvm Index: lib/Target/XCore/XCoreTargetObjectFile.cpp =================================================================== --- lib/Target/XCore/XCoreTargetObjectFile.cpp +++ lib/Target/XCore/XCoreTargetObjectFile.cpp @@ -165,9 +165,8 @@ report_fatal_error("Target does not support TLS or Common sections"); } -const MCSection * -XCoreTargetObjectFile::getSectionForConstant(SectionKind Kind, - const Constant *C) const { +const MCSection *XCoreTargetObjectFile::getSectionForConstant( + SectionKind Kind, const Constant *C, MCStreamer &Streamer) const { if (Kind.isMergeableConst4()) return MergeableConst4Section; if (Kind.isMergeableConst8()) return MergeableConst8Section; if (Kind.isMergeableConst16()) return MergeableConst16Section; Index: test/CodeGen/X86/constant-pool-sharing.ll =================================================================== --- test/CodeGen/X86/constant-pool-sharing.ll +++ test/CodeGen/X86/constant-pool-sharing.ll @@ -1,12 +1,13 @@ -; RUN: llc < %s -mtriple=x86_64-linux -mcpu=corei7 | FileCheck %s -; RUN: llc < %s -mtriple=x86_64-win32 -mcpu=corei7 | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-linux -mcpu=corei7 | FileCheck %s --check-prefix=COMMON --check-prefix=LINUX +; RUN: llc < %s -mtriple=x86_64-win32 -mcpu=corei7 | FileCheck %s --check-prefix=COMMON --check-prefix=MSVC ; llc should share constant pool entries between this integer vector ; and this floating-point vector since they have the same encoding. -; CHECK: LCPI0_0(%rip), %xmm0 -; CHECK: movaps %xmm0, ({{%rdi|%rcx}}) -; CHECK: movaps %xmm0, ({{%rsi|%rdx}}) +; LINUX: LCPI0_0(%rip), %xmm0 +; MSVC: __xmm@40000000400000004000000040000000(%rip), %xmm0 +; COMMON: movaps %xmm0, ({{%rdi|%rcx}}) +; COMMON: movaps %xmm0, ({{%rsi|%rdx}}) define void @foo(<4 x i32>* %p, <4 x float>* %q, i1 %t) nounwind { entry: