diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index d27e6f174d0..13c8ad47fde 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -19,6 +19,7 @@ add_llvm_target(MipsCodeGen MipsSubtarget.cpp MipsTargetAsmInfo.cpp MipsTargetMachine.cpp + MipsTargetObjectFile.cpp ) target_link_libraries (LLVMMipsCodeGen LLVMSelectionDAG) diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 2b7cee8d7a9..710bc945ef2 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -13,10 +13,10 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "mips-lower" - #include "MipsISelLowering.h" #include "MipsMachineFunction.h" #include "MipsTargetMachine.h" +#include "MipsTargetObjectFile.h" #include "MipsSubtarget.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" @@ -30,7 +30,6 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/ValueTypes.h" -#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm; @@ -54,7 +53,7 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { MipsTargetLowering:: MipsTargetLowering(MipsTargetMachine &TM) - : TargetLowering(TM, new TargetLoweringObjectFileELF()) { + : TargetLowering(TM, new MipsTargetObjectFile()) { Subtarget = &TM.getSubtarget(); // Mips does not have i1 type, so use i32 for @@ -210,37 +209,6 @@ AddLiveIn(MachineFunction &MF, unsigned PReg, TargetRegisterClass *RC) return VReg; } -// A address must be loaded from a small section if its size is less than the -// small section size threshold. Data in this section must be addressed using -// gp_rel operator. -bool MipsTargetLowering::IsInSmallSection(unsigned Size) { - return (Size > 0 && (Size <= Subtarget->getSSectionThreshold())); -} - -// Discover if this global address can be placed into small data/bss section. -bool MipsTargetLowering::IsGlobalInSmallSection(GlobalValue *GV) -{ - const TargetData *TD = getTargetData(); - const GlobalVariable *GVA = dyn_cast(GV); - - if (!GVA) - return false; - - const Type *Ty = GV->getType()->getElementType(); - unsigned Size = TD->getTypeAllocSize(Ty); - - // if this is a internal constant string, there is a special - // section for it, but not in small data/bss. - if (GVA->hasInitializer() && GV->hasLocalLinkage()) { - Constant *C = GVA->getInitializer(); - const ConstantArray *CVA = dyn_cast(C); - if (CVA && CVA->isCString()) - return false; - } - - return IsInSmallSection(Size); -} - // Get fp branch code (not opcode) from condition code. static Mips::FPBranchCode GetFPBranchCodeFromCond(Mips::CondCode CC) { if (CC >= Mips::FCOND_F && CC <= Mips::FCOND_NGT) @@ -525,8 +493,10 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) { if (getTargetMachine().getRelocationModel() != Reloc::PIC_) { SDVTList VTs = DAG.getVTList(MVT::i32); + MipsTargetObjectFile &TLOF = (MipsTargetObjectFile&)getObjFileLowering(); + // %gp_rel relocation - if (!isa(GV) && IsGlobalInSmallSection(GV)) { + if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) { SDValue GPRelNode = DAG.getNode(MipsISD::GPRel, dl, VTs, &GA, 1); SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32); return DAG.getNode(ISD::ADD, dl, MVT::i32, GOT, GPRelNode); diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index ec2124325b7..c30d57e4ade 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -88,8 +88,6 @@ namespace llvm { // Subtarget Info const MipsSubtarget *Subtarget; - bool IsGlobalInSmallSection(GlobalValue *GV); - bool IsInSmallSection(unsigned Size); // Lower Operand helpers SDValue LowerCallResult(SDValue Chain, SDValue InFlag, diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index 956fe917549..db114da00d7 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -14,14 +14,8 @@ #include "MipsSubtarget.h" #include "Mips.h" #include "MipsGenSubtarget.inc" -#include "llvm/Support/CommandLine.h" using namespace llvm; -static cl::opt -SSThreshold("mips-ssection-threshold", cl::Hidden, - cl::desc("Small data and bss section threshold size (default=8)"), - cl::init(8)); - MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &FS, bool little) : MipsArchVersion(Mips1), MipsABI(O32), IsLittle(little), IsSingleFloat(false), @@ -35,9 +29,6 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &FS, // Parse features string. ParseSubtargetFeatures(FS, CPU); - // Small section size threshold - SSectionThreshold = SSThreshold; - // Is the target system Linux ? if (TT.find("linux") == std::string::npos) IsLinux = false; diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index a254b6562c4..1d6f87d8c06 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -60,10 +60,6 @@ protected: // isLinux - Target system is Linux. Is false we consider ELFOS for now. bool IsLinux; - // Put global and static items less than or equal to SSectionThreshold - // bytes into the small data or bss section. The default is 8. - unsigned SSectionThreshold; - /// Features related to the presence of specific instructions. // HasSEInReg - SEB and SEH (signext in register) instructions. @@ -113,7 +109,6 @@ public: bool isNotSingleFloat() const { return !IsSingleFloat; }; bool hasVFPU() const { return HasVFPU; }; bool isLinux() const { return IsLinux; }; - unsigned getSSectionThreshold() const { return SSectionThreshold; } /// Features related to the presence of specific instructions. bool hasSEInReg() const { return HasSEInReg; }; diff --git a/lib/Target/Mips/MipsTargetObjectFile.cpp b/lib/Target/Mips/MipsTargetObjectFile.cpp new file mode 100644 index 00000000000..85e9d65a32b --- /dev/null +++ b/lib/Target/Mips/MipsTargetObjectFile.cpp @@ -0,0 +1,93 @@ +//===-- MipsTargetObjectFile.cpp - Mips object files ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MipsTargetObjectFile.h" +#include "llvm/DerivedTypes.h" +#include "llvm/GlobalVariable.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/CommandLine.h" +using namespace llvm; + +static cl::opt +SSThreshold("mips-ssection-threshold", cl::Hidden, + cl::desc("Small data and bss section threshold size (default=8)"), + cl::init(8)); + +void MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ + TargetLoweringObjectFileELF::Initialize(Ctx, TM); + + SmallDataSection = + getELFSection(".sdata", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getDataRel()); + + SmallBSSSection = + getELFSection(".sbss", MCSectionELF::SHT_NOBITS, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getBSS()); + +} + +// A address must be loaded from a small section if its size is less than the +// small section size threshold. Data in this section must be addressed using +// gp_rel operator. +static bool IsInSmallSection(uint64_t Size) { + return Size > 0 && Size <= SSThreshold; +} + +bool MipsTargetObjectFile::IsGlobalInSmallSection(const GlobalValue *GV, + const TargetMachine &TM) const { + if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) + return false; + + return IsGlobalInSmallSection(GV, TM, getKindForGlobal(GV, TM)); +} + +/// IsGlobalInSmallSection - Return true if this global address should be +/// placed into small data/bss section. +bool MipsTargetObjectFile:: +IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, + SectionKind Kind) const { + // Only global variables, not functions. + const GlobalVariable *GVA = dyn_cast(GV); + if (!GVA) + return false; + + // We can only do this for datarel or BSS objects for now. + if (!Kind.isBSS() && !Kind.isDataRel()) + return false; + + // If this is a internal constant string, there is a special + // section for it, but not in small data/bss. + if (Kind.isMergeable1ByteCString()) + return false; + + const Type *Ty = GV->getType()->getElementType(); + return IsInSmallSection(TM.getTargetData()->getTypeAllocSize(Ty)); +} + + + +const MCSection *MipsTargetObjectFile:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + // TODO: Could also support "weak" symbols as well with ".gnu.linkonce.s.*" + // sections? + + // Handle Small Section classification here. + if (Kind.isBSS() && IsGlobalInSmallSection(GV, TM, Kind)) + return SmallBSSSection; + if (Kind.isDataNoRel() && IsGlobalInSmallSection(GV, TM, Kind)) + return SmallDataSection; + + // Otherwise, we work the same as ELF. + return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind, Mang,TM); +} diff --git a/lib/Target/Mips/MipsTargetObjectFile.h b/lib/Target/Mips/MipsTargetObjectFile.h new file mode 100644 index 00000000000..32e0436f0c9 --- /dev/null +++ b/lib/Target/Mips/MipsTargetObjectFile.h @@ -0,0 +1,41 @@ +//===-- llvm/Target/MipsTargetObjectFile.h - Mips Object Info ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_MIPS_TARGETOBJECTFILE_H +#define LLVM_TARGET_MIPS_TARGETOBJECTFILE_H + +#include "llvm/Target/TargetLoweringObjectFile.h" + +namespace llvm { + + class MipsTargetObjectFile : public TargetLoweringObjectFileELF { + const MCSection *SmallDataSection; + const MCSection *SmallBSSSection; + public: + + void Initialize(MCContext &Ctx, const TargetMachine &TM); + + + /// IsGlobalInSmallSection - Return true if this global address should be + /// placed into small data/bss section. + bool IsGlobalInSmallSection(const GlobalValue *GV, + const TargetMachine &TM, SectionKind Kind)const; + bool IsGlobalInSmallSection(const GlobalValue *GV, + const TargetMachine &TM) const; + + const MCSection *SelectSectionForGlobal(const GlobalValue *GV, + SectionKind Kind, + Mangler *Mang, + const TargetMachine &TM) const; + + // TODO: Classify globals as mips wishes. + }; +} // end namespace llvm + +#endif diff --git a/test/CodeGen/Mips/2008-07-15-SmallSection.ll b/test/CodeGen/Mips/2008-07-15-SmallSection.ll new file mode 100644 index 00000000000..0e3f8647953 --- /dev/null +++ b/test/CodeGen/Mips/2008-07-15-SmallSection.ll @@ -0,0 +1,32 @@ +; RUN: llvm-as < %s | llc -mips-ssection-threshold=8 -march=mips -f -o %t0 +; RUN: llvm-as < %s | llc -mips-ssection-threshold=0 -march=mips -f -o %t1 +; RUN: grep {sdata} %t0 | count 1 +; RUN: grep {sbss} %t0 | count 1 +; RUN: grep {gp_rel} %t0 | count 2 +; RUN: not grep {sdata} %t1 +; RUN: not grep {sbss} %t1 +; RUN: not grep {gp_rel} %t1 +; RUN: grep {\%hi} %t1 | count 2 +; RUN: grep {\%lo} %t1 | count 2 + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64" +target triple = "mipsallegrexel-psp-elf" + + %struct.anon = type { i32, i32 } +@s0 = global [8 x i8] c"AAAAAAA\00", align 4 +@foo = global %struct.anon { i32 2, i32 3 } +@bar = global %struct.anon zeroinitializer + +define i8* @A0() nounwind { +entry: + ret i8* getelementptr ([8 x i8]* @s0, i32 0, i32 0) +} + +define i32 @A1() nounwind { +entry: + load i32* getelementptr (%struct.anon* @foo, i32 0, i32 0), align 8 + load i32* getelementptr (%struct.anon* @foo, i32 0, i32 1), align 4 + add i32 %1, %0 + ret i32 %2 +} +