diff options
-rw-r--r-- | lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp | 6 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreISelLowering.cpp | 40 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreInstrInfo.td | 3 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreTargetObjectFile.cpp | 139 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreTargetObjectFile.h | 15 | ||||
-rw-r--r-- | test/CodeGen/XCore/codemodel.ll | 65 |
6 files changed, 239 insertions, 29 deletions
diff --git a/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp b/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp index 10bb6dfa92..c4347357d5 100644 --- a/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp +++ b/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp @@ -69,6 +69,12 @@ static MCCodeGenInfo *createXCoreMCCodeGenInfo(StringRef TT, Reloc::Model RM, if (RM == Reloc::Default) { RM = Reloc::Static; } + if (CM == CodeModel::Default) { + CM = CodeModel::Small; + } + if (CM != CodeModel::Small && CM != CodeModel::Large) + report_fatal_error("Target only supports CodeModel Small or Large"); + X->InitMCCodeGenInfo(RM, CM, OL); return X; } diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index 89ad27daec..6b0a2d0835 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -28,6 +28,7 @@ #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/CallingConv.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" @@ -270,20 +271,35 @@ getGlobalAddressWrapper(SDValue GA, const GlobalValue *GV, SDValue XCoreTargetLowering:: LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { - SDLoc DL(Op); const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op); const GlobalValue *GV = GN->getGlobal(); + SDLoc DL(GN); int64_t Offset = GN->getOffset(); - // We can only fold positive offsets that are a multiple of the word size. - int64_t FoldedOffset = std::max(Offset & ~3, (int64_t)0); - SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, FoldedOffset); - GA = getGlobalAddressWrapper(GA, GV, DAG); - // Handle the rest of the offset. - if (Offset != FoldedOffset) { - SDValue Remaining = DAG.getConstant(Offset - FoldedOffset, MVT::i32); - GA = DAG.getNode(ISD::ADD, DL, MVT::i32, GA, Remaining); + Type *ObjType = GV->getType()->getPointerElementType(); + if (getTargetMachine().getCodeModel() == CodeModel::Small || + !ObjType->isSized() || + getDataLayout()->getTypeAllocSize(ObjType) < CodeModelLargeSize) { + // We can only fold positive offsets that are a multiple of the word size. + int64_t FoldedOffset = std::max(Offset & ~3, (int64_t)0); + SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, FoldedOffset); + GA = getGlobalAddressWrapper(GA, GV, DAG); + // Handle the rest of the offset. + if (Offset != FoldedOffset) { + SDValue Remaining = DAG.getConstant(Offset - FoldedOffset, MVT::i32); + GA = DAG.getNode(ISD::ADD, DL, MVT::i32, GA, Remaining); + } + return GA; + } else { + // Ideally we would not fold in offset with an index <= 11. + Type *Ty = Type::getInt8PtrTy(*DAG.getContext()); + Constant *GA = ConstantExpr::getBitCast(const_cast<GlobalValue*>(GV), Ty); + Ty = Type::getInt32Ty(*DAG.getContext()); + Constant *Idx = ConstantInt::get(Ty, Offset); + Constant *GAI = ConstantExpr::getGetElementPtr(GA, Idx); + SDValue CP = DAG.getConstantPool(GAI, MVT::i32); + return DAG.getLoad(getPointerTy(), DL, DAG.getEntryNode(), CP, + MachinePointerInfo(), false, false, false, 0); } - return GA; } SDValue XCoreTargetLowering:: @@ -307,10 +323,10 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) const SDValue Res; if (CP->isMachineConstantPoolEntry()) { Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT, - CP->getAlignment()); + CP->getAlignment(), CP->getOffset()); } else { Res = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT, - CP->getAlignment()); + CP->getAlignment(), CP->getOffset()); } return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, Res); } diff --git a/lib/Target/XCore/XCoreInstrInfo.td b/lib/Target/XCore/XCoreInstrInfo.td index 934a707e78..3f0d08c17a 100644 --- a/lib/Target/XCore/XCoreInstrInfo.td +++ b/lib/Target/XCore/XCoreInstrInfo.td @@ -1286,3 +1286,6 @@ def : Pat<(setgt GRRegs:$lhs, -1), def : Pat<(sra (shl GRRegs:$src, immBpwSubBitp:$imm), immBpwSubBitp:$imm), (SEXT_rus GRRegs:$src, (bpwsub_xform immBpwSubBitp:$imm))>; + +def : Pat<(load (cprelwrapper tconstpool:$b)), + (LDWCP_lru6 tconstpool:$b)>; diff --git a/lib/Target/XCore/XCoreTargetObjectFile.cpp b/lib/Target/XCore/XCoreTargetObjectFile.cpp index 88e3bfd7b8..61eb2b51f3 100644 --- a/lib/Target/XCore/XCoreTargetObjectFile.cpp +++ b/lib/Target/XCore/XCoreTargetObjectFile.cpp @@ -9,27 +9,52 @@ #include "XCoreTargetObjectFile.h" #include "XCoreSubtarget.h" +#include "llvm/IR/DataLayout.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/Support/ELF.h" #include "llvm/Target/TargetMachine.h" + using namespace llvm; void XCoreTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ TargetLoweringObjectFileELF::Initialize(Ctx, TM); + BSSSection = + Ctx.getELFSection(".dp.bss", ELF::SHT_NOBITS, + ELF::SHF_ALLOC | ELF::SHF_WRITE | + ELF::XCORE_SHF_DP_SECTION, + SectionKind::getBSS()); + BSSSectionLarge = + Ctx.getELFSection(".dp.bss.large", ELF::SHT_NOBITS, + ELF::SHF_ALLOC | ELF::SHF_WRITE | + ELF::XCORE_SHF_DP_SECTION, + SectionKind::getBSS()); DataSection = - Ctx.getELFSection(".dp.data", ELF::SHT_PROGBITS, + Ctx.getELFSection(".dp.data", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::XCORE_SHF_DP_SECTION, SectionKind::getDataRel()); - BSSSection = - Ctx.getELFSection(".dp.bss", ELF::SHT_NOBITS, + DataSectionLarge = + Ctx.getELFSection(".dp.data.large", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::XCORE_SHF_DP_SECTION, - SectionKind::getBSS()); - + SectionKind::getDataRel()); + // This is the wrong place to decide if const data should be placed + // in the .cp or .dp section. + // Ideally we should set up DataRelROSection to use the '.dp.'' and use this + // for const data, unless the front end explicitly states a '.cp.'' section. + ReadOnlySection = + Ctx.getELFSection(".cp.rodata", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | + ELF::XCORE_SHF_CP_SECTION, + SectionKind::getReadOnlyWithRel()); + ReadOnlySectionLarge = + Ctx.getELFSection(".cp.rodata.large", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | + ELF::XCORE_SHF_CP_SECTION, + SectionKind::getReadOnlyWithRel()); MergeableConst4Section = Ctx.getELFSection(".cp.rodata.cst4", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_MERGE | @@ -45,16 +70,100 @@ void XCoreTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::XCORE_SHF_CP_SECTION, SectionKind::getMergeableConst16()); - - // TLS globals are lowered in the backend to arrays indexed by the current - // thread id. After lowering they require no special handling by the linker - // and can be placed in the standard data / bss sections. - TLSDataSection = DataSection; - TLSBSSSection = BSSSection; - - ReadOnlySection = - Ctx.getELFSection(".cp.rodata", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | + CStringSection = + Ctx.getELFSection(".cp.rodata.string", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS | ELF::XCORE_SHF_CP_SECTION, SectionKind::getReadOnlyWithRel()); + // TextSection - see MObjectFileInfo.cpp + // StaticCtorSection - see MObjectFileInfo.cpp + // StaticDtorSection - see MObjectFileInfo.cpp + } + +static SectionKind getXCoreKindForNamedSection(StringRef Name, SectionKind K) { + if (Name.startswith(".cp.")) + return SectionKind::getReadOnly(); + return K; +} + +static unsigned getXCoreSectionType(SectionKind K) { + if (K.isBSS()) + return ELF::SHT_NOBITS; + return ELF::SHT_PROGBITS; +} + +static unsigned getXCoreSectionFlags(SectionKind K) { + unsigned Flags = 0; + + if (!K.isMetadata()) + Flags |= ELF::SHF_ALLOC; + + if (K.isText()) + Flags |= ELF::SHF_EXECINSTR; + else if (K.isReadOnly()) + Flags |= ELF::XCORE_SHF_CP_SECTION; + else + Flags |= ELF::XCORE_SHF_DP_SECTION; + + if (K.isWriteable()) + Flags |= ELF::SHF_WRITE; + + if (K.isMergeableCString() || K.isMergeableConst4() || + K.isMergeableConst8() || K.isMergeableConst16()) + Flags |= ELF::SHF_MERGE; + + if (K.isMergeableCString()) + Flags |= ELF::SHF_STRINGS; + + return Flags; +} + +const MCSection *XCoreTargetObjectFile:: +getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + StringRef SectionName = GV->getSection(); + // Infer section flags from the section name if we can. + Kind = getXCoreKindForNamedSection(SectionName, Kind); + return getContext().getELFSection(SectionName, getXCoreSectionType(Kind), + getXCoreSectionFlags(Kind), Kind); +} + +const MCSection *XCoreTargetObjectFile:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, + const TargetMachine &TM) const{ + if (Kind.isText()) return TextSection; + if (Kind.isMergeable1ByteCString()) return CStringSection; + if (Kind.isMergeableConst4()) return MergeableConst4Section; + if (Kind.isMergeableConst8()) return MergeableConst8Section; + if (Kind.isMergeableConst16()) return MergeableConst16Section; + + Type *ObjType = GV->getType()->getPointerElementType(); + if (TM.getCodeModel() == CodeModel::Small || + !ObjType->isSized() || + TM.getDataLayout()->getTypeAllocSize(ObjType) < CodeModelLargeSize) { + if (Kind.isReadOnly()) return ReadOnlySection; + if (Kind.isBSS()) return BSSSection; + if (Kind.isDataRel()) return DataSection; + if (Kind.isReadOnlyWithRel()) return ReadOnlySection; + } else { + if (Kind.isReadOnly()) return ReadOnlySectionLarge; + if (Kind.isBSS()) return BSSSectionLarge; + if (Kind.isDataRel()) return DataSectionLarge; + if (Kind.isReadOnlyWithRel()) return ReadOnlySectionLarge; + } + + assert((Kind.isThreadLocal() || Kind.isCommon()) && "Unknown section kind"); + report_fatal_error("Target does not support TLS or Common sections"); +} + +const MCSection *XCoreTargetObjectFile:: +getSectionForConstant(SectionKind Kind) const { + if (Kind.isMergeableConst4()) return MergeableConst4Section; + if (Kind.isMergeableConst8()) return MergeableConst8Section; + if (Kind.isMergeableConst16()) return MergeableConst16Section; + assert((Kind.isReadOnly() || Kind.isReadOnlyWithRel()) && + "Unknown section kind"); + // We assume the size of the object is never greater than CodeModelLargeSize. + // To handle CodeModelLargeSize changes to AsmPrinter would be required. + return ReadOnlySection; } diff --git a/lib/Target/XCore/XCoreTargetObjectFile.h b/lib/Target/XCore/XCoreTargetObjectFile.h index 27875e783b..bf9798d508 100644 --- a/lib/Target/XCore/XCoreTargetObjectFile.h +++ b/lib/Target/XCore/XCoreTargetObjectFile.h @@ -14,11 +14,24 @@ namespace llvm { +static const unsigned CodeModelLargeSize = 256; + class XCoreTargetObjectFile : public TargetLoweringObjectFileELF { + const MCSection *BSSSectionLarge; + const MCSection *DataSectionLarge; + const MCSection *ReadOnlySectionLarge; public: void Initialize(MCContext &Ctx, const TargetMachine &TM); - // TODO: Classify globals as xcore wishes. + virtual const MCSection * + getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; + + virtual const MCSection * + SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; + + virtual const MCSection *getSectionForConstant(SectionKind Kind) const; }; } // end namespace llvm diff --git a/test/CodeGen/XCore/codemodel.ll b/test/CodeGen/XCore/codemodel.ll index f5a980524d..e86627cc41 100644 --- a/test/CodeGen/XCore/codemodel.ll +++ b/test/CodeGen/XCore/codemodel.ll @@ -1,5 +1,12 @@ -; RUN: llc < %s -march=xcore | FileCheck %s +; RUN: not llc < %s -march=xcore -code-model=medium 2>&1 | FileCheck %s -check-prefix=BAD_CM +; RUN: not llc < %s -march=xcore -code-model=kernel 2>&1 | FileCheck %s -check-prefix=BAD_CM +; BAD_CM: Target only supports CodeModel Small or Large + + +; RUN: llc < %s -march=xcore -code-model=default | FileCheck %s +; RUN: llc < %s -march=xcore -code-model=small | FileCheck %s +; RUN: llc < %s -march=xcore -code-model=large | FileCheck %s -check-prefix=LARGE ; CHECK: .section .cp.rodata.cst4,"aMc",@progbits,4 ; CHECK: .long 65536 @@ -25,6 +32,40 @@ ; CHECK: ldw r1, dp[s+36] ; CHECK: add r0, r0, r1 ; CHECK: retsp 0 +; +; LARGE: .section .cp.rodata.cst4,"aMc",@progbits,4 +; LARGE: .long 65536 +; LARGE: .section .cp.rodata,"ac",@progbits +; LARGE: .long l +; LARGE: .long l+4 +; LARGE: .long l+392 +; LARGE: .long l+396 +; LARGE: .text +; LARGE-LABEL: f: +; LARGE: ldc r1, 65532 +; LARGE: add r1, r0, r1 +; LARGE: ldw r1, r1[0] +; LARGE: ldw r2, cp[.LCPI0_0] +; LARGE: add r0, r0, r2 +; LARGE: ldw r0, r0[0] +; LARGE: add r0, r1, r0 +; LARGE: ldw r1, cp[.LCPI0_1] +; LARGE: ldw r1, r1[0] +; LARGE: add r0, r0, r1 +; LARGE: ldw r1, cp[.LCPI0_2] +; LARGE: ldw r1, r1[0] +; LARGE: add r0, r0, r1 +; LARGE: ldw r1, cp[.LCPI0_3] +; LARGE: ldw r1, r1[0] +; LARGE: add r0, r0, r1 +; LARGE: ldw r1, cp[.LCPI0_4] +; LARGE: ldw r1, r1[0] +; LARGE: add r0, r0, r1 +; LARGE: ldw r1, dp[s] +; LARGE: add r0, r0, r1 +; LARGE: ldw r1, dp[s+36] +; LARGE: add r0, r0, r1 +; LARGE: retsp 0 define i32 @f(i32* %i) { entry: %0 = getelementptr inbounds i32* %i, i32 16383 @@ -50,17 +91,39 @@ entry: ; CHECK: .section .dp.bss,"awd",@nobits ; CHECK-LABEL: l: ; CHECK: .space 400 +; LARGE: .section .dp.bss.large,"awd",@nobits +; LARGE-LABEL: l: +; LARGE: .space 400 @l = global [100 x i32] zeroinitializer ; CHECK-LABEL: s: ; CHECK: .space 40 +; LARGE: .section .dp.bss,"awd",@nobits +; LARGE-LABEL: s: +; LARGE: .space 40 @s = global [10 x i32] zeroinitializer ; CHECK: .section .cp.rodata,"ac",@progbits ; CHECK-LABEL: cl: ; CHECK: .space 400 +; LARGE: .section .cp.rodata.large,"ac",@progbits +; LARGE-LABEL: cl: +; LARGE: .space 400 @cl = constant [100 x i32] zeroinitializer ; CHECK-LABEL: cs: ; CHECK: .space 40 +; LARGE: .section .cp.rodata,"ac",@progbits +; LARGE-LABEL: cs: +; LARGE: .space 40 @cs = constant [10 x i32] zeroinitializer + +; CHECK: .section .cp.namedsection,"ac",@progbits +; CHECK-LABEL: cpsec: +; CHECK: .long 0 +@cpsec = global i32 0, section ".cp.namedsection" + +; CHECK: .section .dp.namedsection,"awd",@progbits +; CHECK-LABEL: dpsec: +; CHECK: .long 0 +@dpsec = global i32 0, section ".dp.namedsection" |