diff options
Diffstat (limited to 'lib/Target/XCore')
-rw-r--r-- | lib/Target/XCore/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Target/XCore/Disassembler/XCoreDisassembler.cpp | 15 | ||||
-rw-r--r-- | lib/Target/XCore/InstPrinter/XCoreInstPrinter.cpp | 11 | ||||
-rw-r--r-- | lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp | 2 | ||||
-rw-r--r-- | lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h | 2 | ||||
-rw-r--r-- | lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp | 13 | ||||
-rw-r--r-- | lib/Target/XCore/XCore.h | 4 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreAsmPrinter.cpp | 15 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreFrameLowering.cpp | 89 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreISelDAGToDAG.cpp | 56 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreISelLowering.cpp | 256 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreISelLowering.h | 13 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreInstrInfo.cpp | 2 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreInstrInfo.td | 83 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreLowerThreadLocal.cpp | 145 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreRegisterInfo.cpp | 6 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreRegisterInfo.h | 4 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreTargetMachine.cpp | 7 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreTargetObjectFile.cpp | 5 |
19 files changed, 375 insertions, 354 deletions
diff --git a/lib/Target/XCore/CMakeLists.txt b/lib/Target/XCore/CMakeLists.txt index 099ad39..d5bfddc 100644 --- a/lib/Target/XCore/CMakeLists.txt +++ b/lib/Target/XCore/CMakeLists.txt @@ -15,6 +15,7 @@ add_llvm_target(XCoreCodeGen XCoreInstrInfo.cpp XCoreISelDAGToDAG.cpp XCoreISelLowering.cpp + XCoreLowerThreadLocal.cpp XCoreMachineFunctionInfo.cpp XCoreMCInstLower.cpp XCoreRegisterInfo.cpp diff --git a/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp b/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp index 7b99967..dcc0955 100644 --- a/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp +++ b/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp @@ -53,7 +53,7 @@ static bool readInstruction16(const MemoryObject ®ion, uint8_t Bytes[4]; // We want to read exactly 2 Bytes of data. - if (region.readBytes(address, 2, Bytes, NULL) == -1) { + if (region.readBytes(address, 2, Bytes) == -1) { size = 0; return false; } @@ -69,7 +69,7 @@ static bool readInstruction32(const MemoryObject ®ion, uint8_t Bytes[4]; // We want to read exactly 4 Bytes of data. - if (region.readBytes(address, 4, Bytes, NULL) == -1) { + if (region.readBytes(address, 4, Bytes) == -1) { size = 0; return false; } @@ -97,8 +97,8 @@ static DecodeStatus DecodeRRegsRegisterClass(MCInst &Inst, static DecodeStatus DecodeBitpOperand(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder); -static DecodeStatus DecodeMEMiiOperand(MCInst &Inst, unsigned Val, - uint64_t Address, const void *Decoder); +static DecodeStatus DecodeNegImmOperand(MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); static DecodeStatus Decode2RInstruction(MCInst &Inst, unsigned Insn, @@ -242,10 +242,9 @@ static DecodeStatus DecodeBitpOperand(MCInst &Inst, unsigned Val, return MCDisassembler::Success; } -static DecodeStatus DecodeMEMiiOperand(MCInst &Inst, unsigned Val, - uint64_t Address, const void *Decoder) { - Inst.addOperand(MCOperand::CreateImm(Val)); - Inst.addOperand(MCOperand::CreateImm(0)); +static DecodeStatus DecodeNegImmOperand(MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(-(int64_t)Val)); return MCDisassembler::Success; } diff --git a/lib/Target/XCore/InstPrinter/XCoreInstPrinter.cpp b/lib/Target/XCore/InstPrinter/XCoreInstPrinter.cpp index 1592351..9ae8c0d 100644 --- a/lib/Target/XCore/InstPrinter/XCoreInstPrinter.cpp +++ b/lib/Target/XCore/InstPrinter/XCoreInstPrinter.cpp @@ -84,14 +84,3 @@ printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { assert(Op.isExpr() && "unknown operand kind in printOperand"); printExpr(Op.getExpr(), O); } - -void XCoreInstPrinter:: -printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) { - printOperand(MI, opNum, O); - - if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0) - return; - - O << "+"; - printOperand(MI, opNum+1, O); -} diff --git a/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp index 1cfdbda..6f44551 100644 --- a/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp +++ b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp @@ -13,7 +13,7 @@ using namespace llvm; void XCoreMCAsmInfo::anchor() { } -XCoreMCAsmInfo::XCoreMCAsmInfo(const Target &T, StringRef TT) { +XCoreMCAsmInfo::XCoreMCAsmInfo(StringRef TT) { SupportsDebugInformation = true; Data16bitsDirective = "\t.short\t"; Data32bitsDirective = "\t.long\t"; diff --git a/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h index 0767775..b5a9660 100644 --- a/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h +++ b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h @@ -23,7 +23,7 @@ namespace llvm { class XCoreMCAsmInfo : public MCAsmInfo { virtual void anchor(); public: - explicit XCoreMCAsmInfo(const Target &T, StringRef TT); + explicit XCoreMCAsmInfo(StringRef TT); }; } // namespace llvm diff --git a/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp b/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp index b5b072d..10bb6df 100644 --- a/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp +++ b/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp @@ -51,13 +51,13 @@ static MCSubtargetInfo *createXCoreMCSubtargetInfo(StringRef TT, StringRef CPU, return X; } -static MCAsmInfo *createXCoreMCAsmInfo(const Target &T, StringRef TT) { - MCAsmInfo *MAI = new XCoreMCAsmInfo(T, TT); +static MCAsmInfo *createXCoreMCAsmInfo(const MCRegisterInfo &MRI, + StringRef TT) { + MCAsmInfo *MAI = new XCoreMCAsmInfo(TT); // Initial state of the frame pointer is SP. - MachineLocation Dst(MachineLocation::VirtualFP); - MachineLocation Src(XCore::SP, 0); - MAI->addInitialFrameState(0, Dst, Src); + MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(0, XCore::SP, 0); + MAI->addInitialFrameState(Inst); return MAI; } @@ -66,6 +66,9 @@ static MCCodeGenInfo *createXCoreMCCodeGenInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL) { MCCodeGenInfo *X = new MCCodeGenInfo(); + if (RM == Reloc::Default) { + RM = Reloc::Static; + } X->InitMCCodeGenInfo(RM, CM, OL); return X; } diff --git a/lib/Target/XCore/XCore.h b/lib/Target/XCore/XCore.h index 08f091e..2f375fc 100644 --- a/lib/Target/XCore/XCore.h +++ b/lib/Target/XCore/XCore.h @@ -20,12 +20,16 @@ namespace llvm { class FunctionPass; + class ModulePass; class TargetMachine; class XCoreTargetMachine; class formatted_raw_ostream; + void initializeXCoreLowerThreadLocalPass(PassRegistry &p); + FunctionPass *createXCoreISelDag(XCoreTargetMachine &TM, CodeGenOpt::Level OptLevel); + ModulePass *createXCoreLowerThreadLocalPass(); } // end namespace llvm; diff --git a/lib/Target/XCore/XCoreAsmPrinter.cpp b/lib/Target/XCore/XCoreAsmPrinter.cpp index 0d146ba..e177ad3 100644 --- a/lib/Target/XCore/XCoreAsmPrinter.cpp +++ b/lib/Target/XCore/XCoreAsmPrinter.cpp @@ -36,7 +36,6 @@ #include "llvm/MC/MCInst.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" @@ -46,12 +45,6 @@ #include <cctype> using namespace llvm; -static cl::opt<unsigned> MaxThreads("xcore-max-threads", cl::Optional, - cl::desc("Maximum number of threads (for emulation thread-local storage)"), - cl::Hidden, - cl::value_desc("number"), - cl::init(8)); - namespace { class XCoreAsmPrinter : public AsmPrinter { const XCoreSubtarget &Subtarget; @@ -152,10 +145,10 @@ void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { EmitAlignment(Align > 2 ? Align : 2, GV); - unsigned Size = TD->getTypeAllocSize(C->getType()); if (GV->isThreadLocal()) { - Size *= MaxThreads; + report_fatal_error("TLS is not supported by this target!"); } + unsigned Size = TD->getTypeAllocSize(C->getType()); if (MAI->hasDotTypeDotSizeDirective()) { OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject); OutStreamer.EmitRawText("\t.size " + Twine(GVSym->getName()) + "," + @@ -164,10 +157,6 @@ void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { OutStreamer.EmitLabel(GVSym); EmitGlobalConstant(C); - if (GV->isThreadLocal()) { - for (unsigned i = 1; i < MaxThreads; ++i) - EmitGlobalConstant(C); - } // The ABI requires that unsigned scalar types smaller than 32 bits // are padded to 32 bits. if (Size < 4) diff --git a/lib/Target/XCore/XCoreFrameLowering.cpp b/lib/Target/XCore/XCoreFrameLowering.cpp index beeb07f..736a4ef 100644 --- a/lib/Target/XCore/XCoreFrameLowering.cpp +++ b/lib/Target/XCore/XCoreFrameLowering.cpp @@ -116,50 +116,34 @@ void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const { } bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(MF); + bool saveLR = XFI->getUsesLR(); // Do we need to allocate space on the stack? if (FrameSize) { - bool saveLR = XFI->getUsesLR(); - bool LRSavedOnEntry = false; int Opcode; if (saveLR && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0)) { Opcode = (isU6) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6; MBB.addLiveIn(XCore::LR); saveLR = false; - LRSavedOnEntry = true; } else { Opcode = (isU6) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6; } BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize); if (emitFrameMoves) { - std::vector<MachineMove> &Moves = MMI->getFrameMoves(); // Show update of SP. MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel); - - MachineLocation SPDst(MachineLocation::VirtualFP); - MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize * 4); - Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc)); - - if (LRSavedOnEntry) { - MachineLocation CSDst(MachineLocation::VirtualFP, 0); - MachineLocation CSSrc(XCore::LR); - Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc)); - } } - if (saveLR) { - int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot()); - storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4, dl, TII); - MBB.addLiveIn(XCore::LR); + } + if (saveLR) { + int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot()); + storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4, dl, TII); + MBB.addLiveIn(XCore::LR); - if (emitFrameMoves) { - MCSymbol *SaveLRLabel = MMI->getContext().CreateTempSymbol(); - BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLRLabel); - MachineLocation CSDst(MachineLocation::VirtualFP, LRSpillOffset); - MachineLocation CSSrc(XCore::LR); - MMI->getFrameMoves().push_back(MachineMove(SaveLRLabel, CSDst, CSSrc)); - } + if (emitFrameMoves) { + MCSymbol *SaveLRLabel = MMI->getContext().CreateTempSymbol(); + BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLRLabel); } } @@ -172,9 +156,6 @@ void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const { if (emitFrameMoves) { MCSymbol *SaveR10Label = MMI->getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveR10Label); - MachineLocation CSDst(MachineLocation::VirtualFP, FPSpillOffset); - MachineLocation CSSrc(XCore::R10); - MMI->getFrameMoves().push_back(MachineMove(SaveR10Label, CSDst, CSSrc)); } // Set the FP from the SP. unsigned FramePtr = XCore::R10; @@ -184,25 +165,6 @@ void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const { // Show FP is now valid. MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel); - MachineLocation SPDst(FramePtr); - MachineLocation SPSrc(MachineLocation::VirtualFP); - MMI->getFrameMoves().push_back(MachineMove(FrameLabel, SPDst, SPSrc)); - } - } - - if (emitFrameMoves) { - // Frame moves for callee saved. - std::vector<MachineMove> &Moves = MMI->getFrameMoves(); - std::vector<std::pair<MCSymbol*, CalleeSavedInfo> >&SpillLabels = - XFI->getSpillLabels(); - for (unsigned I = 0, E = SpillLabels.size(); I != E; ++I) { - MCSymbol *SpillLabel = SpillLabels[I].first; - CalleeSavedInfo &CSI = SpillLabels[I].second; - int Offset = MFI->getObjectOffset(CSI.getFrameIdx()); - unsigned Reg = CSI.getReg(); - MachineLocation CSDst(MachineLocation::VirtualFP, Offset); - MachineLocation CSSrc(Reg); - Moves.push_back(MachineMove(SpillLabel, CSDst, CSSrc)); } } } @@ -213,6 +175,7 @@ void XCoreFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); const XCoreInstrInfo &TII = *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo()); + XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); DebugLoc dl = MBBI->getDebugLoc(); bool FP = hasFP(MF); @@ -237,24 +200,26 @@ void XCoreFrameLowering::emitEpilogue(MachineFunction &MF, report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize)); } - if (FrameSize) { - XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); + if (FP) { + // Restore R10 + int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot()); + FPSpillOffset += FrameSize*4; + loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl, TII); + } - if (FP) { - // Restore R10 - int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot()); - FPSpillOffset += FrameSize*4; - loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl, TII); - } - bool restoreLR = XFI->getUsesLR(); - if (restoreLR && MFI->getObjectOffset(XFI->getLRSpillSlot()) != 0) { - int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot()); - LRSpillOffset += FrameSize*4; - loadFromStack(MBB, MBBI, XCore::LR, LRSpillOffset, dl, TII); - restoreLR = false; - } + bool restoreLR = XFI->getUsesLR(); + if (restoreLR && + (FrameSize == 0 || MFI->getObjectOffset(XFI->getLRSpillSlot()) != 0)) { + int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot()); + LRSpillOffset += FrameSize*4; + loadFromStack(MBB, MBBI, XCore::LR, LRSpillOffset, dl, TII); + restoreLR = false; + } + + if (FrameSize) { if (restoreLR) { // Fold prologue into return instruction + assert(MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0); assert(MBBI->getOpcode() == XCore::RETSP_u6 || MBBI->getOpcode() == XCore::RETSP_lu6); int Opcode = (isU6) ? XCore::RETSP_u6 : XCore::RETSP_lu6; diff --git a/lib/Target/XCore/XCoreISelDAGToDAG.cpp b/lib/Target/XCore/XCoreISelDAGToDAG.cpp index d16811c..ee183aa 100644 --- a/lib/Target/XCore/XCoreISelDAGToDAG.cpp +++ b/lib/Target/XCore/XCoreISelDAGToDAG.cpp @@ -61,15 +61,13 @@ namespace { if (!isMask_32(value)) { return false; } - int msksize = 32 - CountLeadingZeros_32(value); + int msksize = 32 - countLeadingZeros(value); return (msksize >= 1 && msksize <= 8) || msksize == 16 || msksize == 24 || msksize == 32; } // Complex Pattern Selectors. bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset); - bool SelectADDRdpii(SDValue Addr, SDValue &Base, SDValue &Offset); - bool SelectADDRcpii(SDValue Addr, SDValue &Base, SDValue &Offset); virtual const char *getPassName() const { return "XCore DAG->DAG Pattern Instruction Selection"; @@ -110,50 +108,8 @@ bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base, return false; } -bool XCoreDAGToDAGISel::SelectADDRdpii(SDValue Addr, SDValue &Base, - SDValue &Offset) { - if (Addr.getOpcode() == XCoreISD::DPRelativeWrapper) { - Base = Addr.getOperand(0); - Offset = CurDAG->getTargetConstant(0, MVT::i32); - return true; - } - if (Addr.getOpcode() == ISD::ADD) { - ConstantSDNode *CN = 0; - if ((Addr.getOperand(0).getOpcode() == XCoreISD::DPRelativeWrapper) - && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) - && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) { - // Constant word offset from a object in the data region - Base = Addr.getOperand(0).getOperand(0); - Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); - return true; - } - } - return false; -} - -bool XCoreDAGToDAGISel::SelectADDRcpii(SDValue Addr, SDValue &Base, - SDValue &Offset) { - if (Addr.getOpcode() == XCoreISD::CPRelativeWrapper) { - Base = Addr.getOperand(0); - Offset = CurDAG->getTargetConstant(0, MVT::i32); - return true; - } - if (Addr.getOpcode() == ISD::ADD) { - ConstantSDNode *CN = 0; - if ((Addr.getOperand(0).getOpcode() == XCoreISD::CPRelativeWrapper) - && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) - && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) { - // Constant word offset from a object in the data region - Base = Addr.getOperand(0).getOperand(0); - Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); - return true; - } - } - return false; -} - SDNode *XCoreDAGToDAGISel::Select(SDNode *N) { - DebugLoc dl = N->getDebugLoc(); + SDLoc dl(N); switch (N->getOpcode()) { default: break; case ISD::Constant: { @@ -161,7 +117,7 @@ SDNode *XCoreDAGToDAGISel::Select(SDNode *N) { if (immMskBitp(N)) { // Transformation function: get the size of a mask // Look for the first non-zero bit - SDValue MskSize = getI32Imm(32 - CountLeadingZeros_32(Val)); + SDValue MskSize = getI32Imm(32 - countLeadingZeros(Val)); return CurDAG->getMachineNode(XCore::MKMSK_rus, dl, MVT::i32, MskSize); } @@ -169,7 +125,7 @@ SDNode *XCoreDAGToDAGISel::Select(SDNode *N) { SDValue CPIdx = CurDAG->getTargetConstantPool(ConstantInt::get( Type::getInt32Ty(*CurDAG->getContext()), Val), - TLI.getPointerTy()); + TLI->getPointerTy()); SDNode *node = CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32, MVT::Other, CPIdx, CurDAG->getEntryNode()); @@ -248,12 +204,12 @@ replaceInChain(SelectionDAG *CurDAG, SDValue Chain, SDValue Old, SDValue New) } if (!found) return SDValue(); - return CurDAG->getNode(ISD::TokenFactor, Chain->getDebugLoc(), MVT::Other, + return CurDAG->getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, &Ops[0], Ops.size()); } SDNode *XCoreDAGToDAGISel::SelectBRIND(SDNode *N) { - DebugLoc dl = N->getDebugLoc(); + SDLoc dl(N); // (brind (int_xcore_checkevent (addr))) SDValue Chain = N->getOperand(0); SDValue Addr = N->getOperand(1); diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index a5d2be8..7b89b1a 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -36,6 +36,8 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> + using namespace llvm; const char *XCoreTargetLowering:: @@ -120,9 +122,6 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); setOperationAction(ISD::BlockAddress, MVT::i32 , Custom); - // Thread Local Storage - setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); - // Conversion of i64 -> double produces constantpool nodes setOperationAction(ISD::ConstantPool, MVT::i32, Custom); @@ -172,7 +171,6 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); - case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); case ISD::ConstantPool: return LowerConstantPool(Op, DAG); case ISD::BR_JT: return LowerBR_JT(Op, DAG); @@ -217,7 +215,7 @@ void XCoreTargetLowering::ReplaceNodeResults(SDNode *N, SDValue XCoreTargetLowering:: LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { - DebugLoc dl = Op.getDebugLoc(); + SDLoc dl(Op); SDValue Cond = DAG.getNode(ISD::SETCC, dl, MVT::i32, Op.getOperand(2), Op.getOperand(3), Op.getOperand(4)); return DAG.getNode(ISD::SELECT, dl, MVT::i32, Cond, Op.getOperand(0), @@ -229,7 +227,7 @@ getGlobalAddressWrapper(SDValue GA, const GlobalValue *GV, SelectionDAG &DAG) const { // FIXME there is no actual debug info here - DebugLoc dl = GA.getDebugLoc(); + SDLoc dl(GA); const GlobalValue *UnderlyingGV = GV; // If GV is an alias then use the aliasee to determine the wrapper type if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) @@ -245,58 +243,31 @@ getGlobalAddressWrapper(SDValue GA, const GlobalValue *GV, SDValue XCoreTargetLowering:: LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { - const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); - SDValue GA = DAG.getTargetGlobalAddress(GV, Op.getDebugLoc(), MVT::i32); - return getGlobalAddressWrapper(GA, GV, DAG); + SDLoc DL(Op); + const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op); + const GlobalValue *GV = GN->getGlobal(); + 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); + } + return GA; } -static inline SDValue BuildGetId(SelectionDAG &DAG, DebugLoc dl) { +static inline SDValue BuildGetId(SelectionDAG &DAG, SDLoc dl) { return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, DAG.getConstant(Intrinsic::xcore_getid, MVT::i32)); } -static inline bool isZeroLengthArray(Type *Ty) { - ArrayType *AT = dyn_cast_or_null<ArrayType>(Ty); - return AT && (AT->getNumElements() == 0); -} - -SDValue XCoreTargetLowering:: -LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const -{ - // FIXME there isn't really debug info here - DebugLoc dl = Op.getDebugLoc(); - // transform to label + getid() * size - const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); - SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32); - const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); - if (!GVar) { - // If GV is an alias then use the aliasee to determine size - if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) - GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal()); - } - if (!GVar) { - llvm_unreachable("Thread local object not a GlobalVariable?"); - } - Type *Ty = cast<PointerType>(GV->getType())->getElementType(); - if (!Ty->isSized() || isZeroLengthArray(Ty)) { -#ifndef NDEBUG - errs() << "Size of thread local object " << GVar->getName() - << " is unknown\n"; -#endif - llvm_unreachable(0); - } - SDValue base = getGlobalAddressWrapper(GA, GV, DAG); - const DataLayout *TD = TM.getDataLayout(); - unsigned Size = TD->getTypeAllocSize(Ty); - SDValue offset = DAG.getNode(ISD::MUL, dl, MVT::i32, BuildGetId(DAG, dl), - DAG.getConstant(Size, MVT::i32)); - return DAG.getNode(ISD::ADD, dl, MVT::i32, base, offset); -} - SDValue XCoreTargetLowering:: LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const { - DebugLoc DL = Op.getDebugLoc(); + SDLoc DL(Op); const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); SDValue Result = DAG.getTargetBlockAddress(BA, getPointerTy()); @@ -309,7 +280,7 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) const { ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); // FIXME there isn't really debug info here - DebugLoc dl = CP->getDebugLoc(); + SDLoc dl(CP); EVT PtrVT = Op.getValueType(); SDValue Res; if (CP->isMachineConstantPoolEntry()) { @@ -332,7 +303,7 @@ LowerBR_JT(SDValue Op, SelectionDAG &DAG) const SDValue Chain = Op.getOperand(0); SDValue Table = Op.getOperand(1); SDValue Index = Op.getOperand(2); - DebugLoc dl = Op.getDebugLoc(); + SDLoc dl(Op); JumpTableSDNode *JT = cast<JumpTableSDNode>(Table); unsigned JTI = JT->getIndex(); MachineFunction &MF = DAG.getMachineFunction(); @@ -350,55 +321,58 @@ LowerBR_JT(SDValue Op, SelectionDAG &DAG) const ScaledIndex); } -static bool -IsWordAlignedBasePlusConstantOffset(SDValue Addr, SDValue &AlignedBase, - int64_t &Offset) +SDValue XCoreTargetLowering:: +lowerLoadWordFromAlignedBasePlusOffset(SDLoc DL, SDValue Chain, SDValue Base, + int64_t Offset, SelectionDAG &DAG) const { - if (Addr.getOpcode() != ISD::ADD) { - return false; + if ((Offset & 0x3) == 0) { + return DAG.getLoad(getPointerTy(), DL, Chain, Base, MachinePointerInfo(), + false, false, false, 0); } - ConstantSDNode *CN = 0; - if (!(CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) { - return false; - } - int64_t off = CN->getSExtValue(); - const SDValue &Base = Addr.getOperand(0); - const SDValue *Root = &Base; - if (Base.getOpcode() == ISD::ADD && - Base.getOperand(1).getOpcode() == ISD::SHL) { - ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Base.getOperand(1) - .getOperand(1)); - if (CN && (CN->getSExtValue() >= 2)) { - Root = &Base.getOperand(0); - } - } - if (isa<FrameIndexSDNode>(*Root)) { - // All frame indicies are word aligned - AlignedBase = Base; - Offset = off; - return true; - } - if (Root->getOpcode() == XCoreISD::DPRelativeWrapper || - Root->getOpcode() == XCoreISD::CPRelativeWrapper) { - // All dp / cp relative addresses are word aligned - AlignedBase = Base; - Offset = off; - return true; - } - // Check for an aligned global variable. - if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(*Root)) { - const GlobalValue *GV = GA->getGlobal(); - if (GA->getOffset() == 0 && GV->getAlignment() >= 4) { - AlignedBase = Base; - Offset = off; - return true; - } + // Lower to pair of consecutive word aligned loads plus some bit shifting. + int32_t HighOffset = RoundUpToAlignment(Offset, 4); + int32_t LowOffset = HighOffset - 4; + SDValue LowAddr, HighAddr; + if (GlobalAddressSDNode *GASD = + dyn_cast<GlobalAddressSDNode>(Base.getNode())) { + LowAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(), + LowOffset); + HighAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(), + HighOffset); + } else { + LowAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, + DAG.getConstant(LowOffset, MVT::i32)); + HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, + DAG.getConstant(HighOffset, MVT::i32)); } - return false; + SDValue LowShift = DAG.getConstant((Offset - LowOffset) * 8, MVT::i32); + SDValue HighShift = DAG.getConstant((HighOffset - Offset) * 8, MVT::i32); + + SDValue Low = DAG.getLoad(getPointerTy(), DL, Chain, + LowAddr, MachinePointerInfo(), + false, false, false, 0); + SDValue High = DAG.getLoad(getPointerTy(), DL, Chain, + HighAddr, MachinePointerInfo(), + false, false, false, 0); + SDValue LowShifted = DAG.getNode(ISD::SRL, DL, MVT::i32, Low, LowShift); + SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, HighShift); + SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, LowShifted, HighShifted); + Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1), + High.getValue(1)); + SDValue Ops[] = { Result, Chain }; + return DAG.getMergeValues(Ops, 2, DL); +} + +static bool isWordAligned(SDValue Value, SelectionDAG &DAG) +{ + APInt KnownZero, KnownOne; + DAG.ComputeMaskedBits(Value, KnownZero, KnownOne); + return KnownZero.countTrailingOnes() >= 2; } SDValue XCoreTargetLowering:: LowerLOAD(SDValue Op, SelectionDAG &DAG) const { + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); LoadSDNode *LD = cast<LoadSDNode>(Op); assert(LD->getExtensionType() == ISD::NON_EXTLOAD && "Unexpected extension type"); @@ -414,47 +388,25 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) const { SDValue Chain = LD->getChain(); SDValue BasePtr = LD->getBasePtr(); - DebugLoc DL = Op.getDebugLoc(); - - SDValue Base; - int64_t Offset; - if (!LD->isVolatile() && - IsWordAlignedBasePlusConstantOffset(BasePtr, Base, Offset)) { - if (Offset % 4 == 0) { - // We've managed to infer better alignment information than the load - // already has. Use an aligned load. - // - return DAG.getLoad(getPointerTy(), DL, Chain, BasePtr, - MachinePointerInfo(), - false, false, false, 0); + SDLoc DL(Op); + + if (!LD->isVolatile()) { + const GlobalValue *GV; + int64_t Offset = 0; + if (DAG.isBaseWithConstantOffset(BasePtr) && + isWordAligned(BasePtr->getOperand(0), DAG)) { + SDValue NewBasePtr = BasePtr->getOperand(0); + Offset = cast<ConstantSDNode>(BasePtr->getOperand(1))->getSExtValue(); + return lowerLoadWordFromAlignedBasePlusOffset(DL, Chain, NewBasePtr, + Offset, DAG); + } + if (TLI.isGAPlusOffset(BasePtr.getNode(), GV, Offset) && + MinAlign(GV->getAlignment(), 4) == 4) { + SDValue NewBasePtr = DAG.getGlobalAddress(GV, DL, + BasePtr->getValueType(0)); + return lowerLoadWordFromAlignedBasePlusOffset(DL, Chain, NewBasePtr, + Offset, DAG); } - // Lower to - // ldw low, base[offset >> 2] - // ldw high, base[(offset >> 2) + 1] - // shr low_shifted, low, (offset & 0x3) * 8 - // shl high_shifted, high, 32 - (offset & 0x3) * 8 - // or result, low_shifted, high_shifted - SDValue LowOffset = DAG.getConstant(Offset & ~0x3, MVT::i32); - SDValue HighOffset = DAG.getConstant((Offset & ~0x3) + 4, MVT::i32); - SDValue LowShift = DAG.getConstant((Offset & 0x3) * 8, MVT::i32); - SDValue HighShift = DAG.getConstant(32 - (Offset & 0x3) * 8, MVT::i32); - - SDValue LowAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, LowOffset); - SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, HighOffset); - - SDValue Low = DAG.getLoad(getPointerTy(), DL, Chain, - LowAddr, MachinePointerInfo(), - false, false, false, 0); - SDValue High = DAG.getLoad(getPointerTy(), DL, Chain, - HighAddr, MachinePointerInfo(), - false, false, false, 0); - SDValue LowShifted = DAG.getNode(ISD::SRL, DL, MVT::i32, Low, LowShift); - SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, HighShift); - SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, LowShifted, HighShifted); - Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1), - High.getValue(1)); - SDValue Ops[] = { Result, Chain }; - return DAG.getMergeValues(Ops, 2, DL); } if (LD->getAlignment() == 2) { @@ -517,7 +469,7 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG) const SDValue Chain = ST->getChain(); SDValue BasePtr = ST->getBasePtr(); SDValue Value = ST->getValue(); - DebugLoc dl = Op.getDebugLoc(); + SDLoc dl(Op); if (ST->getAlignment() == 2) { SDValue Low = Value; @@ -564,7 +516,7 @@ LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const { assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::SMUL_LOHI && "Unexpected operand to lower!"); - DebugLoc dl = Op.getDebugLoc(); + SDLoc dl(Op); SDValue LHS = Op.getOperand(0); SDValue RHS = Op.getOperand(1); SDValue Zero = DAG.getConstant(0, MVT::i32); @@ -581,7 +533,7 @@ LowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) const { assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::UMUL_LOHI && "Unexpected operand to lower!"); - DebugLoc dl = Op.getDebugLoc(); + SDLoc dl(Op); SDValue LHS = Op.getOperand(0); SDValue RHS = Op.getOperand(1); SDValue Zero = DAG.getConstant(0, MVT::i32); @@ -666,7 +618,7 @@ TryExpandADDWithMul(SDNode *N, SelectionDAG &DAG) const } else { return SDValue(); } - DebugLoc dl = N->getDebugLoc(); + SDLoc dl(N); SDValue LL, RL, AddendL, AddendH; LL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Mul.getOperand(0), DAG.getConstant(0, MVT::i32)); @@ -725,7 +677,7 @@ ExpandADDSUB(SDNode *N, SelectionDAG &DAG) const return Result; } - DebugLoc dl = N->getDebugLoc(); + SDLoc dl(N); // Extract components SDValue LHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, @@ -758,7 +710,7 @@ LowerVAARG(SDValue Op, SelectionDAG &DAG) const llvm_unreachable("unimplemented"); // FIXME Arguments passed by reference need a extra dereference. SDNode *Node = Op.getNode(); - DebugLoc dl = Node->getDebugLoc(); + SDLoc dl(Node); const Value *V = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); EVT VT = Node->getValueType(0); SDValue VAList = DAG.getLoad(getPointerTy(), dl, Node->getOperand(0), @@ -779,7 +731,7 @@ LowerVAARG(SDValue Op, SelectionDAG &DAG) const SDValue XCoreTargetLowering:: LowerVASTART(SDValue Op, SelectionDAG &DAG) const { - DebugLoc dl = Op.getDebugLoc(); + SDLoc dl(Op); // vastart stores the address of the VarArgsFrameIndex slot into the // memory location argument MachineFunction &MF = DAG.getMachineFunction(); @@ -791,7 +743,7 @@ LowerVASTART(SDValue Op, SelectionDAG &DAG) const SDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { - DebugLoc dl = Op.getDebugLoc(); + SDLoc dl(Op); // Depths > 0 not supported yet! if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0) return SDValue(); @@ -831,7 +783,7 @@ LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const { SDValue Addr = Trmp; - DebugLoc dl = Op.getDebugLoc(); + SDLoc dl(Op); OutChains[0] = DAG.getStore(Chain, dl, DAG.getConstant(0x0a3cd805, MVT::i32), Addr, MachinePointerInfo(TrmpAddr), false, false, 0); @@ -865,7 +817,7 @@ LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const { SDValue XCoreTargetLowering:: LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const { - DebugLoc DL = Op.getDebugLoc(); + SDLoc DL(Op); unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); switch (IntNo) { case Intrinsic::xcore_crc8: @@ -895,7 +847,7 @@ SDValue XCoreTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const { SelectionDAG &DAG = CLI.DAG; - DebugLoc &dl = CLI.DL; + SDLoc &dl = CLI.DL; SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs; SmallVector<SDValue, 32> &OutVals = CLI.OutVals; SmallVector<ISD::InputArg, 32> &Ins = CLI.Ins; @@ -931,7 +883,7 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, SelectionDAG &DAG, + SDLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { // Analyze operands of the call, assigning locations to each operand. @@ -949,7 +901,7 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, unsigned NumBytes = CCInfo.getNextStackOffset(); Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, - getPointerTy(), true)); + getPointerTy(), true), dl); SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass; SmallVector<SDValue, 12> MemOpChains; @@ -1039,7 +991,7 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, getPointerTy(), true), DAG.getConstant(0, getPointerTy(), true), - InFlag); + InFlag, dl); InFlag = Chain.getValue(1); // Handle result values, copying them out of physregs into vregs that we @@ -1054,7 +1006,7 @@ SDValue XCoreTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, SelectionDAG &DAG, + SDLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { // Assign locations to each value returned by this call. @@ -1085,7 +1037,7 @@ XCoreTargetLowering::LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, + SDLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { @@ -1110,7 +1062,7 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, + SDLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); @@ -1236,7 +1188,7 @@ XCoreTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, - DebugLoc dl, SelectionDAG &DAG) const { + SDLoc dl, SelectionDAG &DAG) const { // CCValAssign - represent the assignment of // the return value to a location @@ -1353,7 +1305,7 @@ XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; - DebugLoc dl = N->getDebugLoc(); + SDLoc dl(N); switch (N->getOpcode()) { default: break; case XCoreISD::LADD: { diff --git a/lib/Target/XCore/XCoreISelLowering.h b/lib/Target/XCore/XCoreISelLowering.h index 8d258f5..f765f02 100644 --- a/lib/Target/XCore/XCoreISelLowering.h +++ b/lib/Target/XCore/XCoreISelLowering.h @@ -115,7 +115,7 @@ namespace llvm { CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, SelectionDAG &DAG, + SDLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const; SDValue LowerCCCCallTo(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg, @@ -123,16 +123,19 @@ namespace llvm { const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, SelectionDAG &DAG, + SDLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const; SDValue LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, SelectionDAG &DAG, + SDLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const; SDValue getReturnAddressFrameIndex(SelectionDAG &DAG) const; SDValue getGlobalAddressWrapper(SDValue GA, const GlobalValue *GV, SelectionDAG &DAG) const; + SDValue lowerLoadWordFromAlignedBasePlusOffset(SDLoc DL, SDValue Chain, + SDValue Base, int64_t Offset, + SelectionDAG &DAG) const; // Lower Operand specifics SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG) const; @@ -174,7 +177,7 @@ namespace llvm { CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, SelectionDAG &DAG, + SDLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const; virtual SDValue @@ -186,7 +189,7 @@ namespace llvm { CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, - DebugLoc dl, SelectionDAG &DAG) const; + SDLoc dl, SelectionDAG &DAG) const; virtual bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, diff --git a/lib/Target/XCore/XCoreInstrInfo.cpp b/lib/Target/XCore/XCoreInstrInfo.cpp index e457e0d..eb7a936 100644 --- a/lib/Target/XCore/XCoreInstrInfo.cpp +++ b/lib/Target/XCore/XCoreInstrInfo.cpp @@ -41,7 +41,7 @@ using namespace llvm; XCoreInstrInfo::XCoreInstrInfo() : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP), - RI(*this) { + RI() { } static bool isZeroImm(const MachineOperand &op) { diff --git a/lib/Target/XCore/XCoreInstrInfo.td b/lib/Target/XCore/XCoreInstrInfo.td index 03653cb..e06419a 100644 --- a/lib/Target/XCore/XCoreInstrInfo.td +++ b/lib/Target/XCore/XCoreInstrInfo.td @@ -84,7 +84,7 @@ def msksize_xform : SDNodeXForm<imm, [{ // Transformation function: get the size of a mask assert(isMask_32(N->getZExtValue())); // look for the first non-zero bit - return getI32Imm(32 - CountLeadingZeros_32(N->getZExtValue())); + return getI32Imm(32 - countLeadingZeros(N->getZExtValue())); }]>; def neg_xform : SDNodeXForm<imm, [{ @@ -168,21 +168,20 @@ def ldawb : PatFrag<(ops node:$addr, node:$offset), (sub node:$addr, (shl node:$offset, 2))>; // Instruction operand types -def calltarget : Operand<i32>; +def pcrel_imm : Operand<i32>; +def pcrel_imm_neg : Operand<i32> { + let DecoderMethod = "DecodeNegImmOperand"; +} def brtarget : Operand<OtherVT>; -def pclabel : Operand<i32>; +def brtarget_neg : Operand<OtherVT> { + let DecoderMethod = "DecodeNegImmOperand"; +} // Addressing modes def ADDRspii : ComplexPattern<i32, 2, "SelectADDRspii", [add, frameindex], []>; -def ADDRdpii : ComplexPattern<i32, 2, "SelectADDRdpii", [add, dprelwrapper], - []>; -def ADDRcpii : ComplexPattern<i32, 2, "SelectADDRcpii", [add, cprelwrapper], - []>; // Address operands def MEMii : Operand<i32> { - let PrintMethod = "printMemOperand"; - let DecoderMethod = "DecodeMEMiiOperand"; let MIOperandInfo = (ops i32imm, i32imm); } @@ -274,10 +273,10 @@ multiclass FRU6_LRU6_branch<bits<6> opc, string OpcStr> { } multiclass FRU6_LRU6_backwards_branch<bits<6> opc, string OpcStr> { - def _ru6: _FRU6<opc, (outs), (ins GRRegs:$a, brtarget:$b), - !strconcat(OpcStr, " $a, -$b"), []>; - def _lru6: _FLRU6<opc, (outs), (ins GRRegs:$a, brtarget:$b), - !strconcat(OpcStr, " $a, -$b"), []>; + def _ru6: _FRU6<opc, (outs), (ins GRRegs:$a, brtarget_neg:$b), + !strconcat(OpcStr, " $a, $b"), []>; + def _lru6: _FLRU6<opc, (outs), (ins GRRegs:$a, brtarget_neg:$b), + !strconcat(OpcStr, " $a, $b"), []>; } multiclass FRU6_LRU6_cp<bits<6> opc, string OpcStr> { @@ -515,29 +514,29 @@ def LMUL_l6r : _FL6R< //let Uses = [DP] in ... let neverHasSideEffects = 1, isReMaterializable = 1 in -def LDAWDP_ru6: _FRU6<0b011000, (outs RRegs:$a), (ins MEMii:$b), +def LDAWDP_ru6: _FRU6<0b011000, (outs RRegs:$a), (ins i32imm:$b), "ldaw $a, dp[$b]", []>; let isReMaterializable = 1 in -def LDAWDP_lru6: _FLRU6<0b011000, (outs RRegs:$a), (ins MEMii:$b), +def LDAWDP_lru6: _FLRU6<0b011000, (outs RRegs:$a), (ins i32imm:$b), "ldaw $a, dp[$b]", - [(set RRegs:$a, ADDRdpii:$b)]>; + [(set RRegs:$a, (dprelwrapper tglobaladdr:$b))]>; let mayLoad=1 in -def LDWDP_ru6: _FRU6<0b010110, (outs RRegs:$a), (ins MEMii:$b), +def LDWDP_ru6: _FRU6<0b010110, (outs RRegs:$a), (ins i32imm:$b), "ldw $a, dp[$b]", []>; -def LDWDP_lru6: _FLRU6<0b010110, (outs RRegs:$a), (ins MEMii:$b), +def LDWDP_lru6: _FLRU6<0b010110, (outs RRegs:$a), (ins i32imm:$b), "ldw $a, dp[$b]", - [(set RRegs:$a, (load ADDRdpii:$b))]>; + [(set RRegs:$a, (load (dprelwrapper tglobaladdr:$b)))]>; let mayStore=1 in -def STWDP_ru6 : _FRU6<0b010100, (outs), (ins RRegs:$a, MEMii:$b), +def STWDP_ru6 : _FRU6<0b010100, (outs), (ins RRegs:$a, i32imm:$b), "stw $a, dp[$b]", []>; -def STWDP_lru6 : _FLRU6<0b010100, (outs), (ins RRegs:$a, MEMii:$b), +def STWDP_lru6 : _FLRU6<0b010100, (outs), (ins RRegs:$a, i32imm:$b), "stw $a, dp[$b]", - [(store RRegs:$a, ADDRdpii:$b)]>; + [(store RRegs:$a, (dprelwrapper tglobaladdr:$b))]>; //let Uses = [CP] in .. let mayLoad = 1, isReMaterializable = 1, neverHasSideEffects = 1 in @@ -615,9 +614,9 @@ let Uses = [R11], isCall=1 in defm BLAT : FU6_LU6_np<0b0111001101, "blat">; let isBranch = 1, isTerminator = 1, isBarrier = 1 in { -def BRBU_u6 : _FU6<0b0111011100, (outs), (ins brtarget:$a), "bu -$a", []>; +def BRBU_u6 : _FU6<0b0111011100, (outs), (ins brtarget_neg:$a), "bu $a", []>; -def BRBU_lu6 : _FLU6<0b0111011100, (outs), (ins brtarget:$a), "bu -$a", []>; +def BRBU_lu6 : _FLU6<0b0111011100, (outs), (ins brtarget_neg:$a), "bu $a", []>; def BRFU_u6 : _FU6<0b0111001100, (outs), (ins brtarget:$a), "bu $a", []>; @@ -626,12 +625,12 @@ def BRFU_lu6 : _FLU6<0b0111001100, (outs), (ins brtarget:$a), "bu $a", []>; //let Uses = [CP] in ... let Defs = [R11], neverHasSideEffects = 1, isReMaterializable = 1 in -def LDAWCP_u6: _FU6<0b0111111101, (outs), (ins MEMii:$a), "ldaw r11, cp[$a]", +def LDAWCP_u6: _FU6<0b0111111101, (outs), (ins i32imm:$a), "ldaw r11, cp[$a]", []>; let Defs = [R11], isReMaterializable = 1 in -def LDAWCP_lu6: _FLU6<0b0111111101, (outs), (ins MEMii:$a), "ldaw r11, cp[$a]", - [(set R11, ADDRcpii:$a)]>; +def LDAWCP_lu6: _FLU6<0b0111111101, (outs), (ins i32imm:$a), "ldaw r11, cp[$a]", + [(set R11, (cprelwrapper tglobaladdr:$a))]>; let Defs = [R11] in defm GETSR : FU6_LU6_np<0b0111111100, "getsr r11,">; @@ -658,16 +657,26 @@ defm KRESTSP : FU6_LU6_np<0b0111101111, "krestsp">; // U10 -let Defs = [R11], isReMaterializable = 1, neverHasSideEffects = 1 in -def LDAPF_u10 : _FU10<0b110110, (outs), (ins i32imm:$a), "ldap r11, $a", []>; +let Defs = [R11], isReMaterializable = 1 in { +let neverHasSideEffects = 1 in +def LDAPF_u10 : _FU10<0b110110, (outs), (ins pcrel_imm:$a), "ldap r11, $a", []>; + +def LDAPF_lu10 : _FLU10<0b110110, (outs), (ins pcrel_imm:$a), "ldap r11, $a", + [(set R11, (pcrelwrapper tglobaladdr:$a))]>; -let Defs = [R11], isReMaterializable = 1 in -def LDAPF_lu10 : _FLU10<0b110110, (outs), (ins i32imm:$a), "ldap r11, $a", +let neverHasSideEffects = 1 in +def LDAPB_u10 : _FU10<0b110111, (outs), (ins pcrel_imm_neg:$a), "ldap r11, $a", + []>; + +let neverHasSideEffects = 1 in +def LDAPB_lu10 : _FLU10<0b110111, (outs), (ins pcrel_imm_neg:$a), + "ldap r11, $a", [(set R11, (pcrelwrapper tglobaladdr:$a))]>; -let Defs = [R11], isReMaterializable = 1, isCodeGenOnly = 1 in -def LDAPF_lu10_ba : _FLU10<0b110110, (outs), (ins i32imm:$a), "ldap r11, $a", +let isCodeGenOnly = 1 in +def LDAPF_lu10_ba : _FLU10<0b110110, (outs), (ins pcrel_imm:$a), "ldap r11, $a", [(set R11, (pcrelwrapper tblockaddress:$a))]>; +} let isCall=1, // All calls clobber the link register and the non-callee-saved registers: @@ -676,11 +685,15 @@ def BLACP_u10 : _FU10<0b111000, (outs), (ins i32imm:$a), "bla cp[$a]", []>; def BLACP_lu10 : _FLU10<0b111000, (outs), (ins i32imm:$a), "bla cp[$a]", []>; -def BLRF_u10 : _FU10<0b110100, (outs), (ins calltarget:$a), "bl $a", +def BLRF_u10 : _FU10<0b110100, (outs), (ins pcrel_imm:$a), "bl $a", [(XCoreBranchLink immU10:$a)]>; -def BLRF_lu10 : _FLU10<0b110100, (outs), (ins calltarget:$a), "bl $a", +def BLRF_lu10 : _FLU10<0b110100, (outs), (ins pcrel_imm:$a), "bl $a", [(XCoreBranchLink immU20:$a)]>; + +def BLRB_u10 : _FU10<0b110101, (outs), (ins pcrel_imm_neg:$a), "bl $a", []>; + +def BLRB_lu10 : _FLU10<0b110101, (outs), (ins pcrel_imm_neg:$a), "bl $a", []>; } let Defs = [R11], mayLoad = 1, isReMaterializable = 1, diff --git a/lib/Target/XCore/XCoreLowerThreadLocal.cpp b/lib/Target/XCore/XCoreLowerThreadLocal.cpp new file mode 100644 index 0000000..2e328b4 --- /dev/null +++ b/lib/Target/XCore/XCoreLowerThreadLocal.cpp @@ -0,0 +1,145 @@ +//===-- XCoreLowerThreadLocal - Lower thread local variables --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file contains a pass that lowers thread local variables on the +/// XCore. +/// +//===----------------------------------------------------------------------===// + +#include "XCore.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/CommandLine.h" + +#define DEBUG_TYPE "xcore-lower-thread-local" + +using namespace llvm; + +static cl::opt<unsigned> MaxThreads( + "xcore-max-threads", cl::Optional, + cl::desc("Maximum number of threads (for emulation thread-local storage)"), + cl::Hidden, cl::value_desc("number"), cl::init(8)); + +namespace { + /// Lowers thread local variables on the XCore. Each thread local variable is + /// expanded to an array of n elements indexed by the thread ID where n is the + /// fixed number hardware threads supported by the device. + struct XCoreLowerThreadLocal : public ModulePass { + static char ID; + + XCoreLowerThreadLocal() : ModulePass(ID) { + initializeXCoreLowerThreadLocalPass(*PassRegistry::getPassRegistry()); + } + + bool lowerGlobal(GlobalVariable *GV); + + bool runOnModule(Module &M); + }; +} + +char XCoreLowerThreadLocal::ID = 0; + +INITIALIZE_PASS(XCoreLowerThreadLocal, "xcore-lower-thread-local", + "Lower thread local variables", false, false) + +ModulePass *llvm::createXCoreLowerThreadLocalPass() { + return new XCoreLowerThreadLocal(); +} + +static ArrayType *createLoweredType(Type *OriginalType) { + return ArrayType::get(OriginalType, MaxThreads); +} + +static Constant * +createLoweredInitializer(ArrayType *NewType, Constant *OriginalInitializer) { + SmallVector<Constant *, 8> Elements(MaxThreads); + for (unsigned i = 0; i != MaxThreads; ++i) { + Elements[i] = OriginalInitializer; + } + return ConstantArray::get(NewType, Elements); +} + +static bool hasNonInstructionUse(GlobalVariable *GV) { + for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end(); UI != E; + ++UI) + if (!isa<Instruction>(*UI)) + return true; + + return false; +} + +static bool isZeroLengthArray(Type *Ty) { + ArrayType *AT = dyn_cast<ArrayType>(Ty); + return AT && (AT->getNumElements() == 0); +} + +bool XCoreLowerThreadLocal::lowerGlobal(GlobalVariable *GV) { + Module *M = GV->getParent(); + LLVMContext &Ctx = M->getContext(); + if (!GV->isThreadLocal()) + return false; + + // Skip globals that we can't lower and leave it for the backend to error. + if (hasNonInstructionUse(GV) || + !GV->getType()->isSized() || isZeroLengthArray(GV->getType())) + return false; + + // Create replacement global. + ArrayType *NewType = createLoweredType(GV->getType()->getElementType()); + Constant *NewInitializer = createLoweredInitializer(NewType, + GV->getInitializer()); + GlobalVariable *NewGV = + new GlobalVariable(*M, NewType, GV->isConstant(), GV->getLinkage(), + NewInitializer, "", 0, GlobalVariable::NotThreadLocal, + GV->getType()->getAddressSpace(), + GV->isExternallyInitialized()); + + // Update uses. + SmallVector<User *, 16> Users(GV->use_begin(), GV->use_end()); + for (unsigned I = 0, E = Users.size(); I != E; ++I) { + User *U = Users[I]; + Instruction *Inst = cast<Instruction>(U); + IRBuilder<> Builder(Inst); + Function *GetID = Intrinsic::getDeclaration(GV->getParent(), + Intrinsic::xcore_getid); + Value *ThreadID = Builder.CreateCall(GetID); + SmallVector<Value *, 2> Indices; + Indices.push_back(Constant::getNullValue(Type::getInt64Ty(Ctx))); + Indices.push_back(ThreadID); + Value *Addr = Builder.CreateInBoundsGEP(NewGV, Indices); + U->replaceUsesOfWith(GV, Addr); + } + + // Remove old global. + NewGV->takeName(GV); + GV->eraseFromParent(); + return true; +} + +bool XCoreLowerThreadLocal::runOnModule(Module &M) { + // Find thread local globals. + bool MadeChange = false; + SmallVector<GlobalVariable *, 16> ThreadLocalGlobals; + for (Module::global_iterator GVI = M.global_begin(), E = M.global_end(); + GVI != E; ++GVI) { + GlobalVariable *GV = GVI; + if (GV->isThreadLocal()) + ThreadLocalGlobals.push_back(GV); + } + for (unsigned I = 0, E = ThreadLocalGlobals.size(); I != E; ++I) { + MadeChange |= lowerGlobal(ThreadLocalGlobals[I]); + } + return MadeChange; +} diff --git a/lib/Target/XCore/XCoreRegisterInfo.cpp b/lib/Target/XCore/XCoreRegisterInfo.cpp index 49b5634..dbd2f52 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -37,8 +37,8 @@ using namespace llvm; -XCoreRegisterInfo::XCoreRegisterInfo(const TargetInstrInfo &tii) - : XCoreGenRegisterInfo(XCore::LR), TII(tii) { +XCoreRegisterInfo::XCoreRegisterInfo() + : XCoreGenRegisterInfo(XCore::LR) { } // helper functions @@ -112,6 +112,7 @@ XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int FrameIndex = FrameOp.getIndex(); MachineFunction &MF = *MI.getParent()->getParent(); + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex); int StackSize = MF.getFrameInfo()->getStackSize(); @@ -249,6 +250,7 @@ loadConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, report_fatal_error("loadConstant value too big " + Twine(Value)); } int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6; + const TargetInstrInfo &TII = *MBB.getParent()->getTarget().getInstrInfo(); BuildMI(MBB, I, dl, TII.get(Opcode), DstReg).addImm(Value); } diff --git a/lib/Target/XCore/XCoreRegisterInfo.h b/lib/Target/XCore/XCoreRegisterInfo.h index 1db3248..2370c62 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.h +++ b/lib/Target/XCore/XCoreRegisterInfo.h @@ -25,8 +25,6 @@ class TargetInstrInfo; struct XCoreRegisterInfo : public XCoreGenRegisterInfo { private: - const TargetInstrInfo &TII; - void loadConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned DstReg, int64_t Value, DebugLoc dl) const; @@ -40,7 +38,7 @@ private: unsigned DstReg, int Offset, DebugLoc dl) const; public: - XCoreRegisterInfo(const TargetInstrInfo &tii); + XCoreRegisterInfo(); /// Code Generation virtual methods... diff --git a/lib/Target/XCore/XCoreTargetMachine.cpp b/lib/Target/XCore/XCoreTargetMachine.cpp index 28c3d12..3ef1520 100644 --- a/lib/Target/XCore/XCoreTargetMachine.cpp +++ b/lib/Target/XCore/XCoreTargetMachine.cpp @@ -33,6 +33,7 @@ XCoreTargetMachine::XCoreTargetMachine(const Target &T, StringRef TT, FrameLowering(Subtarget), TLInfo(*this), TSInfo(*this) { + initAsmInfo(); } namespace { @@ -46,6 +47,7 @@ public: return getTM<XCoreTargetMachine>(); } + virtual bool addPreISel(); virtual bool addInstSelector(); }; } // namespace @@ -54,6 +56,11 @@ TargetPassConfig *XCoreTargetMachine::createPassConfig(PassManagerBase &PM) { return new XCorePassConfig(this, PM); } +bool XCorePassConfig::addPreISel() { + addPass(createXCoreLowerThreadLocalPass()); + return false; +} + bool XCorePassConfig::addInstSelector() { addPass(createXCoreISelDag(getXCoreTargetMachine(), getOptLevel())); return false; diff --git a/lib/Target/XCore/XCoreTargetObjectFile.cpp b/lib/Target/XCore/XCoreTargetObjectFile.cpp index 8203899..88e3bfd 100644 --- a/lib/Target/XCore/XCoreTargetObjectFile.cpp +++ b/lib/Target/XCore/XCoreTargetObjectFile.cpp @@ -57,9 +57,4 @@ void XCoreTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ ELF::SHF_ALLOC | ELF::XCORE_SHF_CP_SECTION, SectionKind::getReadOnlyWithRel()); - - // Dynamic linking is not supported. Data with relocations is placed in the - // same section as data without relocations. - DataRelSection = DataRelLocalSection = DataSection; - DataRelROSection = DataRelROLocalSection = ReadOnlySection; } |