[llvm] r196087 - XCore target: Add large code model

Robert Lytton robert at xmos.com
Mon Dec 2 02:18:31 PST 2013


Author: rlytton
Date: Mon Dec  2 04:18:31 2013
New Revision: 196087

URL: http://llvm.org/viewvc/llvm-project?rev=196087&view=rev
Log:
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.

Modified:
    llvm/trunk/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp
    llvm/trunk/lib/Target/XCore/XCoreISelLowering.cpp
    llvm/trunk/lib/Target/XCore/XCoreInstrInfo.td
    llvm/trunk/lib/Target/XCore/XCoreTargetObjectFile.cpp
    llvm/trunk/lib/Target/XCore/XCoreTargetObjectFile.h
    llvm/trunk/test/CodeGen/XCore/codemodel.ll

Modified: llvm/trunk/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp?rev=196087&r1=196086&r2=196087&view=diff
==============================================================================
--- llvm/trunk/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp (original)
+++ llvm/trunk/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp Mon Dec  2 04:18:31 2013
@@ -69,6 +69,12 @@ static MCCodeGenInfo *createXCoreMCCodeG
   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;
 }

Modified: llvm/trunk/lib/Target/XCore/XCoreISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/XCore/XCoreISelLowering.cpp?rev=196087&r1=196086&r2=196087&view=diff
==============================================================================
--- llvm/trunk/lib/Target/XCore/XCoreISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/XCore/XCoreISelLowering.cpp Mon Dec  2 04:18:31 2013
@@ -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, cons
 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, SelectionD
   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);
 }

Modified: llvm/trunk/lib/Target/XCore/XCoreInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/XCore/XCoreInstrInfo.td?rev=196087&r1=196086&r2=196087&view=diff
==============================================================================
--- llvm/trunk/lib/Target/XCore/XCoreInstrInfo.td (original)
+++ llvm/trunk/lib/Target/XCore/XCoreInstrInfo.td Mon Dec  2 04:18:31 2013
@@ -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)>;

Modified: llvm/trunk/lib/Target/XCore/XCoreTargetObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/XCore/XCoreTargetObjectFile.cpp?rev=196087&r1=196086&r2=196087&view=diff
==============================================================================
--- llvm/trunk/lib/Target/XCore/XCoreTargetObjectFile.cpp (original)
+++ llvm/trunk/lib/Target/XCore/XCoreTargetObjectFile.cpp Mon Dec  2 04:18:31 2013
@@ -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(M
                       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;
 }

Modified: llvm/trunk/lib/Target/XCore/XCoreTargetObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/XCore/XCoreTargetObjectFile.h?rev=196087&r1=196086&r2=196087&view=diff
==============================================================================
--- llvm/trunk/lib/Target/XCore/XCoreTargetObjectFile.h (original)
+++ llvm/trunk/lib/Target/XCore/XCoreTargetObjectFile.h Mon Dec  2 04:18:31 2013
@@ -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
 

Modified: llvm/trunk/test/CodeGen/XCore/codemodel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/XCore/codemodel.ll?rev=196087&r1=196086&r2=196087&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/XCore/codemodel.ll (original)
+++ llvm/trunk/test/CodeGen/XCore/codemodel.ll Mon Dec  2 04:18:31 2013
@@ -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", at 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", at progbits,4
+; LARGE: .long 65536
+; LARGE: .section .cp.rodata,"ac", at 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", at nobits
 ; CHECK-LABEL: l:
 ; CHECK: .space 400
+; LARGE: .section  .dp.bss.large,"awd", at nobits
+; LARGE-LABEL: l:
+; LARGE: .space  400
 @l = global [100 x i32] zeroinitializer
 
 ; CHECK-LABEL: s:
 ; CHECK: .space 40
+; LARGE: .section  .dp.bss,"awd", at nobits
+; LARGE-LABEL: s:
+; LARGE: .space  40
 @s = global [10 x i32] zeroinitializer
 
 ; CHECK: .section .cp.rodata,"ac", at progbits
 ; CHECK-LABEL: cl:
 ; CHECK: .space 400
+; LARGE: .section .cp.rodata.large,"ac", at progbits
+; LARGE-LABEL: cl:
+; LARGE: .space 400
 @cl = constant  [100 x i32] zeroinitializer
 
 ; CHECK-LABEL: cs:
 ; CHECK: .space 40
+; LARGE: .section .cp.rodata,"ac", at progbits
+; LARGE-LABEL: cs:
+; LARGE: .space 40
 @cs = constant  [10 x i32] zeroinitializer
+
+; CHECK: .section  .cp.namedsection,"ac", at progbits
+; CHECK-LABEL: cpsec:
+; CHECK: .long 0
+ at cpsec = global i32 0, section ".cp.namedsection"
+
+; CHECK: .section  .dp.namedsection,"awd", at progbits
+; CHECK-LABEL: dpsec:
+; CHECK: .long 0
+ at dpsec = global i32 0, section ".dp.namedsection"





More information about the llvm-commits mailing list