XCore target: Add large code model

When using large code model:
Global objects larger than 'CodeModelLargeSize' bytes are placed in sections named with a trailing ".large"
The folded global address of such objects are lowered into the const pool.

During inspection it was noted that LowerConstantPool() was using a default offset of zero.
A fix was made, but due to only offsets of zero being generated, testing only verifies the change is not detrimental.

Correct the flags emitted for explicitly specified sections.

We assume the size of the object queried by getSectionForConstant() is never greater than CodeModelLargeSize.
To handle greater than CodeModelLargeSize, changes to AsmPrinter would be required.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@196087 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Robert Lytton 2013-12-02 10:18:31 +00:00
parent 7112fa0523
commit 883abacb5b
6 changed files with 240 additions and 30 deletions

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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)>;

View File

@ -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);
DataSection =
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,
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,
ELF::SHF_ALLOC | ELF::SHF_WRITE |
ELF::XCORE_SHF_DP_SECTION,
SectionKind::getDataRel());
DataSectionLarge =
Ctx.getELFSection(".dp.data.large", ELF::SHT_PROGBITS,
ELF::SHF_ALLOC | ELF::SHF_WRITE |
ELF::XCORE_SHF_DP_SECTION,
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;
}

View File

@ -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

View File

@ -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"